Exemple #1
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;
}
Exemple #2
0
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());
}
Exemple #3
0
/* 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;
}
Exemple #4
0
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());
}
Exemple #5
0
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;
}
Exemple #6
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();
}