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 + -
显示快捷键?