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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lqft-python-engine
3
- Version: 0.3.0
4
- Summary: LQFT Engine: Memory Circuit Breaker & Strict Type Safety (v5.0 Stable)
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