⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ovfcns.c

📁 db.* (pronounced dee-be star) is an advanced, high performance, small footprint embedded database fo
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************** *                                                                         * * 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.                                      *  *                                                                         * **************************************************************************//*------------------------------------------------------------------------    contains the following routines:        o_setup:       Initialize the overflow control data for a database open        o_init:        Initialize the overflow control data at trx start        o_fileinit:    Initialize the overflow data that depends on file size        o_search:      Search the overflow for a specific page        o_write:       Write a cache page to the overflow        o_pzwrite:     Write page zero to the overflow file        o_flush:       Flush the transaction recovery data to the overflow file        o_update:      Update the database from the data in the overflow file        o_pages:       Return file's page count at tx start        o_free:        Free dynamically allocated data        o_close:       Close the overflow file------------------------------------------------------------------------*/#include "db.star.h"/* Internal function prototypes */static void INTERNAL_FCN set_ixpbit(int, F_ADDR, DB_TASK *);static unsigned int INTERNAL_FCN ixp_used(int, F_ADDR, DB_TASK *);static F_ADDR INTERNAL_FCN oaddr_of_ixp(int, F_ADDR, DB_TASK *);static void INTERNAL_FCN ov_header_init(DB_TASK *);/* ======================================================================    Index page used test*/static unsigned int INTERNAL_FCN ixp_used(    int file,    F_ADDR ipno,    DB_TASK *task){    register unsigned int mask;    RI_ENTRY             *ri_ptr;    unsigned int          wordpos;    wordpos = (unsigned int) (ipno / BUI);    mask = 1 << ((BUI - 1) - (unsigned int) ((ipno - (F_ADDR) wordpos * BUI)));    ri_ptr = &task->root_ix[file];    return ri_ptr->ri_bitmap[wordpos] & mask;}/* ======================================================================    set index page used bit*/static void INTERNAL_FCN set_ixpbit(int file, F_ADDR ipno, DB_TASK *task){    register unsigned int mask;    RI_ENTRY             *ri_ptr;    unsigned int          wordpos;    wordpos = (unsigned int) (ipno / BUI);    mask = 1 << ((BUI - 1) - (unsigned int) ((ipno - (F_ADDR) wordpos * BUI)));    ri_ptr = &task->root_ix[file];    ri_ptr->ri_bitmap[wordpos] |= mask;}/* ======================================================================    Compute address of index page in overflow file*/static F_ADDR INTERNAL_FCN oaddr_of_ixp(    int file,    F_ADDR ipno,    DB_TASK *task){    register RI_ENTRY *ri_ptr;    ri_ptr = &task->root_ix[file];    return (ri_ptr->base + RI_BITMAP_SIZE(ri_ptr->pg_cnt) * sizeof(int) +              ipno * IX_PAGESIZE);}/*  ======================================================================    Initialize the overflow control data for a database open*/int EXTERNAL_FCN o_setup(DB_TASK *task){    int           ft_lc;                       /* loop control */    size_t        new_size;    size_t        old;    FILE_ENTRY   *file_ptr;    RI_ENTRY     *ri_ptr;    if (!task->ov_setup_done)    {        DB_TCHAR *userid = (task->dbuserid[0]) ?  (DB_TCHAR *) task->dbuserid :                                                  (DB_TCHAR *) DB_TEXT("db.star");        /* create and initialize log file */        if (!task->dblog[0])        {            vtstrncpy(task->dblog, userid, DBNMLEN);            task->dblog[DBNMLEN] = 0;            vtstrcat(task->dblog, DB_TEXT(".log"));        }        else        {            if (psp_pathIsDir(task->dblog))            {                /* directory only, add default file name */                vtstrncat(task->dblog, userid, DBNMLEN);                vtstrcat(task->dblog, DB_TEXT(".log"));            }        }    }    task->ov_file = task->size_ft;    /* allocate and initialize root index space */    new_size = task->size_ft * sizeof(RI_ENTRY);    old =  task->old_size_ft * sizeof(RI_ENTRY);    if (alloc_table((void **) &task->root_ix, new_size, old, task) != S_OKAY)        return task->db_status;    for ( ft_lc = task->size_ft, ri_ptr = &task->root_ix[task->old_size_ft];          --ft_lc >= task->old_size_ft; ++ri_ptr)        ri_ptr->ri_bitmap = NULL;    task->cache_ovfl = FALSE;    /* initialize the task->file_table entry for the overflow file */    file_ptr = &task->file_table[task->ov_file];    vtstrcpy(file_ptr->ft_name, task->dblog);    file_ptr->ft_status = CLOSED;    file_ptr->ft_type = DB_OVERFLOW;    file_ptr->ft_slots = 1;    file_ptr->ft_slsize = IX_PAGESIZE;    file_ptr->ft_pgsize = IX_PAGESIZE;    file_ptr->ft_flags |= NOT_TTS_FILE;    task->ov_setup_done = TRUE;        /* set the initial useable address in the overflow file */    ov_header_init(task);    return (task->db_status);}/* ======================================================================    Initialize overflow/log processing at start of transaction*/int INTERNAL_FCN o_init(DB_TASK *task){    PSP_FH               fh;             /* File handle */    register FILE_NO     ft_lc;            /* loop control */    register FILE_ENTRY *file_ptr;             RI_ENTRY   *ri_ptr;    unsigned long        sav_opt;    /* Create the log file if necessary.  Truncate it to zero bytes.       write the needed stuff to it.  Close the file.  The one assumption       being made here is that the log file is NOT open at this point.    */    if (!task->ov_header_written || task->dboptions & TRUNCATELOG)    {        /* even with READONLY option set, attempt to creat log file */        sav_opt = task->dboptions;        task->dboptions &= ~READONLY;        /* initialize log file */        fh = open_b(task->dblog, O_RDWR | O_CREAT | O_TRUNC, 0, task);        task->dboptions = sav_opt;        if (fh == NULL)            return (dberr(S_DBLACCESS));        STAT_log_open(task);        /* write file count to overflow file */        psp_fileSeek(fh, 0);        if (psp_fileWrite(fh, &task->size_ft, sizeof(short)) < (int) sizeof(short))            return (dberr(S_BADWRITE));        STAT_log_write(sizeof(short), task);        /* write file page sizes and names to overflow file */        for ( ft_lc = task->size_ft, file_ptr = task->file_table; --ft_lc >= 0; ++file_ptr)        {            if (psp_fileWrite(fh, &file_ptr->ft_pgsize,                    sizeof(short)) < (int) sizeof(short))            {                psp_fileClose(fh);                return (dberr(S_BADWRITE));            }            STAT_log_write(sizeof(short), task);            if (psp_fileWrite(fh, file_ptr->ft_name, FILENMLEN *                sizeof(DB_TCHAR)) < FILENMLEN * (int) sizeof(DB_TCHAR))            {                psp_fileClose(fh);                return (dberr(S_BADWRITE));            }            STAT_log_write(FILENMLEN * sizeof(DB_TCHAR), task);        }        psp_fileClose(fh);        task->ov_header_written = TRUE;    /* set to false by ov_header_init() */    }    /* reset start address on log file */    task->ov_nextaddr = task->ov_initaddr;    task->cache_ovfl = FALSE;    /* free any used root index entries */    for (ft_lc = 0; ft_lc < task->size_ft; ft_lc++)    {        ri_ptr = &task->root_ix[ft_lc];        if (ri_ptr->ri_bitmap)        {            psp_freeMemory(ri_ptr->ri_bitmap, 0);            memset(ri_ptr, '\0', sizeof(*ri_ptr));        }    }    return (task->db_status);}/* ======================================================================    Initialize the overflow data that depends on file size*/int INTERNAL_FCN o_fileinit(FILE_NO file, DB_TASK *task){    int       bm_size;    /* Ri_bitmap size in unsigned int units */    F_ADDR    pz_base;    /* was page zero base address */    RI_ENTRY *ri_ptr;    ri_ptr = &task->root_ix[file];    if (ri_ptr->ri_bitmap == NULL)      /* only initialize once */    {        /* fill out the task->root_ix entry for this file */        ri_ptr->pg_cnt = dio_pages(file, task);   /* Number of pages excluding page 0 */        if (ri_ptr->pg_cnt <= 0)            ri_ptr->pg_cnt = (F_ADDR) 1;        ri_ptr->base = task->ov_nextaddr;        pz_base = ((F_ADDR) (IX_BASE(file, ri_ptr->pg_cnt) +                  (IX_SIZE(ri_ptr->pg_cnt) * IX_PAGESIZE)));        task->ov_nextaddr += (F_ADDR) (pz_base + PGZEROSZ - BM_BASE(file));        bm_size = RI_BITMAP_SIZE(ri_ptr->pg_cnt);        ri_ptr->ri_bitmap = (int *) psp_getMemory(bm_size * sizeof(int), 0);        if (ri_ptr->ri_bitmap == NULL)            return (dberr(S_NOMEMORY));        memset(ri_ptr->ri_bitmap, 0, bm_size * sizeof(int));    }    return (task->db_status);}/* ======================================================================    Search the overflow for a specific page*/int INTERNAL_FCN o_search(    FILE_NO  file,    F_ADDR   page,    F_ADDR  *o_addr,    DB_TASK *task){    int         ent;        /* index page entry */    F_ADDR      ipno;       /* Index page of data page */    F_ADDR      ip_addr;    /* Address of ix page in ovfl */    F_ADDR     *eptr;       /* Ptr to index page entry */    PAGE_ENTRY *ixpg_ptr;    if (page > task->root_ix[file].pg_cnt)        *o_addr = 0L;                    /* Can't be in overflow */    else    {        /* Search index */        ipno = (page - 1) / IX_EPP;        if (ixp_used(file, ipno, task))        {            /* Check the index page */            ip_addr = oaddr_of_ixp(file, ipno, task);            if (dio_getpg(task->ov_file, ip_addr, task->ix_tag,                          &task->last_ixpage, &ixpg_ptr, task) == S_OKAY)            {                if (ixpg_ptr->buff == NULL)                    return (dberr(S_INVPTR));                /* get ovfl address of db page */                ent = (int) (page - 1 - ipno * IX_EPP);                eptr = (F_ADDR *) (ixpg_ptr->buff + (sizeof(F_ADDR) * ent));                *o_addr = *eptr;                ixpg_ptr->recently_used = TRUE;            }        }        else            *o_addr = 0L;        /* Not in overflow */    }    return task->db_status;}/* ======================================================================    Write a cache page to the overflow*/int INTERNAL_FCN o_write(PAGE_ENTRY *pg_ptr, DB_TASK *task){    int         ent;           /* index page entry */    F_ADDR      ip_addr;       /* Address of index page in ovfl */    F_ADDR      ipno;          /* Index page number */    F_ADDR      db_page;       /* Database page # of cache page */    F_ADDR     *eptr;          /* Ptr to entry in index page */    FILE_NO     fno;           /* file number */    PAGE_ENTRY *ixpg_ptr;    /**********************************************************************        The cache page will be written in 1 of 3 manners.        1: if the ovfl_addr of the cache page != 0L, the page is written            directly to that address in the overflow file.        2: if the page number to be written is larger than the number of            pages in the database file, it is written to the end of the data            base file it belongs to, at the proper address for that page.        3: otherwise, the page is added to end of the overflow file and            the index is updated with its address.    **********************************************************************/    fno = pg_ptr->file;    if (pg_ptr->ovfl_addr != 0 || pg_ptr->pageno > task->root_ix[fno].pg_cnt)    {        /* write page to end of db file or to overflow file */        dio_out(pg_ptr, task);    }    else    {        /* Add page to end of overflow */        db_page = pg_ptr->pageno;        ipno = (db_page - 1) / IX_EPP;        ip_addr = oaddr_of_ixp(fno, ipno, task);        /* write db page to overflow file and read index page into cache */        pg_ptr->ovfl_addr = task->ov_nextaddr;        task->ov_nextaddr += task->file_table[fno].ft_pgsize;        if (dio_out(pg_ptr, task) != S_OKAY ||                dio_getpg(task->ov_file, ip_addr, task->ix_tag,

⌨️ 快捷键说明

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