dbcheck.c
来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 2,087 行 · 第 1/5 页
C
2,087 行
if ((ts_creat > ts_file) || (ts_modif > ts_file)) { if (print) pr_err(BAD_RSTP, NULL, dbi, task); } } oip = dbi->owners + rid; for (i = 0; i < oip->cnt; i++) { /* For sets this rid owns */ sip = oip->lst + i; if (sip->stampd) { memcpy((char *) &ts_modif, rec + sip->setoff + 3 * sizeof(F_ADDR), sizeof(ts_modif)); if (ts_modif > ts_file) { if (print) pr_err(BAD_SSTP, &oip->lst[i].setno, dbi, task); } } }}/**************************************************************************//**************************************************************************//* Set Checks *//**************************************************************************//**************************************************************************//**************************************************************************** Check consistency of sets which this record owns*/static int chk_own( char *orec, short orid, DB_ADDR odba, DBINFO *dbi, DB_TASK *task){ int status = S_OKAY; SET set; MEMBER memptr; F_ADDR mcnt; int i; ERR_PDBA pdba; ERR_STYP styp; ERR_SCNT scnt; register DB_ADDR mdba, prev_mdba; register REC_SET_INFO *oip; register SET_INFO *sip; register char *bp; static CHKREC chk = {BAD_OMEM, BAD_OMDL, 0, BAD_OMRC, BAD_OMRC, EOF, NULL, 0, 0, 0, 0}; oip = dbi->owners + orid; for (i = 0; i < oip->cnt; i++) { /* For sets this rid owns */ sip = oip->lst + i; /* copy the set structure from the record */ memcpy((char *) &set, orec + sip->setoff, sizeof(SET)); pdba.setno = styp.setno = scnt.setno = sip->setno; if (dbi->opts->counts) dbi->set_cnt[sip->setno] += set.members; /* check the validity of the first and last pointers */ if (chk_dba(set.last, dbi, task) != S_OKAY) { pdba.dba = set.last; pr_err(BAD_OLST, &pdba, dbi, task); } if (chk_dba(set.first, dbi, task) != S_OKAY) { pdba.dba = set.first; pr_err(BAD_OFST, &pdba, dbi, task); continue; /* Must have good first pointer */ } /* get the DB_ADDR of the first member */ mcnt = 0; mdba = set.first; prev_mdba = NULL_DBA; /* scan all members in this set */ while (mdba != NULL_DBA) { pdba.dba = styp.dba = mdba; if (++mcnt > set.members) { pr_err(BAD_LOOP, &pdba, dbi, task); break; } if ((status = chk_rec(mdba, NULL, (char *) &pdba, &chk, dbi, task)) != S_OKAY) return (status); if (!chk.good) { if (prev_mdba != NULL_DBA) { pdba.dba = prev_mdba; vtprintf(DB_TEXT(" (last good member-dba=%s)\n"), pr_dba(&pdba.dba)); } break; } if ((sip = val_mtype(sip->setno, chk.rid, dbi->members, task)) == NULL) { styp.rid = chk.rid; pr_err(BAD_OMTP, &styp, dbi, task); break; } /* obtain the member pointers */ bp = chk.pgptr + sip->memoff; memcpy((char *) &memptr, bp, sizeof(MEMBER)); /* make sure that the owner pointers match up */ if (memptr.owner != odba) pr_err(BAD_OMOW, &pdba, dbi, task); /* if this is the first member, the PREV pointer must be null */ if ((mdba == set.first) && (memptr.prev != NULL_DBA)) { pr_err(BAD_MFPN, &pdba, dbi, task); } else if (memptr.prev != prev_mdba) { /* the previous pointer should point the the previous member */ pr_err(BAD_MNPW, &pdba, dbi, task); pdba.dba = prev_mdba; vtprintf(DB_TEXT(" (last good member-dba=%s)\n"), pr_dba(&pdba.dba)); } /* if this is the last member, the NEXT pointer must be null */ if ((mdba == set.last) && (memptr.next != NULL_DBA)) { pr_err(BAD_MLNN, &pdba, dbi, task); break; } /* point to the next member */ prev_mdba = mdba; mdba = memptr.next; } /* end scan all members in this set */ /* verify the membership count */ if (mcnt != set.members) { scnt.owncnt = set.members; scnt.memcnt = mcnt; pr_err(BAD_OCNT, &scnt, dbi, task); } } /* end scan sets which are owned by this record type */ return (S_OKAY);}/*************************************************************************** Check consistency of sets which this record is a member of*/static int chk_mem( char *mrec, short mrid, DB_ADDR mdba, DBINFO *dbi, DB_TASK *task){ int status = S_OKAY; MEMBER memptr; MEMBER prev_memptr; MEMBER next_memptr; SET set; ERR_PDBA pdba; ERR_STYP styp; register int i; register REC_SET_INFO *mip; register SET_INFO *sip, *tsip; register char *bp; static CHKREC chk = {BAD_MOPB, BAD_MODL, 0, BAD_MORC, BAD_MORC, EOF, NULL, 0, 0, 0, 0}; static CHKREC ptrchk = {0, 0, 0, 0, 0, EOF, NULL, 0, 0, 0, 0}; /* used to check next and prev pointers w/i set. Don't report errors here because they will be duplicates of an error reported elsewhere. */ mip = dbi->members + mrid; for (i = 0; i < mip->cnt; i++) { /* Sets of which rid is a member */ sip = mip->lst + i; /* copy member set into structure */ memcpy((char *) &memptr, mrec + sip->memoff, sizeof(MEMBER)); pdba.setno = styp.setno = sip->setno; pdba.dba = styp.dba = memptr.owner; if (memptr.owner == NULL_DBA) { /* if the owner pointer is null */ /* if either the next or prev pointers are non-null */ if (memptr.prev != NULL_DBA || memptr.next != NULL_DBA) pr_err(BAD_MONL, &pdba, dbi, task); } else { if ((status = chk_rec(memptr.owner, NULL, (char *) &pdba, &chk, dbi, task)) != S_OKAY) return (status); if (!chk.good) continue; if (chk.rid != sip->ownrid) { styp.rid = chk.rid; pr_err(BAD_MOIN, &styp, dbi, task); continue; } /* get the set pointers */ bp = chk.pgptr + sip->setoff; memcpy((char *) &set, bp, sizeof(SET)); /* make sure the first pointer points to this record */ if (memptr.prev == NULL_DBA) { if (set.first != mdba) pr_err(BAD_MNPP, &sip->setno, dbi, task); } else { /* read the .prev record */ if ((status = chk_rec(memptr.prev, NULL, (char *) &pdba, &ptrchk, dbi, task)) != S_OKAY) return (status); /* check for valid record type */ if ( (tsip = val_mtype(sip->setno, ptrchk.rid, dbi->members, task)) == NULL) { pdba.dba = memptr.prev; pr_err(BAD_OMPP, &pdba, dbi, task); pdba.dba = memptr.owner; } else { /* make sure that prevrecord.next points to this record */ memcpy((char *) &prev_memptr, (ptrchk.pgptr + tsip->memoff), sizeof(MEMBER)); if (prev_memptr.next != mdba) pr_err(BAD_SETP, &pdba, dbi, task); } } /* make sure the last pointer points to this record */ if (memptr.next == NULL_DBA) { if (set.last != mdba) pr_err(BAD_MNNP, &sip->setno, dbi, task); } else { /* read the .next record */ if ((status = chk_rec(memptr.next, NULL, (char *) &pdba, &ptrchk, dbi, task)) != S_OKAY) return (status); /* check for valid record type */ if ( (tsip = val_mtype(sip->setno, ptrchk.rid, dbi->members, task)) == NULL) { pdba.dba = memptr.next; pr_err(BAD_OMEM, &pdba, dbi, task); pdba.dba = memptr.owner; } else { /* make sure that nextrecord.prev points to this record */ memcpy((char *) &next_memptr, (ptrchk.pgptr + tsip->memoff), sizeof(MEMBER)); if (next_memptr.prev != mdba) pr_err(BAD_SETN, &pdba, dbi, task); } } } } return (S_OKAY);}/*************************************************************************** Locate the member table entry for this record type*/static SET_INFO *val_mtype( int st, short mrid, REC_SET_INFO *meminfo, DB_TASK *task){ register int i; register REC_SET_INFO *mip; register SET_INFO *sip; if (mrid < 0 || mrid >= task->size_rt) return (NULL); mip = meminfo + mrid; for (i = 0; i < mip->cnt; i++) { sip = mip->lst + i; if (sip->setno == st) return (sip); } return (NULL);}/***************************************************************************//***************************************************************************//* Key File Checks *//***************************************************************************//***************************************************************************//************************************************************************** Perform key file consistency check*/static int key_file( FILE_NO fno, DBINFO *dbi, DB_TASK *task){ int status; register long m; register int slots; F_ADDR top; KEYINFO keyinfo; stat_report(fno, 0, dbi, task); if ((status = read_del_chain(fno, dbi, task)) != S_OKAY) return (status); memset(&keyinfo, 0, sizeof(KEYINFO)); keyinfo.oldno = -1; keyinfo.slot_len = task->file_table[fno].ft_slsize; keyinfo.kdup.frst_slot = TRUE; top = dbi->tops[fno] - 1L; slots = task->file_table[fno].ft_slots; for (m = slots / 2, keyinfo.max_levl = 1; m < top * slots; m *= slots / 2) keyinfo.max_levl++; /* set node number to be specified in error reports */ dbi->errinfo->addr = 1; status = dbi->opts->keyscan ? scan_key(fno, ROOT_ADDR, 1, &keyinfo, dbi, task) : walk_key(fno, &keyinfo, dbi, task); if (status != S_OKAY) return (status); if (keyinfo.kdup.in_series == TRUE) { vtprintf(DB_TEXT(" (total of %ld occurrences of above duplicated value)\n\n"), keyinfo.kdup.count); } if (dbi->opts->keyscan) { if ((status = chk_pglst(fno, dbi, task)) != S_OKAY) dberr(status); } delete_temp_files(dbi->pcache); return (S_OKAY);}/*************************************************************************** Check a key file in page sequential order (Note: it doesn't check the tree structure at all)*/static int walk_key( FILE_NO fno, KEYINFO *ki, DBINFO *dbi, DB_TASK *task){ int status = S_OKAY; register F_ADDR page; F_ADDR top = dbi->tops[fno] - 1L; /* This function only gets called if the -k (keyscan) option was not specified. Walk through all the nodes in the file in physical order, without recursive calls to check b-tree structure. */ for (page = ROOT_ADDR; page <= top; page++) { /* set node number to be specified in error reports */ dbi->errinfo->addr = page; /* check this node only - no recursion, as keyscan option is off */ if ((status = chk_node(fno, page, (short) 0, ki, dbi, task)) != S_OKAY) return (status); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?