lm_fcns.c

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

C
947
字号
   Clear out a dead user's write-locked files*/void clear_user(    LMCB *lmcb,    int   user){    int      ii;    USERTAB *ut = &lmcb->usertab[user];    FILETAB *ft;    DEBUG2(DB_TEXT("clear_user(user = %d)\n"), user);    /* free all the write locks and close the files */    for (ft = lmcb->filetab, ii = 0; ii < lmcb->numfiles; ii++, ft++) {        if (!is_bit_set(ut->u_open, ii))            continue;        if (is_bit_set(ut->u_lock, ii)) {            if (ft->f_lockstat != 'x') {                freelock(lmcb, user, ii);                close_file(lmcb, user, ii);            }        }        else            close_file(lmcb, user, ii);    }     close_user(lmcb, user);}/* ======================================================================   Decrease the size of the user table as far as possible*/void adj_users(    LMCB *lmcb){    /* while the last entry is empty, keep removing it */    while (lmcb->numusers > 0 && !lmcb->usertab[lmcb->numusers - 1].u_name[0])        lmcb->numusers--;    /* If there is only one user, and he is dead, eliminate the entry */    if (usercount(lmcb) == 0 && lmcb->numusers > 0)        clear_user(lmcb, lmcb->numusers - 1);}/* ======================================================================   Decrease the size of the taf table as far as possible*/void adj_tafs(    LMCB *lmcb){    /* while the last entry is empty */    while(lmcb->numtafs > 0 && lmcb->taftab[lmcb->numtafs - 1].t_index == -1)        lmcb->numtafs--;}/* ======================================================================   Count the number of LIVE users*/int usercount(    LMCB *lmcb){    int      ii;    int      count;    USERTAB *ut;    /* An entry that is recovering itself is considered live because the       first user to login may need to recover itself (when exclusive locks       exist, and recovery is required).  This will allow external recovery       to be performed on the first user, even though the entry has been       preserved in the user table.  */    ut = lmcb->usertab;    for (ii = 0, count = 0; ii < lmcb->numusers; ii++, ut++) {        if (*ut->u_name && (ut->u_status == U_LIVE ||                ut->u_status == U_REC_MYSELF || ut->u_status == U_RECOVERING))            count++;    }    return count;}/* ======================================================================   Decrease the size of the file table as far as possible*/void adj_files(    LMCB *lmcb){    while (lmcb->numfiles > 0 &&           lmcb->filetab[lmcb->numfiles - 1].f_index == -1)       lmcb->numfiles--;}void send_lock(    LMCB *lmcb,    int   user,    int   status){    int      ii;    int     *p;    size_t   size;    size_t   locked_files = 0;    LR_LOCK  *msg;    FILETAB  *ft;    for (ft = lmcb->filetab, ii = 0; ii < lmcb->numfiles; ii++) {        if (is_bit_set(ft->f_lock, user))            locked_files++;    }    if (!locked_files)        reply_user(lmcb, user, NULL, 0, status);    else {        size = sizeof(LR_LOCK) + sizeof(int) * (locked_files - 1);        msg = psp_lmcAlloc(size);        msg->ntimestamps = locked_files;        p = msg->timestamps;        for (ft = lmcb->filetab, ii = 0; ii < lmcb->numfiles; ii++, ft++) {            if (is_bit_set(ft->f_lock, user))                *p++ = ft->f_timestamp;        }        reply_user(lmcb, user, msg, size, status);    }}/* ======================================================================   lock_reply()    Reply to all current lock requests that have timedout or a free   has occurred granting the lock requests in the queue.*/void lock_reply(    LMCB *lmcb){    int      ii;    int      repeat = 0;    USERTAB *ut;    do {        for (ut = lmcb->usertab, ii = 0; ii < lmcb->numusers; ii++, ut++) {            /* if this user is not alive, don't check anything */            if (!ut->u_name[0])                continue;            /* if this user is ready */            if (!ut->u_pending && ut->u_waiting) {                DEBUG2(DB_TEXT("\treplying to user # %d\n"), ii);                memset(ut->u_req, 0, lmcb->filebmbytes);                lmcb->locks_granted += ut->u_waiting;                ut->u_timer = 0;                ut->u_waiting = 0;                send_lock(lmcb, ii, L_OKAY);                continue;            }            if (ut->u_pending && ut->u_timeout >= 0 && ut->u_timer == 0) {                lmcb->locks_timedout += free_partial(lmcb, ii);                lmcb->locks_timedout += free_pending(lmcb, ii);                memset(ut->u_req, 0, lmcb->filebmbytes);                reply_user(lmcb, ii, NULL, 0, L_TIMEOUT);                repeat++;                continue;            }        }        if (repeat) {            DEBUG2(DB_TEXT("\trepeat = %d\n"), repeat);            lock_all(lmcb);        }    }    while (repeat--);}/* ======================================================================   Free all file locks that are part of a partial lock request*/int free_partial(    LMCB *lmcb,    int   user){    int      ii;    int      qind;    int      freed = 0;    short    locktype;    USERTAB *ut = &lmcb->usertab[user];    FILETAB *ft;    /* for each file in the file table */    for (ft = lmcb->filetab, ii = 0; ii < lmcb->numfiles; ii++, ft++) {        /* if the file was both requested and locked */        if (is_bit_set(ut->u_lock, ii) && is_bit_set(ut->u_req, ii)) {            /* Make sure that the queued request is not for an upgrade by               searching through the request queue (if any).  If this user               has a pending request that is an upgrade request, then the               original lock is pre-existing, and not to be freed at this               time.  */            qind = ft->f_queue;            while (qind != -1 && lmcb->queuetab[qind].q_user != user)                qind = lmcb->queuetab[qind].q_next;            if (qind != -1)                locktype = lmcb->queuetab[qind].q_locktype;            else                locktype = 'a';            /* fool it */               /* if not an upgrade request */            if (locktype != 'W' && locktype != 'X')            {                /* free this file */                freelock(lmcb, user, ii);                   freed++;                ut->u_waiting--;            }        }    }    return freed;}/* ======================================================================   Find and delete request queue entries for this user*/int free_pending(    LMCB *lmcb,    int   user){    int       ii;    int       qind;    int       qprev;    int       freed = 0;    USERTAB  *ut = &lmcb->usertab[user];    FILETAB  *ft;    QUEUETAB *qt = lmcb->queuetab;    /* for all files, while there are more pending requests */    for (ft = lmcb->filetab, ii = 0; ii < lmcb->numfiles; ii++, ft++) {        /* if the file is requested */        if (is_bit_set(ut->u_req, ii))        {            /* search through the request queue for this user's entry */            qind = ft->f_queue;            qprev = -1;            while (qind != -1) {                if (qt[qind].q_user == user) {                    /* this is the one to delete */                    /* if is the first one on the queue */                    if (qprev == -1) {                        /* it was the first on the queue */                        ft->f_queue = qt[qind].q_next;                    }                    else                    {                        /* point the previous to the next */                        qt[qprev].q_next = qt[qind].q_next;                    }                         /* free this entry */                    free_q(lmcb, qind);                                     freed++;                    if (--ut->u_pending == 0)                        return freed;                    break;                }                qprev = qind;                qind = qt[qind].q_next;            }        }    }    return freed;}/* ====================================================================== *//* return TRUE if map is all zeros */int is_map_zero(    DB_BYTE *map,    size_t   len){    while (len--) {        if (*map++ != '\0')            return 0;    }    return 1;}int count_bits(    DB_BYTE *map,    int      max){    int ii;    int temp;    for (ii = 0, temp = 0; ii < max; ii++) {        if (is_bit_set(map, ii))            temp++;    }    return temp;}int first_bit_set(    DB_BYTE *map,    int      max){    int ii = 0;    while (ii < max && !is_bit_set(map, ii))        ii++;    return ii;}/* ======================================================================   Get an available request queue entry*/int get_q(    LMCB *lmcb){    int qind;    if (lmcb->qHead == -1)        return -1;    qind = lmcb->qHead;    lmcb->qHead = lmcb->queuetab[qind].q_next;    return qind;}/* ======================================================================   Return a queue entry to the empty list*/void free_q(    LMCB *lmcb,    int   entry){    lmcb->queuetab[entry].q_next = lmcb->qHead;    lmcb->qHead = entry;}/* ======================================================================   Check for room in the request queue*/int room_q(    LMCB *lmcb,    int   req){    int       entry = lmcb->qHead;    QUEUETAB *qt = lmcb->queuetab;    while (req--) {        if (entry == -1)            return 0;        entry = qt[entry].q_next;    }    return 1;}/* ======================================================================   Place a queue entry at the head of a file's queue*/void ins_head(    LMCB *lmcb,    int   file,    int   qind){    FILETAB *ft = &lmcb->filetab[file];    lmcb->queuetab[qind].q_next = ft->f_queue;    ft->f_queue = qind;}/* ======================================================================   Place a queue entry at the end of a file's queue*/void ins_tail(    LMCB *lmcb,    int   file,    int   qind){    int      q;    FILETAB  *ft = &lmcb->filetab[file];    QUEUETAB *qt = lmcb->queuetab;    /* if this file does not have an existing queue */    if (ft->f_queue == -1)    {        /* put this entry at the head */        ft->f_queue = qind;    }    else    {        /* find the end of the queue */        q = ft->f_queue;        while (qt[q].q_next != -1)            q = qt[q].q_next;        /* point this last one to the new one */        qt[q].q_next = qind;    }    qt[qind].q_next = -1;}/* ======================================================================   Place a Record lock entry at the head of a file's queue*/void ins_Record(    LMCB *lmcb,    int   file,    int   qind){    int       q;    int       prev = 0;    FILETAB  *ft = &lmcb->filetab[file];    QUEUETAB *qt = lmcb->queuetab;    /* if this file does not have an existing queue */    if ((q = ft->f_queue) == -1) {        /* put this entry at the head */        ft->f_queue = qind;        qt[qind].q_next = -1;    }    else    {         if (qt[q].q_locktype == 'R') {              /* find the last 'R' request in the queue */              while (q != -1 && qt[q].q_locktype == 'R') {                  prev = q;                  q = qt[q].q_next;              }              if (q == -1) {                  qt[prev].q_next = qind;                  qt[qind].q_next = -1;              }              else {                  qt[qind].q_next = qt[prev].q_next;                  qt[prev].q_next = qind;              }         }         else {              qt[qind].q_next = ft->f_queue;              ft->f_queue = qind;         }    }}

⌨️ 快捷键说明

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