scws4r 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/scws4r/xdb.c ADDED
@@ -0,0 +1,636 @@
1
+ /**
2
+ * @file xdb.c (xtree use file storage)
3
+ * @author Hightman Mar
4
+ * @editor set number ; syntax on ; set autoindent ; set tabstop=4 (vim)
5
+ * $Id$
6
+ */
7
+
8
+ #ifdef HAVE_CONFIG_H
9
+ # include "config.h"
10
+ #endif
11
+
12
+ #ifdef WIN32
13
+ # include "config_win32.h"
14
+ #endif
15
+
16
+ #include "xdb.h"
17
+ #include "lock.h"
18
+ #include <stdio.h>
19
+ #include <stdlib.h>
20
+ #ifndef WIN32
21
+ # include <unistd.h>
22
+ #endif
23
+ #include <string.h>
24
+ #include <fcntl.h>
25
+ #include <sys/stat.h>
26
+ #include <sys/types.h>
27
+
28
+ #ifdef HAVE_FLOCK
29
+ # include <sys/file.h>
30
+ #endif
31
+
32
+ #ifdef HAVE_MMAP
33
+ # include <sys/mman.h>
34
+ #endif
35
+
36
+ static int _xdb_hasher(xdb_t x, const char *s, int len)
37
+ {
38
+ unsigned int h = x->base;
39
+ while (len--)
40
+ {
41
+ h += (h<<5);
42
+ h ^= (unsigned char) s[len];
43
+ h &= 0x7fffffff;
44
+ }
45
+ return (h % x->prime);
46
+ }
47
+
48
+ static void _xdb_read_data(xdb_t x, void *buf, unsigned int off, int len)
49
+ {
50
+ /* check off & x->fsize? */
51
+ if (off > x->fsize)
52
+ return;
53
+
54
+ /* fixed the len boundary!! */
55
+ if ((off + len) > x->fsize)
56
+ len = x->fsize - off;
57
+
58
+ if (x->fd >= 0)
59
+ {
60
+ lseek(x->fd, off, SEEK_SET);
61
+ read(x->fd, buf, len);
62
+ }
63
+ else
64
+ {
65
+ memcpy(buf, x->fmap + off, len);
66
+ }
67
+ /* hightman.101230: fixed overflow, thanks to hovea on bbs */
68
+ //memset((void *)((char *)buf + len), 0, 1);
69
+ }
70
+
71
+ /* recursive to search the matched record */
72
+ static void _xdb_rec_get(xdb_t x, xrec_t rec, const char *key, int len)
73
+ {
74
+ unsigned char buf[XDB_MAXKLEN + 2]; // greater than: 255
75
+ int cmp;
76
+
77
+ if (rec->me.len == 0)
78
+ return;
79
+
80
+ // [left][right] = 16\0
81
+ _xdb_read_data(x, buf, rec->me.off + 16, len + 1);
82
+ cmp = memcmp(key, buf+1, len);
83
+ if (!cmp)
84
+ cmp = len - buf[0];
85
+ if (cmp > 0)
86
+ {
87
+ // right
88
+ rec->poff = rec->me.off + sizeof(xptr_st);
89
+ _xdb_read_data(x, &rec->me, rec->me.off + sizeof(xptr_st), sizeof(xptr_st));
90
+ _xdb_rec_get(x, rec, key, len);
91
+ }
92
+ else if (cmp < 0)
93
+ {
94
+ // left
95
+ rec->poff = rec->me.off;
96
+ _xdb_read_data(x, &rec->me, rec->me.off, sizeof(xptr_st));
97
+ _xdb_rec_get(x, rec, key, len);
98
+ }
99
+ else
100
+ {
101
+ // found!
102
+ rec->value.off = rec->me.off + 17 + len;
103
+ rec->value.len = rec->me.len - 17 - len;
104
+ }
105
+ }
106
+
107
+ static xrec_t _xdb_rec_find(xdb_t x, const char *key, int len, xrec_t rec)
108
+ {
109
+ int i;
110
+
111
+ if (rec == NULL)
112
+ rec = (xrec_t) malloc(sizeof(xrec_st));
113
+
114
+ memset(rec, 0, sizeof(xrec_st));
115
+ i = (x->prime > 1 ? _xdb_hasher(x, key, len) : 0);
116
+ rec->poff = i * sizeof(xptr_st) + sizeof(struct xdb_header);
117
+
118
+ _xdb_read_data(x, &rec->me, rec->poff, sizeof(xptr_st));
119
+ _xdb_rec_get(x, rec, key, len);
120
+ return rec;
121
+ }
122
+
123
+ /* mode = r(readonly) | w(write&read) */
124
+ xdb_t xdb_open(const char *fpath, int mode)
125
+ {
126
+ xdb_t x;
127
+ struct stat st;
128
+ struct xdb_header xhdr;
129
+
130
+ /* create the new memory */
131
+ if (!(x = (xdb_t ) malloc(sizeof(xdb_st))))
132
+ return NULL;
133
+
134
+ /* try to open & check the file */
135
+ if ((x->fd = open(fpath, mode == 'w' ? O_RDWR : O_RDONLY)) < 0)
136
+ {
137
+ #ifdef DEBUG
138
+ perror("Failed to open the XDB file");
139
+ #endif
140
+ free(x);
141
+ return NULL;
142
+ }
143
+
144
+ /* check the file */
145
+ if (fstat(x->fd, &st) || !S_ISREG(st.st_mode) || (x->fsize = st.st_size) <= 0)
146
+ {
147
+ #ifdef DEBUG
148
+ perror("Invalid XDB file");
149
+ #endif
150
+ close(x->fd);
151
+ free(x);
152
+ return NULL;
153
+ }
154
+
155
+ /* check the XDB header: XDB+version(1bytes)+base+prime+fsize+<dobule check> = 19bytes */
156
+ lseek(x->fd, 0, SEEK_SET);
157
+ if ((read(x->fd, &xhdr, sizeof(xhdr)) != sizeof(xhdr))
158
+ || memcmp(xhdr.tag, XDB_TAGNAME, 3) || (xhdr.fsize != x->fsize))
159
+ {
160
+ #ifdef DEBUG
161
+ perror("Invalid XDB file format");
162
+ #endif
163
+ close(x->fd);
164
+ free(x);
165
+ return NULL;
166
+ }
167
+ x->prime = xhdr.prime;
168
+ x->base = xhdr.base;
169
+ x->version = (int) xhdr.ver;
170
+ x->fmap = NULL;
171
+ x->mode = mode;
172
+
173
+ /* lock the file in write mode */
174
+ if (mode == 'w')
175
+ _xdb_flock(x->fd, LOCK_EX);
176
+ /* try mmap if readonly */
177
+ #ifdef HAVE_MMAP
178
+ else
179
+ {
180
+ x->fmap = (char *) mmap(NULL, x->fsize, PROT_READ, MAP_SHARED, x->fd, 0);
181
+ close(x->fd);
182
+ x->fd = -1;
183
+
184
+ if (x->fmap == (char *) MAP_FAILED)
185
+ {
186
+ #ifdef DEBUG
187
+ perror("Mmap() failed");
188
+ #endif
189
+ free(x);
190
+ return NULL;
191
+ }
192
+ }
193
+ #endif
194
+ return x;
195
+ }
196
+
197
+ xdb_t xdb_create(const char *fpath, int base, int prime)
198
+ {
199
+ xdb_t x;
200
+ struct xdb_header xhdr;
201
+
202
+ /* create the new memory */
203
+ if (!(x = (xdb_t ) malloc(sizeof(xdb_st))))
204
+ return NULL;
205
+
206
+ /* try to open & check the file */
207
+ if ((x->fd = open(fpath, (O_CREAT|O_RDWR|O_TRUNC|O_EXCL), 0600)) < 0)
208
+ {
209
+ #ifdef DEBUG
210
+ perror("Failed to open & create the db file");
211
+ #endif
212
+ free(x);
213
+ return NULL;
214
+ }
215
+
216
+ /* write the header */
217
+ _xdb_flock(x->fd, LOCK_EX);
218
+ x->prime = prime ? prime : 2047;
219
+ x->base = base ? base : 0xf422f;
220
+ x->fsize = sizeof(xhdr) + x->prime * sizeof(xptr_st);
221
+ x->fmap = NULL;
222
+ x->mode = 'w';
223
+ memset(&xhdr, 0, sizeof(xhdr));
224
+ memcpy(&xhdr.tag, XDB_TAGNAME, 3);
225
+ xhdr.ver = XDB_VERSION;
226
+ xhdr.prime = x->prime;
227
+ xhdr.base = x->base;
228
+ xhdr.fsize = x->fsize;
229
+ xhdr.check = (float)XDB_FLOAT_CHECK;
230
+
231
+ /* check the XDB header: XDB+version(1bytes)+base+prime+fsize+<dobule check> = 19bytes */
232
+ lseek(x->fd, 0, SEEK_SET);
233
+ write(x->fd, &xhdr, sizeof(xhdr));
234
+ return x;
235
+ }
236
+
237
+ void xdb_close(xdb_t x)
238
+ {
239
+ if (x == NULL)
240
+ return;
241
+
242
+ #ifdef HAVE_MMAP
243
+ if (x->fmap != NULL)
244
+ {
245
+ munmap(x->fmap, x->fsize);
246
+ x->fmap = NULL;
247
+ }
248
+ #endif
249
+
250
+ if (x->fd >= 0)
251
+ {
252
+ if (x->mode == 'w')
253
+ {
254
+ lseek(x->fd, 12, SEEK_SET);
255
+ write(x->fd, &x->fsize, sizeof(x->fsize));
256
+ _xdb_flock(x->fd, LOCK_UN);
257
+ }
258
+ close(x->fd);
259
+ x->fd = -1;
260
+ }
261
+ free(x);
262
+ }
263
+
264
+ /* read mode (value require free by user) */
265
+ void *xdb_nget(xdb_t x, const char *key, int len, unsigned int *vlen)
266
+ {
267
+ xrec_st rec;
268
+ void *value = NULL;
269
+
270
+ if (x == NULL || key == NULL || len > XDB_MAXKLEN)
271
+ return NULL;
272
+
273
+ /* not found, return the poff(for write) */
274
+ _xdb_rec_find(x, key, len, &rec);
275
+ if (rec.value.len > 0)
276
+ {
277
+ /* auto append one byte with '\0' */
278
+ value = malloc(rec.value.len + 1);
279
+ if (vlen != NULL)
280
+ *vlen = rec.value.len;
281
+ _xdb_read_data(x, value, rec.value.off, rec.value.len);
282
+ *((char *)value + rec.value.len) = '\0';
283
+ }
284
+ return value;
285
+ }
286
+
287
+ void *xdb_get(xdb_t x, const char *key, unsigned int *vlen)
288
+ {
289
+ if (x == NULL || key == NULL)
290
+ return NULL;
291
+ return xdb_nget(x, key, strlen(key), vlen);
292
+ }
293
+
294
+ /* write mode */
295
+ void xdb_nput(xdb_t x, void *value, unsigned int vlen, const char *key, int len)
296
+ {
297
+ xrec_st rec;
298
+
299
+ if (x == NULL || x->fd < 0 || key == NULL || len > XDB_MAXKLEN)
300
+ return;
301
+
302
+ /* not found, return the poff(for write) */
303
+ _xdb_rec_find(x, key, len, &rec);
304
+ if (rec.value.len > 0 && vlen <= rec.value.len)
305
+ {
306
+ /* just replace */
307
+ if (vlen > 0)
308
+ {
309
+ lseek(x->fd, rec.value.off, SEEK_SET);
310
+ write(x->fd, value, vlen);
311
+ }
312
+ if (vlen < rec.value.len)
313
+ {
314
+ vlen += rec.me.len - rec.value.len;
315
+ lseek(x->fd, rec.poff + 4, SEEK_SET);
316
+ write(x->fd, &vlen, sizeof(vlen));
317
+ }
318
+ }
319
+ else if (vlen > 0)
320
+ {
321
+ /* insert for new data */
322
+ unsigned char buf[512];
323
+ xptr_st pnew;
324
+
325
+ pnew.off = x->fsize;
326
+ memset(buf, 0, sizeof(buf));
327
+ pnew.len = rec.me.len - rec.value.len;
328
+ if (pnew.len > 0)
329
+ {
330
+ _xdb_read_data(x, buf, rec.me.off, pnew.len);
331
+ }
332
+ else
333
+ {
334
+ buf[16] = len; // key len
335
+ strncpy(buf + 17, key, len);
336
+ pnew.len = 17 + len;
337
+ }
338
+ lseek(x->fd, pnew.off, SEEK_SET);
339
+ write(x->fd, buf, pnew.len);
340
+ write(x->fd, value, vlen);
341
+ pnew.len += vlen;
342
+ x->fsize += pnew.len;
343
+
344
+ /* update noff & vlen -> poff */
345
+ lseek(x->fd, rec.poff, SEEK_SET);
346
+ write(x->fd, &pnew, sizeof(pnew));
347
+ }
348
+ }
349
+
350
+ void xdb_put(xdb_t x, const char *value, const char *key)
351
+ {
352
+ if (x == NULL || key == NULL)
353
+ return;
354
+ xdb_nput(x, (void *) value, value ? strlen(value) : 0, key, strlen(key));
355
+ }
356
+
357
+ #ifdef DEBUG
358
+ /* draw the xdb to stdout */
359
+ struct draw_arg
360
+ {
361
+ int depth;
362
+ int count;
363
+ int flag;
364
+ };
365
+
366
+ static void _xdb_draw_node(xdb_t x, xptr_t ptr, struct draw_arg *arg, int depth, char *icon1)
367
+ {
368
+ char *icon2;
369
+
370
+ icon2 = malloc(strlen(icon1) + 4);
371
+ strcpy(icon2, icon1);
372
+
373
+ // output the flag & icon
374
+ if (arg->flag == 'T')
375
+ printf("(T) ");
376
+ else
377
+ {
378
+ printf("%s", icon2);
379
+ if (arg->flag == 'L')
380
+ {
381
+ strcat(icon2, " ┃");
382
+ printf(" ┟(L) ");
383
+ }
384
+ else
385
+ {
386
+ strcat(icon2, "  ");
387
+ printf(" └(R) ");
388
+ }
389
+ }
390
+
391
+ // draw the node data
392
+ if (ptr->len == 0)
393
+ printf("<NULL>\n");
394
+ else
395
+ {
396
+ unsigned char buf[XDB_MAXKLEN + 18]; // greater than 18 = sizeof(xptr_st)*2+1
397
+ int vlen, voff;
398
+
399
+ vlen = sizeof(buf) - 1;
400
+ if (vlen > ptr->len)
401
+ vlen = ptr->len;
402
+
403
+ _xdb_read_data(x, buf, ptr->off, vlen);
404
+ vlen = ptr->len - buf[16] - 17;
405
+ voff = ptr->off + buf[16] + 17;
406
+
407
+ printf("%.*s (vlen=%d, voff=%d)\n", buf[16], buf+17, vlen, voff);
408
+
409
+ arg->count++;
410
+ depth++;
411
+ if (depth > arg->depth)
412
+ arg->depth = depth;
413
+
414
+ // draw the left & right;
415
+ arg->flag = 'L';
416
+ memcpy(ptr, buf, sizeof(xptr_st));
417
+ _xdb_draw_node(x, ptr, arg, depth, icon2);
418
+
419
+ arg->flag = 'R';
420
+ memcpy(ptr, buf + sizeof(xptr_st), sizeof(xptr_st));
421
+ _xdb_draw_node(x, ptr, arg, depth, icon2);
422
+ }
423
+ free(icon2);
424
+ }
425
+
426
+ void xdb_draw(xdb_t x)
427
+ {
428
+ int i;
429
+ struct draw_arg arg;
430
+ xptr_st ptr;
431
+
432
+ if (!x) return;
433
+
434
+ xdb_version(x);
435
+ for (i = 0; i < x->prime; i++)
436
+ {
437
+ arg.depth = 0;
438
+ arg.count = 0;
439
+ arg.flag = 'T';
440
+
441
+ _xdb_read_data(x, &ptr, i * sizeof(xptr_st) + sizeof(struct xdb_header), sizeof(xptr_st));
442
+ _xdb_draw_node(x, &ptr, &arg, 0, "");
443
+
444
+ printf("-----------------------------------------\n");
445
+ printf("Tree(xdb) [%d] max_depth: %d nodes_num: %d\n", i, arg.depth, arg.count);
446
+ }
447
+ }
448
+ #endif
449
+
450
+ /* optimize the xdb */
451
+ typedef struct xdb_cmper
452
+ {
453
+ xptr_st ptr;
454
+ char *key;
455
+ } xcmper_st;
456
+
457
+ static void _xdb_count_nodes(xdb_t x, xptr_t ptr, int *count)
458
+ {
459
+ int off;
460
+ if (ptr->len == 0)
461
+ return;
462
+
463
+ *count += 1;
464
+ off = ptr->off;
465
+
466
+ /* left & right */
467
+ _xdb_read_data(x, ptr, off, sizeof(xptr_st));
468
+ _xdb_count_nodes(x, ptr, count);
469
+
470
+ _xdb_read_data(x, ptr, off + sizeof(xptr_st), sizeof(xptr_st));
471
+ _xdb_count_nodes(x, ptr, count);
472
+ }
473
+
474
+ #ifdef HAVE_STRNDUP
475
+ #define _mem_ndup strndup
476
+ #else
477
+ static inline void *_mem_ndup(const char *src, int len)
478
+ {
479
+ char *dst;
480
+ dst = malloc(len+1);
481
+ memcpy(dst, src, len);
482
+ dst[len] = '\0';
483
+ return dst;
484
+ }
485
+ #endif
486
+
487
+ static void _xdb_load_nodes(xdb_t x, xptr_t ptr, xcmper_st *nodes, int *count)
488
+ {
489
+ int i;
490
+ unsigned char buf[XDB_MAXKLEN + 18];
491
+
492
+ if (ptr->len == 0)
493
+ return;
494
+
495
+ i = sizeof(buf)-1;
496
+ if (i > (int)ptr->len)
497
+ i = ptr->len;
498
+
499
+ _xdb_read_data(x, buf, ptr->off, i);
500
+
501
+ i = *count;
502
+ nodes[i].ptr.off = ptr->off;
503
+ nodes[i].ptr.len = ptr->len;
504
+ nodes[i].key = (char *) _mem_ndup(buf + 17, buf[16]);
505
+ *count = i+1;
506
+
507
+ /* left & right */
508
+ memcpy(ptr, buf, sizeof(xptr_st));
509
+ _xdb_load_nodes(x, ptr, nodes, count);
510
+
511
+ memcpy(ptr, buf + sizeof(xptr_st), sizeof(xptr_st));
512
+ _xdb_load_nodes(x, ptr, nodes, count);
513
+ }
514
+
515
+ static void _xdb_reset_nodes(xdb_t x, xcmper_st *nodes, int low, int high, unsigned int poff)
516
+ {
517
+ xptr_st ptr = { 0, 0 };
518
+
519
+ if (low <= high)
520
+ {
521
+ int mid = (low + high)>>1;
522
+
523
+ memcpy(&ptr, &nodes[mid].ptr, sizeof(xptr_st));
524
+
525
+ _xdb_reset_nodes(x, nodes, low, mid-1, ptr.off);
526
+ _xdb_reset_nodes(x, nodes, mid+1, high, ptr.off + sizeof(xptr_st));
527
+ }
528
+
529
+ /* save it */
530
+ lseek(x->fd, poff, SEEK_SET);
531
+ write(x->fd, &ptr, sizeof(xptr_st));
532
+ }
533
+
534
+ static int _xdb_node_cmp(a, b)
535
+ xcmper_st *a, *b;
536
+ {
537
+ return strcmp(a->key, b->key);
538
+ }
539
+
540
+ void xdb_optimize(xdb_t x)
541
+ {
542
+ int i, cnt, poff;
543
+ xptr_st ptr, head;
544
+ xcmper_st *nodes;
545
+
546
+ if (x == NULL || x->fd < 0)
547
+ return;
548
+
549
+ for (i = 0; i < x->prime; i++)
550
+ {
551
+ poff = i * sizeof(xptr_st) + sizeof(struct xdb_header);
552
+ _xdb_read_data(x, &head, poff, sizeof(xptr_st));
553
+
554
+ cnt = 0;
555
+ ptr = head;
556
+ _xdb_count_nodes(x, &ptr, &cnt);
557
+
558
+ if (cnt > 2)
559
+ {
560
+ nodes = (xcmper_st *) malloc(sizeof(xcmper_st) * cnt);
561
+
562
+ cnt = 0;
563
+ ptr = head;
564
+ _xdb_load_nodes(x, &ptr, nodes, &cnt);
565
+
566
+ qsort(nodes, cnt, sizeof(xcmper_st), _xdb_node_cmp);
567
+ _xdb_reset_nodes(x, nodes, 0, cnt - 1, poff);
568
+
569
+ /* free the nodes & key pointer */
570
+ while (cnt--)
571
+ free(nodes[cnt].key);
572
+ free(nodes);
573
+ }
574
+ }
575
+ }
576
+
577
+ void xdb_version(xdb_t x)
578
+ {
579
+ printf("%s/%d.%d (base=%d, prime=%d)\n", XDB_TAGNAME,
580
+ (x->version >> 5), (x->version & 0x1f), x->base, x->prime);
581
+ }
582
+
583
+ /* convert xdb file to xtree struct(memory) */
584
+ static void _xdb_to_xtree_node(xdb_t x, xtree_t xt, xptr_t ptr)
585
+ {
586
+ unsigned char *buf;
587
+ void *value;
588
+ int voff;
589
+
590
+ if (ptr->len == 0)
591
+ return;
592
+
593
+ buf = (unsigned char *) malloc(ptr->len + 1);
594
+ _xdb_read_data(x, buf, ptr->off, ptr->len);
595
+
596
+ /* save the key & value -> xtree */
597
+ voff = buf[16] + 17;
598
+
599
+ /* 2009-09-22, 11:29, Mistruster: posted on bbs */
600
+ if (voff >= (int)ptr->len)
601
+ return;
602
+ value = pmalloc(xt->p, ptr->len - voff);
603
+ memcpy(value, buf + voff, ptr->len - voff);
604
+ xtree_nput(xt, value, ptr->len - voff, buf + 17, buf[16]);
605
+
606
+ /* left & right */
607
+ memcpy(ptr, buf, sizeof(xptr_st));
608
+ _xdb_to_xtree_node(x, xt, ptr);
609
+
610
+ memcpy(ptr, buf + sizeof(xptr_st), sizeof(xptr_st));
611
+ _xdb_to_xtree_node(x, xt, ptr);
612
+
613
+ free(buf);
614
+ }
615
+
616
+ xtree_t xdb_to_xtree(xdb_t x, xtree_t xt)
617
+ {
618
+ int i = 0;
619
+ xptr_st ptr;
620
+
621
+ if (!x)
622
+ return NULL;
623
+
624
+ if (!xt && !(xt = xtree_new(x->base, x->prime)))
625
+ return NULL;
626
+
627
+ do
628
+ {
629
+ _xdb_read_data(x, &ptr, i * sizeof(xptr_st) + sizeof(struct xdb_header), sizeof(xptr_st));
630
+ _xdb_to_xtree_node(x, xt, &ptr);
631
+ }
632
+ while (++i < x->prime);
633
+
634
+ return xt;
635
+ }
636
+
data/ext/scws4r/xdb.h ADDED
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @file xdb.h (read only)
3
+ * @author Hightman Mar
4
+ * @editor set number ; syntax on ; set autoindent ; set tabstop=4 (vim)
5
+ * $Id$
6
+ */
7
+
8
+ #ifndef _SCWS_XDB_20070525_H_
9
+ #define _SCWS_XDB_20070525_H_
10
+
11
+ #ifdef __cplusplus
12
+ extern "C" {
13
+ #endif
14
+
15
+ /* constant var define */
16
+ #define XDB_FLOAT_CHECK (3.14)
17
+ #define XDB_TAGNAME "XDB"
18
+ #define XDB_MAXKLEN 0xf0
19
+ #define XDB_VERSION 34 /* version: 3bit+5bit */
20
+
21
+ #include "xtree.h"
22
+
23
+ /* data structure for [Record] */
24
+ typedef struct xdb_pointer
25
+ {
26
+ unsigned int off;
27
+ unsigned int len;
28
+ } xptr_st, *xptr_t;
29
+
30
+ typedef struct xdb_record
31
+ {
32
+ unsigned int poff;
33
+ xptr_st me;
34
+ xptr_st value;
35
+ } xrec_st, *xrec_t;
36
+
37
+ /* header struct */
38
+ struct xdb_header
39
+ {
40
+ char tag[3];
41
+ unsigned char ver;
42
+ int base;
43
+ int prime;
44
+ unsigned int fsize;
45
+ float check;
46
+ char unused[12];
47
+ };
48
+
49
+ typedef struct
50
+ {
51
+ int fd; /* file descriptoin */
52
+ int base; /* basenum for hash count */
53
+ int prime; /* base prime for hash mod */
54
+ unsigned int fsize; /* total filesize */
55
+ int version; /* version: low 4bytes */
56
+ char *fmap; /* file content image by mmap (read only) */
57
+ int mode; /* xdb_open for write or read-only */
58
+ } xdb_st, *xdb_t;
59
+
60
+ /* xdb: open the db, mode = r|w|n */
61
+ xdb_t xdb_open(const char *fpath, int mode);
62
+ xdb_t xdb_create(const char *fpath, int base, int prime);
63
+
64
+ /* read mode */
65
+ void *xdb_nget(xdb_t x, const char *key, int len, unsigned int *vlen);
66
+ void *xdb_get(xdb_t x, const char *key, unsigned int *vlen);
67
+
68
+ #ifdef DEBUG
69
+ void xdb_draw(xdb_t x);
70
+ #endif
71
+
72
+ /* return the xtree pointer */
73
+ xtree_t xdb_to_xtree(xdb_t x, xtree_t xt);
74
+
75
+ /* write mode */
76
+ void xdb_nput(xdb_t x, void *value, unsigned int vlen, const char *key, int len);
77
+ void xdb_put(xdb_t x, const char *value, const char *key);
78
+ void xdb_optimize(xdb_t x);
79
+
80
+ /* xdb: close the db */
81
+ void xdb_close(xdb_t x);
82
+ void xdb_version(xdb_t x);
83
+
84
+ #ifdef __cplusplus
85
+ }
86
+ #endif
87
+
88
+ #endif