recover.c

来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 257 行

C
257
字号
/*************************************************************************** *                                                                         * * db.*                                                                    * * open source database kernel                                             * *                                                                         * * Copyright (c) 2000 Centura Software Corporation. All rights reserved.   * *                                                                         * * Use of this software, whether in source code format, or in executable,  * * binary object code form, is governed by the CENTURA OPEN SOURCE LICENSE * * which is fully described in the LICENSE.TXT file, included within this  * * distribution of source code files.                                      *  *                                                                         * **************************************************************************/#include "db.star.h"typedef struct RFT_ENTRY_S{    short pgsize;                    /* file page size */    DB_TCHAR fname[FILENMLEN];          /* file name */    RI_ENTRY rix;                       /* root index entry */}  RFT_ENTRY;                          /* recovery file table entry */static short nfiles;                   /* number of files in logged db */static RFT_ENTRY *rft = NULL;      /* db recovery file table */static int max_pg_size;                   /* max db page size */static char *pgbuf = NULL;         /* db page buffer */static long *ixbuf = NULL;         /* index page buffer *//* ======================================================================    Perform automatic database recovery*/int INTERNAL_FCN drecover(const DB_TCHAR *logfile, DB_TASK *task){    PSP_FH        lfh;              /* log file descriptor */    PSP_FH        dbf;              /* database file descriptor */    int           bm_size;    size_t        size;    unsigned long rd_opt;    F_ADDR        ix_pg_cnt, ip, ixp_addr, db_page,                  pz_base;    unsigned int  mask, wordpos, ixp_used;    int           slot, fno;    RFT_ENTRY    *rft_ptr;    DB_TCHAR      realLog[FILENMLEN], *ptr;        /* even with READONLY option set, attempt to recover */    rd_opt = task->dboptions & READONLY;    if (rd_opt)        task->dboptions &= ~READONLY;    /* Since all the LOG files for a database group must be in the same       physical place, and since the lockmgr will never ask you to recover       anyone using a different TAF--each database group having only one       TAF--and since userA's log path may be invalid for userB doing the       recovery, userB can find userA's log file by using userB's log path.    */    vtstrcpy(realLog, task->dblog);    ptr = vtstrrchr(realLog, DIRCHAR);    if (ptr)                      /* keep your path, lose your file */        ptr[1] = DB_TEXT('\0');    else        realLog[0] = DB_TEXT('\0');    ptr = vtstrrchr(logfile, DIRCHAR);    if (ptr)                      /* lose their path, keep their file */        ++ptr;    else        ptr = (DB_TCHAR *) logfile; /* cast kills const/volatile warning */    vtstrcat(realLog, ptr);               /* add their file to your path */        /* ptr to const data, not const ptr to data--compiler warning */    logfile = (const DB_TCHAR *) realLog;    /* allocate memory for index page buffer */    if ((ixbuf = (long *) psp_getMemory(IX_EPP * sizeof(F_ADDR), 0)) == NULL)        goto memerr;    /* open log file */    if ((lfh = open_b(logfile, O_RDWR, PSP_FLAG_SYNC, task)) == NULL)        goto logerr;    /* read number of files in logged db */    if (psp_fileSeekRead(lfh, 0, &nfiles, sizeof(short)) < (int) sizeof(short))        goto readerr;    rft = (RFT_ENTRY *) psp_getMemory(nfiles * sizeof(RFT_ENTRY), 0);    if (rft == NULL)        goto memerr;    /* read page size and name of each file in logged db */    size = sizeof(short) + (FILENMLEN * sizeof(DB_TCHAR));    for (max_pg_size = fno = 0, rft_ptr = rft; fno < nfiles; ++fno, ++rft_ptr)    {        if (psp_fileSeekRead(lfh, sizeof(short) + fno * size, rft_ptr,                size) < (int) size)            goto readerr;        if (rft_ptr->pgsize > max_pg_size)            max_pg_size = rft_ptr->pgsize;    }        /* allocate page buffer */    if ((pgbuf = psp_getMemory(max_pg_size, 0)) == NULL)        goto memerr;    /* read root index for each file */    size = sizeof(short) + size * nfiles;    for (fno = 0, rft_ptr = rft; fno < nfiles; ++fno, ++rft_ptr)    {        if (psp_fileSeekRead(lfh, size + fno * RI_ENTRY_IOSIZE, &rft_ptr->rix,                RI_ENTRY_IOSIZE) < (int) RI_ENTRY_IOSIZE)            goto readerr;    }    /* read index page ri_bitmaps */    for (fno = 0, rft_ptr = rft; fno < nfiles; ++fno, ++rft_ptr)    {        if (rft_ptr->rix.base)        {            bm_size = RI_BITMAP_SIZE(rft_ptr->rix.pg_cnt) * sizeof(int);            rft_ptr->rix.ri_bitmap = (int *) psp_getMemory(bm_size, 0);            if (rft_ptr->rix.ri_bitmap == NULL)                goto memerr;            if (psp_fileSeekRead(lfh, rft_ptr->rix.base, rft_ptr->rix.ri_bitmap,                    bm_size) < bm_size)                goto readerr;        }    }    /* update db files */    for (fno = 0, rft_ptr = rft; fno < nfiles; ++fno, ++rft_ptr)    {        if (rft_ptr->rix.base == 0L)            continue;                if ((dbf = open_b(rft_ptr->fname, O_RDWR, PSP_FLAG_SYNC, task)) == NULL)            goto fileerr;                ix_pg_cnt = IX_SIZE(rft_ptr->rix.pg_cnt);        size = rft_ptr->pgsize;                /* read file's index pages */        for (ip = 0; ip < ix_pg_cnt; ++ip)        {            wordpos = (unsigned int) (ip / BUI);            mask = 1 << (BUI - 1 - (unsigned int) (ip - (F_ADDR) wordpos * BUI));            ixp_used = rft_ptr->rix.ri_bitmap[wordpos] & mask;            if (ixp_used)            {                /* read index page from log file */                ixp_addr = rft_ptr->rix.base + RI_BITMAP_SIZE(rft_ptr->rix.pg_cnt) *                        sizeof(int) + ip * IX_PAGESIZE;                if (psp_fileSeekRead(lfh, ixp_addr, ixbuf,                        IX_PAGESIZE) < IX_PAGESIZE)                    goto readerr;                /* scan each db page entry on index page */                for (slot = 0; slot < IX_EPP; ++slot)                {                    if (ixbuf[slot])                    {                        long curr_time;                        db_page = (F_ADDR) (ip * IX_EPP + slot + 1);                        /* read db page from log file */                        if (psp_fileSeekRead(lfh, ixbuf[slot], pgbuf,                                size) < (int) size)                            goto readerr;        #ifdef DB_DEBUG                        if (task->db_status == S_OKAY && (task->db_debug & PAGE_CHECK))                        {                            DB_ADDR page_id;                            ENCODE_DBA(min(fno, 255), db_page, &page_id);                            if (memcmp(pgbuf, &page_id, sizeof(DB_ADDR)) != 0)                            {                                dberr(SYS_INVLOGPAGE);                                goto readerr;                            }                        }#endif                        /* write db page to db file */                        curr_time = psp_timeSecs(); /* get the current time */                        memcpy(pgbuf, &curr_time, sizeof(curr_time));                        if (psp_fileSeekWrite(dbf, db_page * size, pgbuf,                                size) < (int) size)                            goto writeerr;                    }                }            }        }        /* read page zero from log file */        if (rft_ptr->rix.pz_modified)        {            pz_base = rft_ptr->rix.base + RI_BITMAP_SIZE(rft_ptr->rix.pg_cnt) *                      sizeof(int);            pz_base += IX_SIZE(rft_ptr->rix.pg_cnt) * IX_PAGESIZE;                      if (psp_fileSeekRead(lfh, pz_base, pgbuf, PGZEROSZ) <                    (int) PGZEROSZ)                goto readerr;                        /* write page zero to db file */            if (psp_fileSeekWrite(dbf, 0, pgbuf, PGZEROSZ) < (int) PGZEROSZ)                goto writeerr;        }        psp_fileClose(dbf);        psp_freeMemory(rft_ptr->rix.ri_bitmap, 0);    }    psp_freeMemory(rft, 0);    psp_freeMemory(pgbuf, 0);    psp_freeMemory(ixbuf, 0);    psp_fileClose(lfh);    if (task->db_status == S_OKAY && tafbuf.user_count > 0)        --tafbuf.user_count;    goto exit;fileerr:    dberr(S_NOFILE);    goto exit;memerr:    dberr(S_NOMEMORY);    goto exit;logerr:    goto exit;readerr:    dberr(S_BADREAD);    goto exit;writeerr:    dberr(S_BADWRITE);    goto exit;exit:    task->dboptions |= rd_opt;    return (task->db_status);}

⌨️ 快捷键说明

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