lqft-python-engine 0.3.0__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lqft_python_engine-0.3.0 → lqft_python_engine-0.7.0}/PKG-INFO +2 -2
- lqft_python_engine-0.7.0/lqft_engine.c +583 -0
- lqft_python_engine-0.7.0/lqft_engine.py +109 -0
- {lqft_python_engine-0.3.0 → lqft_python_engine-0.7.0}/lqft_python_engine.egg-info/PKG-INFO +2 -2
- {lqft_python_engine-0.3.0 → lqft_python_engine-0.7.0}/lqft_python_engine.egg-info/SOURCES.txt +0 -1
- {lqft_python_engine-0.3.0 → lqft_python_engine-0.7.0}/lqft_python_engine.egg-info/top_level.txt +0 -1
- {lqft_python_engine-0.3.0 → lqft_python_engine-0.7.0}/setup.py +3 -3
- lqft_python_engine-0.3.0/lqft_engine.c +0 -373
- lqft_python_engine-0.3.0/lqft_engine.py +0 -237
- lqft_python_engine-0.3.0/pure_python_ds.py +0 -139
- {lqft_python_engine-0.3.0 → lqft_python_engine-0.7.0}/LICENSE.md +0 -0
- {lqft_python_engine-0.3.0 → lqft_python_engine-0.7.0}/lqft_python_engine.egg-info/dependency_links.txt +0 -0
- {lqft_python_engine-0.3.0 → lqft_python_engine-0.7.0}/lqft_python_engine.egg-info/requires.txt +0 -0
- {lqft_python_engine-0.3.0 → lqft_python_engine-0.7.0}/pyproject.toml +0 -0
- {lqft_python_engine-0.3.0 → lqft_python_engine-0.7.0}/setup.cfg +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lqft-python-engine
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: LQFT Engine:
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: LQFT Engine: Strict Native C-Core & Hardware Concurrency (v0.7.0 Stable)
|
|
5
5
|
Home-page: https://github.com/ParjadM/Log-Quantum-Fractal-Tree-LQFT-
|
|
6
6
|
Author: Parjad Minooei
|
|
7
7
|
License: MIT
|
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
#define PY_SSIZE_T_CLEAN
|
|
2
|
+
#include <Python.h>
|
|
3
|
+
|
|
4
|
+
#ifndef _CRT_SECURE_NO_WARNINGS
|
|
5
|
+
#define _CRT_SECURE_NO_WARNINGS
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
#include <stdio.h>
|
|
9
|
+
#include <stdlib.h>
|
|
10
|
+
#include <string.h>
|
|
11
|
+
#include <stdint.h>
|
|
12
|
+
|
|
13
|
+
// --- PHASE 2: CROSS-PLATFORM HARDWARE LOCKS ---
|
|
14
|
+
#ifdef _WIN32
|
|
15
|
+
#include <windows.h>
|
|
16
|
+
typedef SRWLOCK lqft_rwlock_t;
|
|
17
|
+
#define LQFT_RWLOCK_INIT(lock) InitializeSRWLock(lock)
|
|
18
|
+
#define LQFT_RWLOCK_RDLOCK(lock) AcquireSRWLockShared(lock)
|
|
19
|
+
#define LQFT_RWLOCK_WRLOCK(lock) AcquireSRWLockExclusive(lock)
|
|
20
|
+
#define LQFT_RWLOCK_UNLOCK_RD(lock) ReleaseSRWLockShared(lock)
|
|
21
|
+
#define LQFT_RWLOCK_UNLOCK_WR(lock) ReleaseSRWLockExclusive(lock)
|
|
22
|
+
#else
|
|
23
|
+
#include <pthread.h>
|
|
24
|
+
typedef pthread_rwlock_t lqft_rwlock_t;
|
|
25
|
+
#define LQFT_RWLOCK_INIT(lock) pthread_rwlock_init(lock, NULL)
|
|
26
|
+
#define LQFT_RWLOCK_RDLOCK(lock) pthread_rwlock_rdlock(lock)
|
|
27
|
+
#define LQFT_RWLOCK_WRLOCK(lock) pthread_rwlock_wrlock(lock)
|
|
28
|
+
#define LQFT_RWLOCK_UNLOCK_RD(lock) pthread_rwlock_unlock(lock)
|
|
29
|
+
#define LQFT_RWLOCK_UNLOCK_WR(lock) pthread_rwlock_unlock(lock)
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* LQFT C-Engine - V0.6.0 (Hardware Concurrency)
|
|
34
|
+
* Architect: Parjad Minooei
|
|
35
|
+
* * CHANGE LOG:
|
|
36
|
+
* - Implemented SRWLOCK / pthread_rwlock for true multi-core utilization.
|
|
37
|
+
* - Bypassed Python GIL using Py_BEGIN_ALLOW_THREADS.
|
|
38
|
+
* - Fixed Macro brace expansions for thread safe early returns.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
#define BIT_PARTITION 5
|
|
42
|
+
#define MAX_BITS 64
|
|
43
|
+
#define MASK 0x1F
|
|
44
|
+
#define REGISTRY_SIZE 8000009
|
|
45
|
+
#define TOMBSTONE ((LQFTNode*)1)
|
|
46
|
+
|
|
47
|
+
typedef struct LQFTNode {
|
|
48
|
+
void* value;
|
|
49
|
+
uint64_t key_hash;
|
|
50
|
+
struct LQFTNode* children[32];
|
|
51
|
+
char struct_hash[17];
|
|
52
|
+
uint64_t full_hash_val;
|
|
53
|
+
int ref_count;
|
|
54
|
+
} LQFTNode;
|
|
55
|
+
|
|
56
|
+
static LQFTNode** registry = NULL;
|
|
57
|
+
static int physical_node_count = 0;
|
|
58
|
+
static LQFTNode* global_root = NULL;
|
|
59
|
+
static lqft_rwlock_t engine_lock; // The Master Hardware Lock
|
|
60
|
+
static int lock_initialized = 0;
|
|
61
|
+
|
|
62
|
+
const uint64_t FNV_OFFSET_BASIS = 14695981039346656037ULL;
|
|
63
|
+
const uint64_t FNV_PRIME = 1099511628211ULL;
|
|
64
|
+
|
|
65
|
+
// -------------------------------------------------------------------
|
|
66
|
+
// Utilities
|
|
67
|
+
// -------------------------------------------------------------------
|
|
68
|
+
uint64_t fnv1a_update(uint64_t hash, const void* data, size_t len) {
|
|
69
|
+
const uint8_t* p = (const uint8_t*)data;
|
|
70
|
+
for (size_t i = 0; i < len; i++) {
|
|
71
|
+
hash ^= p[i];
|
|
72
|
+
hash *= FNV_PRIME;
|
|
73
|
+
}
|
|
74
|
+
return hash;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
char* portable_strdup(const char* s) {
|
|
78
|
+
if (!s) return NULL;
|
|
79
|
+
#ifdef _WIN32
|
|
80
|
+
return _strdup(s);
|
|
81
|
+
#else
|
|
82
|
+
return strdup(s);
|
|
83
|
+
#endif
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static int init_registry() {
|
|
87
|
+
if (!lock_initialized) {
|
|
88
|
+
LQFT_RWLOCK_INIT(&engine_lock);
|
|
89
|
+
lock_initialized = 1;
|
|
90
|
+
}
|
|
91
|
+
if (registry == NULL) {
|
|
92
|
+
registry = (LQFTNode**)calloc(REGISTRY_SIZE, sizeof(LQFTNode*));
|
|
93
|
+
if (registry == NULL) return 0;
|
|
94
|
+
}
|
|
95
|
+
return 1;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
LQFTNode* create_node(void* value, uint64_t key_hash) {
|
|
99
|
+
LQFTNode* node = (LQFTNode*)malloc(sizeof(LQFTNode));
|
|
100
|
+
if (!node) return NULL;
|
|
101
|
+
node->value = value;
|
|
102
|
+
node->key_hash = key_hash;
|
|
103
|
+
node->full_hash_val = 0;
|
|
104
|
+
node->ref_count = 0;
|
|
105
|
+
for (int i = 0; i < 32; i++) node->children[i] = NULL;
|
|
106
|
+
return node;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// -------------------------------------------------------------------
|
|
110
|
+
// Memory Management (ARC)
|
|
111
|
+
// -------------------------------------------------------------------
|
|
112
|
+
void decref(LQFTNode* node) {
|
|
113
|
+
if (!node) return;
|
|
114
|
+
node->ref_count--;
|
|
115
|
+
if (node->ref_count <= 0) {
|
|
116
|
+
for (int i = 0; i < 32; i++) {
|
|
117
|
+
if (node->children[i]) decref(node->children[i]);
|
|
118
|
+
}
|
|
119
|
+
uint32_t idx = node->full_hash_val % REGISTRY_SIZE;
|
|
120
|
+
uint32_t start_idx = idx;
|
|
121
|
+
while (registry[idx] != NULL) {
|
|
122
|
+
if (registry[idx] == node) {
|
|
123
|
+
registry[idx] = TOMBSTONE;
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
idx = (idx + 1) % REGISTRY_SIZE;
|
|
127
|
+
if (idx == start_idx) break;
|
|
128
|
+
}
|
|
129
|
+
if (node->value) free(node->value);
|
|
130
|
+
free(node);
|
|
131
|
+
physical_node_count--;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
static PyObject* method_free_all(PyObject* self, PyObject* args) {
|
|
136
|
+
Py_BEGIN_ALLOW_THREADS
|
|
137
|
+
LQFT_RWLOCK_WRLOCK(&engine_lock);
|
|
138
|
+
if (registry != NULL) {
|
|
139
|
+
for (int i = 0; i < REGISTRY_SIZE; i++) {
|
|
140
|
+
if (registry[i] != NULL && registry[i] != TOMBSTONE) {
|
|
141
|
+
if (registry[i]->value) free(registry[i]->value);
|
|
142
|
+
free(registry[i]);
|
|
143
|
+
}
|
|
144
|
+
registry[i] = NULL;
|
|
145
|
+
}
|
|
146
|
+
free(registry);
|
|
147
|
+
registry = NULL;
|
|
148
|
+
}
|
|
149
|
+
physical_node_count = 0;
|
|
150
|
+
global_root = NULL;
|
|
151
|
+
LQFT_RWLOCK_UNLOCK_WR(&engine_lock);
|
|
152
|
+
Py_END_ALLOW_THREADS
|
|
153
|
+
|
|
154
|
+
Py_RETURN_NONE;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// -------------------------------------------------------------------
|
|
158
|
+
// Disk Persistence (Binary Serialization)
|
|
159
|
+
// -------------------------------------------------------------------
|
|
160
|
+
static PyObject* method_save_to_disk(PyObject* self, PyObject* args) {
|
|
161
|
+
const char* filepath;
|
|
162
|
+
if (!PyArg_ParseTuple(args, "s", &filepath)) return NULL;
|
|
163
|
+
|
|
164
|
+
int success = 1;
|
|
165
|
+
|
|
166
|
+
// Release GIL, Lock Engine for Writing
|
|
167
|
+
Py_BEGIN_ALLOW_THREADS
|
|
168
|
+
LQFT_RWLOCK_WRLOCK(&engine_lock);
|
|
169
|
+
|
|
170
|
+
if (!registry) {
|
|
171
|
+
success = 0;
|
|
172
|
+
} else {
|
|
173
|
+
FILE* fp = fopen(filepath, "wb");
|
|
174
|
+
if (!fp) {
|
|
175
|
+
success = 0;
|
|
176
|
+
} else {
|
|
177
|
+
char magic[4] = "LQFT";
|
|
178
|
+
fwrite(magic, 1, 4, fp);
|
|
179
|
+
fwrite(&physical_node_count, sizeof(int), 1, fp);
|
|
180
|
+
uint64_t root_hash = global_root ? global_root->full_hash_val : 0;
|
|
181
|
+
fwrite(&root_hash, sizeof(uint64_t), 1, fp);
|
|
182
|
+
|
|
183
|
+
for (int i = 0; i < REGISTRY_SIZE; i++) {
|
|
184
|
+
LQFTNode* node = registry[i];
|
|
185
|
+
if (node != NULL && node != TOMBSTONE) {
|
|
186
|
+
fwrite(&node->full_hash_val, sizeof(uint64_t), 1, fp);
|
|
187
|
+
fwrite(&node->key_hash, sizeof(uint64_t), 1, fp);
|
|
188
|
+
fwrite(node->struct_hash, 1, 17, fp);
|
|
189
|
+
fwrite(&node->ref_count, sizeof(int), 1, fp);
|
|
190
|
+
|
|
191
|
+
int has_val = (node->value != NULL) ? 1 : 0;
|
|
192
|
+
fwrite(&has_val, sizeof(int), 1, fp);
|
|
193
|
+
if (has_val) {
|
|
194
|
+
int v_len = (int)strlen((char*)node->value);
|
|
195
|
+
fwrite(&v_len, sizeof(int), 1, fp);
|
|
196
|
+
fwrite(node->value, 1, v_len, fp);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
uint64_t child_refs[32] = {0};
|
|
200
|
+
for (int c = 0; c < 32; c++) {
|
|
201
|
+
if (node->children[c]) child_refs[c] = node->children[c]->full_hash_val;
|
|
202
|
+
}
|
|
203
|
+
fwrite(child_refs, sizeof(uint64_t), 32, fp);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
fclose(fp);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
LQFT_RWLOCK_UNLOCK_WR(&engine_lock);
|
|
210
|
+
Py_END_ALLOW_THREADS
|
|
211
|
+
|
|
212
|
+
if (!success) return PyErr_SetFromErrno(PyExc_IOError);
|
|
213
|
+
Py_RETURN_TRUE;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
LQFTNode* find_in_registry(uint64_t full_hash) {
|
|
217
|
+
if (full_hash == 0) return NULL;
|
|
218
|
+
uint32_t idx = full_hash % REGISTRY_SIZE;
|
|
219
|
+
uint32_t start_idx = idx;
|
|
220
|
+
while (registry[idx] != NULL) {
|
|
221
|
+
if (registry[idx] != TOMBSTONE && registry[idx]->full_hash_val == full_hash) {
|
|
222
|
+
return registry[idx];
|
|
223
|
+
}
|
|
224
|
+
idx = (idx + 1) % REGISTRY_SIZE;
|
|
225
|
+
if (idx == start_idx) break;
|
|
226
|
+
}
|
|
227
|
+
return NULL;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
static PyObject* method_load_from_disk(PyObject* self, PyObject* args) {
|
|
231
|
+
const char* filepath;
|
|
232
|
+
if (!PyArg_ParseTuple(args, "s", &filepath)) return NULL;
|
|
233
|
+
|
|
234
|
+
int success = 1;
|
|
235
|
+
int format_error = 0;
|
|
236
|
+
|
|
237
|
+
Py_BEGIN_ALLOW_THREADS
|
|
238
|
+
LQFT_RWLOCK_WRLOCK(&engine_lock);
|
|
239
|
+
|
|
240
|
+
FILE* fp = fopen(filepath, "rb");
|
|
241
|
+
if (!fp) {
|
|
242
|
+
success = 0;
|
|
243
|
+
} else {
|
|
244
|
+
char magic[5] = {0};
|
|
245
|
+
fread(magic, 1, 4, fp);
|
|
246
|
+
if (strcmp(magic, "LQFT") != 0) {
|
|
247
|
+
fclose(fp);
|
|
248
|
+
format_error = 1;
|
|
249
|
+
success = 0;
|
|
250
|
+
} else {
|
|
251
|
+
// Internal clear
|
|
252
|
+
if (registry != NULL) {
|
|
253
|
+
for (int i = 0; i < REGISTRY_SIZE; i++) {
|
|
254
|
+
if (registry[i] != NULL && registry[i] != TOMBSTONE) {
|
|
255
|
+
if (registry[i]->value) free(registry[i]->value);
|
|
256
|
+
free(registry[i]);
|
|
257
|
+
}
|
|
258
|
+
registry[i] = NULL;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
physical_node_count = 0;
|
|
262
|
+
global_root = NULL;
|
|
263
|
+
init_registry();
|
|
264
|
+
|
|
265
|
+
int total_nodes;
|
|
266
|
+
uint64_t root_hash;
|
|
267
|
+
fread(&total_nodes, sizeof(int), 1, fp);
|
|
268
|
+
fread(&root_hash, sizeof(uint64_t), 1, fp);
|
|
269
|
+
|
|
270
|
+
uint64_t* all_child_refs = (uint64_t*)malloc(total_nodes * 32 * sizeof(uint64_t));
|
|
271
|
+
LQFTNode** loaded_nodes = (LQFTNode**)malloc(total_nodes * sizeof(LQFTNode*));
|
|
272
|
+
|
|
273
|
+
for (int i = 0; i < total_nodes; i++) {
|
|
274
|
+
LQFTNode* node = create_node(NULL, 0);
|
|
275
|
+
fread(&node->full_hash_val, sizeof(uint64_t), 1, fp);
|
|
276
|
+
fread(&node->key_hash, sizeof(uint64_t), 1, fp);
|
|
277
|
+
fread(node->struct_hash, 1, 17, fp);
|
|
278
|
+
fread(&node->ref_count, sizeof(int), 1, fp);
|
|
279
|
+
|
|
280
|
+
int has_val;
|
|
281
|
+
fread(&has_val, sizeof(int), 1, fp);
|
|
282
|
+
if (has_val) {
|
|
283
|
+
int v_len;
|
|
284
|
+
fread(&v_len, sizeof(int), 1, fp);
|
|
285
|
+
char* val_str = (char*)malloc(v_len + 1);
|
|
286
|
+
fread(val_str, 1, v_len, fp);
|
|
287
|
+
val_str[v_len] = '\0';
|
|
288
|
+
node->value = val_str;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
fread(&all_child_refs[i * 32], sizeof(uint64_t), 32, fp);
|
|
292
|
+
|
|
293
|
+
uint32_t idx = node->full_hash_val % REGISTRY_SIZE;
|
|
294
|
+
while (registry[idx] != NULL) idx = (idx + 1) % REGISTRY_SIZE;
|
|
295
|
+
registry[idx] = node;
|
|
296
|
+
loaded_nodes[i] = node;
|
|
297
|
+
physical_node_count++;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
for (int i = 0; i < total_nodes; i++) {
|
|
301
|
+
for (int c = 0; c < 32; c++) {
|
|
302
|
+
uint64_t target_hash = all_child_refs[i * 32 + c];
|
|
303
|
+
if (target_hash != 0) loaded_nodes[i]->children[c] = find_in_registry(target_hash);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
global_root = find_in_registry(root_hash);
|
|
308
|
+
free(all_child_refs);
|
|
309
|
+
free(loaded_nodes);
|
|
310
|
+
fclose(fp);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
LQFT_RWLOCK_UNLOCK_WR(&engine_lock);
|
|
314
|
+
Py_END_ALLOW_THREADS
|
|
315
|
+
|
|
316
|
+
if (format_error) {
|
|
317
|
+
PyErr_SetString(PyExc_ValueError, "Invalid LQFT binary file format.");
|
|
318
|
+
return NULL;
|
|
319
|
+
}
|
|
320
|
+
if (!success) return PyErr_SetFromErrno(PyExc_IOError);
|
|
321
|
+
|
|
322
|
+
Py_RETURN_TRUE;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// -------------------------------------------------------------------
|
|
326
|
+
// Merkle-DAG Core (Standard Operations)
|
|
327
|
+
// -------------------------------------------------------------------
|
|
328
|
+
LQFTNode* get_canonical(void* value, uint64_t key_hash, LQFTNode** children) {
|
|
329
|
+
if (!init_registry()) return NULL;
|
|
330
|
+
|
|
331
|
+
uint64_t full_hash = FNV_OFFSET_BASIS;
|
|
332
|
+
if (value != NULL) {
|
|
333
|
+
full_hash = fnv1a_update(full_hash, "leaf:", 5);
|
|
334
|
+
full_hash = fnv1a_update(full_hash, value, strlen((char*)value));
|
|
335
|
+
full_hash = fnv1a_update(full_hash, &key_hash, sizeof(uint64_t));
|
|
336
|
+
} else {
|
|
337
|
+
full_hash = fnv1a_update(full_hash, "branch:", 7);
|
|
338
|
+
if (children) {
|
|
339
|
+
for (int i = 0; i < 32; i++) {
|
|
340
|
+
if (children[i]) {
|
|
341
|
+
full_hash = fnv1a_update(full_hash, &i, sizeof(int));
|
|
342
|
+
full_hash = fnv1a_update(full_hash, children[i]->struct_hash, 16);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
char lookup_hash[17];
|
|
349
|
+
sprintf(lookup_hash, "%016llx", (unsigned long long)full_hash);
|
|
350
|
+
uint32_t idx = full_hash % REGISTRY_SIZE;
|
|
351
|
+
uint32_t start_idx = idx;
|
|
352
|
+
int first_tombstone = -1;
|
|
353
|
+
|
|
354
|
+
while (registry[idx] != NULL) {
|
|
355
|
+
if (registry[idx] == TOMBSTONE) {
|
|
356
|
+
if (first_tombstone == -1) first_tombstone = (int)idx;
|
|
357
|
+
} else if (registry[idx]->full_hash_val == full_hash && strcmp(registry[idx]->struct_hash, lookup_hash) == 0) {
|
|
358
|
+
if (value) free(value);
|
|
359
|
+
return registry[idx];
|
|
360
|
+
}
|
|
361
|
+
idx = (idx + 1) % REGISTRY_SIZE;
|
|
362
|
+
if (idx == start_idx) break;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
LQFTNode* new_node = create_node(value, key_hash);
|
|
366
|
+
if (!new_node) return NULL;
|
|
367
|
+
|
|
368
|
+
if (children) {
|
|
369
|
+
for (int i = 0; i < 32; i++) {
|
|
370
|
+
new_node->children[i] = children[i];
|
|
371
|
+
if (children[i]) children[i]->ref_count++;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
strcpy(new_node->struct_hash, lookup_hash);
|
|
376
|
+
new_node->full_hash_val = full_hash;
|
|
377
|
+
|
|
378
|
+
uint32_t insert_idx = (first_tombstone != -1) ? (uint32_t)first_tombstone : idx;
|
|
379
|
+
registry[insert_idx] = new_node;
|
|
380
|
+
physical_node_count++;
|
|
381
|
+
|
|
382
|
+
return new_node;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
static PyObject* method_insert(PyObject* self, PyObject* args) {
|
|
386
|
+
unsigned long long h;
|
|
387
|
+
char* val_str;
|
|
388
|
+
if (!PyArg_ParseTuple(args, "Ks", &h, &val_str)) return NULL;
|
|
389
|
+
|
|
390
|
+
// Copy the string before dropping the GIL to prevent memory corruption
|
|
391
|
+
char* val_copy = portable_strdup(val_str);
|
|
392
|
+
|
|
393
|
+
// Bypass GIL & Lock Engine (Exclusive Write Lock)
|
|
394
|
+
Py_BEGIN_ALLOW_THREADS
|
|
395
|
+
LQFT_RWLOCK_WRLOCK(&engine_lock);
|
|
396
|
+
|
|
397
|
+
if (!global_root) {
|
|
398
|
+
init_registry();
|
|
399
|
+
global_root = get_canonical(NULL, 0, NULL);
|
|
400
|
+
global_root->ref_count++;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
LQFTNode* old_root = global_root;
|
|
404
|
+
LQFTNode* path_nodes[20];
|
|
405
|
+
uint32_t path_segs[20];
|
|
406
|
+
int path_len = 0;
|
|
407
|
+
LQFTNode* curr = global_root;
|
|
408
|
+
int bit_depth = 0;
|
|
409
|
+
|
|
410
|
+
while (curr != NULL && curr->value == NULL) {
|
|
411
|
+
uint32_t segment = (h >> bit_depth) & MASK;
|
|
412
|
+
path_nodes[path_len] = curr;
|
|
413
|
+
path_segs[path_len] = segment;
|
|
414
|
+
path_len++;
|
|
415
|
+
if (curr->children[segment] == NULL) { curr = NULL; break; }
|
|
416
|
+
curr = curr->children[segment];
|
|
417
|
+
bit_depth += BIT_PARTITION;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
LQFTNode* new_sub_node = NULL;
|
|
421
|
+
if (curr == NULL) {
|
|
422
|
+
new_sub_node = get_canonical(portable_strdup(val_copy), h, NULL);
|
|
423
|
+
} else if (curr->key_hash == h) {
|
|
424
|
+
new_sub_node = get_canonical(portable_strdup(val_copy), h, curr->children);
|
|
425
|
+
} else {
|
|
426
|
+
unsigned long long old_h = curr->key_hash;
|
|
427
|
+
char* old_val = portable_strdup((char*)curr->value);
|
|
428
|
+
int temp_depth = bit_depth;
|
|
429
|
+
while (temp_depth < 64) {
|
|
430
|
+
uint32_t s_old = (old_h >> temp_depth) & MASK;
|
|
431
|
+
uint32_t s_new = (h >> temp_depth) & MASK;
|
|
432
|
+
if (s_old != s_new) {
|
|
433
|
+
LQFTNode* c_old = get_canonical(old_val, old_h, curr->children);
|
|
434
|
+
LQFTNode* c_new = get_canonical(portable_strdup(val_copy), h, NULL);
|
|
435
|
+
LQFTNode* new_children[32] = {NULL};
|
|
436
|
+
new_children[s_old] = c_old;
|
|
437
|
+
new_children[s_new] = c_new;
|
|
438
|
+
new_sub_node = get_canonical(NULL, 0, new_children);
|
|
439
|
+
break;
|
|
440
|
+
} else {
|
|
441
|
+
path_nodes[path_len] = NULL;
|
|
442
|
+
path_segs[path_len] = s_old;
|
|
443
|
+
path_len++;
|
|
444
|
+
temp_depth += BIT_PARTITION;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
if (new_sub_node == NULL) new_sub_node = get_canonical(portable_strdup(val_copy), h, curr->children);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
for (int i = path_len - 1; i >= 0; i--) {
|
|
451
|
+
if (path_nodes[i] == NULL) {
|
|
452
|
+
LQFTNode* new_children[32] = {NULL};
|
|
453
|
+
new_children[path_segs[i]] = new_sub_node;
|
|
454
|
+
new_sub_node = get_canonical(NULL, 0, new_children);
|
|
455
|
+
} else {
|
|
456
|
+
LQFTNode* p_node = path_nodes[i];
|
|
457
|
+
uint32_t segment = path_segs[i];
|
|
458
|
+
LQFTNode* new_children[32];
|
|
459
|
+
for (int j = 0; j < 32; j++) new_children[j] = p_node->children[j];
|
|
460
|
+
new_children[segment] = new_sub_node;
|
|
461
|
+
new_sub_node = get_canonical(p_node->value, p_node->key_hash, new_children);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
global_root = new_sub_node;
|
|
466
|
+
global_root->ref_count++;
|
|
467
|
+
if (old_root) decref(old_root);
|
|
468
|
+
|
|
469
|
+
free(val_copy);
|
|
470
|
+
LQFT_RWLOCK_UNLOCK_WR(&engine_lock);
|
|
471
|
+
Py_END_ALLOW_THREADS
|
|
472
|
+
|
|
473
|
+
Py_RETURN_NONE;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
static PyObject* method_search(PyObject* self, PyObject* args) {
|
|
477
|
+
unsigned long long h;
|
|
478
|
+
if (!PyArg_ParseTuple(args, "K", &h)) return NULL;
|
|
479
|
+
|
|
480
|
+
char* result_str = NULL;
|
|
481
|
+
|
|
482
|
+
// Bypass GIL & Lock Engine (Shared Read Lock - Multiple threads can enter simultaneously!)
|
|
483
|
+
Py_BEGIN_ALLOW_THREADS
|
|
484
|
+
LQFT_RWLOCK_RDLOCK(&engine_lock);
|
|
485
|
+
|
|
486
|
+
if (global_root) {
|
|
487
|
+
LQFTNode* curr = global_root;
|
|
488
|
+
int bit_depth = 0;
|
|
489
|
+
while (curr != NULL && curr->value == NULL) {
|
|
490
|
+
uint32_t segment = (h >> bit_depth) & MASK;
|
|
491
|
+
curr = curr->children[segment];
|
|
492
|
+
bit_depth += BIT_PARTITION;
|
|
493
|
+
}
|
|
494
|
+
if (curr != NULL && curr->key_hash == h) {
|
|
495
|
+
result_str = (char*)curr->value;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
LQFT_RWLOCK_UNLOCK_RD(&engine_lock);
|
|
500
|
+
Py_END_ALLOW_THREADS
|
|
501
|
+
|
|
502
|
+
if (result_str) return PyUnicode_FromString(result_str);
|
|
503
|
+
Py_RETURN_NONE;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
static PyObject* method_delete(PyObject* self, PyObject* args) {
|
|
507
|
+
unsigned long long h;
|
|
508
|
+
if (!PyArg_ParseTuple(args, "K", &h)) return NULL;
|
|
509
|
+
|
|
510
|
+
Py_BEGIN_ALLOW_THREADS
|
|
511
|
+
LQFT_RWLOCK_WRLOCK(&engine_lock);
|
|
512
|
+
|
|
513
|
+
if (global_root) {
|
|
514
|
+
LQFTNode* path_nodes[20];
|
|
515
|
+
uint32_t path_segs[20];
|
|
516
|
+
int path_len = 0;
|
|
517
|
+
LQFTNode* curr = global_root;
|
|
518
|
+
int bit_depth = 0;
|
|
519
|
+
|
|
520
|
+
while (curr != NULL && curr->value == NULL) {
|
|
521
|
+
uint32_t segment = (h >> bit_depth) & MASK;
|
|
522
|
+
path_nodes[path_len] = curr;
|
|
523
|
+
path_segs[path_len] = segment;
|
|
524
|
+
path_len++;
|
|
525
|
+
curr = curr->children[segment];
|
|
526
|
+
bit_depth += BIT_PARTITION;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (curr != NULL && curr->key_hash == h) {
|
|
530
|
+
LQFTNode* old_root = global_root;
|
|
531
|
+
LQFTNode* new_sub_node = NULL;
|
|
532
|
+
|
|
533
|
+
for (int i = path_len - 1; i >= 0; i--) {
|
|
534
|
+
LQFTNode* p_node = path_nodes[i];
|
|
535
|
+
uint32_t segment = path_segs[i];
|
|
536
|
+
LQFTNode* new_children[32];
|
|
537
|
+
int has_other_children = 0;
|
|
538
|
+
|
|
539
|
+
for (uint32_t j = 0; j < 32; j++) {
|
|
540
|
+
if (j == segment) new_children[j] = new_sub_node;
|
|
541
|
+
else {
|
|
542
|
+
new_children[j] = p_node->children[j];
|
|
543
|
+
if (new_children[j]) has_other_children = 1;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (!has_other_children && i > 0) new_sub_node = NULL;
|
|
548
|
+
else new_sub_node = get_canonical(NULL, 0, new_children);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
global_root = (new_sub_node) ? new_sub_node : get_canonical(NULL, 0, NULL);
|
|
552
|
+
if (global_root) global_root->ref_count++;
|
|
553
|
+
if (old_root) decref(old_root);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
LQFT_RWLOCK_UNLOCK_WR(&engine_lock);
|
|
558
|
+
Py_END_ALLOW_THREADS
|
|
559
|
+
|
|
560
|
+
Py_RETURN_NONE;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
static PyObject* method_get_metrics(PyObject* self, PyObject* args) {
|
|
564
|
+
return Py_BuildValue("{s:i}", "physical_nodes", physical_node_count);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
static PyMethodDef LQFTMethods[] = {
|
|
568
|
+
{"insert", method_insert, METH_VARARGS, "Insert key-value"},
|
|
569
|
+
{"delete", method_delete, METH_VARARGS, "Delete key"},
|
|
570
|
+
{"search", method_search, METH_VARARGS, "Search key"},
|
|
571
|
+
{"save_to_disk", method_save_to_disk, METH_VARARGS, "Serialize to .bin"},
|
|
572
|
+
{"load_from_disk", method_load_from_disk, METH_VARARGS, "Deserialize from .bin"},
|
|
573
|
+
{"get_metrics", method_get_metrics, METH_VARARGS, "Get stats"},
|
|
574
|
+
{"free_all", method_free_all, METH_VARARGS, "Total memory wipe"},
|
|
575
|
+
{NULL, NULL, 0, NULL}
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
static struct PyModuleDef lqftmodule = { PyModuleDef_HEAD_INIT, "lqft_c_engine", NULL, -1, LQFTMethods };
|
|
579
|
+
PyMODINIT_FUNC PyInit_lqft_c_engine(void) {
|
|
580
|
+
LQFT_RWLOCK_INIT(&engine_lock);
|
|
581
|
+
lock_initialized = 1;
|
|
582
|
+
return PyModule_Create(&lqftmodule);
|
|
583
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import psutil
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
# ---------------------------------------------------------
|
|
7
|
+
# STRICT NATIVE ENTERPRISE ENGINE (v0.7.0)
|
|
8
|
+
# ---------------------------------------------------------
|
|
9
|
+
# Architect: Parjad Minooei
|
|
10
|
+
# Status: Pure Python fallback removed. Strict C-Core interface.
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
import lqft_c_engine
|
|
14
|
+
except ImportError:
|
|
15
|
+
print("\n[!] CRITICAL FATAL ERROR: Native C-Engine not found.")
|
|
16
|
+
print("[!] The LQFT is now a strictly native database. Pure Python fallback is disabled.")
|
|
17
|
+
print("[!] Run: python setup.py build_ext --inplace\n")
|
|
18
|
+
sys.exit(1)
|
|
19
|
+
|
|
20
|
+
class LQFT:
|
|
21
|
+
def __init__(self):
|
|
22
|
+
self.is_native = True
|
|
23
|
+
self.auto_purge_enabled = True
|
|
24
|
+
self.max_memory_mb = 1000.0
|
|
25
|
+
self.total_ops = 0
|
|
26
|
+
self._process = psutil.Process(os.getpid())
|
|
27
|
+
|
|
28
|
+
def _validate_type(self, key, value=None):
|
|
29
|
+
if not isinstance(key, str):
|
|
30
|
+
raise TypeError(f"LQFT keys must be strings. Received: {type(key).__name__}")
|
|
31
|
+
if value is not None and not isinstance(value, str):
|
|
32
|
+
raise TypeError(f"LQFT values must be strings. Received: {type(value).__name__}")
|
|
33
|
+
|
|
34
|
+
def _get_64bit_hash(self, key):
|
|
35
|
+
return int(hashlib.md5(key.encode()).hexdigest()[:16], 16)
|
|
36
|
+
|
|
37
|
+
def set_auto_purge_threshold(self, threshold: float):
|
|
38
|
+
self.max_memory_mb = threshold
|
|
39
|
+
|
|
40
|
+
def purge(self):
|
|
41
|
+
current_mb = self._process.memory_info().rss / (1024 * 1024)
|
|
42
|
+
print(f"\n[⚠️ CIRCUIT Breaker] Engine exceeded limit (Currently {current_mb:.1f} MB). Auto-Purging!")
|
|
43
|
+
self.clear()
|
|
44
|
+
|
|
45
|
+
# --- Native Disk Persistence ---
|
|
46
|
+
def save_to_disk(self, filepath: str):
|
|
47
|
+
lqft_c_engine.save_to_disk(filepath)
|
|
48
|
+
|
|
49
|
+
def load_from_disk(self, filepath: str):
|
|
50
|
+
if not os.path.exists(filepath):
|
|
51
|
+
raise FileNotFoundError(f"Missing LQFT database file: {filepath}")
|
|
52
|
+
lqft_c_engine.load_from_disk(filepath)
|
|
53
|
+
|
|
54
|
+
# --- Core Operations ---
|
|
55
|
+
def insert(self, key, value):
|
|
56
|
+
self._validate_type(key, value)
|
|
57
|
+
self.total_ops += 1
|
|
58
|
+
|
|
59
|
+
# Memory Circuit Breaker
|
|
60
|
+
if self.auto_purge_enabled and self.total_ops % 5000 == 0:
|
|
61
|
+
current_mb = self._process.memory_info().rss / (1024 * 1024)
|
|
62
|
+
if current_mb >= self.max_memory_mb:
|
|
63
|
+
self.purge()
|
|
64
|
+
|
|
65
|
+
h = self._get_64bit_hash(key)
|
|
66
|
+
lqft_c_engine.insert(h, value)
|
|
67
|
+
|
|
68
|
+
def remove(self, key):
|
|
69
|
+
self._validate_type(key)
|
|
70
|
+
h = self._get_64bit_hash(key)
|
|
71
|
+
lqft_c_engine.delete(h)
|
|
72
|
+
|
|
73
|
+
def delete(self, key):
|
|
74
|
+
self.remove(key)
|
|
75
|
+
|
|
76
|
+
def search(self, key):
|
|
77
|
+
self._validate_type(key)
|
|
78
|
+
h = self._get_64bit_hash(key)
|
|
79
|
+
return lqft_c_engine.search(h)
|
|
80
|
+
|
|
81
|
+
# --- Pythonic Syntactic Sugar ---
|
|
82
|
+
def __setitem__(self, key, value):
|
|
83
|
+
self.insert(key, value)
|
|
84
|
+
|
|
85
|
+
def __getitem__(self, key):
|
|
86
|
+
res = self.search(key)
|
|
87
|
+
if res is None:
|
|
88
|
+
raise KeyError(key)
|
|
89
|
+
return res
|
|
90
|
+
|
|
91
|
+
def clear(self):
|
|
92
|
+
return lqft_c_engine.free_all()
|
|
93
|
+
|
|
94
|
+
def get_stats(self):
|
|
95
|
+
return lqft_c_engine.get_metrics()
|
|
96
|
+
|
|
97
|
+
def __del__(self):
|
|
98
|
+
try: self.clear()
|
|
99
|
+
except: pass
|
|
100
|
+
|
|
101
|
+
def status(self):
|
|
102
|
+
return {
|
|
103
|
+
"mode": "Strict Native C-Engine",
|
|
104
|
+
"items": lqft_c_engine.get_metrics().get('physical_nodes', 0),
|
|
105
|
+
"threshold": "DISABLED (Pure Hardware Mode)"
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
# Alias mapping so older benchmark scripts don't crash
|
|
109
|
+
AdaptiveLQFT = LQFT
|