summaryrefslogtreecommitdiff
path: root/qdbm/villa.c
diff options
context:
space:
mode:
Diffstat (limited to 'qdbm/villa.c')
-rw-r--r--qdbm/villa.c2666
1 files changed, 0 insertions, 2666 deletions
diff --git a/qdbm/villa.c b/qdbm/villa.c
deleted file mode 100644
index 0783ac5d..00000000
--- a/qdbm/villa.c
+++ /dev/null
@@ -1,2666 +0,0 @@
-/*************************************************************************************************
- * Implementation of Villa
- * Copyright (C) 2000-2007 Mikio Hirabayashi
- * This file is part of QDBM, Quick Database Manager.
- * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
- * Lesser General Public License as published by the Free Software Foundation; either version
- * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307 USA.
- *************************************************************************************************/
-
-
-#define QDBM_INTERNAL 1
-
-#include "villa.h"
-#include "myconf.h"
-
-#define VL_LEAFIDMIN 1 /* minimum number of leaf ID */
-#define VL_NODEIDMIN 100000000 /* minimum number of node ID */
-#define VL_VNUMBUFSIZ 8 /* size of a buffer for variable length number */
-#define VL_NUMBUFSIZ 32 /* size of a buffer for a number */
-#define VL_PAGEBUFSIZ 32768 /* size of a buffer to read each page */
-#define VL_MAXLEAFSIZ 49152 /* maximum size of each leaf */
-#define VL_DEFLRECMAX 49 /* default number of records in each leaf */
-#define VL_DEFNIDXMAX 192 /* default number of indexes in each node */
-#define VL_DEFLCNUM 1024 /* default number of leaf cache */
-#define VL_DEFNCNUM 512 /* default number of node cache */
-#define VL_CACHEOUT 8 /* number of pages in a process of cacheout */
-#define VL_INITBNUM 32749 /* initial bucket number */
-#define VL_PAGEALIGN -3 /* alignment for pages */
-#define VL_FBPOOLSIZ 128 /* size of free block pool */
-#define VL_PATHBUFSIZ 1024 /* size of a path buffer */
-#define VL_TMPFSUF MYEXTSTR "vltmp" /* suffix of a temporary file */
-#define VL_ROOTKEY -1 /* key of the root key */
-#define VL_LASTKEY -2 /* key of the last key */
-#define VL_LNUMKEY -3 /* key of the number of leaves */
-#define VL_NNUMKEY -4 /* key of the number of nodes */
-#define VL_RNUMKEY -5 /* key of the number of records */
-#define VL_CRDNUM 7 /* default division number for Vista */
-
-/* set a buffer for a variable length number */
-#define VL_SETVNUMBUF(VL_len, VL_buf, VL_num) \
- do { \
- int _VL_num; \
- _VL_num = VL_num; \
- if(_VL_num == 0){ \
- ((signed char *)(VL_buf))[0] = 0; \
- (VL_len) = 1; \
- } else { \
- (VL_len) = 0; \
- while(_VL_num > 0){ \
- int _VL_rem = _VL_num & 0x7f; \
- _VL_num >>= 7; \
- if(_VL_num > 0){ \
- ((signed char *)(VL_buf))[(VL_len)] = -_VL_rem - 1; \
- } else { \
- ((signed char *)(VL_buf))[(VL_len)] = _VL_rem; \
- } \
- (VL_len)++; \
- } \
- } \
- } while(FALSE)
-
-/* read a variable length buffer */
-#define VL_READVNUMBUF(VL_buf, VL_size, VL_num, VL_step) \
- do { \
- int _VL_i, _VL_base; \
- (VL_num) = 0; \
- _VL_base = 1; \
- if((VL_size) < 2){ \
- (VL_num) = ((signed char *)(VL_buf))[0]; \
- (VL_step) = 1; \
- } else { \
- for(_VL_i = 0; _VL_i < (VL_size); _VL_i++){ \
- if(((signed char *)(VL_buf))[_VL_i] >= 0){ \
- (VL_num) += ((signed char *)(VL_buf))[_VL_i] * _VL_base; \
- break; \
- } \
- (VL_num) += _VL_base * (((signed char *)(VL_buf))[_VL_i] + 1) * -1; \
- _VL_base *= 128; \
- } \
- (VL_step) = _VL_i + 1; \
- } \
- } while(FALSE)
-
-enum { /* enumeration for flags */
- VL_FLISVILLA = 1 << 0, /* whether for Villa */
- VL_FLISZLIB = 1 << 1, /* whether with ZLIB */
- VL_FLISLZO = 1 << 2, /* whether with LZO */
- VL_FLISBZIP = 1 << 3 /* whether with BZIP2 */
-};
-
-
-/* private function prototypes */
-static int vllexcompare(const char *aptr, int asiz, const char *bptr, int bsiz);
-static int vlintcompare(const char *aptr, int asiz, const char *bptr, int bsiz);
-static int vlnumcompare(const char *aptr, int asiz, const char *bptr, int bsiz);
-static int vldeccompare(const char *aptr, int asiz, const char *bptr, int bsiz);
-static int vldpputnum(DEPOT *depot, int knum, int vnum);
-static int vldpgetnum(DEPOT *depot, int knum, int *vnp);
-static VLLEAF *vlleafnew(VILLA *villa, int prev, int next);
-static int vlleafcacheout(VILLA *villa, int id);
-static int vlleafsave(VILLA *villa, VLLEAF *leaf);
-static VLLEAF *vlleafload(VILLA *villa, int id);
-static VLLEAF *vlgethistleaf(VILLA *villa, const char *kbuf, int ksiz);
-static int vlleafaddrec(VILLA *villa, VLLEAF *leaf, int dmode,
- const char *kbuf, int ksiz, const char *vbuf, int vsiz);
-static int vlleafdatasize(VLLEAF *leaf);
-static VLLEAF *vlleafdivide(VILLA *villa, VLLEAF *leaf);
-static VLNODE *vlnodenew(VILLA *villa, int heir);
-static int vlnodecacheout(VILLA *villa, int id);
-static int vlnodesave(VILLA *villa, VLNODE *node);
-static VLNODE *vlnodeload(VILLA *villa, int id);
-static void vlnodeaddidx(VILLA *villa, VLNODE *node, int order,
- int pid, const char *kbuf, int ksiz);
-static int vlsearchleaf(VILLA *villa, const char *kbuf, int ksiz);
-static int vlcacheadjust(VILLA *villa);
-static VLREC *vlrecsearch(VILLA *villa, VLLEAF *leaf, const char *kbuf, int ksiz, int *ip);
-
-
-
-/*************************************************************************************************
- * public objects
- *************************************************************************************************/
-
-
-/* Comparing functions. */
-VLCFUNC VL_CMPLEX = vllexcompare;
-VLCFUNC VL_CMPINT = vlintcompare;
-VLCFUNC VL_CMPNUM = vlnumcompare;
-VLCFUNC VL_CMPDEC = vldeccompare;
-
-
-/* Get a database handle. */
-VILLA *vlopen(const char *name, int omode, VLCFUNC cmp){
- DEPOT *depot;
- int dpomode, flags, cmode, root, last, lnum, nnum, rnum;
- VILLA *villa;
- VLLEAF *leaf;
- assert(name && cmp);
- dpomode = DP_OREADER;
- if(omode & VL_OWRITER){
- dpomode = DP_OWRITER;
- if(omode & VL_OCREAT) dpomode |= DP_OCREAT;
- if(omode & VL_OTRUNC) dpomode |= DP_OTRUNC;
- }
- if(omode & VL_ONOLCK) dpomode |= DP_ONOLCK;
- if(omode & VL_OLCKNB) dpomode |= DP_OLCKNB;
- if(!(depot = dpopen(name, dpomode, VL_INITBNUM))) return NULL;
- flags = dpgetflags(depot);
- cmode = 0;
- root = -1;
- last = -1;
- lnum = 0;
- nnum = 0;
- rnum = 0;
- if(dprnum(depot) > 0){
- if(!(flags & VL_FLISVILLA) ||
- !vldpgetnum(depot, VL_ROOTKEY, &root) || !vldpgetnum(depot, VL_LASTKEY, &last) ||
- !vldpgetnum(depot, VL_LNUMKEY, &lnum) || !vldpgetnum(depot, VL_NNUMKEY, &nnum) ||
- !vldpgetnum(depot, VL_RNUMKEY, &rnum) || root < VL_LEAFIDMIN || last < VL_LEAFIDMIN ||
- lnum < 0 || nnum < 0 || rnum < 0){
- dpclose(depot);
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- return NULL;
- }
- if(flags & VL_FLISZLIB){
- cmode = VL_OZCOMP;
- } else if(flags & VL_FLISLZO){
- cmode = VL_OYCOMP;
- } else if(flags & VL_FLISBZIP){
- cmode = VL_OXCOMP;
- }
- } else if(omode & VL_OWRITER){
- if(omode & VL_OZCOMP){
- cmode = VL_OZCOMP;
- } else if(omode & VL_OYCOMP){
- cmode = VL_OYCOMP;
- } else if(omode & VL_OXCOMP){
- cmode = VL_OXCOMP;
- }
- }
- if(omode & VL_OWRITER){
- flags |= VL_FLISVILLA;
- if(_qdbm_deflate && cmode == VL_OZCOMP){
- flags |= VL_FLISZLIB;
- } else if(_qdbm_lzoencode && cmode == VL_OYCOMP){
- flags |= VL_FLISLZO;
- } else if(_qdbm_bzencode && cmode == VL_OXCOMP){
- flags |= VL_FLISBZIP;
- }
- if(!dpsetflags(depot, flags) || !dpsetalign(depot, VL_PAGEALIGN) ||
- !dpsetfbpsiz(depot, VL_FBPOOLSIZ)){
- dpclose(depot);
- return NULL;
- }
- }
- CB_MALLOC(villa, sizeof(VILLA));
- villa->depot = depot;
- villa->cmp = cmp;
- villa->wmode = (omode & VL_OWRITER);
- villa->cmode = cmode;
- villa->root = root;
- villa->last = last;
- villa->lnum = lnum;
- villa->nnum = nnum;
- villa->rnum = rnum;
- villa->leafc = cbmapopen();
- villa->nodec = cbmapopen();
- villa->hnum = 0;
- villa->hleaf = -1;
- villa->lleaf = -1;
- villa->curleaf = -1;
- villa->curknum = -1;
- villa->curvnum = -1;
- villa->leafrecmax = VL_DEFLRECMAX;
- villa->nodeidxmax = VL_DEFNIDXMAX;
- villa->leafcnum = VL_DEFLCNUM;
- villa->nodecnum = VL_DEFNCNUM;
- villa->tran = FALSE;
- villa->rbroot = -1;
- villa->rblast = -1;
- villa->rblnum = -1;
- villa->rbnnum = -1;
- villa->rbrnum = -1;
- if(root == -1){
- leaf = vlleafnew(villa, -1, -1);
- villa->root = leaf->id;
- villa->last = leaf->id;
- if(!vltranbegin(villa) || !vltranabort(villa)){
- vlclose(villa);
- return NULL;
- }
- }
- return villa;
-}
-
-
-/* Close a database handle. */
-int vlclose(VILLA *villa){
- int err, pid;
- const char *tmp;
- assert(villa);
- err = FALSE;
- if(villa->tran){
- if(!vltranabort(villa)) err = TRUE;
- }
- cbmapiterinit(villa->leafc);
- while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){
- pid = *(int *)tmp;
- if(!vlleafcacheout(villa, pid)) err = TRUE;
- }
- cbmapiterinit(villa->nodec);
- while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){
- pid = *(int *)tmp;
- if(!vlnodecacheout(villa, pid)) err = TRUE;
- }
- if(villa->wmode){
- if(!dpsetalign(villa->depot, 0)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE;
- }
- cbmapclose(villa->leafc);
- cbmapclose(villa->nodec);
- if(!dpclose(villa->depot)) err = TRUE;
- free(villa);
- return err ? FALSE : TRUE;
-}
-
-
-/* Store a record. */
-int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){
- VLLEAF *leaf, *newleaf;
- VLNODE *node, *newnode;
- VLIDX *idxp;
- CBDATUM *key;
- int i, pid, todiv, heir, parent, mid;
- assert(villa && kbuf && vbuf);
- villa->curleaf = -1;
- villa->curknum = -1;
- villa->curvnum = -1;
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- if(ksiz < 0) ksiz = strlen(kbuf);
- if(vsiz < 0) vsiz = strlen(vbuf);
- if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){
- if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return FALSE;
- if(!(leaf = vlleafload(villa, pid))) return FALSE;
- }
- if(!vlleafaddrec(villa, leaf, dmode, kbuf, ksiz, vbuf, vsiz)){
- dpecodeset(DP_EKEEP, __FILE__, __LINE__);
- return FALSE;
- }
- todiv = FALSE;
- switch(CB_LISTNUM(leaf->recs) % 4){
- case 0:
- if(CB_LISTNUM(leaf->recs) >= 4 &&
- vlleafdatasize(leaf) > VL_MAXLEAFSIZ * (villa->cmode > 0 ? 2 : 1)){
- todiv = TRUE;
- break;
- }
- case 2:
- if(CB_LISTNUM(leaf->recs) > villa->leafrecmax) todiv = TRUE;
- break;
- }
- if(todiv){
- if(!(newleaf = vlleafdivide(villa, leaf))) return FALSE;
- if(leaf->id == villa->last) villa->last = newleaf->id;
- heir = leaf->id;
- pid = newleaf->id;
- key = ((VLREC *)CB_LISTVAL(newleaf->recs, 0))->key;
- key = cbdatumdup(key);
- while(TRUE){
- if(villa->hnum < 1){
- node = vlnodenew(villa, heir);
- vlnodeaddidx(villa, node, TRUE, pid, CB_DATUMPTR(key), CB_DATUMSIZE(key));
- villa->root = node->id;
- CB_DATUMCLOSE(key);
- break;
- }
- parent = villa->hist[--villa->hnum];
- if(!(node = vlnodeload(villa, parent))){
- CB_DATUMCLOSE(key);
- return FALSE;
- }
- vlnodeaddidx(villa, node, FALSE, pid, CB_DATUMPTR(key), CB_DATUMSIZE(key));
- CB_DATUMCLOSE(key);
- if(CB_LISTNUM(node->idxs) <= villa->nodeidxmax) break;
- mid = CB_LISTNUM(node->idxs) / 2;
- idxp = (VLIDX *)CB_LISTVAL(node->idxs, mid);
- newnode = vlnodenew(villa, idxp->pid);
- heir = node->id;
- pid = newnode->id;
- CB_DATUMOPEN2(key, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key));
- for(i = mid + 1; i < CB_LISTNUM(node->idxs); i++){
- idxp = (VLIDX *)CB_LISTVAL(node->idxs, i);
- vlnodeaddidx(villa, newnode, TRUE, idxp->pid,
- CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key));
- }
- for(i = 0; i < CB_LISTNUM(newnode->idxs); i++){
- idxp = (VLIDX *)cblistpop(node->idxs, NULL);
- CB_DATUMCLOSE(idxp->key);
- free(idxp);
- }
- node->dirty = TRUE;
- }
- }
- if(!villa->tran && !vlcacheadjust(villa)) return FALSE;
- return TRUE;
-}
-
-
-/* Delete a record. */
-int vlout(VILLA *villa, const char *kbuf, int ksiz){
- VLLEAF *leaf;
- VLREC *recp;
- int pid, ri, vsiz;
- char *vbuf;
- assert(villa && kbuf);
- villa->curleaf = -1;
- villa->curknum = -1;
- villa->curvnum = -1;
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- if(ksiz < 0) ksiz = strlen(kbuf);
- if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){
- if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return FALSE;
- if(!(leaf = vlleafload(villa, pid))) return FALSE;
- }
- if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, &ri))){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(recp->rest){
- CB_DATUMCLOSE(recp->first);
- vbuf = cblistshift(recp->rest, &vsiz);
- CB_DATUMOPEN2(recp->first, vbuf, vsiz);
- free(vbuf);
- if(CB_LISTNUM(recp->rest) < 1){
- CB_LISTCLOSE(recp->rest);
- recp->rest = NULL;
- }
- } else {
- CB_DATUMCLOSE(recp->key);
- CB_DATUMCLOSE(recp->first);
- free(cblistremove(leaf->recs, ri, NULL));
- }
- leaf->dirty = TRUE;
- villa->rnum--;
- if(!villa->tran && !vlcacheadjust(villa)) return FALSE;
- return TRUE;
-}
-
-
-/* Retrieve a record. */
-char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp){
- VLLEAF *leaf;
- VLREC *recp;
- char *rv;
- int pid;
- assert(villa && kbuf);
- if(ksiz < 0) ksiz = strlen(kbuf);
- if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){
- if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL;
- if(!(leaf = vlleafload(villa, pid))) return NULL;
- }
- if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return NULL;
- }
- if(!villa->tran && !vlcacheadjust(villa)) return NULL;
- if(sp) *sp = CB_DATUMSIZE(recp->first);
- CB_MEMDUP(rv, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first));
- return rv;
-}
-
-
-/* Get the size of the value of a record. */
-int vlvsiz(VILLA *villa, const char *kbuf, int ksiz){
- VLLEAF *leaf;
- VLREC *recp;
- int pid;
- assert(villa && kbuf);
- if(ksiz < 0) ksiz = strlen(kbuf);
- if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){
- if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return -1;
- if(!(leaf = vlleafload(villa, pid))) return -1;
- }
- if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return -1;
- }
- if(!villa->tran && !vlcacheadjust(villa)) return -1;
- return CB_DATUMSIZE(recp->first);
-}
-
-
-/* Get the number of records corresponding a key. */
-int vlvnum(VILLA *villa, const char *kbuf, int ksiz){
- VLLEAF *leaf;
- VLREC *recp;
- int pid;
- assert(villa && kbuf);
- if(ksiz < 0) ksiz = strlen(kbuf);
- if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){
- if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return 0;
- if(!(leaf = vlleafload(villa, pid))) return 0;
- }
- if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return 0;
- }
- if(!villa->tran && !vlcacheadjust(villa)) return 0;
- return 1 + (recp->rest ? CB_LISTNUM(recp->rest) : 0);
-}
-
-
-/* Store plural records corresponding a key. */
-int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals){
- int i, vsiz;
- const char *vbuf;
- assert(villa && kbuf && vals);
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- if(CB_LISTNUM(vals) < 1){
- dpecodeset(DP_EMISC, __FILE__, __LINE__);
- return FALSE;
- }
- if(ksiz < 0) ksiz = strlen(kbuf);
- for(i = 0; i < CB_LISTNUM(vals); i++){
- vbuf = CB_LISTVAL2(vals, i, vsiz);
- if(!vlput(villa, kbuf, ksiz, vbuf, vsiz, VL_DDUP)) return FALSE;
- }
- return TRUE;
-}
-
-
-/* Delete all records corresponding a key. */
-int vloutlist(VILLA *villa, const char *kbuf, int ksiz){
- int i, vnum;
- assert(villa && kbuf);
- if(!villa->wmode){
- dpecodeset(DP_EMISC, __FILE__, __LINE__);
- return FALSE;
- }
- if(ksiz < 0) ksiz = strlen(kbuf);
- if((vnum = vlvnum(villa, kbuf, ksiz)) < 1) return FALSE;
- for(i = 0; i < vnum; i++){
- if(!vlout(villa, kbuf, ksiz)) return FALSE;
- }
- return TRUE;
-}
-
-
-/* Retrieve values of all records corresponding a key. */
-CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz){
- VLLEAF *leaf;
- VLREC *recp;
- int pid, i, vsiz;
- CBLIST *vals;
- const char *vbuf;
- assert(villa && kbuf);
- if(ksiz < 0) ksiz = strlen(kbuf);
- if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){
- if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL;
- if(!(leaf = vlleafload(villa, pid))) return NULL;
- }
- if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return NULL;
- }
- CB_LISTOPEN(vals);
- CB_LISTPUSH(vals, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first));
- if(recp->rest){
- for(i = 0; i < CB_LISTNUM(recp->rest); i++){
- vbuf = CB_LISTVAL2(recp->rest, i, vsiz);
- CB_LISTPUSH(vals, vbuf, vsiz);
- }
- }
- if(!villa->tran && !vlcacheadjust(villa)){
- CB_LISTCLOSE(vals);
- return NULL;
- }
- return vals;
-}
-
-
-/* Retrieve concatenated values of all records corresponding a key. */
-char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp){
- VLLEAF *leaf;
- VLREC *recp;
- int pid, i, vsiz, rsiz;
- char *rbuf;
- const char *vbuf;
- assert(villa && kbuf);
- if(ksiz < 0) ksiz = strlen(kbuf);
- if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){
- if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL;
- if(!(leaf = vlleafload(villa, pid))) return NULL;
- }
- if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return NULL;
- }
- rsiz = CB_DATUMSIZE(recp->first);
- CB_MALLOC(rbuf, rsiz + 1);
- memcpy(rbuf, CB_DATUMPTR(recp->first), rsiz);
- if(recp->rest){
- for(i = 0; i < CB_LISTNUM(recp->rest); i++){
- vbuf = CB_LISTVAL2(recp->rest, i, vsiz);
- CB_REALLOC(rbuf, rsiz + vsiz + 1);
- memcpy(rbuf + rsiz, vbuf, vsiz);
- rsiz += vsiz;
- }
- }
- rbuf[rsiz] = '\0';
- if(!villa->tran && !vlcacheadjust(villa)){
- free(rbuf);
- return NULL;
- }
- if(sp) *sp = rsiz;
- return rbuf;
-}
-
-
-/* Move the cursor to the first record. */
-int vlcurfirst(VILLA *villa){
- VLLEAF *leaf;
- assert(villa);
- villa->curleaf = VL_LEAFIDMIN;
- villa->curknum = 0;
- villa->curvnum = 0;
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- while(CB_LISTNUM(leaf->recs) < 1){
- villa->curleaf = leaf->next;
- villa->curknum = 0;
- villa->curvnum = 0;
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- }
- return TRUE;
-}
-
-
-/* Move the cursor to the last record. */
-int vlcurlast(VILLA *villa){
- VLLEAF *leaf;
- VLREC *recp;
- assert(villa);
- villa->curleaf = villa->last;
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- while(CB_LISTNUM(leaf->recs) < 1){
- villa->curleaf = leaf->prev;
- if(villa->curleaf == -1){
- villa->curleaf = -1;
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- }
- villa->curknum = CB_LISTNUM(leaf->recs) - 1;
- recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum);
- villa->curvnum = recp->rest ? CB_LISTNUM(recp->rest) : 0;
- return TRUE;
-}
-
-
-/* Move the cursor to the previous record. */
-int vlcurprev(VILLA *villa){
- VLLEAF *leaf;
- VLREC *recp;
- assert(villa);
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf)) || CB_LISTNUM(leaf->recs) < 1){
- villa->curleaf = -1;
- return FALSE;
- }
- recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum);
- villa->curvnum--;
- if(villa->curvnum < 0){
- villa->curknum--;
- if(villa->curknum < 0){
- villa->curleaf = leaf->prev;
- if(villa->curleaf == -1){
- villa->curleaf = -1;
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- while(CB_LISTNUM(leaf->recs) < 1){
- villa->curleaf = leaf->prev;
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- }
- villa->curknum = CB_LISTNUM(leaf->recs) - 1;
- recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum);
- villa->curvnum = recp->rest ? CB_LISTNUM(recp->rest) : 0;
- }
- recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum);
- villa->curvnum = recp->rest ? CB_LISTNUM(recp->rest) : 0;
- }
- if(!villa->tran && !vlcacheadjust(villa)) return FALSE;
- return TRUE;
-}
-
-
-/* Move the cursor to the next record. */
-int vlcurnext(VILLA *villa){
- VLLEAF *leaf;
- VLREC *recp;
- assert(villa);
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf)) || CB_LISTNUM(leaf->recs) < 1){
- villa->curleaf = -1;
- return FALSE;
- }
- recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum);
- villa->curvnum++;
- if(villa->curvnum > (recp->rest ? CB_LISTNUM(recp->rest) : 0)){
- villa->curknum++;
- villa->curvnum = 0;
- }
- if(villa->curknum >= CB_LISTNUM(leaf->recs)){
- villa->curleaf = leaf->next;
- villa->curknum = 0;
- villa->curvnum = 0;
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- while(CB_LISTNUM(leaf->recs) < 1){
- villa->curleaf = leaf->next;
- villa->curknum = 0;
- villa->curvnum = 0;
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- }
- }
- if(!villa->tran && !vlcacheadjust(villa)) return FALSE;
- return TRUE;
-}
-
-
-/* Move the cursor to a position around a record. */
-int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode){
- VLLEAF *leaf;
- VLREC *recp;
- int pid, index;
- assert(villa && kbuf);
- if(ksiz < 0) ksiz = strlen(kbuf);
- if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1){
- villa->curleaf = -1;
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, pid))){
- villa->curleaf = -1;
- return FALSE;
- }
- while(CB_LISTNUM(leaf->recs) < 1){
- villa->curleaf = (jmode == VL_JFORWARD) ? leaf->next : leaf->prev;
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- }
- if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, &index))){
- if(jmode == VL_JFORWARD){
- villa->curleaf = leaf->id;
- if(index >= CB_LISTNUM(leaf->recs)) index--;
- villa->curknum = index;
- villa->curvnum = 0;
- recp = (VLREC *)CB_LISTVAL(leaf->recs, index);
- if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)) < 0) return TRUE;
- villa->curvnum = (recp->rest ? CB_LISTNUM(recp->rest) : 0);
- return vlcurnext(villa);
- } else {
- villa->curleaf = leaf->id;
- if(index >= CB_LISTNUM(leaf->recs)) index--;
- villa->curknum = index;
- recp = (VLREC *)CB_LISTVAL(leaf->recs, index);
- villa->curvnum = (recp->rest ? CB_LISTNUM(recp->rest) : 0);
- if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)) > 0) return TRUE;
- villa->curvnum = 0;
- return vlcurprev(villa);
- }
- }
- if(jmode == VL_JFORWARD){
- villa->curleaf = pid;
- villa->curknum = index;
- villa->curvnum = 0;
- } else {
- villa->curleaf = pid;
- villa->curknum = index;
- villa->curvnum = (recp->rest ? CB_LISTNUM(recp->rest) : 0);
- }
- return TRUE;
-}
-
-
-/* Get the key of the record where the cursor is. */
-char *vlcurkey(VILLA *villa, int *sp){
- VLLEAF *leaf;
- VLREC *recp;
- const char *kbuf;
- char *rv;
- int ksiz;
- assert(villa);
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum);
- kbuf = CB_DATUMPTR(recp->key);
- ksiz = CB_DATUMSIZE(recp->key);
- if(sp) *sp = ksiz;
- CB_MEMDUP(rv, kbuf, ksiz);
- return rv;
-}
-
-
-/* Get the value of the record where the cursor is. */
-char *vlcurval(VILLA *villa, int *sp){
- VLLEAF *leaf;
- VLREC *recp;
- const char *vbuf;
- char *rv;
- int vsiz;
- assert(villa);
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum);
- if(villa->curvnum < 1){
- vbuf = CB_DATUMPTR(recp->first);
- vsiz = CB_DATUMSIZE(recp->first);
- } else {
- vbuf = CB_LISTVAL2(recp->rest, villa->curvnum - 1, vsiz);
- }
- if(sp) *sp = vsiz;
- CB_MEMDUP(rv, vbuf, vsiz);
- return rv;
-}
-
-
-/* Insert a record around the cursor. */
-int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode){
- VLLEAF *leaf;
- VLREC *recp;
- char *tbuf;
- int tsiz;
- assert(villa && vbuf);
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- if(vsiz < 0) vsiz = strlen(vbuf);
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum);
- switch(cpmode){
- case VL_CPBEFORE:
- if(villa->curvnum < 1){
- if(!recp->rest){
- CB_DATUMTOMALLOC(recp->first, tbuf, tsiz);
- CB_DATUMOPEN2(recp->first, vbuf, vsiz);
- CB_LISTOPEN(recp->rest);
- CB_LISTPUSHBUF(recp->rest, tbuf, tsiz);
- } else {
- cblistunshift(recp->rest, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first));
- CB_DATUMSETSIZE(recp->first, 0);
- CB_DATUMCAT(recp->first, vbuf, vsiz);
- }
- } else {
- CB_LISTINSERT(recp->rest, villa->curvnum - 1, vbuf, vsiz);
- }
- villa->rnum++;
- break;
- case VL_CPAFTER:
- if(!recp->rest) CB_LISTOPEN(recp->rest);
- CB_LISTINSERT(recp->rest, villa->curvnum, vbuf, vsiz);
- villa->curvnum++;
- villa->rnum++;
- break;
- default:
- if(villa->curvnum < 1){
- CB_DATUMSETSIZE(recp->first, 0);
- CB_DATUMCAT(recp->first, vbuf, vsiz);
- } else {
- cblistover(recp->rest, villa->curvnum - 1, vbuf, vsiz);
- }
- break;
- }
- leaf->dirty = TRUE;
- return TRUE;
-}
-
-
-/* Delete the record where the cursor is. */
-int vlcurout(VILLA *villa){
- VLLEAF *leaf;
- VLREC *recp;
- char *vbuf;
- int vsiz;
- assert(villa);
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum);
- if(villa->curvnum < 1){
- if(recp->rest){
- vbuf = cblistshift(recp->rest, &vsiz);
- CB_DATUMSETSIZE(recp->first, 0);
- CB_DATUMCAT(recp->first, vbuf, vsiz);
- free(vbuf);
- if(CB_LISTNUM(recp->rest) < 1){
- CB_LISTCLOSE(recp->rest);
- recp->rest = NULL;
- }
- } else {
- CB_DATUMCLOSE(recp->first);
- CB_DATUMCLOSE(recp->key);
- free(cblistremove(leaf->recs, villa->curknum, NULL));
- }
- } else {
- free(cblistremove(recp->rest, villa->curvnum - 1, NULL));
- if(villa->curvnum - 1 >= CB_LISTNUM(recp->rest)){
- villa->curknum++;
- villa->curvnum = 0;
- }
- if(CB_LISTNUM(recp->rest) < 1){
- CB_LISTCLOSE(recp->rest);
- recp->rest = NULL;
- }
- }
- villa->rnum--;
- leaf->dirty = TRUE;
- if(villa->curknum >= CB_LISTNUM(leaf->recs)){
- villa->curleaf = leaf->next;
- villa->curknum = 0;
- villa->curvnum = 0;
- while(villa->curleaf != -1 && (leaf = vlleafload(villa, villa->curleaf)) != NULL &&
- CB_LISTNUM(leaf->recs) < 1){
- villa->curleaf = leaf->next;
- }
- }
- return TRUE;
-}
-
-
-/* Set the tuning parameters for performance. */
-void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum){
- assert(villa);
- if(lrecmax < 1) lrecmax = VL_DEFLRECMAX;
- if(lrecmax < 3) lrecmax = 3;
- if(nidxmax < 1) nidxmax = VL_DEFNIDXMAX;
- if(nidxmax < 4) nidxmax = 4;
- if(lcnum < 1) lcnum = VL_DEFLCNUM;
- if(lcnum < VL_CACHEOUT * 2) lcnum = VL_CACHEOUT * 2;
- if(ncnum < 1) ncnum = VL_DEFNCNUM;
- if(ncnum < VL_CACHEOUT * 2) ncnum = VL_CACHEOUT * 2;
- villa->leafrecmax = lrecmax;
- villa->nodeidxmax = nidxmax;
- villa->leafcnum = lcnum;
- villa->nodecnum = ncnum;
-}
-
-
-/* Set the size of the free block pool of a database handle. */
-int vlsetfbpsiz(VILLA *villa, int size){
- assert(villa && size >= 0);
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- return dpsetfbpsiz(villa->depot, size);
-}
-
-
-/* Synchronize updating contents with the file and the device. */
-int vlsync(VILLA *villa){
- int err;
- err = FALSE;
- if(!vlmemsync(villa)) err = TRUE;
- if(!dpsync(villa->depot)) err = TRUE;
- return err ? FALSE : TRUE;
-}
-
-
-/* Optimize a database. */
-int vloptimize(VILLA *villa){
- int err;
- assert(villa);
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- if(villa->tran){
- dpecodeset(DP_EMISC, __FILE__, __LINE__);
- return FALSE;
- }
- err = FALSE;
- if(!vlsync(villa)) return FALSE;
- if(!dpoptimize(villa->depot, -1)) err = TRUE;
- return err ? FALSE : TRUE;
-}
-
-
-/* Get the name of a database. */
-char *vlname(VILLA *villa){
- assert(villa);
- return dpname(villa->depot);
-}
-
-
-/* Get the size of a database file. */
-int vlfsiz(VILLA *villa){
- return dpfsiz(villa->depot);
-}
-
-
-/* Get the number of the leaf nodes of B+ tree. */
-int vllnum(VILLA *villa){
- assert(villa);
- return villa->lnum;
-}
-
-
-/* Get the number of the non-leaf nodes of B+ tree. */
-int vlnnum(VILLA *villa){
- assert(villa);
- return villa->nnum;
-}
-
-
-/* Get the number of the records stored in a database. */
-int vlrnum(VILLA *villa){
- assert(villa);
- return villa->rnum;
-}
-
-
-/* Check whether a database handle is a writer or not. */
-int vlwritable(VILLA *villa){
- assert(villa);
- return villa->wmode;
-}
-
-
-/* Check whether a database has a fatal error or not. */
-int vlfatalerror(VILLA *villa){
- assert(villa);
- return dpfatalerror(villa->depot);
-}
-
-
-/* Get the inode number of a database file. */
-int vlinode(VILLA *villa){
- assert(villa);
- return dpinode(villa->depot);
-}
-
-
-/* Get the last modified time of a database. */
-time_t vlmtime(VILLA *villa){
- assert(villa);
- return dpmtime(villa->depot);
-}
-
-
-/* Begin the transaction. */
-int vltranbegin(VILLA *villa){
- int err, pid;
- const char *tmp;
- VLLEAF *leaf;
- VLNODE *node;
- assert(villa);
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- if(villa->tran){
- dpecodeset(DP_EMISC, __FILE__, __LINE__);
- return FALSE;
- }
- err = FALSE;
- cbmapiterinit(villa->leafc);
- while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){
- pid = *(int *)tmp;
- leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&pid, sizeof(int), NULL);
- if(leaf->dirty && !vlleafsave(villa, leaf)) err = TRUE;
- }
- cbmapiterinit(villa->nodec);
- while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){
- pid = *(int *)tmp;
- node = (VLNODE *)cbmapget(villa->nodec, (char *)&pid, sizeof(int), NULL);
- if(node->dirty && !vlnodesave(villa, node)) err = TRUE;
- }
- if(!dpsetalign(villa->depot, 0)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE;
- if(!dpmemsync(villa->depot)) err = TRUE;
- if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE;
- villa->tran = TRUE;
- villa->rbroot = villa->root;
- villa->rblast = villa->last;
- villa->rblnum = villa->lnum;
- villa->rbnnum = villa->nnum;
- villa->rbrnum = villa->rnum;
- return err ? FALSE : TRUE;
-}
-
-
-/* Commit the transaction. */
-int vltrancommit(VILLA *villa){
- int err, pid;
- const char *tmp;
- VLLEAF *leaf;
- VLNODE *node;
- assert(villa);
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- if(!villa->tran){
- dpecodeset(DP_EMISC, __FILE__, __LINE__);
- return FALSE;
- }
- err = FALSE;
- cbmapiterinit(villa->leafc);
- while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){
- pid = *(int *)tmp;
- leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&pid, sizeof(int), NULL);
- if(leaf->dirty && !vlleafsave(villa, leaf)) err = TRUE;
- }
- cbmapiterinit(villa->nodec);
- while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){
- pid = *(int *)tmp;
- node = (VLNODE *)cbmapget(villa->nodec, (char *)&pid, sizeof(int), NULL);
- if(node->dirty && !vlnodesave(villa, node)) err = TRUE;
- }
- if(!dpsetalign(villa->depot, 0)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE;
- if(!dpmemsync(villa->depot)) err = TRUE;
- if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE;
- villa->tran = FALSE;
- villa->rbroot = -1;
- villa->rblast = -1;
- villa->rblnum = -1;
- villa->rbnnum = -1;
- villa->rbrnum = -1;
- while(cbmaprnum(villa->leafc) > villa->leafcnum || cbmaprnum(villa->nodec) > villa->nodecnum){
- if(!vlcacheadjust(villa)){
- err = TRUE;
- break;
- }
- }
- return err ? FALSE : TRUE;
-}
-
-
-/* Abort the transaction. */
-int vltranabort(VILLA *villa){
- int err, pid;
- const char *tmp;
- VLLEAF *leaf;
- VLNODE *node;
- assert(villa);
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- if(!villa->tran){
- dpecodeset(DP_EMISC, __FILE__, __LINE__);
- return FALSE;
- }
- err = FALSE;
- cbmapiterinit(villa->leafc);
- while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){
- pid = *(int *)tmp;
- if(!(leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&pid, sizeof(int), NULL))){
- err = TRUE;
- continue;
- }
- if(leaf->dirty){
- leaf->dirty = FALSE;
- if(!vlleafcacheout(villa, pid)) err = TRUE;
- }
- }
- cbmapiterinit(villa->nodec);
- while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){
- pid = *(int *)tmp;
- if(!(node = (VLNODE *)cbmapget(villa->nodec, (char *)&pid, sizeof(int), NULL))){
- err = TRUE;
- continue;
- }
- if(node->dirty){
- node->dirty = FALSE;
- if(!vlnodecacheout(villa, pid)) err = TRUE;
- }
- }
- villa->tran = FALSE;
- villa->root = villa->rbroot;
- villa->last = villa->rblast;
- villa->lnum = villa->rblnum;
- villa->nnum = villa->rbnnum;
- villa->rnum = villa->rbrnum;
- while(cbmaprnum(villa->leafc) > villa->leafcnum || cbmaprnum(villa->nodec) > villa->nodecnum){
- if(!vlcacheadjust(villa)){
- err = TRUE;
- break;
- }
- }
- return err ? FALSE : TRUE;
-}
-
-
-/* Remove a database file. */
-int vlremove(const char *name){
- assert(name);
- return dpremove(name);
-}
-
-
-/* Repair a broken database file. */
-int vlrepair(const char *name, VLCFUNC cmp){
- DEPOT *depot;
- VILLA *tvilla;
- char path[VL_PATHBUFSIZ], *kbuf, *vbuf, *zbuf, *rp, *tkbuf, *tvbuf;
- int i, err, flags, omode, ksiz, vsiz, zsiz, size, step, tksiz, tvsiz, vnum;
- assert(name && cmp);
- err = FALSE;
- if(!dprepair(name)) err = TRUE;
- if(!(depot = dpopen(name, DP_OREADER, -1))) return FALSE;
- flags = dpgetflags(depot);
- if(!(flags & VL_FLISVILLA)){
- dpclose(depot);
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- return FALSE;
- }
- sprintf(path, "%s%s", name, VL_TMPFSUF);
- omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC;
- if(flags & VL_FLISZLIB){
- omode |= VL_OZCOMP;
- } else if(flags & VL_FLISLZO){
- omode |= VL_OXCOMP;
- } else if(flags & VL_FLISBZIP){
- omode |= VL_OYCOMP;
- }
- if(!(tvilla = vlopen(path, omode, cmp))){
- dpclose(depot);
- return FALSE;
- }
- if(!dpiterinit(depot)) err = TRUE;
- while((kbuf = dpiternext(depot, &ksiz)) != NULL){
- if(ksiz == sizeof(int) && *(int *)kbuf < VL_NODEIDMIN && *(int *)kbuf > 0){
- if((vbuf = dpget(depot, (char *)kbuf, sizeof(int), 0, -1, &vsiz)) != NULL){
- if(_qdbm_inflate && (flags & VL_FLISZLIB) &&
- (zbuf = _qdbm_inflate(vbuf, vsiz, &zsiz, _QDBM_ZMRAW)) != NULL){
- free(vbuf);
- vbuf = zbuf;
- vsiz = zsiz;
- } else if(_qdbm_lzodecode && (flags & VL_FLISLZO) &&
- (zbuf = _qdbm_lzodecode(vbuf, vsiz, &zsiz)) != NULL){
- free(vbuf);
- vbuf = zbuf;
- vsiz = zsiz;
- } else if(_qdbm_bzdecode && (flags & VL_FLISBZIP) &&
- (zbuf = _qdbm_bzdecode(vbuf, vsiz, &zsiz)) != NULL){
- free(vbuf);
- vbuf = zbuf;
- vsiz = zsiz;
- }
- rp = vbuf;
- size = vsiz;
- if(size >= 1){
- VL_READVNUMBUF(rp, size, vnum, step);
- rp += step;
- size -= step;
- }
- if(size >= 1){
- VL_READVNUMBUF(rp, size, vnum, step);
- rp += step;
- size -= step;
- }
- while(size >= 1){
- VL_READVNUMBUF(rp, size, tksiz, step);
- rp += step;
- size -= step;
- if(size < tksiz) break;
- tkbuf = rp;
- rp += tksiz;
- size -= tksiz;
- if(size < 1) break;
- VL_READVNUMBUF(rp, size, vnum, step);
- rp += step;
- size -= step;
- if(vnum < 1 || size < 1) break;
- for(i = 0; i < vnum && size >= 1; i++){
- VL_READVNUMBUF(rp, size, tvsiz, step);
- rp += step;
- size -= step;
- if(size < tvsiz) break;
- tvbuf = rp;
- rp += tvsiz;
- size -= tvsiz;
- if(!vlput(tvilla, tkbuf, tksiz, tvbuf, tvsiz, VL_DDUP)) err = TRUE;
- }
- }
- free(vbuf);
- }
- }
- free(kbuf);
- }
- if(!vlclose(tvilla)) err = TRUE;
- if(!dpclose(depot)) err = TRUE;
- if(!dpremove(name)) err = TRUE;
- if(rename(path, name) == -1){
- if(!err) dpecodeset(DP_EMISC, __FILE__, __LINE__);
- err = TRUE;
- }
- return err ? FALSE : TRUE;
-}
-
-
-/* Dump all records as endian independent data. */
-int vlexportdb(VILLA *villa, const char *name){
- DEPOT *depot;
- char path[VL_PATHBUFSIZ], *kbuf, *vbuf, *nkey;
- int i, err, ksiz, vsiz, ki;
- assert(villa && name);
- sprintf(path, "%s%s", name, VL_TMPFSUF);
- if(!(depot = dpopen(path, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1))) return FALSE;
- err = FALSE;
- vlcurfirst(villa);
- for(i = 0; !err && (kbuf = vlcurkey(villa, &ksiz)) != NULL; i++){
- if((vbuf = vlcurval(villa, &vsiz)) != NULL){
- CB_MALLOC(nkey, ksiz + VL_NUMBUFSIZ);
- ki = sprintf(nkey, "%X\t", i);
- memcpy(nkey + ki, kbuf, ksiz);
- if(!dpput(depot, nkey, ki + ksiz, vbuf, vsiz, DP_DKEEP)) err = TRUE;
- free(nkey);
- free(vbuf);
- } else {
- err = TRUE;
- }
- free(kbuf);
- vlcurnext(villa);
- }
- if(!dpexportdb(depot, name)) err = TRUE;
- if(!dpclose(depot)) err = TRUE;
- if(!dpremove(path)) err = TRUE;
- return !err && !vlfatalerror(villa);
-}
-
-
-/* Load all records from endian independent data. */
-int vlimportdb(VILLA *villa, const char *name){
- DEPOT *depot;
- char path[VL_PATHBUFSIZ], *kbuf, *vbuf, *rp;
- int err, ksiz, vsiz;
- assert(villa && name);
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- if(vlrnum(villa) > 0){
- dpecodeset(DP_EMISC, __FILE__, __LINE__);
- return FALSE;
- }
- kbuf = dpname(villa->depot);
- sprintf(path, "%s%s", kbuf, VL_TMPFSUF);
- free(kbuf);
- if(!(depot = dpopen(path, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1))) return FALSE;
- err = FALSE;
- if(!dpimportdb(depot, name)) err = TRUE;
- dpiterinit(depot);
- while(!err && (kbuf = dpiternext(depot, &ksiz)) != NULL){
- if((vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){
- if((rp = strchr(kbuf, '\t')) != NULL){
- rp++;
- if(!vlput(villa, rp, ksiz - (rp - kbuf), vbuf, vsiz, VL_DDUP)) err = TRUE;
- } else {
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- err = TRUE;
- }
- free(vbuf);
- } else {
- err = TRUE;
- }
- free(kbuf);
- }
- if(!dpclose(depot)) err = TRUE;
- if(!dpremove(path)) err = TRUE;
- return !err && !vlfatalerror(villa);
-}
-
-
-
-/*************************************************************************************************
- * features for experts
- *************************************************************************************************/
-
-
-/* Number of division of the database for Vista. */
-int *vlcrdnumptr(void){
- static int defvlcrdnum = VL_CRDNUM;
- void *ptr;
- if(_qdbm_ptsafe){
- if(!(ptr = _qdbm_settsd(&defvlcrdnum, sizeof(int), &defvlcrdnum))){
- defvlcrdnum = DP_EMISC;
- return &defvlcrdnum;
- }
- return (int *)ptr;
- }
- return &defvlcrdnum;
-}
-
-
-/* Synchronize updating contents on memory. */
-int vlmemsync(VILLA *villa){
- int err, pid;
- const char *tmp;
- assert(villa);
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- if(villa->tran){
- dpecodeset(DP_EMISC, __FILE__, __LINE__);
- return FALSE;
- }
- err = FALSE;
- cbmapiterinit(villa->leafc);
- while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){
- pid = *(int *)tmp;
- if(!vlleafcacheout(villa, pid)) err = TRUE;
- }
- cbmapiterinit(villa->nodec);
- while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){
- pid = *(int *)tmp;
- if(!vlnodecacheout(villa, pid)) err = TRUE;
- }
- if(!dpsetalign(villa->depot, 0)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE;
- if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE;
- if(!dpmemsync(villa->depot)) err = TRUE;
- return err ? FALSE : TRUE;
-}
-
-
-/* Synchronize updating contents on memory, not physically. */
-int vlmemflush(VILLA *villa){
- int err, pid;
- const char *tmp;
- assert(villa);
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- if(villa->tran){
- dpecodeset(DP_EMISC, __FILE__, __LINE__);
- return FALSE;
- }
- err = FALSE;
- cbmapiterinit(villa->leafc);
- while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){
- pid = *(int *)tmp;
- if(!vlleafcacheout(villa, pid)) err = TRUE;
- }
- cbmapiterinit(villa->nodec);
- while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){
- pid = *(int *)tmp;
- if(!vlnodecacheout(villa, pid)) err = TRUE;
- }
- if(!dpsetalign(villa->depot, 0)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE;
- if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE;
- if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE;
- if(!dpmemflush(villa->depot)) err = TRUE;
- return err ? FALSE : TRUE;
-}
-
-
-/* Refer to a volatile cache of a value of a record. */
-const char *vlgetcache(VILLA *villa, const char *kbuf, int ksiz, int *sp){
- VLLEAF *leaf;
- VLREC *recp;
- int pid;
- assert(villa && kbuf);
- if(ksiz < 0) ksiz = strlen(kbuf);
- if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){
- if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL;
- if(!(leaf = vlleafload(villa, pid))) return NULL;
- }
- if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return NULL;
- }
- if(!villa->tran && !vlcacheadjust(villa)) return NULL;
- if(sp) *sp = CB_DATUMSIZE(recp->first);
- return CB_DATUMPTR(recp->first);
-}
-
-
-/* Refer to volatile cache of the key of the record where the cursor is. */
-const char *vlcurkeycache(VILLA *villa, int *sp){
- VLLEAF *leaf;
- VLREC *recp;
- const char *kbuf;
- int ksiz;
- assert(villa);
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum);
- kbuf = CB_DATUMPTR(recp->key);
- ksiz = CB_DATUMSIZE(recp->key);
- if(sp) *sp = ksiz;
- return kbuf;
-}
-
-
-/* Refer to volatile cache of the value of the record where the cursor is. */
-const char *vlcurvalcache(VILLA *villa, int *sp){
- VLLEAF *leaf;
- VLREC *recp;
- const char *vbuf;
- int vsiz;
- assert(villa);
- if(villa->curleaf == -1){
- dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
- return FALSE;
- }
- if(!(leaf = vlleafload(villa, villa->curleaf))){
- villa->curleaf = -1;
- return FALSE;
- }
- recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum);
- if(villa->curvnum < 1){
- vbuf = CB_DATUMPTR(recp->first);
- vsiz = CB_DATUMSIZE(recp->first);
- } else {
- vbuf = CB_LISTVAL2(recp->rest, villa->curvnum - 1, vsiz);
- }
- if(sp) *sp = vsiz;
- return vbuf;
-}
-
-
-/* Get a multiple cursor handle. */
-VLMULCUR *vlmulcuropen(VILLA *villa){
- VLMULCUR *mulcur;
- assert(villa);
- if(villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return NULL;
- }
- CB_MALLOC(mulcur, sizeof(VLMULCUR));
- mulcur->villa = villa;
- mulcur->curleaf = -1;
- mulcur->curknum = -1;
- mulcur->curvnum = -1;
- return mulcur;
-}
-
-
-/* Close a multiple cursor handle. */
-void vlmulcurclose(VLMULCUR *mulcur){
- assert(mulcur);
- free(mulcur);
-}
-
-
-/* Move a multiple cursor to the first record. */
-int vlmulcurfirst(VLMULCUR *mulcur){
- VLMULCUR swap;
- int rv;
- assert(mulcur);
- swap.curleaf = mulcur->villa->curleaf;
- swap.curknum = mulcur->villa->curknum;
- swap.curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = mulcur->curleaf;
- mulcur->villa->curknum = mulcur->curknum;
- mulcur->villa->curvnum = mulcur->curvnum;
- rv = vlcurfirst(mulcur->villa);
- mulcur->curleaf = mulcur->villa->curleaf;
- mulcur->curknum = mulcur->villa->curknum;
- mulcur->curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = swap.curleaf;
- mulcur->villa->curknum = swap.curknum;
- mulcur->villa->curvnum = swap.curvnum;
- return rv;
-}
-
-
-/* Move a multiple cursor to the last record. */
-int vlmulcurlast(VLMULCUR *mulcur){
- VLMULCUR swap;
- int rv;
- assert(mulcur);
- swap.curleaf = mulcur->villa->curleaf;
- swap.curknum = mulcur->villa->curknum;
- swap.curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = mulcur->curleaf;
- mulcur->villa->curknum = mulcur->curknum;
- mulcur->villa->curvnum = mulcur->curvnum;
- rv = vlcurlast(mulcur->villa);
- mulcur->curleaf = mulcur->villa->curleaf;
- mulcur->curknum = mulcur->villa->curknum;
- mulcur->curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = swap.curleaf;
- mulcur->villa->curknum = swap.curknum;
- mulcur->villa->curvnum = swap.curvnum;
- return rv;
-}
-
-
-/* Move a multiple cursor to the previous record. */
-int vlmulcurprev(VLMULCUR *mulcur){
- VLMULCUR swap;
- int rv;
- assert(mulcur);
- swap.curleaf = mulcur->villa->curleaf;
- swap.curknum = mulcur->villa->curknum;
- swap.curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = mulcur->curleaf;
- mulcur->villa->curknum = mulcur->curknum;
- mulcur->villa->curvnum = mulcur->curvnum;
- rv = vlcurprev(mulcur->villa);
- mulcur->curleaf = mulcur->villa->curleaf;
- mulcur->curknum = mulcur->villa->curknum;
- mulcur->curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = swap.curleaf;
- mulcur->villa->curknum = swap.curknum;
- mulcur->villa->curvnum = swap.curvnum;
- return rv;
-}
-
-
-/* Move a multiple cursor to the next record. */
-int vlmulcurnext(VLMULCUR *mulcur){
- VLMULCUR swap;
- int rv;
- assert(mulcur);
- swap.curleaf = mulcur->villa->curleaf;
- swap.curknum = mulcur->villa->curknum;
- swap.curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = mulcur->curleaf;
- mulcur->villa->curknum = mulcur->curknum;
- mulcur->villa->curvnum = mulcur->curvnum;
- rv = vlcurnext(mulcur->villa);
- mulcur->curleaf = mulcur->villa->curleaf;
- mulcur->curknum = mulcur->villa->curknum;
- mulcur->curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = swap.curleaf;
- mulcur->villa->curknum = swap.curknum;
- mulcur->villa->curvnum = swap.curvnum;
- return rv;
-}
-
-
-/* Move a multiple cursor to a position around a record. */
-int vlmulcurjump(VLMULCUR *mulcur, const char *kbuf, int ksiz, int jmode){
- VLMULCUR swap;
- int rv;
- assert(mulcur);
- swap.curleaf = mulcur->villa->curleaf;
- swap.curknum = mulcur->villa->curknum;
- swap.curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = mulcur->curleaf;
- mulcur->villa->curknum = mulcur->curknum;
- mulcur->villa->curvnum = mulcur->curvnum;
- rv = vlcurjump(mulcur->villa, kbuf, ksiz, jmode);
- mulcur->curleaf = mulcur->villa->curleaf;
- mulcur->curknum = mulcur->villa->curknum;
- mulcur->curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = swap.curleaf;
- mulcur->villa->curknum = swap.curknum;
- mulcur->villa->curvnum = swap.curvnum;
- return rv;
-}
-
-
-/* Get the key of the record where a multiple cursor is. */
-char *vlmulcurkey(VLMULCUR *mulcur, int *sp){
- VLMULCUR swap;
- char *rv;
- assert(mulcur);
- swap.curleaf = mulcur->villa->curleaf;
- swap.curknum = mulcur->villa->curknum;
- swap.curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = mulcur->curleaf;
- mulcur->villa->curknum = mulcur->curknum;
- mulcur->villa->curvnum = mulcur->curvnum;
- rv = vlcurkey(mulcur->villa, sp);
- mulcur->curleaf = mulcur->villa->curleaf;
- mulcur->curknum = mulcur->villa->curknum;
- mulcur->curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = swap.curleaf;
- mulcur->villa->curknum = swap.curknum;
- mulcur->villa->curvnum = swap.curvnum;
- return rv;
-}
-
-
-/* Get the value of the record where a multiple cursor is. */
-char *vlmulcurval(VLMULCUR *mulcur, int *sp){
- VLMULCUR swap;
- char *rv;
- assert(mulcur);
- swap.curleaf = mulcur->villa->curleaf;
- swap.curknum = mulcur->villa->curknum;
- swap.curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = mulcur->curleaf;
- mulcur->villa->curknum = mulcur->curknum;
- mulcur->villa->curvnum = mulcur->curvnum;
- rv = vlcurval(mulcur->villa, sp);
- mulcur->curleaf = mulcur->villa->curleaf;
- mulcur->curknum = mulcur->villa->curknum;
- mulcur->curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = swap.curleaf;
- mulcur->villa->curknum = swap.curknum;
- mulcur->villa->curvnum = swap.curvnum;
- return rv;
-}
-
-
-/* Refer to volatile cache of the key of the record where a multiple cursor is. */
-const char *vlmulcurkeycache(VLMULCUR *mulcur, int *sp){
- VLMULCUR swap;
- const char *rv;
- assert(mulcur);
- swap.curleaf = mulcur->villa->curleaf;
- swap.curknum = mulcur->villa->curknum;
- swap.curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = mulcur->curleaf;
- mulcur->villa->curknum = mulcur->curknum;
- mulcur->villa->curvnum = mulcur->curvnum;
- rv = vlcurkeycache(mulcur->villa, sp);
- mulcur->curleaf = mulcur->villa->curleaf;
- mulcur->curknum = mulcur->villa->curknum;
- mulcur->curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = swap.curleaf;
- mulcur->villa->curknum = swap.curknum;
- mulcur->villa->curvnum = swap.curvnum;
- return rv;
-}
-
-
-/* Refer to volatile cache of the value of the record where a multiple cursor is. */
-const char *vlmulcurvalcache(VLMULCUR *mulcur, int *sp){
- VLMULCUR swap;
- const char *rv;
- assert(mulcur);
- swap.curleaf = mulcur->villa->curleaf;
- swap.curknum = mulcur->villa->curknum;
- swap.curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = mulcur->curleaf;
- mulcur->villa->curknum = mulcur->curknum;
- mulcur->villa->curvnum = mulcur->curvnum;
- rv = vlcurvalcache(mulcur->villa, sp);
- mulcur->curleaf = mulcur->villa->curleaf;
- mulcur->curknum = mulcur->villa->curknum;
- mulcur->curvnum = mulcur->villa->curvnum;
- mulcur->villa->curleaf = swap.curleaf;
- mulcur->villa->curknum = swap.curknum;
- mulcur->villa->curvnum = swap.curvnum;
- return rv;
-}
-
-
-
-/*************************************************************************************************
- * private objects
- *************************************************************************************************/
-
-
-/* Compare keys of two records by lexical order.
- `aptr' specifies the pointer to the region of one key.
- `asiz' specifies the size of the region of one key.
- `bptr' specifies the pointer to the region of the other key.
- `bsiz' specifies the size of the region of the other key.
- The return value is positive if the former is big, negative if the latter is big, 0 if both
- are equivalent. */
-static int vllexcompare(const char *aptr, int asiz, const char *bptr, int bsiz){
- int i, min;
- assert(aptr && asiz >= 0 && bptr && bsiz >= 0);
- min = asiz < bsiz ? asiz : bsiz;
- for(i = 0; i < min; i++){
- if(((unsigned char *)aptr)[i] != ((unsigned char *)bptr)[i])
- return ((unsigned char *)aptr)[i] - ((unsigned char *)bptr)[i];
- }
- if(asiz == bsiz) return 0;
- return asiz - bsiz;
-}
-
-
-/* Compare keys of two records as native integers.
- `aptr' specifies the pointer to the region of one key.
- `asiz' specifies the size of the region of one key.
- `bptr' specifies the pointer to the region of the other key.
- `bsiz' specifies the size of the region of the other key.
- The return value is positive if the former is big, negative if the latter is big, 0 if both
- are equivalent. */
-static int vlintcompare(const char *aptr, int asiz, const char *bptr, int bsiz){
- int anum, bnum;
- assert(aptr && asiz >= 0 && bptr && bsiz >= 0);
- if(asiz != bsiz) return asiz - bsiz;
- anum = (asiz == sizeof(int) ? *(int *)aptr : INT_MIN);
- bnum = (bsiz == sizeof(int) ? *(int *)bptr : INT_MIN);
- return anum - bnum;
-}
-
-
-/* Compare keys of two records as numbers of big endian.
- `aptr' specifies the pointer to the region of one key.
- `asiz' specifies the size of the region of one key.
- `bptr' specifies the pointer to the region of the other key.
- `bsiz' specifies the size of the region of the other key.
- The return value is positive if the former is big, negative if the latter is big, 0 if both
- are equivalent. */
-static int vlnumcompare(const char *aptr, int asiz, const char *bptr, int bsiz){
- int i;
- assert(aptr && asiz >= 0 && bptr && bsiz >= 0);
- if(asiz != bsiz) return asiz - bsiz;
- for(i = 0; i < asiz; i++){
- if(aptr[i] != bptr[i]) return aptr[i] - bptr[i];
- }
- return 0;
-}
-
-
-/* Compare keys of two records as numeric strings of octal, decimal or hexadecimal.
- `aptr' specifies the pointer to the region of one key.
- `asiz' specifies the size of the region of one key.
- `bptr' specifies the pointer to the region of the other key.
- `bsiz' specifies the size of the region of the other key.
- The return value is positive if the former is big, negative if the latter is big, 0 if both
- are equivalent. */
-static int vldeccompare(const char *aptr, int asiz, const char *bptr, int bsiz){
- assert(aptr && asiz >= 0 && bptr && bsiz >= 0);
- return (int)(strtod(aptr, NULL) - strtod(bptr, NULL));
-}
-
-
-/* Store a record composed of a pair of integers.
- `depot' specifies an internal database handle.
- `knum' specifies an integer of the key.
- `vnum' specifies an integer of the value.
- The return value is true if successful, else, it is false. */
-static int vldpputnum(DEPOT *depot, int knum, int vnum){
- assert(depot);
- return dpput(depot, (char *)&knum, sizeof(int), (char *)&vnum, sizeof(int), DP_DOVER);
-}
-
-
-/* Retrieve a record composed of a pair of integers.
- `depot' specifies an internal database handle.
- `knum' specifies an integer of the key.
- `vip' specifies the pointer to a variable to assign the result to.
- The return value is true if successful, else, it is false. */
-static int vldpgetnum(DEPOT *depot, int knum, int *vnp){
- char *vbuf;
- int vsiz;
- assert(depot && vnp);
- vbuf = dpget(depot, (char *)&knum, sizeof(int), 0, -1, &vsiz);
- if(!vbuf || vsiz != sizeof(int)){
- free(vbuf);
- return FALSE;
- }
- *vnp = *(int *)vbuf;
- free(vbuf);
- return TRUE;
-}
-
-
-/* Create a new leaf.
- `villa' specifies a database handle.
- `prev' specifies the ID number of the previous leaf.
- `next' specifies the ID number of the previous leaf.
- The return value is a handle of the leaf. */
-static VLLEAF *vlleafnew(VILLA *villa, int prev, int next){
- VLLEAF lent;
- assert(villa);
- lent.id = villa->lnum + VL_LEAFIDMIN;
- lent.dirty = TRUE;
- CB_LISTOPEN(lent.recs);
- lent.prev = prev;
- lent.next = next;
- villa->lnum++;
- cbmapput(villa->leafc, (char *)&(lent.id), sizeof(int), (char *)&lent, sizeof(VLLEAF), TRUE);
- return (VLLEAF *)cbmapget(villa->leafc, (char *)&(lent.id), sizeof(int), NULL);
-}
-
-
-/* Remove a leaf from the cache.
- `villa' specifies a database handle.
- `id' specifies the ID number of the leaf.
- The return value is true if successful, else, it is false. */
-static int vlleafcacheout(VILLA *villa, int id){
- VLLEAF *leaf;
- VLREC *recp;
- CBLIST *recs;
- int i, err, ln;
- assert(villa && id >= VL_LEAFIDMIN);
- if(!(leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&id, sizeof(int), NULL))) return FALSE;
- err = FALSE;
- if(leaf->dirty && !vlleafsave(villa, leaf)) err = TRUE;
- recs = leaf->recs;
- ln = CB_LISTNUM(recs);
- for(i = 0; i < ln; i++){
- recp = (VLREC *)CB_LISTVAL(recs, i);
- CB_DATUMCLOSE(recp->key);
- CB_DATUMCLOSE(recp->first);
- if(recp->rest) CB_LISTCLOSE(recp->rest);
- }
- CB_LISTCLOSE(recs);
- cbmapout(villa->leafc, (char *)&id, sizeof(int));
- return err ? FALSE : TRUE;
-}
-
-
-/* Save a leaf into the database.
- `villa' specifies a database handle.
- `leaf' specifies a leaf handle.
- The return value is true if successful, else, it is false. */
-static int vlleafsave(VILLA *villa, VLLEAF *leaf){
- VLREC *recp;
- CBLIST *recs;
- CBDATUM *buf;
- char vnumbuf[VL_VNUMBUFSIZ], *zbuf;
- const char *vbuf;
- int i, j, ksiz, vnum, vsiz, prev, next, vnumsiz, ln, zsiz;
- assert(villa && leaf);
- CB_DATUMOPEN(buf);
- prev = leaf->prev;
- if(prev == -1) prev = VL_NODEIDMIN - 1;
- VL_SETVNUMBUF(vnumsiz, vnumbuf, prev);
- CB_DATUMCAT(buf, vnumbuf, vnumsiz);
- next = leaf->next;
- if(next == -1) next = VL_NODEIDMIN - 1;
- VL_SETVNUMBUF(vnumsiz, vnumbuf, next);
- CB_DATUMCAT(buf, vnumbuf, vnumsiz);
- recs = leaf->recs;
- ln = CB_LISTNUM(recs);
- for(i = 0; i < ln; i++){
- recp = (VLREC *)CB_LISTVAL(recs, i);
- ksiz = CB_DATUMSIZE(recp->key);
- VL_SETVNUMBUF(vnumsiz, vnumbuf, ksiz);
- CB_DATUMCAT(buf, vnumbuf, vnumsiz);
- CB_DATUMCAT(buf, CB_DATUMPTR(recp->key), ksiz);
- vnum = 1 + (recp->rest ? CB_LISTNUM(recp->rest) : 0);
- VL_SETVNUMBUF(vnumsiz, vnumbuf, vnum);
- CB_DATUMCAT(buf, vnumbuf, vnumsiz);
- vsiz = CB_DATUMSIZE(recp->first);
- VL_SETVNUMBUF(vnumsiz, vnumbuf, vsiz);
- CB_DATUMCAT(buf, vnumbuf, vnumsiz);
- CB_DATUMCAT(buf, CB_DATUMPTR(recp->first), vsiz);
- if(recp->rest){
- for(j = 0; j < CB_LISTNUM(recp->rest); j++){
- vbuf = CB_LISTVAL2(recp->rest, j, vsiz);
- VL_SETVNUMBUF(vnumsiz, vnumbuf, vsiz);
- CB_DATUMCAT(buf, vnumbuf, vnumsiz);
- CB_DATUMCAT(buf, vbuf, vsiz);
- }
- }
- }
- if(_qdbm_deflate && villa->cmode == VL_OZCOMP){
- if(!(zbuf = _qdbm_deflate(CB_DATUMPTR(buf), CB_DATUMSIZE(buf), &zsiz, _QDBM_ZMRAW))){
- CB_DATUMCLOSE(buf);
- dpecodeset(DP_EMISC, __FILE__, __LINE__);
- return FALSE;
- }
- if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), zbuf, zsiz, DP_DOVER)){
- CB_DATUMCLOSE(buf);
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- return FALSE;
- }
- free(zbuf);
- } else if(_qdbm_lzoencode && villa->cmode == VL_OYCOMP){
- if(!(zbuf = _qdbm_lzoencode(CB_DATUMPTR(buf), CB_DATUMSIZE(buf), &zsiz))){
- CB_DATUMCLOSE(buf);
- dpecodeset(DP_EMISC, __FILE__, __LINE__);
- return FALSE;
- }
- if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), zbuf, zsiz, DP_DOVER)){
- CB_DATUMCLOSE(buf);
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- return FALSE;
- }
- free(zbuf);
- } else if(_qdbm_bzencode && villa->cmode == VL_OXCOMP){
- if(!(zbuf = _qdbm_bzencode(CB_DATUMPTR(buf), CB_DATUMSIZE(buf), &zsiz))){
- CB_DATUMCLOSE(buf);
- dpecodeset(DP_EMISC, __FILE__, __LINE__);
- return FALSE;
- }
- if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), zbuf, zsiz, DP_DOVER)){
- CB_DATUMCLOSE(buf);
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- return FALSE;
- }
- free(zbuf);
- } else {
- if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int),
- CB_DATUMPTR(buf), CB_DATUMSIZE(buf), DP_DOVER)){
- CB_DATUMCLOSE(buf);
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- return FALSE;
- }
- }
- CB_DATUMCLOSE(buf);
- leaf->dirty = FALSE;
- return TRUE;
-}
-
-
-/* Load a leaf from the database.
- `villa' specifies a database handle.
- `id' specifies the ID number of the leaf.
- If successful, the return value is the pointer to the leaf, else, it is `NULL'. */
-static VLLEAF *vlleafload(VILLA *villa, int id){
- char wbuf[VL_PAGEBUFSIZ], *buf, *rp, *kbuf, *vbuf, *zbuf;
- int i, size, step, ksiz, vnum, vsiz, prev, next, zsiz;
- VLLEAF *leaf, lent;
- VLREC rec;
- assert(villa && id >= VL_LEAFIDMIN);
- if((leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&id, sizeof(int), NULL)) != NULL){
- cbmapmove(villa->leafc, (char *)&id, sizeof(int), FALSE);
- return leaf;
- }
- ksiz = -1;
- prev = -1;
- next = -1;
- if((size = dpgetwb(villa->depot, (char *)&id, sizeof(int), 0, VL_PAGEBUFSIZ, wbuf)) > 0 &&
- size < VL_PAGEBUFSIZ){
- buf = NULL;
- } else if(!(buf = dpget(villa->depot, (char *)&id, sizeof(int), 0, -1, &size))){
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- return NULL;
- }
- if(_qdbm_inflate && villa->cmode == VL_OZCOMP){
- if(!(zbuf = _qdbm_inflate(buf ? buf : wbuf, size, &zsiz, _QDBM_ZMRAW))){
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- free(buf);
- return NULL;
- }
- free(buf);
- buf = zbuf;
- size = zsiz;
- } else if(_qdbm_lzodecode && villa->cmode == VL_OYCOMP){
- if(!(zbuf = _qdbm_lzodecode(buf ? buf : wbuf, size, &zsiz))){
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- free(buf);
- return NULL;
- }
- free(buf);
- buf = zbuf;
- size = zsiz;
- } else if(_qdbm_bzdecode && villa->cmode == VL_OXCOMP){
- if(!(zbuf = _qdbm_bzdecode(buf ? buf : wbuf, size, &zsiz))){
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- free(buf);
- return NULL;
- }
- free(buf);
- buf = zbuf;
- size = zsiz;
- }
- rp = buf ? buf : wbuf;
- if(size >= 1){
- VL_READVNUMBUF(rp, size, prev, step);
- rp += step;
- size -= step;
- if(prev >= VL_NODEIDMIN - 1) prev = -1;
- }
- if(size >= 1){
- VL_READVNUMBUF(rp, size, next, step);
- rp += step;
- size -= step;
- if(next >= VL_NODEIDMIN - 1) next = -1;
- }
- lent.id = id;
- lent.dirty = FALSE;
- CB_LISTOPEN(lent.recs);
- lent.prev = prev;
- lent.next = next;
- while(size >= 1){
- VL_READVNUMBUF(rp, size, ksiz, step);
- rp += step;
- size -= step;
- if(size < ksiz) break;
- kbuf = rp;
- rp += ksiz;
- size -= ksiz;
- VL_READVNUMBUF(rp, size, vnum, step);
- rp += step;
- size -= step;
- if(vnum < 1 || size < 1) break;
- for(i = 0; i < vnum && size >= 1; i++){
- VL_READVNUMBUF(rp, size, vsiz, step);
- rp += step;
- size -= step;
- if(size < vsiz) break;
- vbuf = rp;
- rp += vsiz;
- size -= vsiz;
- if(i < 1){
- CB_DATUMOPEN2(rec.key, kbuf, ksiz);
- CB_DATUMOPEN2(rec.first, vbuf, vsiz);
- rec.rest = NULL;
- } else {
- if(!rec.rest) CB_LISTOPEN(rec.rest);
- CB_LISTPUSH(rec.rest, vbuf, vsiz);
- }
- }
- if(i > 0) CB_LISTPUSH(lent.recs, (char *)&rec, sizeof(VLREC));
- }
- free(buf);
- cbmapput(villa->leafc, (char *)&(lent.id), sizeof(int), (char *)&lent, sizeof(VLLEAF), TRUE);
- return (VLLEAF *)cbmapget(villa->leafc, (char *)&(lent.id), sizeof(int), NULL);
-}
-
-
-/* Load the historical leaf from the database.
- `villa' specifies a database handle.
- `kbuf' specifies the pointer to the region of a key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is the pointer to the leaf, else, it is `NULL'. */
-static VLLEAF *vlgethistleaf(VILLA *villa, const char *kbuf, int ksiz){
- VLLEAF *leaf;
- VLREC *recp;
- int ln, rv;
- assert(villa && kbuf && ksiz >= 0);
- if(!(leaf = vlleafload(villa, villa->hleaf))) return NULL;
- if((ln = CB_LISTNUM(leaf->recs)) < 2) return NULL;
- recp = (VLREC *)CB_LISTVAL(leaf->recs, 0);
- rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key));
- if(rv == 0) return leaf;
- if(rv < 0) return NULL;
- recp = (VLREC *)CB_LISTVAL(leaf->recs, ln - 1);
- rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key));
- if(rv <= 0 || leaf->next < VL_LEAFIDMIN) return leaf;
- return NULL;
-}
-
-
-/* Add a record to a leaf.
- `villa' specifies a database handle.
- `leaf' specifies a leaf handle.
- `dmode' specifies behavior when the key overlaps.
- `kbuf' specifies the pointer to the region of a key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of a value.
- `vsiz' specifies the size of the region of the value.
- The return value is true if successful, else, it is false. */
-static int vlleafaddrec(VILLA *villa, VLLEAF *leaf, int dmode,
- const char *kbuf, int ksiz, const char *vbuf, int vsiz){
- VLREC *recp, rec;
- CBLIST *recs;
- int i, rv, left, right, ln, tsiz;
- char *tbuf;
- assert(villa && leaf && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- left = 0;
- recs = leaf->recs;
- ln = CB_LISTNUM(recs);
- right = ln;
- i = (left + right) / 2;
- while(right >= left && i < ln){
- recp = (VLREC *)CB_LISTVAL(recs, i);
- rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key));
- if(rv == 0){
- break;
- } else if(rv <= 0){
- right = i - 1;
- } else {
- left = i + 1;
- }
- i = (left + right) / 2;
- }
- while(i < ln){
- recp = (VLREC *)CB_LISTVAL(recs, i);
- rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key));
- if(rv == 0){
- switch(dmode){
- case VL_DKEEP:
- return FALSE;
- case VL_DCAT:
- CB_DATUMCAT(recp->first, vbuf, vsiz);
- break;
- case VL_DDUP:
- if(!recp->rest) CB_LISTOPEN(recp->rest);
- CB_LISTPUSH(recp->rest, vbuf, vsiz);
- villa->rnum++;
- break;
- case VL_DDUPR:
- if(!recp->rest){
- CB_DATUMTOMALLOC(recp->first, tbuf, tsiz);
- CB_DATUMOPEN2(recp->first, vbuf, vsiz);
- CB_LISTOPEN(recp->rest);
- CB_LISTPUSHBUF(recp->rest, tbuf, tsiz);
- } else {
- cblistunshift(recp->rest, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first));
- CB_DATUMSETSIZE(recp->first, 0);
- CB_DATUMCAT(recp->first, vbuf, vsiz);
- }
- villa->rnum++;
- break;
- default:
- CB_DATUMSETSIZE(recp->first, 0);
- CB_DATUMCAT(recp->first, vbuf, vsiz);
- break;
- }
- break;
- } else if(rv < 0){
- CB_DATUMOPEN2(rec.key, kbuf, ksiz);
- CB_DATUMOPEN2(rec.first, vbuf, vsiz);
- rec.rest = NULL;
- CB_LISTINSERT(recs, i, (char *)&rec, sizeof(VLREC));
- villa->rnum++;
- break;
- }
- i++;
- }
- if(i >= ln){
- CB_DATUMOPEN2(rec.key, kbuf, ksiz);
- CB_DATUMOPEN2(rec.first, vbuf, vsiz);
- rec.rest = NULL;
- CB_LISTPUSH(recs, (char *)&rec, sizeof(VLREC));
- villa->rnum++;
- }
- leaf->dirty = TRUE;
- return TRUE;
-}
-
-
-/* Calculate the size of data of a leaf.
- `leaf' specifies a leaf handle.
- The return value is size of data of the leaf. */
-static int vlleafdatasize(VLLEAF *leaf){
- VLREC *recp;
- CBLIST *recs, *rest;
- const char *vbuf;
- int i, j, sum, rnum, restnum, vsiz;
- assert(leaf);
- sum = 0;
- recs = leaf->recs;
- rnum = CB_LISTNUM(recs);
- for(i = 0; i < rnum; i++){
- recp = (VLREC *)CB_LISTVAL(recs, i);
- sum += CB_DATUMSIZE(recp->key);
- sum += CB_DATUMSIZE(recp->first);
- if(recp->rest){
- rest = recp->rest;
- restnum = CB_LISTNUM(rest);
- for(j = 0; j < restnum; j++){
- vbuf = CB_LISTVAL2(rest, j, vsiz);
- sum += vsiz;
- }
- }
- }
- return sum;
-}
-
-
-/* Divide a leaf into two.
- `villa' specifies a database handle.
- `leaf' specifies a leaf handle.
- The return value is the handle of a new leaf, or `NULL' on failure. */
-static VLLEAF *vlleafdivide(VILLA *villa, VLLEAF *leaf){
- VLLEAF *newleaf, *nextleaf;
- VLREC *recp;
- CBLIST *recs, *newrecs;
- int i, mid, ln;
- assert(villa && leaf);
- villa->hleaf = -1;
- recs = leaf->recs;
- mid = CB_LISTNUM(recs) / 2;
- recp = (VLREC *)CB_LISTVAL(recs, mid);
- newleaf = vlleafnew(villa, leaf->id, leaf->next);
- if(newleaf->next != -1){
- if(!(nextleaf = vlleafload(villa, newleaf->next))) return NULL;
- nextleaf->prev = newleaf->id;
- nextleaf->dirty = TRUE;
- }
- leaf->next = newleaf->id;
- leaf->dirty = TRUE;
- ln = CB_LISTNUM(recs);
- newrecs = newleaf->recs;
- for(i = mid; i < ln; i++){
- recp = (VLREC *)CB_LISTVAL(recs, i);
- CB_LISTPUSH(newrecs, (char *)recp, sizeof(VLREC));
- }
- ln = CB_LISTNUM(newrecs);
- for(i = 0; i < ln; i++){
- CB_LISTDROP(recs);
- }
- return newleaf;
-}
-
-
-/* Create a new node.
- `villa' specifies a database handle.
- `heir' specifies the ID of the child before the first index.
- The return value is a handle of the node. */
-static VLNODE *vlnodenew(VILLA *villa, int heir){
- VLNODE nent;
- assert(villa && heir >= VL_LEAFIDMIN);
- nent.id = villa->nnum + VL_NODEIDMIN;
- nent.dirty = TRUE;
- nent.heir = heir;
- CB_LISTOPEN(nent.idxs);
- villa->nnum++;
- cbmapput(villa->nodec, (char *)&(nent.id), sizeof(int), (char *)&nent, sizeof(VLNODE), TRUE);
- return (VLNODE *)cbmapget(villa->nodec, (char *)&(nent.id), sizeof(int), NULL);
-}
-
-
-/* Remove a node from the cache.
- `villa' specifies a database handle.
- `id' specifies the ID number of the node.
- The return value is true if successful, else, it is false. */
-static int vlnodecacheout(VILLA *villa, int id){
- VLNODE *node;
- VLIDX *idxp;
- int i, err, ln;
- assert(villa && id >= VL_NODEIDMIN);
- if(!(node = (VLNODE *)cbmapget(villa->nodec, (char *)&id, sizeof(int), NULL))) return FALSE;
- err = FALSE;
- if(node->dirty && !vlnodesave(villa, node)) err = TRUE;
- ln = CB_LISTNUM(node->idxs);
- for(i = 0; i < ln; i++){
- idxp = (VLIDX *)CB_LISTVAL(node->idxs, i);
- CB_DATUMCLOSE(idxp->key);
- }
- CB_LISTCLOSE(node->idxs);
- cbmapout(villa->nodec, (char *)&id, sizeof(int));
- return err ? FALSE : TRUE;
-}
-
-
-/* Save a node into the database.
- `villa' specifies a database handle.
- `node' specifies a node handle.
- The return value is true if successful, else, it is false. */
-static int vlnodesave(VILLA *villa, VLNODE *node){
- CBDATUM *buf;
- char vnumbuf[VL_VNUMBUFSIZ];
- VLIDX *idxp;
- int i, heir, pid, ksiz, vnumsiz, ln;
- assert(villa && node);
- CB_DATUMOPEN(buf);
- heir = node->heir;
- VL_SETVNUMBUF(vnumsiz, vnumbuf, heir);
- CB_DATUMCAT(buf, vnumbuf, vnumsiz);
- ln = CB_LISTNUM(node->idxs);
- for(i = 0; i < ln; i++){
- idxp = (VLIDX *)CB_LISTVAL(node->idxs, i);
- pid = idxp->pid;
- VL_SETVNUMBUF(vnumsiz, vnumbuf, pid);
- CB_DATUMCAT(buf, vnumbuf, vnumsiz);
- ksiz = CB_DATUMSIZE(idxp->key);
- VL_SETVNUMBUF(vnumsiz, vnumbuf, ksiz);
- CB_DATUMCAT(buf, vnumbuf, vnumsiz);
- CB_DATUMCAT(buf, CB_DATUMPTR(idxp->key), ksiz);
- }
- if(!dpput(villa->depot, (char *)&(node->id), sizeof(int),
- CB_DATUMPTR(buf), CB_DATUMSIZE(buf), DP_DOVER)){
- CB_DATUMCLOSE(buf);
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- return FALSE;
- }
- CB_DATUMCLOSE(buf);
- node->dirty = FALSE;
- return TRUE;
-}
-
-
-/* Load a node from the database.
- `villa' specifies a database handle.
- `id' specifies the ID number of the node.
- If successful, the return value is the pointer to the node, else, it is `NULL'. */
-static VLNODE *vlnodeload(VILLA *villa, int id){
- char wbuf[VL_PAGEBUFSIZ], *buf, *rp, *kbuf;
- int size, step, heir, pid, ksiz;
- VLNODE *node, nent;
- VLIDX idx;
- assert(villa && id >= VL_NODEIDMIN);
- if((node = (VLNODE *)cbmapget(villa->nodec, (char *)&id, sizeof(int), NULL)) != NULL){
- cbmapmove(villa->nodec, (char *)&id, sizeof(int), FALSE);
- return node;
- }
- heir = -1;
- if((size = dpgetwb(villa->depot, (char *)&id, sizeof(int), 0, VL_PAGEBUFSIZ, wbuf)) > 0 &&
- size < VL_PAGEBUFSIZ){
- buf = NULL;
- } else if(!(buf = dpget(villa->depot, (char *)&id, sizeof(int), 0, -1, &size))){
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- return NULL;
- }
- rp = buf ? buf : wbuf;
- if(size >= 1){
- VL_READVNUMBUF(rp, size, heir, step);
- rp += step;
- size -= step;
- }
- if(heir < 0){
- free(buf);
- return NULL;
- }
- nent.id = id;
- nent.dirty = FALSE;
- nent.heir = heir;
- CB_LISTOPEN(nent.idxs);
- while(size >= 1){
- VL_READVNUMBUF(rp, size, pid, step);
- rp += step;
- size -= step;
- if(size < 1) break;
- VL_READVNUMBUF(rp, size, ksiz, step);
- rp += step;
- size -= step;
- if(size < ksiz) break;
- kbuf = rp;
- rp += ksiz;
- size -= ksiz;
- idx.pid = pid;
- CB_DATUMOPEN2(idx.key, kbuf, ksiz);
- CB_LISTPUSH(nent.idxs, (char *)&idx, sizeof(VLIDX));
- }
- free(buf);
- cbmapput(villa->nodec, (char *)&(nent.id), sizeof(int), (char *)&nent, sizeof(VLNODE), TRUE);
- return (VLNODE *)cbmapget(villa->nodec, (char *)&(nent.id), sizeof(int), NULL);
-}
-
-
-/* Add an index to a node.
- `villa' specifies a database handle.
- `node' specifies a node handle.
- `order' specifies whether the calling sequence is orderd or not.
- `pid' specifies the ID number of referred page.
- `kbuf' specifies the pointer to the region of a key.
- `ksiz' specifies the size of the region of the key. */
-static void vlnodeaddidx(VILLA *villa, VLNODE *node, int order,
- int pid, const char *kbuf, int ksiz){
- VLIDX idx, *idxp;
- int i, rv, left, right, ln;
- assert(villa && node && pid >= VL_LEAFIDMIN && kbuf && ksiz >= 0);
- idx.pid = pid;
- CB_DATUMOPEN2(idx.key, kbuf, ksiz);
- if(order){
- CB_LISTPUSH(node->idxs, (char *)&idx, sizeof(VLIDX));
- } else {
- left = 0;
- right = CB_LISTNUM(node->idxs);
- i = (left + right) / 2;
- ln = CB_LISTNUM(node->idxs);
- while(right >= left && i < ln){
- idxp = (VLIDX *)CB_LISTVAL(node->idxs, i);
- rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key));
- if(rv == 0){
- break;
- } else if(rv <= 0){
- right = i - 1;
- } else {
- left = i + 1;
- }
- i = (left + right) / 2;
- }
- ln = CB_LISTNUM(node->idxs);
- while(i < ln){
- idxp = (VLIDX *)CB_LISTVAL(node->idxs, i);
- if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)) < 0){
- CB_LISTINSERT(node->idxs, i, (char *)&idx, sizeof(VLIDX));
- break;
- }
- i++;
- }
- if(i >= CB_LISTNUM(node->idxs)) CB_LISTPUSH(node->idxs, (char *)&idx, sizeof(VLIDX));
- }
- node->dirty = TRUE;
-}
-
-
-/* Search the leaf corresponding to a key.
- `villa' specifies a database handle.
- `kbuf' specifies the pointer to the region of a key.
- `ksiz' specifies the size of the region of the key.
- The return value is the ID number of the leaf, or -1 on failure. */
-static int vlsearchleaf(VILLA *villa, const char *kbuf, int ksiz){
- VLNODE *node;
- VLIDX *idxp;
- int i, pid, rv, left, right, ln;
- assert(villa && kbuf && ksiz >= 0);
- pid = villa->root;
- idxp = NULL;
- villa->hnum = 0;
- villa->hleaf = -1;
- while(pid >= VL_NODEIDMIN){
- if(!(node = vlnodeload(villa, pid)) || (ln = CB_LISTNUM(node->idxs)) < 1){
- dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
- return -1;
- }
- villa->hist[villa->hnum++] = node->id;
- left = 1;
- right = ln;
- i = (left + right) / 2;
- while(right >= left && i < ln){
- idxp = (VLIDX *)CB_LISTVAL(node->idxs, i);
- rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key));
- if(rv == 0){
- break;
- } else if(rv <= 0){
- right = i - 1;
- } else {
- left = i + 1;
- }
- i = (left + right) / 2;
- }
- if(i > 0) i--;
- while(i < ln){
- idxp = (VLIDX *)CB_LISTVAL(node->idxs, i);
- if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)) < 0){
- if(i == 0){
- pid = node->heir;
- break;
- }
- idxp = (VLIDX *)CB_LISTVAL(node->idxs, i - 1);
- pid = idxp->pid;
- break;
- }
- i++;
- }
- if(i >= ln) pid = idxp->pid;
- }
- if(villa->lleaf == pid) villa->hleaf = pid;
- villa->lleaf = pid;
- return pid;
-}
-
-
-/* Adjust the caches for leaves and nodes.
- `villa' specifies a database handle.
- The return value is true if successful, else, it is false. */
-static int vlcacheadjust(VILLA *villa){
- const char *tmp;
- int i, pid, err;
- err = FALSE;
- if(cbmaprnum(villa->leafc) > villa->leafcnum){
- cbmapiterinit(villa->leafc);
- for(i = 0; i < VL_CACHEOUT; i++){
- tmp = cbmapiternext(villa->leafc, NULL);
- pid = *(int *)tmp;
- if(!vlleafcacheout(villa, pid)) err = TRUE;
- }
- }
- if(cbmaprnum(villa->nodec) > villa->nodecnum){
- cbmapiterinit(villa->nodec);
- for(i = 0; i < VL_CACHEOUT; i++){
- tmp = cbmapiternext(villa->nodec, NULL);
- pid = *(int *)tmp;
- if(!vlnodecacheout(villa, pid)) err = TRUE;
- }
- }
- return err ? FALSE : TRUE;
-}
-
-
-/* Search a record of a leaf.
- `villa' specifies a database handle.
- `leaf' specifies a leaf handle.
- `kbuf' specifies the pointer to the region of a key.
- `ksiz' specifies the size of the region of the key.
- `ip' specifies the pointer to a variable to fetch the index of the correspnding record.
- The return value is the pointer to a corresponding record, or `NULL' on failure. */
-static VLREC *vlrecsearch(VILLA *villa, VLLEAF *leaf, const char *kbuf, int ksiz, int *ip){
- VLREC *recp;
- CBLIST *recs;
- int i, rv, left, right, ln;
- assert(villa && leaf && kbuf && ksiz >= 0);
- recs = leaf->recs;
- ln = CB_LISTNUM(recs);
- left = 0;
- right = ln;
- i = (left + right) / 2;
- while(right >= left && i < ln){
- recp = (VLREC *)CB_LISTVAL(recs, i);
- rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key));
- if(rv == 0){
- if(ip) *ip = i;
- return recp;
- } else if(rv <= 0){
- right = i - 1;
- } else {
- left = i + 1;
- }
- i = (left + right) / 2;
- }
- if(ip) *ip = i;
- return NULL;
-}
-
-
-/* Get flags of a database. */
-int vlgetflags(VILLA *villa){
- assert(villa);
- return dpgetflags(villa->depot);
-}
-
-
-/* Set flags of a database.
- `villa' specifies a database handle connected as a writer.
- `flags' specifies flags to set. Lesser ten bits are reserved for internal use.
- If successful, the return value is true, else, it is false. */
-int vlsetflags(VILLA *villa, int flags){
- assert(villa);
- if(!villa->wmode){
- dpecodeset(DP_EMODE, __FILE__, __LINE__);
- return FALSE;
- }
- return dpsetflags(villa->depot, flags);
-}
-
-
-
-/* END OF FILE */