dbcheck.c
来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 2,087 行 · 第 1/5 页
C
2,087 行
if (!psp_pathIsDir(path)) { len = vtstrlen(path); path[len++] = DIRCHAR; path[len] = 0; } } vtstrcpy(dbi->pcache->dchain->name, path); vtstrcat(dbi->pcache->dchain->name, DB_TEXT("dbcheck.dch")); vtstrcpy(dbi->pcache->used->name, path); vtstrcat(dbi->pcache->used->name, DB_TEXT("dbcheck.use")); return (S_OKAY);}/************************************************************************* Free heap memory allocated during setup for database info.*/static void free_dbinfo(DBINFO *dbi){ int i; if (!dbi) return; if (dbi->pcache) /* allocated in setup_temp_files */ cache_free(dbi->pcache); if (dbi->owners) /* allocated in setup_sets */ { for (i = 0; i < dbi->num_recs; i++) { if (dbi->owners[i].lst) psp_freeMemory(dbi->owners[i].lst, 0); } psp_freeMemory(dbi->owners, 0); } if (dbi->members) /* allocated in setup_sets */ { for (i = 0; i < dbi->num_recs; i++) { if (dbi->members[i].lst) psp_freeMemory(dbi->members[i].lst, 0); } psp_freeMemory(dbi->members, 0); } if (dbi->keys) /* allocated in setup_keys */ { for (i = 0; i < dbi->num_recs; i++) { if (dbi->keys[i].lst) psp_freeMemory(dbi->keys[i].lst, 0); } psp_freeMemory(dbi->keys, 0); } if (dbi->key_fld) /* allocated in setup_keys */ psp_freeMemory(dbi->key_fld, 0); if (dbi->key_len) /* allocated in setup_keys */ psp_freeMemory(dbi->key_len, 0); if (dbi->rec_cnt) /* allocated in setup_cnts */ psp_freeMemory(dbi->rec_cnt, 0); if (dbi->set_cnt) psp_freeMemory(dbi->set_cnt, 0); if (dbi->key_cnt) psp_freeMemory(dbi->key_cnt, 0); if (dbi->tops) /* allocated in setup_tots */ psp_freeMemory(dbi->tops, 0); if (dbi->errinfo) /* allocated in setup_db */ psp_freeMemory(dbi->errinfo, 0); psp_freeMemory(dbi, 0);}/*************************************************************************** Scan the data and key files*/static int scan( char *pgbuf, DBINFO *dbi, DB_TASK *task){ DB_TCHAR filnam[FILENMLEN]; register int pass; register int i; register FILE_NO fno; int status = S_OKAY; DB_TCHAR *dbname = dbi->opts->dbname; DB_TCHAR **fnames = dbi->opts->fnames; short nfnames = dbi->opts->nfnames; for (pass = (dbi->opts->ignorekey ? 1:0); pass < 2; pass++) { /* First key, then data files */ for (fno = 0; fno < task->size_ft; fno++) { /* Scan each database file */ if (nfnames) { /* If name list, search for name */ for (i = 0; i < nfnames; i++) { if (vtstrcmp(task->file_table[fno].ft_name, fnames[i]) == 0) break; con_dbf(filnam, fnames[i], dbname, task->dbfpath, task); if (vtstrcmp(task->file_table[fno].ft_name, filnam) == 0) break; } if (i == nfnames) continue; } /* set file number to be specified in error reports */ dbi->errinfo->fno = fno; /* reset number of deleted records / nodes in current file */ dbi->num_del = 0; if ((task->file_table[fno].ft_type == DATA) && (pass == 1)) { if ((status = data_file(fno, pgbuf, dbi, task)) != S_OKAY) return (status); } else if ((task->file_table[fno].ft_type == KEY) && (pass == 0)) { if ((status = key_file(fno, dbi, task)) != S_OKAY) return (status); } cache_clear(dbi->pcache); d_closeall(task); } } return (S_OKAY);}/*************************************************************************//*************************************************************************//* Data File Checks *//*************************************************************************//*************************************************************************//************************************************************************* Perform data file consistency check*/static int data_file( FILE_NO fno, char *pgbuf, DBINFO *dbi, DB_TASK *task){ int status = S_OKAY; F_ADDR rno; F_ADDR top; DB_ADDR dba; static CHKREC chk = { 0, 0, BAD_LOCK, BAD_RID, BAD_RDBA, 0, NULL, 0, 0, 0, 0 }; stat_report(fno, 0, dbi, task); if ((status = read_del_chain(fno, dbi, task)) != S_OKAY) return (status); top = dbi->tops[fno] - 1L; /* read each record in data file */ for (rno = 1; rno <= top; rno++) { /* set record number to be specified in error reports */ dbi->errinfo->addr = rno; /* report progress */ stat_report(fno, rno, dbi, task); d_encode_dba(fno, rno, &dba); if ((status = chk_rec(dba, pgbuf, NULL, &chk, dbi, task)) != S_OKAY) return (status); if (chk.del) { if ((status = chk_del_chain(rno, FALSE, dbi, task)) < S_OKAY) dberr(status); } else if (chk.good) { if (dbi->opts->counts) dbi->rec_cnt[chk.rid]++; if (dbi->opts->setscan) { /* check the set connections */ if ((status = chk_own(pgbuf, chk.rid, dba, dbi, task)) != S_OKAY) return (status); if ((status = chk_mem(pgbuf, chk.rid, dba, dbi, task)) != S_OKAY) return (status); } if (dbi->opts->datkey) /* check the keys */ { if ((status = chk_key(pgbuf, chk.rid, dba, dbi, task)) != S_OKAY) return (status); } if (dbi->opts->timestmp) /* check the timestamps */ chk_stmp(pgbuf, chk.rid, fno, TRUE, dbi, task); } } delete_temp_files(dbi->pcache); return (S_OKAY);}/*************************************************************************** Read a data record, and figure out if it has any errors*/static int chk_rec( DB_ADDR dba, /* database address to check */ char *pgptr, char *errblk, CHKREC *chk, DBINFO *dbi, DB_TASK *task){ int status = S_OKAY; register DB_ADDR *rdba; register DB_BOOLEAN bad_rid = FALSE; FILE_NO fno; DB_ADDR rno; d_decode_dba(dba, &fno, &rno); chk->good = FALSE; if (chk_dba(dba, dbi, task) != S_OKAY) { if (chk->dba_msg) pr_err(chk->dba_msg, errblk, dbi, task); return (S_OKAY); } /* read next record */ if ((status = tio_read(dba, &chk->pgptr, dbi, task)) != S_OKAY) return (status); get_rid_info(chk->pgptr, (RECINFO *) & chk->rid); if (pgptr != NULL) memcpy(pgptr, chk->pgptr, task->file_table[fno].ft_slsize); chk->good = TRUE; /* check if deleted */ if (chk->del_msg && chk->del) pr_err(chk->del_msg, errblk, dbi, task); /* check the lock bit */ if (chk->lock_msg && chk->lck) pr_err(chk->lock_msg, errblk, dbi, task); /* check the record id */ if ( (chk->rid < 0) || (chk->rid >= task->size_rt) || (task->record_table[chk->rid].rt_file != fno) ) { bad_rid = TRUE; chk->good = FALSE; if (chk->rid_msg) { pr_err(chk->rid_msg, (errblk == NULL) ? (char *) &chk->rid : errblk, dbi, task); } } /* check the database address */ rdba = (DB_ADDR *) (chk->pgptr + REC_DBA); if ((! chk->del) && (ADDRcmp(&dba, rdba) != 0)) { chk->good = FALSE; if (chk->idba_msg && ((chk->idba_msg != chk->rid_msg) || (! bad_rid))) { pr_err(chk->idba_msg, (errblk == NULL) ? (void *)rdba : (void *) errblk, dbi, task); } } /* make sure the system record is in slot [x:0001] */ if (! bad_rid) { if ((task->record_table[chk->rid].rt_fdtot == -1) && (rno != (DB_ADDR)1)) { /* The slot number of the record being checked by this function (i.e. rno) may not be the same as the slot number to be used in error reports (i.e. dbi->errinfo->addr). For this error, we need to report the problem as being in slot rno - so temporarily set the current error-report slot to rno, then replace whatever was in there before. */ F_ADDR addr = dbi->errinfo->addr; dbi->errinfo->addr = rno; pr_err(BAD_SYSR, NULL, dbi, task); dbi->errinfo->addr = addr; chk->good = FALSE; } } return (S_OKAY);}/************************************************************************* For each key field, check the key value in the key file*/static int chk_key( char *pgptr, int rid, DB_ADDR dba, DBINFO *dbi, DB_TASK *task){ int status = S_OKAY; short fd; register int i; register char *fptr; register FIELD_ENTRY *kf_ptr; register REC_KEY_INFO *kip; char key[MAXKEYSIZE]; kip = dbi->keys + rid; for (i = 0; i < kip->cnt; i++) { fd = kip->lst[i]; kf_ptr = task->field_table + fd; /* try to find the key, and prepare for an error */ /* make the next key to check */ if ((status = key_init(fd, task)) != S_OKAY) return (status); if (kf_ptr->fd_type == COMKEY) { key_bldcom(fd, pgptr + task->record_table[rid].rt_data, key, TRUE, task); fptr = key; } else fptr = pgptr + kf_ptr->fd_ptr; status = key_locpos(fptr, &dba, task); /* if the key is optional */ if (kf_ptr->fd_flags & OPTKEYMASK) { /* if the "stored" bit is set, but key not found */ if (r_tstopt(kf_ptr, pgptr, task)) { if (status != S_OKAY) pr_err(BAD_MOKEY, &fd, dbi, task); } /* else if the bit is not set, but the key was found */ else if (status == S_OKAY) pr_err(BAD_OKEY, &fd, dbi, task); } else if (status != S_OKAY) { /* a non-optional key must be found */ pr_err(BAD_MKEY, &fd, dbi, task); } } return (S_OKAY);}/*************************************************************************** For the record and each set this record owns, check the timestamp*/static void chk_stmp( register char *rec, int rid, FILE_NO fno, DB_BOOLEAN print, DBINFO *dbi, DB_TASK *task){ register int i; register REC_SET_INFO *oip; register SET_INFO *sip; register DB_ULONG ts_file; DB_ULONG ts_creat, ts_modif; ts_file = task->pgzero[fno].pz_timestamp; if (task->record_table[rid].rt_flags & TIMESTAMPED) { memcpy((char *) &ts_creat, rec + REC_STMP, sizeof(ts_creat)); memcpy((char *) &ts_modif, rec + REC_STMP + sizeof(ts_creat), sizeof(ts_modif));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?