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

📄 dio.c

📁 db.* (pronounced dee-be star) is an advanced, high performance, small footprint embedded database fo
💻 C
📖 第 1 页 / 共 5 页
字号:
    else    {        pg_ptr->recently_used = 1;        pg_ptr->modified = TRUE;        if (release)        {            if (--(pg_ptr->holdcnt) < 0)                dberr(SYS_INVHOLD);        }    }    return (task->db_status);}/* ======================================================================    Release database page hold*/int EXTERNAL_FCN dio_release(DB_ADDR dba, int release, DB_TASK *task){    short       file;    DB_ULONG    us1, us2;    PAGE_ENTRY *pg_ptr = NULL;    DECODE_DBA(dba, &file, &us1);    file = (FILE_NO) NUM2INT(file, ft_offset);    us2 = (us1 - 1) / task->file_table[file].ft_slots;    if (dio_findpg(file, us2 + 1, &task->last_datapage, &pg_ptr, task) != S_OKAY)    {        dberr(S_FAULT);    }    else if (release)    {        if (--(pg_ptr->holdcnt) < 0)            dberr(SYS_INVHOLD);    }    return (task->db_status);}/* ======================================================================    Read record lock bit*/int INTERNAL_FCN dio_rrlb(    DB_ADDR  dba,    short   *rid,    DB_TASK *task){    FILE_NO     file;           /* file number */    F_ADDR      page;           /* page number */    F_ADDR      sno;            /* slot number */    short       spp;            /* slots per page */    off_t       offset;         /* lseek offset from start of file */    FILE_ENTRY *file_ptr;    PAGE_ENTRY *pg_ptr = NULL;    const SG   *sg;    DECODE_DBA(dba, &file, &sno);    file = (FILE_NO) NUM2INT(file, ft_offset);    file_ptr = &task->file_table[file];    spp = file_ptr->ft_slots;    page = ((sno - 1) / spp) + 1;    offset = PGHDRSIZE + (off_t)(sno - 1 - (page - 1) * spp) * file_ptr->ft_slsize;    /* This fcn always goes to disk on a read-locked file because multiple       users could update the same page.  If the file is write- or exclusely-       locked, then the cache can be used because the cache and disk are in       sync since no one else can update the file.  Also, if d_rlbclr() is       called in a trx, the disk does not get updated until d_trend().    */    if ((task->dbopen > 1) || task->excl_locks[file] || (task->app_locks[file] < 0))    {        if (dio_getpg(file, page, task->db_tag, &task->last_datapage,                      &pg_ptr, task) != S_OKAY)        {            /* this failure was a system level failure, not S_NOTFOUND! */            return (task->db_status);        }        if (pg_ptr->buff == NULL)            return (dberr(S_INVPTR));        /* record in cache - update only rlb in rid */        memcpy(rid, &pg_ptr->buff[offset], sizeof(short));    }    else    {        offset += page * file_ptr->ft_pgsize;        if ((sg = task->sgs[file]) != NULL)        {            off_t  begin;            off_t  off;            size_t size;            block_parms(offset, sizeof(short), &begin, &size, &off, sg);            if (dio_readfile(file, begin, task->enc_buff, size, 0,                    NULL, task) != S_OKAY)                return task->db_status;            (*sg->dec)(sg->data, task->enc_buff, size);            memcpy(&rid, (char *) task->enc_buff + off, sizeof(short));        }        else        {            if (dio_readfile(file, offset, rid, sizeof(short), 0, NULL,                    task) != S_OKAY)                return (task->db_status);        }        STAT_rlb_read(file, sizeof(short), task);    }    return (task->db_status);}/* ======================================================================    Write record lock bit*//*    Setting the RLB requires that both the cache and the disk be updated    at the same time if the file is locked, else just the disk when not    locked.    Clearing the RLB requires that both the cache and disk be updated when    locked, too.  However, if clearing in a trx, then update only the cache    because the d_trend() will write the cache to disk thus clearing the    RLB on disk.  When clearing the RLB in a trx, we need it to remain set    on disk until the end of the trx or to be not cleared if d_trabort()    is called.*/int INTERNAL_FCN dio_wrlb(    DB_ADDR  dba,    short    rid,    DB_TASK *task){    FILE_NO     file;       /* file number */    F_ADDR      page;       /* page number */    F_ADDR      sno;        /* slot number */    short       spp;        /* slots per page */    off_t       offset;     /* offset from start of page or file */    int         clr_in_trx; /* true if called from d_rlbclr in trx */    short       trid;       /* temp rid */    FILE_ENTRY *file_ptr;    PAGE_ENTRY *pg_ptr = NULL;    const SG   *sg;    if (task->dboptions & READONLY)        return (dberr(S_READONLY));    DECODE_DBA(dba, &file, &sno);    file = (FILE_NO) NUM2INT(file, ft_offset);    file_ptr = &task->file_table[file];    spp = file_ptr->ft_slots;    page = ((sno - 1) / spp) + 1;    offset = PGHDRSIZE + (off_t)(sno - 1 - (page - 1) * spp) * file_ptr->ft_slsize;    /* d_rlbclr() inside a trx requires a w-/x-lock, caught by d_rlbclr() */    clr_in_trx = !(rid & RLBMASK) && task->trans_id[0];    /* one-user or (x-locked or (not not-locked)) */    if (task->dbopen > 1 || task->excl_locks[file] || task->app_locks[file])    {        /* file is locked -- update the cache */        if (dio_getpg(file, page, task->db_tag, &task->last_datapage, &pg_ptr,                      task) != S_OKAY)        {            /* this failure was a system level failure, not S_NOTFOUND! */            return (task->db_status);        }        if (pg_ptr->buff == NULL)            return (dberr(S_INVPTR));        /* record in cache - update only rlb in rid */        memcpy(&trid, &pg_ptr->buff[offset], sizeof(short));        rid = (short) ((trid & ~((short) RLBMASK)) | (rid & RLBMASK));        memcpy(&pg_ptr->buff[offset], &rid, sizeof(short));        if (clr_in_trx)            pg_ptr->modified = TRUE;    }    if (! clr_in_trx)    {        /* update directly to disk (rlb part of record only) */        offset += page * file_ptr->ft_pgsize;        if ((sg = task->sgs[file]) != NULL)        {            /* If we have an encrypted database, we can't just update the                record lock bit field directly.  Instead we have to grab the               data around it on boundaries based on the block size of the               encryption algorithm and unencrypt it.  Then we can get the               record lock bit out, update it and copy it back, at which               time we can re-encrypt and re-write the block(s)*/            off_t  begin;            off_t  off;            size_t size;            block_parms(offset, sizeof(short), &begin, &size, &off, sg);            if (dio_readfile(file, begin, task->enc_buff, size, 0, NULL,                    task) != S_OKAY)                return task->db_status;            (*sg->dec)(sg->data, task->enc_buff, size);            memcpy(&trid, (char *) task->enc_buff + off, sizeof(short));            rid = (short) ((trid & ~((short) RLBMASK)) | (rid & RLBMASK));            /* write original rid out with modified rlb */            memcpy((char *) task->enc_buff + off, &rid, sizeof(short));            (*sg->enc)(sg->data, task->enc_buff, size);            if (dio_writefile(file, begin, task->enc_buff, size, 0,                    task) != S_OKAY)                return task->db_status;        }        else        {            if (dio_readfile(file, offset, &trid, sizeof(short), 0, NULL,                    task) != S_OKAY)                return (task->db_status);            rid = (short) ((trid & ~((short) RLBMASK)) | (rid & RLBMASK));            /* write original rid out with modified rlb */            if (dio_writefile(file, offset, &rid, sizeof(short), 0,                    task) != S_OKAY)                return (task->db_status);        }        STAT_rlb_read(file, sizeof(short), task);        STAT_rlb_write(file, sizeof(short), task);        commit_file(file_ptr->ft_desc, task);    }    return (task->db_status);}/* ======================================================================    Search a cache for page*/int INTERNAL_FCN dio_findpg(    FILE_NO file,               /* file table index */    F_ADDR page,                /* page in file */    PAGE_ENTRY **last_lu,       /* the last looked-up page */    PAGE_ENTRY **xpg_ptr,    DB_TASK *task){    PAGE_TABLE *pgtab = (file == task->ov_file) ? &task->cache->ix_pgtab : &task->cache->db_pgtab;    register PAGE_ENTRY *pg_ptr;    short bucket;    /* check if desired page was last one */    if (last_lu && *last_lu)    {        pg_ptr = *last_lu;        /* sanity check */        if (pg_ptr >= pgtab->pg_table         && pg_ptr <  pgtab->pg_table + pgtab->pgtab_sz)        {            if ((file == pg_ptr->file) && (page == pg_ptr->pageno))            {                if (xpg_ptr) *xpg_ptr = pg_ptr;                return (task->db_status);            }        }    }    /* perform hash lookup */    bucket = LU_HASH(file, page, pgtab->lookup_sz);    pg_ptr = pgtab->lookup[bucket];    while (pg_ptr && ((pg_ptr->file != file) || (pg_ptr->pageno != page)))    {        /* search the chain for this bucket */#ifdef DB_DEBUG        if (pg_ptr->next == pg_ptr)            return (dberr(SYS_HASHCYCLE));#endif        pg_ptr = pg_ptr->next;    }    if (last_lu) *last_lu = pg_ptr;    if (xpg_ptr) *xpg_ptr = pg_ptr;    if (!pg_ptr)        task->db_status = S_NOTFOUND;    return (task->db_status);}/* ======================================================================    Find page to replace in the single unified cache.    Returns S_FAULT if there are no available pages*/static int INTERNAL_FCN dio_findlru(    FILE_NO file,       /* file table index */    F_ADDR page,        /* page in file */    short pg_tag,    PAGE_ENTRY **rlu_ptr,    DB_TASK *task){    PAGE_TABLE *pgtab = (file == task->ov_file) ? &task->cache->ix_pgtab : &task->cache->db_pgtab;    short      *lru_page = &(task->cache->tag_table[pg_tag].lru_page);    int         pass, x;    PAGE_ENTRY *pg_ptr;#ifdef DB_DEBUG    if (*lru_page < 0 || *lru_page >= pgtab->pgtab_sz)        return (dberr(SYS_INVLRU));#endif    pg_ptr = &pgtab->pg_table[*lru_page]; *rlu_ptr = NULL;    for (pass = 2; pass > 0; --pass)    {        for (x = pgtab->pgtab_sz; x > 0; --x)        {            if (pg_ptr->recently_used)            {                if (pg_ptr->holdcnt == 0)                    pg_ptr->recently_used = 0;            }            else if (!pg_ptr->holdcnt)            {                *rlu_ptr = pg_ptr;                break;            }            if (++*lru_page >= pgtab->pgtab_sz)            {                *lru_page = 0;                pg_ptr = pgtab->pg_table;            }            else                ++pg_ptr;        }        if (*rlu_ptr)        {            if (++*lru_page >= pgtab->pgtab_sz)                *lru_page = 0;            return (task->db_status);        }    }    if (!(*rlu_ptr))        dberr(S_FAULT);    return (task->db_status);}/* ======================================================================*/static void INTERNAL_FCN dio_unhash(PAGE_ENTRY *pg_ptr, DB_TASK *task){    FILE_NO file = pg_ptr->file;    PAGE_TABLE *pgtab = (file == task->ov_file) ? &task->cache->ix_pgtab : &task->cache->db_pgtab;    short bucket;#ifdef DB_DEBUG    if (pg_ptr <  pgtab->pg_table     || pg_ptr >= pgtab->pg_table + pgtab->pgtab_sz)    {        dberr(SYS_INVPAGE);        return;    }#endif    if (pg_ptr->next)        pg_ptr->next->prev = pg_ptr->prev;    if (pg_ptr->prev)        pg_ptr->prev->next = pg_ptr->next;    else    {        bucket = LU_HASH(file, pg_ptr->pageno, pgtab->lookup_sz);        pgtab->lookup[bucket] = pg_ptr->next;    }    pg_ptr->next = pg_ptr->prev = NULL;}static void INTERNAL_FCN dio_rehash(PAGE_ENTRY *pg_ptr, DB_TASK *task){    FILE_NO file = pg_ptr->file;    PAGE_TABLE *pgtab = (file == task->ov_file) ? &task->cache->ix_pgtab : &task->cache->db_pgtab;    LOOKUP_ENTRY *lu_ptr;    short bucket;#ifdef DB_DEBUG    if (pg_ptr <  pgtab->pg_table     || pg_ptr >= pgtab->pg_table + pgtab->pgtab_sz)    {        dberr(SYS_INVPAGE);        return;    }#endif    bucket = LU_HASH(file, pg_ptr->pageno, pgtab->lookup_sz);    lu_ptr = &pgtab->lookup[bucket];    pg_ptr->next   = *lu_ptr;    *lu_ptr        = pg_ptr;    if (pg_ptr->next)        pg_ptr->next->prev = pg_ptr;}/* ======================================================================    Clear a page from the cache*/int INTERNAL_FCN dio_clrpage(PAGE_ENTRY *pg_ptr, DB_TASK *task){    dio_unhash(pg_ptr, task);    if (pg_ptr->file != task->ov_file)    {        if (pg_ptr->n_pg)            pg_ptr->n_pg->p_pg = pg_ptr->p_pg;        if (pg_ptr->p_pg)            pg_ptr->p_pg->n_pg = pg_ptr->n_pg;        else            task->pgzero[pg_ptr->file].pg_ptr = pg_ptr->n_pg;        pg_ptr->n_pg = pg_ptr->p_pg = NULL;    }    STAT_pages(pg_ptr->file, -1, task);    pg_ptr->file = -1;    pg_ptr->modified = 0;    pg_ptr->holdcnt = 0;    pg_ptr->ovfl_addr = 0L;    pg_ptr->recently_used = 0;    if (task->cache->tag_table[pg_ptr->tag].num_pages < 1)        return (dberr(SYS_INVPGCOUNT));    --task->cache->tag_table[pg_ptr->tag].num_pages;    return (task->db_status);}

⌨️ 快捷键说明

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