Пример #1
0
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());
}
Пример #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());
}
Пример #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;
}
Пример #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());
}
Пример #5
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();
}