dbcheck.c

来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 2,087 行 · 第 1/5 页

C
2,087
字号
    return (S_OKAY);}/**************************************************************************    Check the key file in ascending tree sequential order*/static int scan_key(    FILE_NO fno,    F_ADDR page,    short levl,    KEYINFO *ki,    DBINFO *dbi,    DB_TASK *task){    int status = S_OKAY;    ERR_LEVL linf;    if (levl > ki->max_levl)    {        linf.levl = levl;        linf.mlvl = ki->max_levl;        pr_err(BAD_TRLV, &linf, dbi, task);    }    /* This function only gets called if the -k (keyscan) option was       specified, for recursive checking of b-tree structure. Test       whether we have already encountered this node:    */    if ((status = reg_page(page, dbi->pcache, USAGE_ID)) != S_OKAY)    {        /* We must abort on this error because there might be a loop in           the b-tree pointers.        */        if (status < S_OKAY)            dberr(status);        else            status = S_KEYERR;        pr_err(BAD_KBTL, NULL, dbi, task);        dbi->opts->treetrace = TRUE;        return (status);    }    /* chk_node will check the node and all its children recursively, as       keyscan option is on.    */    return (chk_node(fno, page, levl, ki, dbi, task));}/**************************************************************************    Process a single key node (page)*/static int chk_node(    FILE_NO fno,    F_ADDR page,    short levl,    KEYINFO *ki,    DBINFO *dbi,    DB_TASK *task){    SLINFO              slinfo;    register short      slot, last_slot;    int                 status = S_OKAY;    stat_report(fno, ++(ki->btree_pages), dbi, task);    if ((status = tio_get(fno, page, (char **) &slinfo.node, NOPGHOLD, dbi, task)) != S_OKAY)        return (status);    last_slot = slinfo.node->used_slots;    if ((last_slot < 0) || (last_slot >= task->file_table[fno].ft_slots))    {        pr_err(BAD_SLCT, &slinfo.node->used_slots, dbi, task);        if (dbi->opts->treetrace)            return (S_KEYERR);    }    else if ((last_slot == 0) && (page != ROOT_ADDR))    {        /* deleted node, make sure it is found on delete chain */        if ((status = chk_del_chain(page, FALSE, dbi, task)) < S_OKAY)            dberr(status);        if (dbi->opts->keyscan)        {            pr_err(BAD_KWDL, NULL, dbi, task);     /* Deleted nodes don't  */            if (dbi->opts->treetrace)              /* belong on the b-tree */                return (S_KEYERR);        }    }    else    {        slinfo.all_null = 0;        slinfo.levl = levl;        for (slot = 0; slot <= last_slot; slot++)        {            /* lock page in cache */            if ((status = tio_get(fno, page, (char **) &slinfo.node, PGHOLD, dbi, task)) != S_OKAY)                return (status);            slinfo.slot = slot;            slinfo.last = (DB_BOOLEAN) (slot == last_slot);            slinfo.sl_addr = slinfo.node->slots + (slot * ki->slot_len);            memcpy(&slinfo.child, slinfo.sl_addr + SLOT_CHILD, sizeof(F_ADDR));            memcpy(&slinfo.keyno, slinfo.sl_addr + SLOT_KEYNO, sizeof(short));            status = chk_slot(fno, ki, &slinfo, dbi, task);            tio_unget(fno, page, PGFREE, dbi, task);            if (status != S_OKAY)                return (status);            if (dbi->opts->keyscan)            {                /* recursive b-tree check - scan_child rereads page if necessary */                if ((status = scan_child(fno, page, ki, &slinfo, dbi, task)) != S_OKAY)                    return (status);            }        }    }    return (S_OKAY);}/***************************************************************************    Process a single slot on a given key node (page)*/static int chk_slot(    FILE_NO fno,    KEYINFO *ki,    SLINFO *si,    DBINFO *dbi,    DB_TASK *task){    int                      status = S_OKAY;    register FIELD_ENTRY    *kf_ptr;    register char           *fptr;    char                     key[MAXKEYSIZE];    static CHKREC chk = {BAD_KDBA, BAD_KDAD, 0, BAD_KREC, BAD_KREC, TRUE,                         NULL, 0, 0, 0, 0};    /* Check to verify that all null pointers are on the same level */    if (ki->null_levl == 0)    {        if (si->child == NULL_NODE)            ki->null_levl = si->levl;    }    else if ((si->child == NULL_NODE) &&                (ki->null_levl > 0) && (si->levl != ki->null_levl))    {        pr_err(BAD_CHSL, NULL, dbi, task);        ki->null_levl = EOF;    }    /* Check to verify that all pointers on page are either       null or non-null    */    if (si->all_null != EOF)    {        if (si->slot == 0)            si->all_null = (DB_BOOLEAN) (si->child == NULL_NODE);        else if (si->all_null != (si->child == NULL_NODE))        {            pr_err(BAD_CHSM, NULL, dbi, task);            si->all_null = EOF;        }    }    if (si->last)        return (S_OKAY);    /* extract key prefix */    if ((si->keyno < 0) || (si->keyno >= dbi->num_keys))    {        pr_err(BAD_KEYP, si, dbi, task);        si->keyno = EOF;        return (S_OKAY);    }    si->keyfd = dbi->key_fld[si->keyno];    si->keyln = dbi->key_len[si->keyno];    si->kf_ptr = kf_ptr = &(task->field_table[si->keyfd]);    if (kf_ptr->fd_keyfile != fno)    {        pr_err(BAD_KPFL, si, dbi, task);        return (S_OKAY);    }    if (dbi->opts->counts)        dbi->key_cnt[si->keyno]++;    /* extract database address */    memcpy((char *) &si->dba, si->sl_addr + SLOT_DBA(si->keyln),              sizeof(DB_ADDR));    if (!dbi->opts->keydat)        return (S_OKAY);    if ((status = chk_rec(si->dba, NULL, (char *) si, &chk, dbi, task)) != S_OKAY)        return (status);    if (!chk.good)        return (S_OKAY);    if (kf_ptr->fd_type == COMKEY)    {                                   /* build a compound key */        key_bldcom(si->keyfd, chk.pgptr + task->record_table[chk.rid].rt_data,                      key, TRUE, task);        fptr = key;    }    else        fptr = chk.pgptr + kf_ptr->fd_ptr;        /* copy a simple key */    if (fldcmp(kf_ptr, si->sl_addr + SLOT_KEY, fptr, task) != 0)        pr_err(BAD_KDAT, si, dbi, task);    return (S_OKAY);}/***************************************************************************    Traverses the child pointer, then checks to see that all the child keys    were less than the current key.*/static int scan_child(    FILE_NO fno,    F_ADDR page,    KEYINFO *ki,    SLINFO *si,    DBINFO *dbi,    DB_TASK *task){    int status = S_OKAY;    if (si->child != NULL_NODE)    {        if ((si->child < 0L) || (si->child > dbi->tops[fno] - 1))            pr_err(BAD_CHPT, si, dbi, task);        else        {            /* error reports refer to child node from now on */            dbi->errinfo->addr = si->child;            status = scan_key(fno, si->child, (short) (si->levl + 1), ki, dbi, task);            /* recursed back up - error reports now refer to parent again */            dbi->errinfo->addr = page;            if (status != S_OKAY)            {                pr_err(BAD_BTRC, si, dbi, task);                return (status);            }            if (!si->last)            {                if ((status = tio_get(fno, page, (char **) &si->node, NOPGHOLD, dbi, task)) != S_OKAY)                    return (status);                si->sl_addr = si->node->slots + (si->slot * ki->slot_len);            }        }    }    if (si->last)        return (S_OKAY);    if (si->keyno == EOF)        return (S_OKAY);    if ((si->keyno < ki->oldno) ||        ((si->keyno == ki->oldno) &&         (fldcmp(si->kf_ptr, si->sl_addr + SLOT_KEY, ki->oldkey, task) < 0)))    {        pr_err(BAD_BTUO, si, dbi, task);        if (dbi->opts->treetrace)            return (S_KEYERR);        /* Throw away the old key, start again */        ki->oldno = -1;    }    else if ((si->keyno == ki->oldno) && (si->dba == ki->olddba))    {        pr_err(BAD_BTDD, si, dbi, task);    }    else if ((si->kf_ptr->fd_key == UNIQUE) &&             (si->keyno == ki->oldno) &&             (fldcmp(si->kf_ptr, si->sl_addr + SLOT_KEY, ki->oldkey, task) == 0))    {        ki->kdup.dba = si->dba;        ki->kdup.frstdba = ki->olddba;        ki->kdup.fldno = dbi->key_fld[si->keyno]; /* index into field table */        ki->kdup.buf = ki->oldkey;        pr_err(BAD_UKNU, &(ki->kdup), dbi, task);        ki->kdup.in_series = TRUE;    }    else    {        if (ki->kdup.in_series == TRUE)        {            vtprintf(DB_TEXT("   (total of %ld occurrences of above duplicated value)\n\n"),                   ki->kdup.count);            ki->kdup.count = 0;            ki->kdup.in_series = FALSE;        }        ki->oldno = si->keyno;        ki->olddba = si->dba;        memcpy(ki->oldkey, si->sl_addr + SLOT_KEY, si->keyln);    }    ki->kdup.frst_slot = FALSE;    return (S_OKAY);}/*****************************************************************************//*****************************************************************************//*                       Key File Completeness Checks                        *//*****************************************************************************//*****************************************************************************/static int reg_page(F_ADDR page, PAGE_CACHE *pcache, long id){    int               rc;    long              byte;    long              bit;    long              page_id;       /* this should be < 32K */    long              page_offset;   /* this will be < 8 */    unsigned char    *pglst;    byte = ((long) page - 1L) / 8L;    bit = ((long) page - 1L) % 8L;    page_id = byte / CACHE_PG_SIZE;    page_offset = byte % CACHE_PG_SIZE;    pglst = (unsigned char *) cache_find(page_id + id, pcache);    if (pglst == NULL)    {        vtprintf(DB_TEXT("Failed to find page %ld in temporary file %ld (reg_page).\n"),             page_id, id);        return (S_SYSERR);    }    rc = (*(pglst + page_offset) & (1 << bit));    if (rc)        return (S_DUPLICATE);    *(pglst + page_offset) |= (1 << bit);    return (S_OKAY);}/**************************************************************************/static int chk_pglst(    FILE_NO fno,    DBINFO *dbi,    DB_TASK *task){    unsigned char       *lsta,                        *lstb;    register F_ADDR      page;    int                  rc1,                         rc2;    long                 byte;    long                 bit;    long                 page_id;    long                 page_offset;    /* Check that all nodes in the file appear either in the b-tree (i.e.       a bit is set in the USAGE_ID bitmap) of in the delete chain (i.e. a       bit is set in the DCHAIN_ID bitmap).    */    for (page = ROOT_ADDR; page < dbi->tops[fno]; page++)    {        byte = ((long) page - 1L) / 8L;        bit = ((long) page - 1L) % 8L;        page_id = byte / CACHE_PG_SIZE;          /* this should be < 32K */        page_offset = byte % CACHE_PG_SIZE;      /* this will be < 8 */        lsta = (unsigned char *)                cache_find(page_id + DCHAIN_ID, dbi->pcache);        lstb = (unsigned char *)                cache_find(page_id + USAGE_ID, dbi->pcache);        if ((lsta == NULL) || (lstb == NULL))        {            if (lsta == NULL)                vtprintf(DB_TEXT("Failed to find page %ld in temporary file %ld(chk_pglst)\n"), page_id, DCHAIN_ID);            if (lstb == NULL)                vtprintf(DB_TEXT("Failed to find page %ld in temporary file %ld(chk_pglst)\n"), page_id, USAGE_ID);            return (S_SYSERR);        }        rc1 = (*(lsta + page_offset) & (1 << bit));        rc2 = (*(lstb + page_offset) & (1 << bit));        if (!rc1 && !rc2)        {            dbi->errinfo->addr = page;            pr_err(BAD_KPST, NULL, dbi, task);        }    }    return (S_OKAY);}/*******************************************************************

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?