lcknfree.c

来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 633 行 · 第 1/2 页

C
633
字号
/*************************************************************************** *                                                                         * * 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"#include "rntmint.h"static int INTERNAL_FCN process_lock(struct lock_descr *, DB_TCHAR, DB_TASK *);static int INTERNAL_FCN keep_locks(struct lock_descr *, DB_TASK *);static int INTERNAL_FCN free_files(struct lock_descr *, DB_TASK *);static int INTERNAL_FCN lock_files(int, LOCK_REQUEST *, DB_TASK *);#define KEYMARK ((unsigned) 30000)/* ======================================================================    Establish record file locks*/int INTERNAL_FCN dreclock(int rec, DB_TCHAR *lock_type, DB_TASK *task, int dbn){    LOCK_REQUEST  lr;    RECORD_ENTRY *rec_ptr;    int           nrec;    if (nrec_check(rec, &nrec, &rec_ptr, task) != S_OKAY)        return (task->db_status);    lr.item = rec;    lr.type = *lock_type;    return (dlock(1, &lr, task, dbn));}/* ======================================================================    Establish set file locks*/int INTERNAL_FCN dsetlock(int set, DB_TCHAR *lock_type, DB_TASK *task, int dbn){    LOCK_REQUEST lr;    SET_ENTRY   *set_ptr;    int          nset;    if (nset_check(set, &nset, &set_ptr, task) != S_OKAY)        return (task->db_status);    lr.item = set;    lr.type = *lock_type;    return (dlock(1, &lr, task, dbn));}/* ======================================================================    Lock key file*/int INTERNAL_FCN dkeylock(long key, DB_TCHAR *lock_type, DB_TASK *task, int dbn){    int           fld,                  rec;    LOCK_REQUEST  lr;    RECORD_ENTRY *rec_ptr;    FIELD_ENTRY  *fld_ptr;    if (nfld_check(key, &rec, &fld, &rec_ptr, &fld_ptr, task) != S_OKAY)        return (task->db_status);    if (fld_ptr->fd_key == NOKEY)        return (dberr(S_NOTKEY));    lr.item = (unsigned int)fld + KEYMARK;    lr.type = *lock_type;    return (dlock(1, &lr, task, dbn));}/* ======================================================================    Lock a group of records and/or sets*/int INTERNAL_FCN dlock(int count, LOCK_REQUEST *lrpkt, DB_TASK *task, int dbn){    register unsigned int  item;    register int           i;    register LOCK_REQUEST *lrpkt_ptr;    struct lock_descr     *ld_ptr = NULL;    if (task->dbopen >= 2)        return (task->db_status);    task->lock_pkt->nfiles = 0;    for (i = 0, lrpkt_ptr = lrpkt; (task->db_status == S_OKAY) && (i < count);         ++i, ++lrpkt_ptr)    {        if (lrpkt_ptr->item >= KEYMARK)        {            item = task->field_table[lrpkt_ptr->item - KEYMARK].fd_keyno;            ld_ptr = &task->key_locks[item];        }        else if (lrpkt_ptr->item >= SETMARK)        {            item = NUM2INT(lrpkt_ptr->item - SETMARK, st_offset);            if (item < (unsigned) ORIGIN(st_offset) ||                item >= (unsigned) (DB_REF(Size_st) + ORIGIN(st_offset)))                dberr(S_INVSET);            else                ld_ptr = &task->set_locks[item];        }        else if (lrpkt_ptr->item >= RECMARK)        {            item = NUM2INT(lrpkt_ptr->item - RECMARK, rt_offset);            if (item < (unsigned) ORIGIN(rt_offset) ||                item >= (unsigned) (DB_REF(Size_rt) + ORIGIN(rt_offset)))                dberr(S_INVREC);            else if (task->record_table[item].rt_flags & STATIC)                dberr(S_STATIC);            else                ld_ptr = &task->rec_locks[item];        }        else            dberr(S_INVNUM);        if (task->db_status == S_OKAY)        {            process_lock(ld_ptr, (DB_TCHAR) lrpkt_ptr->type, task);            /* if process_lock() fails, break out of loop after i is incremented */        }        else            break;    }    if (task->db_status == S_OKAY)        lock_files(count, lrpkt, task);    else        count = i;  /* only reset as many as were processed */    if (task->db_status != S_OKAY)    {        /* reset lock descriptor tables to previous state */        for (i = 0, lrpkt_ptr = lrpkt; i < count; ++i, ++lrpkt_ptr)        {            if (lrpkt_ptr->item >= KEYMARK)            {                item = task->field_table[lrpkt_ptr->item - KEYMARK].fd_keyno;                ld_ptr = &task->key_locks[item];            }            else if (lrpkt_ptr->item >= SETMARK)            {                item = NUM2INT(lrpkt_ptr->item - (unsigned) SETMARK, st_offset);                ld_ptr = &task->set_locks[item];            }            else if (lrpkt_ptr->item >= RECMARK)            {                item = NUM2INT(lrpkt_ptr->item - (unsigned) RECMARK, rt_offset);                ld_ptr = &task->rec_locks[item];            }            else                continue;            ld_ptr->fl_type = ld_ptr->fl_prev;        }    }    return (task->db_status);}/* ======================================================================    Process set/record lock*/static int INTERNAL_FCN process_lock(struct lock_descr *ld_ptr, DB_TCHAR type,                                     DB_TASK *task){    register int            fl_lc;                 /* loop control */    FILE_NO                 fno;    register unsigned short i;    register DB_LOCKREQ    *lockreq_ptr;    FILE_NO                *fl_ptr;    FILE_NO                 fref;    ld_ptr->fl_prev = ld_ptr->fl_type;    switch (type)    {        case DB_TEXT('k'):            if (!task->trans_id[0])                dberr(S_NOTRANS);            else if (ld_ptr->fl_prev == DB_TEXT('f'))                dberr(S_NOTLOCKED);            else if (ld_ptr->fl_prev != DB_TEXT('x'))                return (keep_locks(ld_ptr, task));            break;        case DB_TEXT('r'):            if (ld_ptr->fl_prev != DB_TEXT('f'))                dberr(S_NOTFREE);            else                ld_ptr->fl_type = DB_TEXT('r');            break;        case DB_TEXT('w'):            if (!task->trans_id[0])                dberr(S_NOTRANS);            else if (ld_ptr->fl_prev != DB_TEXT('f') &&                    ld_ptr->fl_prev != DB_TEXT('r'))                dberr(S_NOTFREE);            else                ld_ptr->fl_type = DB_TEXT('w');            break;        case DB_TEXT('x'):            if (ld_ptr->fl_prev != DB_TEXT('f') &&                    ld_ptr->fl_prev != DB_TEXT('r'))                dberr(S_NOTFREE);            else                ld_ptr->fl_type = DB_TEXT('x');            break;        default:            dberr(S_BADTYPE);    }    if (task->db_status == S_OKAY)    {        /* build lock request packet */        fl_ptr = (FILE_NO *) ld_ptr->fl_list;        for (fl_lc = ld_ptr->fl_cnt; --fl_lc >= 0; ++fl_ptr)        {            fref = task->file_refs[fno = *fl_ptr];            if (fref == -1)                continue;      /* file is TEMPORARY */            for ( i = 0, lockreq_ptr = task->lock_pkt->locks;                  (i < task->lock_pkt->nfiles) && (lockreq_ptr->fref != fref);                  ++i, ++lockreq_ptr)                ; /* null statement */            if (i < task->lock_pkt->nfiles)            {                /* file already is in lock request packet */                if (lockreq_ptr->type == DB_TEXT('r') ||                        ld_ptr->fl_type == DB_TEXT('x'))                    lockreq_ptr->type = ld_ptr->fl_type;            }            else if (!task->excl_locks[fno] && (!task->app_locks[fno] ||                    (ld_ptr->fl_type == DB_TEXT('w') &&                    task->app_locks[fno] > 0) ||                    (ld_ptr->fl_type == DB_TEXT('x'))))            {                /* add to lock request packet */                ++task->lock_pkt->nfiles;                lockreq_ptr->fref = fref;                lockreq_ptr->type = ld_ptr->fl_type;            }        }    }    return task->db_status;}/* ======================================================================    Lock database files*/static int INTERNAL_FCN lock_files(    int           count,    LOCK_REQUEST *lrpkt,    DB_TASK      *task){    register int          fl_lc;                 /* loop control */    struct lock_descr    *ld_ptr;    FILE_NO               fno;    register unsigned int item;    int                   l;    LOCK_REQUEST         *lrpkt_ptr;    int                  *appl_ptr;    int                  *excl_ptr;    FILE_NO              *fl_ptr;    DB_BOOLEAN            clearStatic;    if (send_lock_pkt(NULL, task) == S_OKAY)    {        /* update task->app_locks and excl_lock tables */        for (l = 0, lrpkt_ptr = lrpkt; l < count; ++l, ++lrpkt_ptr)        {            if (lrpkt_ptr->type == DB_TEXT('k'))                continue;               /* skip keep lock requests */            /* process each record/set lock */            if (lrpkt_ptr->item >= KEYMARK)            {                clearStatic = 0;                item = task->field_table[lrpkt_ptr->item - KEYMARK].fd_keyno;                ld_ptr = &task->key_locks[item];            }            else if (lrpkt_ptr->item >= SETMARK)            {                /* Since all the records in the file are static, the file will                    be flagged as static.  However, the set pointers CAN be                    updated in a static record, thus requiring the pages to be                    read in again.                */                clearStatic = 1;                item = NUM2INT(lrpkt_ptr->item - (unsigned) SETMARK, st_offset);

⌨️ 快捷键说明

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