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