int btcls(BTA* b) { int ioerr; bterr("",0,NULL); if ((ioerr=bvalap("BTCLS",b)) != 0) return(ioerr); btact = b; /* set context pointer */ /* Undo any locks and flush buffers before closing file */ while (btact->lckcnt > 0) bulock(); /* close index file and free context memory */ ioerr = fclose(btact->idxunt); if (ioerr != 0) { bterr("BTCLS",QCLSIO,btact->idxfid); } else { btact->idxunt = NULL; bacfre(btact); } return(btgerr()); }
int bgtslt() { int idx, i; idx = -1; /* any slots free? */ for (i=0;i<ZMXBLK;i++) { #if DEBUG >= 2 printf("bgtslt: cntrl[%d].inmem = " ZINTFMT "\n", i,((btact->cntrl)+i)->inmem); #endif if (((btact->cntrl)+i)->inmem < 0) { idx = i; break; } } if (idx < 0 ) { /* nope, need to free a memory block (least recently used) */ idx = bqhead(); } if (idx < 0) bterr("BGTSLT",QNOMEM,NULL); else { /* flush block to disk if slot not empty */ if (((btact->cntrl)+idx)->inmem >= 0) if (bwrblk(((btact->cntrl)+idx)->inmem) != 0) bterr("BGTSLT",QWRBLK,itostr(((btact->cntrl)+idx)->inmem)); } #if DEBUG >= 2 printf("bgtslt: found idx of %d\n",idx); #endif return(idx); }
int btinit() { int i,cnt=0,blksz; static int btinited = FALSE; if (btinited) { bterr("BTINIT",QINERR,NULL); return(QINERR); } /* ensure ZBLKSZ is a power of 2 */ blksz = ZBLKSZ; for (i=0;i<(ZBYTEW*sizeof(int));i++) { if ((blksz & 0x1) == 1) cnt++; blksz = blksz>>1; } if (cnt != 1) { bterr("BTINIT",QBLKSZERR,itostr(ZBLKSZ)); return(QBLKSZERR); } for (i=0;i<ZMXACT;i++) { btat[i].idxunt = NULL; btat[i].idxfid[0] = '\0'; btat[i].cntrl = NULL; btat[i].memrec = NULL; btat[i].cntxt = NULL; btat[i].fd = -1; } btinited = TRUE; return(0); }
BTint bgtinf(BTint blk,int type) { BTint val; int ioerr,idx; val = 0; if (type >= ZINFSZ) bterr("BGTINF",QINFER,NULL); else { ioerr = brdblk(blk,&idx); if (idx < 0) { bterr("BGTINF",QRDBLK,itostr((long) blk)); } else { switch (type) { case ZBTYPE: val = ((btact->memrec)+idx)->infblk[ZBTYPE] & MASK; break; case ZBTVER: val = ((btact->memrec)+idx)->infblk[ZBTYPE] >> ((ZBPW/2)*ZBYTEW); break; default: val = ((btact->memrec)+idx)->infblk[type]; } } } return(val); }
int brepky(BTint blk,int loc,char *key,BTint val,BTint link1,BTint link2) { int idx,ioerr; if (loc >= ZMXKEY || loc < 0) { bterr("BREPKY",QLOCTB,itostr(loc)); } else { ioerr = brdblk(blk,&idx); if (idx < 0) { bterr("BREPKY",QRDBLK,itostr(blk)); } else { strcpy(((btact->memrec)+idx)->keyblk[loc],key); ((btact->memrec)+idx)->valblk[loc] = val; ((btact->memrec)+idx)->lnkblk[loc] = link1; ((btact->memrec)+idx)->lnkblk[loc+1] = link2; ((btact->cntrl)+idx)->writes++; #if DEBUG >= 1 printf("BREPKY: Replaced target at blk: " ZINTFMT ", pos: %d\n", blk,loc); printf(" ..using '%s', val = " ZINTFMT ", llink = " ZINTFMT ", rlink = " ZINTFMT "\n", key,val,link1,link2); #endif } } return(0); }
void balblk() { BTint val,llink,rlink,cblk; int nkeys,cnkeys,result,diff; char tkey[ZKYLEN]; cblk = btact->cntxt->lf.lfblk; /* get parent block */ btact->cntxt->lf.lfpos = bpull(); btact->cntxt->lf.lfblk = bpull(); nkeys = bgtinf(btact->cntxt->lf.lfblk,ZNKEYS); cnkeys = bgtinf(cblk,ZNKEYS); if (btact->cntxt->lf.lfpos < nkeys) { /* check right sister block */ bsrhbk(btact->cntxt->lf.lfblk,tkey,&btact->cntxt->lf.lfpos,&val, &llink,&rlink,&result); if (result != 0) { bterr("BALBLK",QBALSE,NULL); goto fin; } nkeys = bgtinf(rlink,ZNKEYS); diff = cnkeys-nkeys; if (abs(diff) > (int)(ZMXKEY/2)) { balbk1(cblk,rlink,diff,tkey,val); goto fin; } } if (btact->cntxt->lf.lfpos > 0) { /* check left sister block */ btact->cntxt->lf.lfpos--; bsrhbk(btact->cntxt->lf.lfblk,tkey,&btact->cntxt->lf.lfpos, &val,&llink,&rlink,&result); if (result != 0) { bterr("BALBLK",QBALSE,NULL); goto fin; } nkeys = bgtinf(llink,ZNKEYS); diff = nkeys-cnkeys; if (abs(diff) > (int)(ZMXKEY/2)) { balbk1(llink,cblk,diff,tkey,val); goto fin; } btact->cntxt->lf.lfpos++; } /* no balancing possible; restore original environment */ bpush(btact->cntxt->lf.lfblk); bpush(btact->cntxt->lf.lfpos); btact->cntxt->lf.lfblk = cblk; fin: return; }
int binsky(BTA *b, char *key,BTint val) { BTint lval,dups_allowed; int status; KEYENT keyent; bterr("",0,NULL); if ((status=bvalap("BINSKY",b)) != 0) return(status); btact = b; if (btact->shared) { if (!block()) { bterr("BINSKY",QBUSY,NULL); goto fin; } } if (b->cntxt->super.smode != 0) { /* read only, can't insert */ bterr("BINSKY",QNOWRT,NULL); } else { dups_allowed = bgtinf(btact->cntxt->super.scroot,ZMISC); strncpy(keyent.key,key,ZKYLEN); keyent.key[ZKYLEN-1] = '\0'; keyent.val = val; keyent.dup = ZNULL; status = bfndky(b,keyent.key,&lval); if (status == QNOKEY || (status == 0 && dups_allowed)) { /* QNOKEY is not an error in this context; remove it */ bterr("",0,NULL); if (status == 0) { /* inserting duplicate key */ btdupkey(key,val); } else { bleaf(1); bputky(btact->cntxt->lf.lfblk,&keyent,ZNULL,ZNULL); } } else { bterr("BINSKY",QDUP,key); } } fin: if (btact->shared) bulock(); return(btgerr()); }
/* btsync: sync memory blocks with B tree index file returns zero if no errors, error code otherwise */ int btsync() { int i,ioerr; if (btact->idxunt != NULL) { /* write out all in-memory blocks */ for (i=0;i<ZMXBLK;i++) { ioerr = bwrblk(((btact->cntrl)+i)->inmem); if (ioerr != 0) { bterr("BTSYNC",QWRBLK,itostr(((btact->cntrl)+i)->inmem)); goto fin; } } /* write super block if necessary */ if (btact->cntxt->super.smod != 0) { if ( bwrsup() != 0) goto fin; btact->cntxt->super.smod = 0; } } /* force writes to disk */ fflush(btact->idxunt); /* re-initialise control blocks to ensure blocks will be re-read from disk */ initcntrl(btact); fin: return(btgerr()); }
int bulock(void) { if (btact->lckcnt > 1) { /* don't unlock if lock request nested (only top level will * unlock) */ #if DEBUG >= 2 fprintf(stderr,"BULOCK: soft unlock - lckcnt %d\n",btact->lckcnt); #endif btact->lckcnt--; return(0); } else if (btact->lckcnt == 1) { #if DEBUG >= 2 fprintf(stderr,"BULOCK: hard unlock - lckcnt %d\n",btact->lckcnt); #endif /* write any changed in-memory blocks to file */ btsync(); if (btact->fd >= 0) { lck.l_type = F_UNLCK; if (fcntl(btact->fd,F_SETLK,&lck) == -1) { bterr("BULOCK",QUNLCK,NULL); } } btact->lckcnt = 0; } return(0); }
int context_ok(char* fun) { if (btact->cntxt->lf.lfblk == ZNULL || btact->cntxt->lf.lfpos == ZNULL || !btact->cntxt->lf.lfexct) { bterr(fun,QBADCTXT,NULL); return FALSE; } return TRUE; }
int sco_disconn_ind(struct hci_conn *hcon, __u8 reason) { BT_DBG("hcon %p reason %d", hcon, reason); if (hcon->type != SCO_LINK) return 0; sco_conn_del(hcon, bterr(reason)); return 0; }
static int l2cap_disconn_ind(struct hci_conn *hcon, __u8 reason) { BT_DBG("hcon %p reason %d", hcon, reason); if (hcon->type != ACL_LINK) return 0; l2cap_conn_del(hcon, bterr(reason)); return 0; }
int bqmove(int idx) { int i; #if DEBUG >= 4 printf("Before move of idx %d: lruh: %d, lrut: %d\n",idx,btact->cntxt->lru.lruh,btact->cntxt->lru.lrut); for (i=0;i<ZMXBLK;i++) printf("lrunxt[%d] = %d ",i,((btact->cntrl)+i)->lrunxt); printf("\n"); #endif if (idx < 0) { bterr("BQMOVE",QBADIX,itostr(idx)); goto fin; } if (idx == btact->cntxt->lru.lrut) return(0); if (idx == btact->cntxt->lru.lruh) btact->cntxt->lru.lruh = ((btact->cntrl)+idx)->lrunxt; else { i = btact->cntxt->lru.lruh; while (i>=0) { if (((btact->cntrl)+i)->lrunxt == idx) break; i = ((btact->cntrl)+i)->lrunxt; } if (i >= 0) ((btact->cntrl)+i)->lrunxt = ((btact->cntrl)+idx)->lrunxt; else { bterr("BQMOVE",QLRUER,itostr(idx)); } } ((btact->cntrl)+btact->cntxt->lru.lrut)->lrunxt = idx; ((btact->cntrl)+idx)->lrunxt = -1; btact->cntxt->lru.lrut = idx; #if DEBUG >= 4 printf("After move: lruh: %d, lrut: %d\n",btact->cntxt->lru.lruh, btact->cntxt->lru.lrut); for (i=0;i<ZMXBLK;i++) printf("lrunxt[%d] = %d ",i, ((btact->cntrl)+i)->lrunxt); printf("\n"); #endif fin: return(0); }
int block(void) { int i, ierr; if (btact->lckcnt > 0 ) { btact->lckcnt++; #if DEBUG >= 2 fprintf(stderr,"BLOCK: soft lock - lcknt %d\n",btact->lckcnt); #endif return (TRUE); /* lock already in use for this process */ } lck.l_type = F_WRLCK; if (signal(SIGALRM,sigalrm_handler) == SIG_ERR) { bterr("BLOCK",QBADAL,NULL); return(FALSE); } /* save current signal mask in environment; enables proper repeat * behaviour when repetive calls to block are made */ if (sigsetjmp(env_alrm,1) != 0) { /* get here when alarm goes off; couldn't lock file */ signal(SIGALRM,SIG_DFL); alarm(0); return(FALSE); } alarm(ZSLEEP); if (fcntl(btact->fd,F_SETLKW,&lck) == -1) { signal(SIGALRM,SIG_DFL); alarm(0); return(FALSE); } alarm(0); #if DEBUG >= 2 fprintf(stderr,"BLOCK: hard lock - lcknt %d\n",btact->lckcnt); #endif if (btact->shared && btact->cntxt->super.scroot != ZNULL) { /* ensure super block info is up-to-date */ brdsup(); /* ensure current root is in memory and locked */ /* if not creating new index file (when scroot is ZNULL) */ ierr = brdblk(btact->cntxt->super.scroot,&i); if (ierr == 0) { bsetbs(btact->cntxt->super.scroot,1); } } btact->lckcnt = 1; return(TRUE); }
static int l2cap_connect_cfm(struct hci_conn *hcon, __u8 status) { BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); if (hcon->type != ACL_LINK) return 0; if (!status) { struct l2cap_conn *conn; conn = l2cap_conn_add(hcon, status); if (conn) l2cap_conn_ready(conn); } else l2cap_conn_del(hcon, bterr(status)); return 0; }
int bsetbk(BTint blk,BTint type,BTint misc,BTint nxblk,BTint nkeys, BTint nblks,BTint dupblk) { int ioerr,idx; ioerr = brdblk(blk,&idx); if (idx < 0) { bterr("BSETBK",QRDBLK,itostr(blk)); } else { bstinf(blk,ZBTYPE,type); ((btact->memrec)+idx)->infblk[ZMISC] = misc; ((btact->memrec)+idx)->infblk[ZNXBLK] = nxblk; ((btact->memrec)+idx)->infblk[ZNKEYS] = nkeys; ((btact->memrec)+idx)->infblk[ZNBLKS] = nblks; ((btact->memrec)+idx)->infblk[ZNXDUP] = dupblk; ((btact->cntrl)+idx)->writes++; } return(0); }
int bwrblk(BTint blk) { BTint pos; int i,ioerr; ioerr = 0; for (i=0;i<ZMXBLK;i++) if (((btact->cntrl)+i)->inmem == blk) break; if (i == ZMXBLK) { bterr("BWRBLK",QWRMEM,itostr(blk)); } else { if (((btact->cntrl)+i)->writes != 0) { pos = fseeko(btact->idxunt,blk*ZBLKSZ,SEEK_SET); if (pos >= 0) { if ((ioerr = fwrite((btact->memrec)+i,sizeof(char), ZBLKSZ, btact->idxunt)) == ZBLKSZ) { btact->cntxt->stat.xphywr++; ioerr = 0; #if DEBUG > 0 fprintf(stderr,"BWRBLK: writing block " ZINTFMT ", from idx %d\n",blk,i); #endif } else { ioerr = -1; } } else { ioerr = -1; } } else { btact->cntxt->stat.xlogwr++; } } ((btact->cntrl)+i)->writes = 0; return(ioerr); }
int bputky(BTint blk,char *key,BTint val,BTint link1,BTint link2) { int i,idx,ioerr; char lkey[ZKYLEN]; #if DEBUG >= 1 fprintf(stderr, "bputky: blk = " ZINTFMT ", key = %s, val = " ZINTMFT ", link1 = " ZINTFMT ", link2 = " ZINTFMT "\n", blk,key,val,link1,link2); #endif ioerr = brdblk(blk,&idx); if (idx < 0) { bterr("BPUTKY",QRDBLK,itostr(blk)); } else { /* get local copy of key, truncated if necessary */ strncpy(lkey,key,ZKYLEN); lkey[ZKYLEN-1] = '\0'; if (((btact->memrec)+idx)->infblk[ZNKEYS] == ZMXKEY) { bterr("BPUTKY",QBLKFL,itostr(blk)); goto fin; } if (((btact->memrec)+idx)->infblk[ZNKEYS] == 0) { /* block empty */ strcpy(((btact->memrec)+idx)->keyblk[0],lkey); ((btact->memrec)+idx)->valblk[0] = val; ((btact->memrec)+idx)->lnkblk[0] = link1; ((btact->memrec)+idx)->lnkblk[1] = link2; } else { for (i=((btact->memrec)+idx)->infblk[ZNKEYS];i>0;i--) { if (strcmp(key,((btact->memrec)+idx)->keyblk[i-1]) < 0) { /* move info to make room */ strcpy(((btact->memrec)+idx)->keyblk[i], ((btact->memrec)+idx)->keyblk[i-1]); ((btact->memrec)+idx)->valblk[i] = ((btact->memrec)+idx)->valblk[i-1]; ((btact->memrec)+idx)->lnkblk[i+1] = ((btact->memrec)+idx)->lnkblk[i]; } else break; } /* move left link if inserting in first position */ if (i == 0) ((btact->memrec)+idx)->lnkblk[1] = ((btact->memrec)+idx)->lnkblk[0]; strcpy(((btact->memrec)+idx)->keyblk[i],lkey); ((btact->memrec)+idx)->valblk[i] = val; if (link1 == ZNULL && link2 == ZNULL) { /* inserting a leaf key */ ((btact->memrec)+idx)->lnkblk[i] = ZNULL; ((btact->memrec)+idx)->lnkblk[i+1] = ZNULL; } else { /* if inserting in first pos, then use llink */ if (i == 0) ((btact->memrec)+idx)->lnkblk[0] = link1; /* rlink is inserted if ZERO or positive */ if (link2 >= 0) ((btact->memrec)+idx)->lnkblk[i+1] = link2; } } } ((btact->memrec)+idx)->infblk[ZNKEYS]++; ((btact->cntrl)+idx)->writes++; fin: return(0); }
int bnxtky(BTA* b,char *key,BTint *val) { int idx,nkeys,status; int found; bterr("",0,NULL); if ((status=bvalap("BNXTKY",b)) != 0) return(status); btact = b; /* set global context pointer */ if (btact->shared) { if (!block()) { bterr("BNXTKY",QBUSY,NULL); goto fin; } } /* handle duplicate positioning */ found = btduppos(ZNEXT,val); if (found > 0) { goto fin; } else if (found == 0) { strncpy(key,btact->cntxt->lf.lfkey,ZKYLEN); key[ZKYLEN-1] = '\0'; goto fin; } if (btact->shared && btact->cntxt->lf.lfblk != ZNULL) { /* position to last found key via bfndky, since context could * have been invalidated by concurrent updates by other users. * Note we don't care if the key is found or not, so the error * status is always cleared. */ status = bfndky(btact,btact->cntxt->lf.lfkey,val); bterr("",0,NULL); } found = FALSE; while (btact->cntxt->lf.lfblk != ZNULL && !found) { status = brdblk(btact->cntxt->lf.lfblk,&idx); if (idx < 0) { bterr("BNXTKY",QRDBLK,itostr(btact->cntxt->lf.lfblk)); break; } nkeys = bgtinf(btact->cntxt->lf.lfblk,ZNKEYS); #if DEBUG >= 1 printf("BNXTKY: lfblk: " ZINTFMT ", lfpos: %d, nkeys: %d\n", btact->cntxt->lf.lfblk,btact->cntxt->lf.lfpos,nkeys); #endif if (btact->cntxt->lf.lfpos >= nkeys || nkeys == 0) { /* finished with this block (or no key was found at all), * get parent from stack */ btact->cntxt->lf.lfpos = bpull(); btact->cntxt->lf.lfblk = bpull(); btact->cntxt->lf.lfexct = FALSE; continue; } if (!btact->cntxt->lf.lfexct) { btact->cntxt->lf.lfexct = TRUE; } else { btact->cntxt->lf.lfpos++; /* invalidate existing dup chain */ btact->cntxt->lf.draddr = ZNULL; idx = bleaf(0); if (idx < 0) continue; } if (btact->cntxt->lf.lfpos < nkeys) { found = TRUE; strncpy(key, ((btact->memrec)+idx)->keyblk[btact->cntxt->lf.lfpos].key, ZKYLEN); key[ZKYLEN-1] = '\0'; /* remember found key (need for shared mode) */ strncpy(btact->cntxt->lf.lfkey,key,ZKYLEN); btact->cntxt->lf.lfkey[ZKYLEN-1] = '\0'; *val = ((btact->memrec)+idx)->keyblk[btact->cntxt->lf.lfpos].val; btduppos(ZNEXT,val); } } if (btact->cntxt->lf.lfblk == ZNULL) { /* end of index reached */ bclrlf(); bterr("BNXTKY",QNOKEY,NULL); } fin: if (btact->shared) bulock(); return btgerr(); }
KEYENT* bsrhbk(BTint blk, char *key, int *loc, BTint *val, BTint *link1, BTint *link2, int *result) { int quit,idx,lo,hi,md,ioerr,nkeys; KEYENT* keyentp = NULL; ioerr = brdblk(blk,&idx); if (idx < 0) { bterr("BSRHBK",QRDBLK,itostr(blk)); goto fin; } nkeys = ((btact->memrec)+idx)->infblk[ZNKEYS]; #if DEBUG > 0 printf("BSRHBK: blk: " ZINTFMT ", nkeys: %d\n",blk,nkeys); printf("BSRHBK: loc: %d, val: " ZINTFMT ", link1: " ZINTFMT ", link2: " ZINTFMT "\n",*loc,*val,*link1,*link2); #endif if (*loc >= 0) { if (*loc >= nkeys) { /* requested loc not in block range */ *result = -1; goto fin; } else { *result = 0; strncpy(key,((btact->memrec)+idx)->keyblk[*loc].key,ZKYLEN); key[ZKYLEN-1] = '\0'; } } else { /* binary search */ *loc = -1; /* init location at impossible position */ *result = -1; quit = FALSE; lo = 0; hi = nkeys-1; md = -1; while (lo <= hi && !quit) { quit = (lo == hi); md = (lo+hi)/2; *result = strcmp(key,((btact->memrec)+idx)->keyblk[md].key); #if DEBUG >= 2 printf("key: \"%s\" vs \"%s\"\n",key, ((btact->memrec)+idx)->keyblk[md].key); printf("lo: %d, hi: %d, md: %d\n",lo,hi,md); printf("result: %d, quit: %d\n",*result,quit); #endif if (*result > 0) { lo = md+1; } else if (*result < 0) { hi = md-1; } else { break; } } *loc = md; } if (*loc < 0) { *val = 0; *link1 = ZNULL; *link2 = ZNULL; } else { *val = ((btact->memrec)+idx)->keyblk[*loc].val; *link1 = ((btact->memrec)+idx)->lnkblk[*loc]; *link2 = ((btact->memrec)+idx)->lnkblk[*loc+1]; keyent = ((btact->memrec)+idx)->keyblk[*loc]; keyentp = &keyent; #if DEBUG >=2 fprintf(stderr,"BSRHBK: val: " ZINTFMT ", link1: " ZINTFMT ", link2: " ZINTFMT "\n",*val,*link1,*link2); #endif } fin: return keyentp; }
/* Checks structure of index file, from current root. Returns number * of keys found or ZNULL if structure is damaged (either empty blocks * that are non-root, or inconsistent leaf depth). */ BTint btkeys(BTA* b,int stats) { BTint tblks = 0, tnkeys = 0, empty_blk = ZNULL, blkno = ZNULL; BTint val,link1,link2; int ioerr,idx,result,loc = 0; int blk_depth[STKMAX+1]; int leaf_depth = -1,balanced = TRUE; char key[ZKYLEN]; bterr("",0,NULL); if ((ioerr=bvalap("BTKEYS",b)) != 0) return(ioerr); if (btact->shared) { if (!block()) { bterr("BTKEYS",QBUSY,NULL); goto fin; } } btact = b; /* set context pointer */ if (btact->idxunt == NULL) { bterr("BTKEYS",QNOBTF,NULL); goto fin; } for (idx=0;idx<=STKMAX;idx++) blk_depth[idx] = 0; tblks = 0; tnkeys = 0; blkno = ZNULL; do { int depth,nkeys; bnxtbk(&blkno); depth = btstk_depth()/2; tblks++; blk_depth[depth]++; ioerr = brdblk(blkno,&idx); nkeys = bgtinf(blkno,ZNKEYS); if (nkeys == 0 && empty_blk == ZNULL) { if (bgtinf(blkno,ZBTYPE) != ZROOT) empty_blk = blkno; } else { bsrhbk(blkno,key,&loc,&val,&link1,&link2,&result); if (link1 == ZNULL) { if (leaf_depth < 0) { leaf_depth = depth; } else if (leaf_depth != depth) { balanced = FALSE; if (depth > leaf_depth) leaf_depth = depth; } } nkeys = btcntkeys(blkno); if (nkeys == ZNULL) return FALSE; tnkeys += nkeys; } } while (blkno != btact->cntxt->super.scroot); if (stats) { printf("Block stats:\n"); if (empty_blk != ZNULL) { printf("At least one non-root block has no keys. " "First encountered was " ZINTFMT "\n",empty_blk); } printf("Index balanced: %s\n",(balanced)?"YES":"NO"); printf("Max leaf depth: %d\n",leaf_depth); printf("Depth Number of blocks\n"); for (idx=0;idx<=leaf_depth;idx++) { printf("%5d %18d\n",idx,blk_depth[idx]); } } fin: return (empty_blk != ZNULL || !balanced)?ZNULL:tnkeys; }
void bdemte(BTint *cblk) { BTint newblk,val,link1,link2,jblk,llink,rlink; int nkeys,type,result; int rblke; char tkey[ZKYLEN]; nkeys = bgtinf(btact->cntxt->lf.lfblk,ZNKEYS); if (nkeys == 0) { type = bgtinf(btact->cntxt->lf.lfblk,ZBTYPE); if (type != ZROOT) { /* pull parent */ btact->cntxt->lf.lfpos = bpull(); btact->cntxt->lf.lfblk = bpull(); nkeys = bgtinf(btact->cntxt->lf.lfblk,ZNKEYS); if (btact->cntxt->lf.lfpos != 0) { /* ensure that empty block is on the right */ rblke = TRUE; btact->cntxt->lf.lfpos--; } else { /* first block empty, so can't put on right */ rblke = FALSE; } bsrhbk(btact->cntxt->lf.lfblk,tkey,&btact->cntxt->lf.lfpos,&val, &link1,&link2,&result); if (result != 0) { bterr("BDEMTE",QDEMSE,NULL); goto fin; } #if DEBUG >= 1 printf("BDEMTE: Demoting key %s from blk: " ZINTFMT "\n",tkey, btact->cntxt->lf.lfblk); #endif /* remove key from original block */ bremky(btact->cntxt->lf.lfblk,btact->cntxt->lf.lfpos); /* prepare for split check */ if (rblke) jblk = link1; else jblk = link2; /* if target block for demotion is full, split it */ nkeys = bgtinf(jblk,ZNKEYS); if (nkeys == ZMXKEY) { bsptbk(jblk,&newblk); if (newblk == ZNULL) { bterr("BDEMTE",QDEMSP,NULL); goto fin; } if (rblke) { link1 = newblk; } } if (!rblke) { /* copy keys from right block to empty left block */ nkeys = bgtinf(link2,ZNKEYS); bsetbs(link1,1); bcpybk(link1,link2,0,0,nkeys); bstinf(link1,ZNKEYS,nkeys); bsetbs(link1,0); llink = *cblk; rlink = ZNULL; /* 0 replaced by ZNULL for C */ } else { llink = ZNULL; /* 0 replaced by ZNULL for C */ rlink = *cblk; } bputky(link1,tkey,val,llink,rlink); bmkfre(link2); /* set new potentially dangling block */ *cblk = link1; } else { /* empty block is root; copy keys from child and then free * the child block */ nkeys = bgtinf(*cblk,ZNKEYS); bcpybk(btact->cntxt->lf.lfblk,*cblk,0,0,nkeys); bstinf(btact->cntxt->lf.lfblk,ZNKEYS,nkeys); bmkfre(*cblk); *cblk = ZNULL; } } else { *cblk = ZNULL; } fin: return; }
int bfndky(BTA *b,char *key,BTint *val) { BTint cblk, link1, link2, newblk; int index, result, nkeys, status; char lkey[ZKYLEN]; bterr("",0,NULL); status = QNOKEY; if ((result=bvalap("BFNDKY",b)) != 0) return(result); btact = b; /* set context pointer */ if (btact->shared) { if (!block()) { bterr("BFNDKY",QBUSY,NULL); goto fin; } } /* take local copy of key, truncating if necessary */ strncpy(lkey,key,ZKYLEN); lkey[ZKYLEN-1] = '\0'; /* initialise stack etc */ btact->cntxt->lf.lfexct = FALSE; cblk = btact->cntxt->super.scroot; bstkin(); btact->cntxt->lf.lfblk = -1; btact->cntxt->lf.lfpos = -1; strcpy(btact->cntxt->lf.lfkey,lkey); while (cblk >= 0) { #if DEBUG >= 2 fprintf(stderr,"BFNDKY: searching block " ZINTFMT "\n",cblk); #endif nkeys = bgtinf(cblk,ZNKEYS); if (nkeys == ZMXKEY && btact->cntxt->super.smode == 0) { /* split if block full and updating permitted */ bsptbk(cblk,&newblk); if (newblk < 0) { bterr("BFNDKY",QSPLIT,NULL); break; } /* if split occured, then must re-examine parent */ if (cblk != btact->cntxt->super.scroot) { index = btact->cntxt->lf.lfpos; cblk = btact->cntxt->lf.lfblk; btact->cntxt->lf.lfpos = bpull(); btact->cntxt->lf.lfblk = bpull(); } } else { index = -1; bpush(btact->cntxt->lf.lfblk); bpush(btact->cntxt->lf.lfpos); bsrhbk(cblk,lkey,&index,val,&link1,&link2,&result); btact->cntxt->lf.lfblk = cblk; btact->cntxt->lf.lfpos = index; /* if block is empty, leave lfpos at -1 */ if (result < 0) { /* must examine left block */ cblk = link1; continue; } else if (result > 0) { /* must examine right block */ cblk = link2; /* increment index to indicate this key "visited" */ btact->cntxt->lf.lfpos++; continue; } else { status = 0; btact->cntxt->lf.lfexct = TRUE; break; } } } fin: if (btact->shared) bulock(); /* non-zero status indicates no such key found */ if (status) bterr("BFNDKY",QNOKEY,lkey); return(btgerr()); }