1 #if defined(__i386__) || defined(__x86_64__)
2 #if defined (__linux__)
11 #define entityIdIndex indecies[entityIdIdx]
12 #define entityNmIndex indecies[entityNmIdx]
13 #define freeStoreIndex indecies[freeStoreIdx]
14 #define addrStoreIndex indecies[addrStoreIdx]
15 #define freeSpaceIndex indecies[cache.freeIdx]
16 #define addrSpaceIndex indecies[cache.addrIdx]
18 #define noThrow std::nothrow
20 #define likely(x) (__builtin_constant_p(x) ? !!(x) : __builtin_expect(!!(x), 1))
21 #define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __builtin_expect(!!(x), 0))
24 #define lengthof(x) ((int)(sizeof(x)/sizeof(x[0])))
28 inline void *operator new(size_t n) { void *vp = malloc(n); bzero(vp,n); return vp; }
29 inline void operator delete(void *t) { free(t); }
30 inline void operator delete(void *t,size_t n) { free(t); }
31 inline void *operator new[](size_t n) { void *vp = malloc(n); bzero(vp,n); return vp; }
32 inline void operator delete[](void *t) { free(t); }
33 inline void operator delete[](void *t,size_t n) { free(t); }
41 #include <linux/futex.h>
42 #include <sys/syscall.h>
50 class nm##Obj : public Db::Obj { public:
53 class nm##Loc : public Db::ObjectLoc { public: \
54 nm##Obj *operator ->() { return (nm##Obj *)addr(); } \
55 nm##Loc(Db::Entity *ep) : Db::ObjectLoc(ep) {} \
56 nm##Loc(Db::Entity &e) : Db::ObjectLoc(&e) {}
59 #define basic_def(ty,n) class t_##n { public: ty v; t_##n() {} \
60 t_##n(const ty &i) : v(i) {} \
61 t_##n(const t_##n &i) : v(i.v) {} \
62 t_##n &operator =(const t_##n &i) { v = i.v; return *this; } \
63 ty &operator =(const ty &i) { return v = i; } \
64 ty *addr() { return &v; } int size() { return sizeof(v); } \
68 #define array_def(ty,n,l) class t_##n { public: ty v[l]; t_##n() {} \
69 t_##n(const t_##n &i) { memcpy(&v,&i.v,sizeof(v)); } \
70 t_##n(ty *i) { memcpy(&v,i,sizeof(v)); } \
71 t_##n(ty(*i)[l]) { memcpy(&v,i,sizeof(v)); } \
72 ty *operator =(const ty *i) { memcpy(&v,i,sizeof(v)); return &v[0]; } \
73 ty *addr() { return &v[0]; } int size() { return sizeof(v); } \
76 // variable array definitions
77 #define varray_def(ty,n) \
78 class t_##n { public: char *v; int l; t_##n() {} \
79 t_##n(const char *i, int sz) { v = (char *)i; l = sz; } \
80 t_##n(const unsigned char *i, int sz) { v = (char *)i; l = sz; } \
81 ty *addr() { return (ty *)v; } int size() { return l; } \
84 // string array definitions
85 #define sarray_def(ty,n) \
86 class t_##n { public: char *v; int l; t_##n() {} \
87 t_##n(const char *i, int sz) { v = (char *)i; l = sz; } \
88 t_##n(const unsigned char *i, int sz) { v = (char *)i; l = sz; } \
89 t_##n(const char *i) { t_##n(i,strlen(i)+1); } \
90 t_##n(const unsigned char *i) { t_##n(i,strlen(v)+1); } \
91 ty *addr() { return (ty *)v; } int size() { return l; } \
95 #define basic_ref(ty,n) \
96 ty *_##n() { return (*this)->v_##n.addr(); } \
97 ty n() { return *_##n(); } \
98 void n(ty i) { _wr(); *_##n() = i; } \
99 int size_##n() { return (*this)->v_##n.size(); } \
102 #define array_ref(ty,n,l) \
103 ty *_##n() { return (*this)->v_##n.addr(); } \
104 ty (&n())[l] { return *(ty (*)[l])_##n(); } \
105 void n(const ty *i,int m) { _wr(); if( m > 0 ) memcpy(n(),i,m); } \
106 void n(const ty *i) { n(i,(*this)->v_##n.size()); } \
107 int size_##n() { return (*this)->v_##n.size(); } \
109 //variable array type ref
110 #define varray_ref(ty,n) \
111 ty *_##n() { return (ty *)addr((*this)->v_##n); } \
112 ty *_##n(int sz) { size((*this)->v_##n, sz); \
113 return sz > 0 ? (ty *)addr_wr((*this)->v_##n) : 0; } \
114 ty (&n())[] { return *(ty (*)[])_##n(); } \
115 int n(const ty *v, int sz) { ty *vp=_##n(sz); \
116 if( vp && sz > 0 ) memcpy(vp, v, sz); return 0; } \
117 int size_##n() { return (*this)->v_##n.size(); } \
119 //string array type ref
120 #define sarray_ref(ty,n) \
121 ty *_##n() { return (ty *)addr((*this)->v_##n); } \
122 ty *_##n(int sz) { size((*this)->v_##n, sz); \
123 return sz > 0 ? (ty *)addr_wr((*this)->v_##n) : 0; } \
124 ty (&n())[] { return *(ty (*)[])_##n(); } \
125 int n(const ty *v, int sz) { ty *vp=_##n(sz); \
126 if( vp && sz > 0 ) memcpy(vp, v, sz); return 0; } \
127 int n(const char *v) { return n((ty *)v,strlen(v)+1); } \
128 int n(const unsigned char *v) { return n((const char *)v); } \
129 int size_##n() { return (*this)->v_##n.size(); } \
134 #define DEBUG_TIMESTAMPS
135 #define DBBUG_ERR 0x00000001
136 #define DBBUG_FAIL 0x00000002
138 //#define CHK 1 ? 0 :
155 int root_magic; // info_magic label
156 int root_info_size; // root_info blob size
160 ioAddr root_info_addr;
161 ioAddr last_info_addr;
162 transId transaction_id; // current transaction
163 ioAddr file_size; // current file size
164 pageId freePages; // free page table page list
165 int indeciesUsed; // number of active indecies
166 int pageTableUsed; // number of active pages
171 int shm_init, no_shm;
173 static void *get_mem8_t(int id);
174 static void *new_mem8_t(int size, int &id);
175 static int del_mem8_t(const void *vp, int id);
176 static void *get_shm8_t(int id);
177 static void *new_shm8_t(int size, int &id);
178 static int del_shm8_t(const void *vp, int id);
179 void *(*get_mem)(int id);
180 void *(*new_mem)(int size, int &id);
181 int (*del_mem)(const void *vp, int id);
184 uint8_t *get_uint8_t(int id, int pg=-1);
185 uint8_t *new_uint8_t(int size, int &id, int pg=-1);
186 int del_uint8_t(const void *vp, int id=-1, int pg=-1);
189 typedef int (*CmprFn)(char *,char *);
190 static int cmprFrSt(char *a, char *b);
191 static int cmprAdSt(char *a, char *b);
192 static int cmprFrSp(char *a, char *b);
193 static int cmprAdSp(char *a, char *b);
194 static int cmprOIds(char *a, char *b);
195 static int cmprStr(char *a, char *b);
196 static int cmprKey(char *a, char *b);
197 static int cmprLast(char *a, char *b);
198 static CmprFn cmprFns[];
199 typedef void (*errCallback)(Db *db, int v);
200 static const pageId NIL=-1, DDONE=-2;
218 idxId = 0, nmSz = 32,
220 keyLT=-2, keyLE=-1, keyEQ=0, keyGE=1, keyGT=2,
229 static void zincr(volatile int &v) { /* atomic(++v) */
230 asm ( " lock incl %1\n" : "+m" (v) :: );
232 static void zdecr(volatile int &v) { /* atomic(--v) */
233 asm ( " lock decl %1\n" : "+m" (v) :: );
235 static char tdecr(volatile int &v) {
236 char ret; /* ret = atomic(--loc >= 0 ? 1 : 0) */
237 asm ( " lock decl %1\n setge %0\n" : "=r" (ret), "+m" (v) :: );
240 static char tincr(volatile int &v) {
241 char ret; /* ret = atomic(++loc > 0 ? 1 : 0) */
242 asm ( " lock incl %1\n setg %0\n" : "=r" (ret), "+m" (v) :: );
245 static int zcmpxchg(int old, int val, volatile int &v) {
247 asm volatile( " lock\n cmpxchgl %2,%1\n"
248 : "+a" (ret), "+m" (v) : "r" (val) : "memory" );
251 static int zxchg(int val, volatile int &v) {
252 asm volatile( " xchgl %0,%1\n"
253 : "+r" (val), "+m" (v) :: "memory" );
256 static int zadd(int n, volatile int &v) {
258 do { val = (old=v)+n; mod = zcmpxchg(old,val,v);
259 } while( mod != old );
262 static void zmfence() {
263 asm volatile ( " mfence\n" ::: "memory" );
271 #define ZLOCK_INIT zzlock_t()
275 int zfutex(int op, int val, timespec *time=0) {
276 return syscall(SYS_futex,&loc,op,val,time,0,0);
281 int zwake(int nwakeups);
282 int zwait(int val, timespec *ts=0);
283 int zwait() { return zwait(loc); }
284 zloc_t() : loc(-1) {}
288 class zlock_t : zloc_t {
292 void *vp; asm ("movq %%fs:%c1,%q0" : "=r" (vp) : "i" (16));
294 void *vp; asm ("mov %%fs:%c1,%q0" : "=r" (vp) : "i" (16));
299 friend class zblock_t;
300 friend class zrwlock_t;
302 int zunlock(int nwakeups=1);
306 int v, ret = unlikely( (v=zcmpxchg(-1,0,loc)) >= 0 ) ? zlock(v) : 0;
311 if( unlikely(loc < 0) ) { return zemsg1(); }
313 int v, ret = unlikely( (v=zcmpxchg(0,-1,loc)) != 0 ) ? zunlock() : 0;
316 zlock_t() { owner = 0; }
320 class zblock_t : zlock_t {
322 void block() { loc = 0; zwait(0); }
323 void unblock() { loc = -1; zwake(INT_MAX); }
328 class zrwlock_t : zloc_t {
333 void enter() { zincr(loc); if( unlikely( lk.loc >= 0 ) ) zenter(); }
334 void leave() { if( unlikely( !tdecr(loc) ) ) zleave(); }
337 int locked() { return loc >= 0 ? 0 : lk.loc >= 0 ? 1 : -1; }
338 int blocked() { return lk.loc >= 0 ? 1 : 0; }
344 #define ZLOCK_INIT { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER }
348 pthread_mutex_t zlock;
350 void lock() { pthread_mutex_lock(&zlock); }
351 void unlock() { pthread_mutex_unlock(&zlock); }
352 zlock_t() { pthread_mutex_init(&zlock, 0); }
353 ~zlock_t() { pthread_mutex_destroy(&zlock); }
357 pthread_mutex_t zblock;
361 pthread_mutex_init(&zblock, 0);
362 pthread_cond_init(&cond, 0);
365 pthread_mutex_destroy(&zblock);
366 pthread_cond_destroy(&cond);
369 pthread_mutex_lock(&zblock);
370 pthread_cond_wait(&cond, &zblock);
371 pthread_mutex_unlock(&zblock);
373 void unblock() { pthread_cond_broadcast(&cond); }
376 class zrwlock_t : zlock_t {
377 volatile int blocking, users;
380 void wait() { pthread_cond_wait(&cond, &zlock); }
381 void wake() { pthread_cond_signal(&cond); }
383 void enter() { lock();
384 while( blocking ) { unlock(); lk.lock(); lk.unlock(); lock(); }
387 void leave() { lock(); if( !--users && blocking ) wake(); unlock(); }
388 void write_enter() { lk.lock(); blocking = 1;
389 lock(); while( users ) wait(); unlock();
391 void write_leave() { blocking = 0; lk.unlock(); }
392 int count() { return users; }
393 int locked() { return users ? 0 : blocking ? 1 : -1; }
394 int blocked() { return blocking; }
396 zrwlock_t() { pthread_cond_init(&cond, 0); users = 0; blocking = 0; }
397 ~zrwlock_t() { pthread_cond_destroy(&cond); }
405 locked(zlock_t &l) : lk(l) { lk.lock(); }
406 ~locked() { lk.unlock(); }
412 read_locked(zrwlock_t &l) : rwlk(l) { rwlk.enter(); }
413 ~read_locked() { rwlk.leave(); }
416 class write_blocked {
419 write_blocked(zrwlock_t &l) : rwlk(l) { rwlk.write_enter(); }
420 ~write_blocked() { rwlk.write_leave(); }
426 db_magic=0x00624474, // tDb
427 idx_magic=0x00786469, // idx
428 info_magic=0x6f666e69, // info
429 root_magic=0x746f6f72, // root
430 page_magic=0x6770, // pg
431 entity_magic = 0x6d65, // em
433 root_info_extra_pages = 2,
434 idxNil=0, idxBin=1, idxStr=2,
435 ktyBin=0, ktyInd=1, ktyDir=2,
436 opDelete=-1, opFind=0, opInsert=1,
437 pg_unknown=0, pg_root_info=1, pg_free=2,
438 pg_entity=0x0100, pg_index=0x1000,
439 max_entity_type = pg_index-pg_entity-1,
440 max_index_type = 0x10000-pg_index-1,
441 min_heap_allocation = 32,
442 entityIdIdx = 0, entityNmIdx = 1,
443 freeStoreIdx = 2, addrStoreIdx = 3,
444 freeSpaceIdx = 4, addrSpaceIdx = 5,
446 fl_wr=1, fl_rd=2, fl_new=4, fl_free=8,
448 defaultStoreBlockSize = 8192,
449 defaultPageTableHunkSize = 8192,
450 defaultIndexTableHunkSize = 4096,
451 defaultBinaryBlockSize = 16384,
452 defaultStringBlockSize = 4096,
453 defaultEntityPageSize = 65536,
458 errCallback err_callback;
460 transId active_transaction;
464 static const char *errMsgs[];
465 static void dmsg(int msk, const char *msg,...);
466 int _err_(int v,const char *fn,int ln);
467 int _fail_(int v,const char *fn,int ln);
468 #define err_(v) _err_(v,__func__,__LINE__)
469 #define fail_(v) _fail_(v,__func__,__LINE__)
471 static void dmsg(int msk, const char *msg,...) {}
472 int _err_(int v) { error(v); return v; }
473 int _fail_(int v) { return v; }
474 #define err_(v) _err_(v)
475 #define fail_(v) _fail_(v)
478 #define Err(v) return err_(v)
479 #define Fail(v) return fail_(v)
481 #define if_ret(fn) do{ int _ret; \
482 if(unlikely((_ret=(fn))<0)) return _ret; \
484 #define if_err(fn) do{ int _ret; \
485 if(unlikely((_ret=(fn))<0)) Err(_ret); \
487 #define if_fail(fn) do{ int _ret; \
488 if(unlikely((_ret=(fn))<0)) Fail(_ret); \
494 int owner, last_owner;
495 int info_key, info_id;
499 zlock_t infoLk; // lock dbinfo up to here
500 zrwlock_t dbRwLk; // global lock
501 zrwlock_t pgTblLk;// pageTable realloc
502 zlock_t pgAlLk; // new page pagesUsed/pagesAllocated
503 zlock_t pgLdLk; // pageLoad
504 zlock_t blkAlLk; // blockAllocate/Free
505 zlock_t objAlLk; // objectAllocate/Free
506 zrwlock_t rw_locks[max_entity_type];
508 DbInfo(int pid, int key, int id);
510 int new_info(int key);
511 int get_info(int key);
516 int attach_rw(int zrw) { return zrw ? attach_wr() : attach_rd(); }
523 unsigned short magic;
528 Page *get_Page(pageId pid) volatile { return pageTable[pid]; }
529 void set_Page(pageId pid, Page *pp) { pageTable[pid] = pp; }
530 //Page *get_page(pageId pid) { blocked by(pgTblk); return get_Page(pid); }
531 Page *get_page(pageId pid); // locked pageTable access
533 static pageId getPageId(unsigned char *&bp) {
534 int i = sizeof(pageId); pageId id;
535 for( id = *bp++; --i > 0; id |= *bp++ ) id <<= 8;
538 static void putPageId(unsigned char *&bp, pageId id) {
539 int i = sizeof(pageId) * 8;
540 while( (i -= 8) >= 0 ) *bp++ = id >> i;
542 static pageId readPageId(char *cp) {
543 unsigned char *bp = (unsigned char *)cp;
544 return getPageId(bp);
546 static void writePageId(char *cp, pageId id) {
547 unsigned char *bp = (unsigned char *)cp;
551 class keyBlock : public pagePrefix {
552 char rightLink[sizeof(pageId)];
554 int right_link() { return readPageId(&rightLink[0]); }
555 void right_link(pageId id) { writePageId(&rightLink[0],id); }
558 static int defaultBlockSizes[];
560 class IndexTypeInfo {
563 short type; /* type of index */
565 char name[nmSz]; /* index string identifier */
568 class IndexBaseType : public IndexTypeInfo {
570 IndexBaseType(int typ);
573 class IndexRecdInfo {
575 int idx; /* index in db->indecies[] */
576 int keySz, dataSz; /* sizeof key/data fields in bytes */
577 pageId rootPageId; /* index root page ID */
578 pageId rightHandSide; /* the right hand side of the tree for this index */
579 pageId freeBlocks; /* free index page list */
580 unsigned int blockSize; /* size of new index blocks */
582 long count; /* index population count */
585 class IndexBaseRecd : public IndexRecdInfo {
587 IndexBaseRecd(int typ, int zidx, int ksz, int dsz);
590 class IndexBaseStorage;
591 class IndexBaseInfo : public IndexTypeInfo, public IndexRecdInfo {
593 operator IndexBaseStorage *() { return (IndexBaseStorage *)this; }
596 class IndexBaseStorage : public IndexBaseInfo {
598 IndexBaseStorage(int typ, int zidx, int ksz, int dsz);
599 IndexBaseStorage() {}
600 ~IndexBaseStorage() {}
604 IndexBaseStorage *st;
606 Db *db; /* owner db */
608 pgRef lastAccess, lastFind; /* last operational access/find location */
609 pgRef lastInsert, lastDelete; /* last operational insert/delete location */
610 pgRef lastNext; /* last operational next location */
611 int kdSz; /* keySz + dataSz */
612 int lastOp; /* last operation, delete=-1/find=0/insert=1 */
613 int cInsCount; /* number of consecutive insertions */
614 int cFindCount; /* number of consecutive finds */
615 int cDelCount; /* number of consecutive deletions */
618 virtual int keyMap(pageId s, int(IndexBase::*fn)(pageId id)) = 0;
619 virtual int keyCopy(pageId s, IndexBase *ib) = 0;
620 int blockAllocate(pageId &pid, keyBlock *&bp);
621 int blockAllocate(pageId &pid, keyBlock *&bp, Page *&pp, char *&cp) {
622 pp = 0; cp = 0; if_err( blockAllocate(pid, bp) );
623 pp = db->get_page(pid); cp = (char *)(bp + 1);
626 int blockFree(pageId pid);
627 int blockRelease(pageId pid);
628 int blockLoad(pageId pid);
629 int deleteFreeBlocks();
631 void chkLastInsert();
632 void chkLastDelete();
633 void chkLastFind(pgRef &last);
636 int _err_(int v,const char *fn,int ln) { return db->_err_(v,fn,ln); }
637 int _fail_(int v,const char *fn,int ln) { return db->_fail_(v,fn,ln); }
639 int _err_(int v) { return db->_err_(v); }
640 int _fail_(int v) { return db->_fail_(v); }
642 virtual int Locate(int op,void *key,CmprFn cmpr,void *rtnKey,void *rtnData) = 0;
643 virtual int Find(void *key,void *rtnData) = 0;
644 virtual int Insert(void *key,void *data) = 0;
645 virtual int Delete(void *key) = 0;
646 virtual int First(void *rtnKey,void *rtnData) = 0;
647 virtual int Last(void *rtnKey,void *rtnData) = 0;
648 virtual int Modify(void *key,void *recd) = 0;
649 virtual int Next(pgRef &loc,void *rtnKey,void *rtnData) = 0;
650 int First(pgRef &loc,void *rtnKey,void *rtnData) {
651 if_fail( First(rtnKey, rtnData) );
655 int Next(void *rtnKey,void *rtnData) {
656 if( lastNext.id < 0 ) Fail(errInvalid);
657 return Next(lastNext,rtnKey,rtnData);
659 long Count() { return st->count; }
663 int NextLoc(pgRef &loc) { loc = lastNext; return 0; }
664 IndexBase(Db *zdb, int typ, int zidx, int ksz, int dsz);
665 IndexBase(Db *zdb, IndexBaseStorage &d);
666 virtual ~IndexBase();
669 int indeciesAllocated, indecies_sz;
671 class IndexBinaryStorage;
672 class IndexBinaryInfo {
674 operator IndexBinaryStorage *() { return (IndexBinaryStorage *)this; }
678 class IndexBinaryStorage : public IndexBinaryInfo {
680 IndexBinaryStorage(int cmprId) { this->cmprId = cmprId; }
681 IndexBinaryStorage() {}
682 ~IndexBinaryStorage() {}
685 class IndexBinary : public IndexBase {
686 IndexBinaryStorage *bst;
688 CmprFn compare; /* the key compare function type */
689 char *akey; /* pointer to key argument */
690 int keyInterior; /* last insert interior/exterior */
691 int idf; /* interior delete flag */
692 char *iky, *tky; /* search/promoted temp key storage */
695 int keyMap(pageId s, int(IndexBase::*fn)(pageId id));
696 int keyCopy(pageId s, IndexBase *ib);
697 int keyBlockUnderflow(int &t,keyBlock *lbb,pageId p,keyBlock *pbb,int pi);
698 void makeKey(char *cp,char *key,int l,char *recd,int n);
699 void setLastKey(pageId s,pageId u,int k);
700 int keyLocate(pgRef &last,pageId s, int op,void *ky, CmprFn cmpr);
701 int chkNext(pgRef &loc, char *&kp);
702 int keyNext(pgRef &loc, char *kp);
703 int chkFind(pgRef &loc, char *key);
704 int keyFind(pgRef &loc,void *ky, pageId s);
705 int chkInsert(void *key,void *data);
706 int keyInsert(pageId s, pageId &t);
707 int chkDelete(pgRef &loc, void *kp);
708 int keyDelete(int &t,void *kp,pageId s,pageId p,keyBlock *pbb,int pi);
709 int keyFirst(pgRef &loc, pageId s);
710 int keyLast(pgRef &loc, pageId s);
712 int refLocate(pgRef &loc, int op,void *key, CmprFn cmpr);
713 int Locate(int op,void *key,CmprFn cmpr,void *rtnKey,void *rtnData);
714 int refFind(pgRef &loc, void *key);
715 int Find(void *key,void *rtnData);
716 int Insert(void *key,void *data);
717 int Delete(void *key);
718 int First(void *rtnKey,void *rtnData);
719 int Last(void *rtnKey,void *rtnData);
720 int Modify(void *key,void *recd);
721 int Next(pgRef &loc,void *rtnKey,void *rtnData);
722 int Next(void *rtnKey,void *rtnData) {
723 return IndexBase::Next(rtnKey,rtnData);
725 void wr_key(void *kp, char *bp, int sz) {
726 switch( st->key_type ) {
727 case ktyBin: memcpy(bp,kp,sz); break;
729 case ktyInd: ((Key *)kp)->wr_key(bp); break;
732 char *ikey() { return iky; }
733 char *tkey() { return tky; }
735 IndexBinary(Db *zdb, int zidx, int ksz, int dsz, CmprFn cmpr);
736 IndexBinary(Db *zdb, IndexBaseStorage *b, IndexBinaryStorage *d);
737 IndexBinary(IndexBase *ib, IndexBaseStorage *b, IndexBinaryStorage *d);
740 friend class IndexBinary;
742 class IndexStringStorage;
743 class IndexStringInfo {
744 char dummy; // compiler needs this for some reason
746 operator IndexStringStorage *() { return (IndexStringStorage *)this; }
749 class IndexStringStorage : public IndexStringInfo {
751 IndexStringStorage() {}
752 ~IndexStringStorage() {}
755 class IndexString : public IndexBase {
756 IndexStringStorage *sst;
758 static int ustrcmp(unsigned char *a, unsigned char *b) {
759 return strncmp((char *)a,(char *)b,keysz);
761 static void ustrcpy(unsigned char *a, unsigned char *b) {
762 strncpy((char *)a,(char *)b,keysz);
764 static void umemmove(unsigned char *&a, unsigned char *b, int n) {
765 memmove(a,b,n); a += n;
767 static int kpress(unsigned char *kp, unsigned char *lp, unsigned char *cp);
768 int split(int n, int i, pageId s, pageId &l, pageId r);
770 int keyMap(pageId s, int(IndexBase::*fn)(pageId id));
771 int keyCopy(pageId s, IndexBase *ib);
772 int chkInsert(void *key,void *data);
773 int keyInsert(pageId &t, pageId s);
774 int keyFirst(pageId s);
775 int keyLast(pageId s);
776 int keyLocate(pgRef &last,pageId s,int &t, int op,
777 unsigned char *ky,CmprFn cmpr, unsigned char *rky);
778 int chkFind(pgRef &loc, char *key, unsigned char *lkey, unsigned char *lky=0);
779 int keyFind(pgRef &loc, unsigned char *ky);
780 int keyNext(pgRef &loc, unsigned char *rky);
781 int keyUnderflow(pageId s, pageId &t, int k);
782 int keyOverflow(pageId s, pageId &t, int k, int o);
783 int keyRemap(pageId s, pageId &t, int k, int o);
784 int keyDelete(pageId s, pageId &t);
786 unsigned char lastAccKey[keysz], lastFndKey[keysz];
787 unsigned char lastInsKey[keysz], lastDelKey[keysz];
788 unsigned char lastNxtKey[keysz];
789 unsigned char *tky, *dky; // dataSz+keysz+1
790 unsigned char *tbfr; // 3*allocated
791 unsigned char akey[keysz]; // key in use
792 int idf; /* interior delete flag */
794 int refLocate(pgRef &loc, int op, void *key, CmprFn cmpr, unsigned char *rkey);
795 int Locate(int op,void *key,CmprFn cmpr,void *rtnKey,void *rtnData);
796 int refFind(pgRef &loc, void *key);
797 int Find(void *key,void *rtnData);
798 int Insert(void *key,void *data);
799 int Delete(void *key);
800 int First(void *rtnKey,void *rtnData);
801 int Last(void *rtnKey,void *rtnData);
802 int Modify(void *key,void *recd);
803 int Next(pgRef &loc,void *rtnKey,void *rtnData);
804 int Next(void *rtnKey,void *rtnData) {
805 return IndexBase::Next(rtnKey,rtnData);
809 IndexString(Db *zdb, int zidx, int dsz);
810 IndexString(Db *zdb, IndexBaseStorage *b, IndexStringStorage *d);
811 IndexString(IndexBase *ib, IndexBaseStorage *b, IndexStringStorage *d);
814 friend class IndexString;
816 class IndexBinaryData : public IndexBaseInfo, public IndexBinaryInfo {};
817 class IndexStringData : public IndexBaseInfo, public IndexStringInfo {};
824 IndexInfo *index_info; /* image for index storage */
828 unsigned short magic;
833 class freeStoreRecord {
839 class addrStoreRecord {
845 class freeSpaceRecord {
852 class addrSpaceRecord {
864 int cacheFlush(Db *db);
865 int Get(Db *db,int &size, pgRef &ref);
866 int Load(Db *db, pageId id, int ofs, int sz);
867 void init() { loc.id = NIL; loc.offset = 0; avail = 0; }
868 void init(pageId id, int ofs, int sz) {
869 loc.id = id; loc.offset = ofs; avail = sz;
872 printf("loc: %d/%d avl: %d\n", loc.id,loc.offset,avail);
874 int freeIdx, addrIdx;
875 int init_idx(Db *db, const char *nm);
878 int cacheFlush() { return alloc_cache.cacheFlush(this); }
879 void cacheDelete(AllocCache &cache);
880 int cache_all_flush();
885 unsigned int allocated;
886 unsigned short flags;
897 PageStorage() { init(); }
899 int chk_flags(int fl) { return flags & fl; }
900 int set_flags(int fl) { return flags |= fl; }
901 int clr_flags(int fl) { return flags &= ~fl; }
911 // PageStorage access
912 int iused() { return st->used-sizeof(keyBlock); }
913 void iused(int v) { st->used = v+sizeof(keyBlock); }
914 int iallocated() { return st->allocated-sizeof(keyBlock); }
915 void iallocated(int v) { st->allocated = v+sizeof(keyBlock); }
916 PageStorage *operator ->() { return st; }
918 void reset_to(Page *pp);
919 Page(PageStorage &d) { st = &d; init(); }
923 int pageTableAllocated, page_table_sz;
927 int pageTableHunkSize;
928 int indexTableHunkSize;
937 int cfnAllocated, cfnUsed;
938 undoData() : cfn(0), cfnAllocated(0), cfnUsed(0) {}
939 ~undoData() { delete [] cfn; cfnAllocated = cfnUsed = 0; }
944 ioAddr file_position;
946 char *bfr, *lmt, *inp;
950 int write_bfr(char *dp, int sz);
956 inline static unsigned int on_bits(unsigned int n) {
957 n = (n & 0x55555555) + ((n >> 1) & 0x55555555);
958 n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
959 n = (n & 0x0f0f0f0f) + ((n >> 4) & 0x0f0f0f0f);
960 n += n >> 8; n += n >> 16; //ok, fldsz > 5 bits
965 inline static unsigned int low_bit(unsigned int n) {
969 // bit number of lowest on bit
970 inline static unsigned int low_bit_no(unsigned int n) {
971 return on_bits(low_bit(n) - 1);
974 // highest on bit, and all lower bits set
975 inline static unsigned int high_bit_mask(unsigned int n) {
976 n |= n >> 1; n |= n >> 2;
977 n |= n >> 4; n |= n >> 8;
983 inline static unsigned int high_bit(unsigned int n) {
984 unsigned m = high_bit_mask(n);
988 // bit number of highest on bit
989 inline static unsigned int high_bit_no(unsigned int n) {
990 return on_bits(high_bit_mask(n)) - 1;
994 static inline int cpu_aligned() {
996 asm volatile( "pushf\n" "pop %0\n" : "=rm" (flags) );
997 return (flags>>18) & 1;
1003 uint64_t clip(int64_t v) { return v<0 ? 0 : (uint64_t)v>vmx ? vmx : v; }
1005 enum { alignBits = 8, };
1007 static void init(int v=-1) { aligned = v >= 0 ? v : cpu_aligned(); }
1008 void put(uint64_t v, int n);
1009 void putc(uint64_t v, int n) { put(clip(v), n); }
1010 void iput(int v) { put(v, 8*sizeof(int)); }
1011 void lput(int64_t v) { put(v, 8*sizeof(int64_t)); }
1012 uint64_t get(int n);
1013 int iget() { return get(8*sizeof(int)); }
1014 int64_t lget() { return get(8*sizeof(int64_t)); }
1015 int pos() { return idx; }
1016 void seek(int i) { idx = i; }
1017 void init(uint8_t *bp) { bits = bp; idx = 0; vmx = 0; }
1018 uint8_t *bfr() { return this->bits; }
1019 void align() { idx = (idx+alignBits-1) & ~(alignBits-1); }
1020 void *addr() { return &bits[idx/8]; }
1021 void set_max(uint64_t v) { vmx = v; }
1023 pack() : bits(0) { idx = 0; }
1024 pack(uint8_t *bp) { init(bp); }
1034 static int64_t bit_size(int len, int w);
1035 static int64_t byte_size(int len, int w);
1036 static void build(uint8_t *kp, uint8_t *bp, int w, int len) {
1037 mediaKey key(kp, bp, w, len);
1039 static int64_t count(void *kp) {
1040 mediaKey *mkp = (mediaKey *)kp;
1041 return be64toh(mkp->cnt);
1043 static int64_t set_count(void *kp, int64_t v) {
1044 mediaKey *mkp = (mediaKey *)kp;
1045 return mkp->cnt = htobe64(v);
1047 static int64_t incr_count(void *kp, int64_t dv) {
1048 return set_count(kp, count(kp) + dv);
1050 static int64_t count1(uint8_t *kp);
1051 mediaKey(uint8_t *kp, uint8_t *bp, int w, int len);
1057 int w, len, dsz, psz, spos;
1058 int64_t cnt, *dat, **dp;
1059 void get_fields(int n, int k);
1060 int dsize(int n) { int m = (n+1)/2; return m>1 ? m+dsize(m) : 1; }
1063 void load(uint8_t *kp);
1065 mediaLoad(uint8_t *bp);
1071 int w, len, dsz, psz, spos;
1072 int64_t acnt, bcnt, *adat, *bdat, **adp, **bdp;
1074 uint64_t sqr(int64_t v) { return v*v; }
1075 int dsize(int n) { int m = (n+1)/2; return m>1 ? m+dsize(m) : 1; }
1076 uint64_t chk_fields(int m, int k);
1077 int cmpr_fields(int m, int k);
1080 uint64_t chk(uint8_t *kp, uint64_t lmt=~0);
1081 int cmpr(uint8_t *kp, uint64_t lmt=~0);
1083 mediaCmpr(uint8_t *bp);
1090 typedef IndexBase *Index;
1091 int new_entity(Entity &entity, const char *nm, int sz);
1092 int get_entity(Entity &entity, const char *nm);
1093 int del_entity(Entity &entity);
1095 class Obj { /* per object storage base class */
1103 int size() { return len; }
1104 void init() { len = -1; loc.id = NIL; loc.offset = 0; }
1105 void del(Entity *entity) { len = -1; entity->deallocate(loc); }
1107 typedef varObj Obj::*vRef;
1113 Obj *addr(pgRef &loc) {
1115 return loc.id < 0 || entity->db->addrRead(loc,op) ? 0 : (Obj *)op;
1117 Obj *addr_wr(pgRef &loc) {
1119 return loc.id < 0 || entity->db->addrWrite(loc,op) ? 0 : (Obj *)op;
1121 void _wr() { Page &pg = *entity->db->get_page(obj.id); pg->set_flags(fl_wr); }
1122 Obj *addr() { return addr(obj); }
1123 Obj *addr_wr() { return addr_wr(obj); }
1124 void *addr(varObj &vobj) { return addr(vobj.loc); }
1125 void *addr_wr(varObj &vobj) { return addr_wr(vobj.loc); }
1126 Obj *operator ->() { return (Obj *)addr(); }
1127 ObjectLoc(Entity *ep) : entity(ep) { obj.id = NIL; obj.offset = 0; }
1130 virtual int allocate(int sz=0) { return entity->allocate(*this,sz); }
1131 virtual int construct() { return entity->construct(*this); }
1132 virtual int destruct() { return entity->destruct(*this); }
1133 virtual int deallocate() { return entity->deallocate(*this); }
1134 virtual int insertCascade() { return 0; }
1135 virtual int insertProhibit() { return 0; }
1136 virtual int deleteCascade() { return 0; }
1137 virtual int deleteProhibit() { return 0; }
1138 virtual int modifyCascade() { return 0; }
1139 virtual int modifyProhibit() { return 0; }
1140 virtual int copy(ObjectLoc &dobj);
1141 int id() { ObjectLoc &oloc = *this; return oloc->id; }
1142 const int *_id() { ObjectLoc &oloc = *this; return &oloc->id; }
1143 int _id_size() { return sizeof(int); }
1144 int size(varObj &vobj) { return vobj.len; }
1145 int size(varObj &vobj, int sz);
1146 Index index(int i) { return entity->index(i); }
1150 int FindId(int id) { return index(idxId)->Find(&id,&obj); }
1151 int LocateId(int op, int id) { return index(idxId)->Locate(op,&id,0,0,&obj); }
1152 int FirstId() { return index(idxId)->First(0,&obj); }
1153 int LastId() { return index(idxId)->Last(0,&obj); }
1154 int NextId() { return index(idxId)->Next(0,&obj); }
1155 int FirstId(pgRef &loc) { return index(idxId)->First(loc,0,&obj); }
1156 int NextId(pgRef &loc) { return index(idxId)->Next(loc,0,&obj); }
1157 int NextLocId(pgRef &loc) { return index(idxId)->NextLoc(loc); }
1159 static int cmpr_char(const char *ap, int asz, const char *bp, int bsz);
1160 static int cmpr_uchar(const unsigned char *ap, int asz, const unsigned char *bp, int bsz);
1161 static int cmpr_short(const short *ap, int asz, const short *bp, int bsz);
1162 static int cmpr_ushort(const unsigned short *ap, int asz, const unsigned short *bp, int bsz);
1163 static int cmpr_int(const int *ap, int asz, const int *bp, int bsz);
1164 static int cmpr_uint(const unsigned int *ap, int asz, const unsigned int *bp, int bsz);
1165 static int cmpr_long(const long *ap, int asz, const long *bp, int bsz);
1166 static int cmpr_ulong(const unsigned long *ap, int asz, const unsigned long *bp, int bsz);
1167 static int cmpr_float(const float *ap, int asz, const float *bp, int bsz);
1168 static int cmpr_double(const double *ap, int asz, const double *bp, int bsz);
1170 static int cmpr_media(const unsigned char *ap, int asz, const unsigned char *bp, int bsz);
1174 int _err_(int v,const char *fn,int ln) { return entity->db->_err_(v,fn,ln); }
1175 int _fail_(int v,const char *fn,int ln) { return entity->db->_fail_(v,fn,ln); }
1177 int _err_(int v) { return entity->db->_err_(v); }
1178 int _fail_(int v) { return entity->db->_fail_(v); }
1181 int last(Index idx,ObjectLoc &last_loc);
1182 int last(const char *nm,int (ObjectLoc::*ip)());
1183 unsigned int last(const char *nm,unsigned int (ObjectLoc::*ip)());
1191 virtual int wr_key(char *cp) = 0;
1192 Key(Index i, ObjectLoc &l, CmprFn c) : loc(l), idx(i), cmpr(c) {}
1193 Key(const char *nm, ObjectLoc &l, CmprFn c) : loc(l), cmpr(c) {
1194 idx = loc.entity->index(nm);
1196 operator void *() { return (void *)this; }
1198 int _err_(int v,const char *fn,int ln) { return loc._err_(v,fn,ln); }
1199 int _fail_(int v,const char *fn,int ln) { return loc._fail_(v,fn,ln); }
1201 int _err_(int v) { return loc._err_(v); }
1202 int _fail_(int v) { return loc._fail_(v); }
1206 class rKey : public Key {
1208 rKey(Index i, ObjectLoc &l, CmprFn c) : Key(i,l,c) {}
1209 rKey(const char *nm, ObjectLoc &l, CmprFn c) : Key(nm,l,c) {}
1210 virtual int wr_key(char *cp=0) { return -1; }
1211 int NextLoc(pgRef &pos) { return idx->NextLoc(pos); }
1212 int First(); int First(pgRef &pos);
1213 int Next(); int Next(pgRef &pos);
1215 int Locate(int op=keyGE);
1218 class iKey : protected rKey {
1220 iKey(Index i, ObjectLoc &l, CmprFn c) : rKey(i,l,c) {}
1221 iKey(const char *nm, ObjectLoc &l, CmprFn c) : rKey(nm,l,c) {}
1222 int NextLoc(pgRef &pos) { return idx->NextLoc(pos); }
1224 int Locate(int op=keyGE);
1228 class EntityObj : public Obj { /* entity storage */
1230 char name[nmSz]; /* string identifier */
1231 AllocCache alloc_cache; /* entity allocator cache */
1232 int maxId; /* highest ID value */
1233 int recdSz; /* record size in bytes */
1234 int count; /* number of records */
1235 int nidxs; /* index count */
1236 int indexs[1]; /* id/loc index */
1237 EntityObj(EntityObj &eobj, int eid);
1240 class EntityLoc : public ObjectLoc {
1242 EntityObj *operator ->() { return (EntityObj *)addr(); }
1243 EntityLoc(Entity *ep) : ObjectLoc(ep) {}
1246 EntityLoc &eloc = *this; _wr();
1247 return eloc->alloc_cache.cacheFlush(entity->db);
1252 typedef varObjRef *varObjs;
1257 varObjRef(varObjs &lp, vRef rp) : next(lp), ref(rp) {}
1260 static int ioCmpr(const void *a, const void *b, void *c);
1269 operator zrwlock_t&() { return *rw_lock; }
1272 int _err_(int v,const char *fn,int ln) { return db->_err_(v,fn,ln); }
1273 int _fail_(int v,const char *fn,int ln) { return db->_fail_(v,fn,ln); }
1275 int _err_(int v) { return db->_err_(v); }
1276 int _fail_(int v) { return db->_fail_(v); }
1278 Entity(Db *const db) : db(db), ent(this), vobjs(0) {}
1281 int allocate(ObjectLoc &loc,int sz=0);
1282 int construct_(ObjectLoc &loc, int id);
1283 int construct(ObjectLoc &loc) { return construct_(loc,ent->maxId); }
1284 int destruct_(ObjectLoc &loc, int id);
1285 int destruct(ObjectLoc &loc) { return destruct_(loc, loc->id); }
1286 int deallocate(pgRef &obj) { return db->deallocate(obj,ent->alloc_cache); }
1287 int deallocate(ObjectLoc &loc) { return deallocate(loc.obj); }
1288 int get_index(const char *nm, CmprFn cmpr=0);
1289 Index index(int i) { return db->indecies[ent->indexs[i]]; }
1290 Index index(const char *nm) {
1291 int idx = get_index(nm);
1292 return idx >= 0 ? index(idx) : 0;
1294 int MaxId() { return ent->maxId; }
1295 int Count() { return ent->count; }
1296 int add_index(int idx, int kty=ktyBin);
1297 int add_bindex(const char *nm,int keySz,int dataSz) {
1298 int idx = db->new_binary_index(nm,keySz,dataSz);
1299 if_err( idx ); if_err( add_index(idx,ktyBin) );
1302 int add_ind_index(const char *nm) {
1303 int idx = db->new_binary_index(nm,0,sizeof(int),Db::cmprKey);
1304 if_err( idx ); if_err( add_index(idx,ktyInd) );
1307 int add_dir_index(const char *nm,int keySz) {
1308 int idx = db->new_binary_index(nm,keySz,sizeof(int),Db::cmprKey);
1309 if_err( idx ); if_err( add_index(idx,ktyDir) );
1312 int add_str_index(const char *nm,int dataSz) {
1313 int idx = db->new_string_index(nm, dataSz);
1314 if_err( idx ); if_err( add_index(idx,ktyDir) );
1317 int del_index_(int idx);
1318 int del_index(int idx);
1319 int del_index(const char *nm);
1320 int new_entity(const char *nm, int sz) { return db->new_entity(*this,nm,sz); }
1321 int get_entity(const char *nm) { return db->get_entity(*this,nm); }
1322 int del_entity() { return db->del_entity(*this); }
1323 void add_vref(vRef rp) { vobjs = new varObjRef(vobjs,rp); }
1327 typedef ObjectList *Objects;
1328 static void finit(Objects objects);
1334 ObjectList(Objects op, ObjectLoc &o) : next(op), obj(&o) {}
1338 int new_entity_(Entity &entity, const char *nm, int sz);
1340 int findCmprFn(CmprFn fn);
1341 int pageLoad(pageId id, Page &pg);
1342 int addrRead_(pgRef &loc, char *&vp, int mpsz=0) {
1343 Page &pg = *get_page(loc.id); vp = 0;
1344 if( unlikely( !pg.addr || pg->chk_flags(fl_rd) ) ) {
1345 if_err( pageLoad(loc.id, pg) );
1347 vp = (char *)pg.addr+loc.offset+mpsz;
1350 int addrRead_(pgRef &loc, keyBlock *&vp, int mpsz=0) {
1351 return addrRead_(loc,*(char**)&vp, mpsz);
1353 int addrRead_(pgRef &loc, allocPrefix *&vp, int mpsz=0) {
1354 return addrRead_(loc,*(char**)&vp, mpsz);
1356 int addrRead_(pgRef &loc, pagePrefix *&vp, int mpsz=0) {
1357 return addrRead_(loc,*(char**)&vp, mpsz);
1359 int addrWrite_(pgRef &loc, char *&vp, int mpsz=0) {
1360 Page &pg = *get_page(loc.id); vp = 0;
1361 if( unlikely( !pg.addr || pg->chk_flags(fl_rd) ) ) {
1362 if_err( pageLoad(loc.id, pg) );
1364 pg->set_flags(fl_wr);
1365 vp = (char *)pg.addr+loc.offset+mpsz;
1368 int addrWrite_(pgRef &loc, keyBlock *&vp, int mpsz=0) {
1369 return addrWrite_(loc,*(char**)&vp, mpsz);
1371 int addrWrite_(pgRef &loc, allocPrefix *&vp, int mpsz=0) {
1372 return addrWrite_(loc,*(char**)&vp, mpsz);
1374 int addrWrite_(pgRef &loc, pagePrefix *&vp, int mpsz=0) {
1375 return addrWrite_(loc,*(char**)&vp, mpsz);
1377 int addrRead(pgRef &loc, char *&vp) {
1378 return addrRead_(loc, vp, sizeof(allocPrefix));
1380 int addrWrite(pgRef &loc, char *&vp) {
1381 return addrWrite_(loc, vp, sizeof(allocPrefix));
1384 int objectHeapInsert(int sz,int pg,int off,AllocCache &cache);
1385 int objectHeapDelete(int sz,int pg,int off,AllocCache &cache);
1386 int objectAllocate(int typ, int &size, pgRef &loc,AllocCache &cache);
1387 int objectFree(pgRef &loc,AllocCache &cache);
1388 int pgRefGet(int &size, pgRef &loc,AllocCache &cache);
1389 int pgRefNew(int &size, pgRef &lo,AllocCache &cache);
1390 int pgRefAllocate(int &size, pgRef &lo,AllocCache &cache);
1392 int storeInsert(long size, ioAddr io_addr);
1393 int storeDelete(long size, ioAddr io_addr);
1394 int storeGet(int &size, ioAddr &io_addr);
1395 int storeNew(int &size, ioAddr &io_addr);
1396 int storeAllocate(int &size, ioAddr &io_addr);
1397 int storeFree(int size, ioAddr io_addr);
1399 int icommit(int force);
1404 int iopen(int undo_save=1);
1409 void del_page(int id);
1410 int alloc_pageTable(int sz);
1411 void free_page_(int pid);
1412 void free_page(int pid) { locked by(db_info->pgAlLk); free_page_(pid); }
1413 pageId lower_page(int mid);
1414 int alloc_indecies(int n);
1416 void del_index(int idx);
1417 int new_index(IndexBase *&ibp, IndexBaseInfo *b, IndexBinaryInfo *d);
1418 int new_index(IndexBase *&ibp, IndexBaseInfo *b, IndexStringInfo *d);
1419 int indexRead(pageId pid, int df, keyBlock *&bp) {
1420 pgRef pg; pg.id = pid; pg.offset = 0;
1421 return !df ? addrRead_(pg,*(char**)&bp) : addrWrite_(pg,*(char**)&bp);
1423 int indexRead(pageId pid,int df,keyBlock *&bp, Page *&pp, char *&cp) {
1424 pp = 0; cp = 0; if_err( indexRead(pid, df, bp) );
1425 pp = get_page(pid); cp = (char *)(bp + 1);
1428 void pageDealloc(Page &pg, int mode=1);
1429 int pageRead(ioAddr io_adr, uint8_t *bp, int len);
1430 int pageWrite(Page &pg);
1431 int seek_data(ioAddr io_addr);
1432 int size_data(char *dp, int sz);
1433 int read_data(char *dp, int sz);
1434 int write_data(char *dp, int sz);
1435 int write_zeros(ioAddr io_addr);
1436 int write_padding(ioAddr io_addr);
1437 int readRootInfo(int(Db::*fn)(char *dp,int sz));
1438 int writeRootInfo(int(Db::*fn)(char *dp,int sz));
1439 ioAddr storeBlocks(ioAddr sz) { return (sz+storeBlockSize-1)/storeBlockSize; }
1440 ioAddr entityPages(ioAddr sz) { return (sz+entityPageSize-1)/entityPageSize; }
1441 int indeciesHunks(int sz) { return (sz+indexTableHunkSize-1)/indexTableHunkSize; }
1442 int pageTableHunks(int sz) { return (sz+pageTableHunkSize-1)/pageTableHunkSize; }
1443 int pagePrefixHunks(int sz) { return (sz+sizeof(pagePrefix)-1)/sizeof(pagePrefix); }
1449 int start_transaction(int undo_save=1);
1450 void enter() { db_info->dbRwLk.enter(); }
1451 void leave() { db_info->dbRwLk.leave(); }
1452 void write_enter() { db_info->dbRwLk.write_enter(); }
1453 void write_leave() { db_info->dbRwLk.write_leave(); }
1456 // 1:wr, 0:rd, -1:unlocked
1457 int is_locked() { return db_info->dbRwLk.locked(); }
1458 int is_blocked() { return db_info->dbRwLk.blocked(); }
1461 int open(int zfd, int zkey=-1);
1464 int attach(int zrw, int zfd, int zkey);
1465 int attach(int zrw=0) { return attach(fd, key, zrw); }
1468 int copy(Db *db, Objects objs);
1469 int new_binary_index(const char *nm, int ksz, int dsz, CmprFn cmpr=0);
1470 int new_string_index(const char *nm, int dsz);
1471 int get_index(const char *nm, CmprFn cmpr=0);
1472 long get_count(int r);
1473 int ins (int r, void *key, void *data);
1474 int del (int r, void *key);
1475 int find (int r, void *key, void *rtnData=0);
1476 int locate(int r, int op, void *key, CmprFn cmpr, void *rtnKey, void *rtnData=0);
1477 int locate(int r, int op, void *key, void *rtnKey, void *rtnData=0) {
1478 return locate(r,op,key,0,rtnKey,rtnData);
1480 int first (int r, void *key, void *rtnData=0);
1481 int last (int r, void *key, void *rtnData=0);
1482 int next (int r, void *key, void *rtnData=0);
1483 int nextloc(int r, pgRef &loc);
1484 int allocate(int typ, int size, pgRef &loc, AllocCache &cache);
1485 int reallocate(int size, pgRef &loc, AllocCache &cache);
1486 int deallocate(pgRef &loc, AllocCache &cache);
1487 int commit(int force=0);
1491 int transaction() { return !root_info ? -1 : root_info->transaction_id; }
1492 int64_t filesize() { return !root_info ? -1 : root_info->file_size; }
1493 int opened() { return fd>=0 ? 1 : 0; }
1494 void use_shm(int v) { no_shm = v ? 0 : 1; }
1495 int error() { return err_no; }
1497 void Error(int v,const char *msg);
1499 int load_indecies();
1509 void admp(); void achk(); void fchk();
1510 void edmp(AllocCache &cache);
1511 void bdmp(AllocCache &cache);