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 + -
显示快捷键?