lmcore.c
来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 1,370 行 · 第 1/3 页
C
1,370 行
psp_lmcFree(msg); reply_user(lmcb, ii, NULL, 0, L_OKAY); DEBUG5(DB_TEXT("Adding user:\n\tuser name: %s\n") DB_TEXT("\tuser table entry %hd\n\ttaf table entry: %hd\n") DB_TEXT("\tconnection: %08X\n"), ut->u_name, ii, taf, user) return;unavail: psp_lmcFree(msg); reply_non_user(lmcb, user, NULL, 0, L_UNAVAIL);}static void l_logout( LMCB *lmcb, int user, void *msg){ USERTAB *ut = &lmcb->usertab[user]; reply_user(lmcb, user, NULL, 0, L_OKAY); close_user(lmcb, user);}static void l_terminate( LMCB *lmcb, int user, void *msg){ DEBUG2(DB_TEXT("l_terminate(user = %d)\n"), user); reply_non_user(lmcb, user, NULL, 0, L_OKAY); term_flag = 1;}static void l_clearuser( LMCB *lmcb, int user, LM_USERID *msg){ short ii; USERTAB *ut = lmcb->usertab; DEBUG2(DB_TEXT("l_clearuser(user = %d)\n"), user) for (ii = 0; ii < lmcb->numusers; ii++, ut++) { if (vtstrcmp(ut->u_name, msg->dbuserid) == 0) { dead_user(lmcb, ii, 1); break; } } reply_non_user(lmcb, user, NULL, 0, L_OKAY);}static int chk_recover( LMCB *lmcb, int user, int type){ int taf; short recstat; USERTAB *ut = &lmcb->usertab[user]; USERTAB *rt; TAFTAB *tt; LR_RECOVER *recover; if ((taf = ut->u_taf) == -1) { reply_user(lmcb, user, NULL, 0, L_UNAVAIL); return 1; } /* Check to see if recover needs to be done for somebody or if recover is already in progress */ tt = &lmcb->taftab[taf]; if ((recstat = tt->t_status) == REC_NEEDED) { tt->t_status = REC_PENDING; rt = &lmcb->usertab[ut->u_recuser = tt->t_recuser]; rt->u_status = U_BEING_REC; recover = psp_lmcAlloc(sizeof(LR_RECOVER)); vtstrcpy(recover->logfile, fileid_get(lmcb->fidtab, rt->u_logfile)); reply_user(lmcb, user, recover, sizeof(LR_RECOVER), L_RECOVER); return 1; } if (recstat == REC_PENDING || (recstat == REC_EXTERNAL && (type != L_DBOPEN || tt->t_recuser != user))) { reply_user(lmcb, user, NULL, 0, L_UNAVAIL); return 1; } return 0;}static void l_dbopen( LMCB *lmcb, int user, LM_DBOPEN *msg){ short ii; short jj; long kk; short new = 0; short avail; short count; short open_slots; size_t resp_size; USERTAB *ut = &lmcb->usertab[user]; FILETAB *ft; LR_DBOPEN *response; DB_TCHAR *names; DB_TCHAR filename[FILENMLEN]; DB_TCHAR lastname[FILENMLEN]; DEBUG4(DB_TEXT("l_dbopen(user = %d, type = %c, nfiles = %d)\n"), user, msg->type, msg->nfiles) DEBUG2(DB_TEXT("\tnumfiles = %d\n"), lmcb->numfiles) if (msg->nfiles > lmcb->maxfiles) goto unavail; if (chk_recover(lmcb, user, L_DBOPEN)) { psp_lmcFree(msg); return; } /* first, verify that 1) if this is an exclusive open then none of the files are already open and 2) if this is a shared open the none of the files are already exclusively opened. */ filename[0] = lastname[0] = 0; for (names = msg->fnames, ii = 0; ii < msg->nfiles; ii++) { count = (short) *names++; vtstrcpy(filename, lastname); vtstrcpy(filename + count, names); vtstrcpy(lastname, filename); names += vtstrlen(names) + 1; if (vtstrlen(filename) == 0) goto unavail; if ((kk = fileid_fnd(lmcb->fidtab, filename)) == -1) { new++; continue; } for (ft = lmcb->filetab, jj = 0; jj < lmcb->numfiles; jj++, ft++) { if (kk != ft->f_index) continue; if (msg->type == 'x' || ft->f_lockstat == 'X') goto unavail; if (ft->f_taf != ut->u_taf) { psp_lmcFree(msg); reply_user(lmcb, user, NULL, 0, L_BADTAF); return; } break; } } DEBUG2(DB_TEXT("\tnew files = %hd\n"), new); ft = lmcb->filetab; for (open_slots = 0, ii = 0; ii < lmcb->numfiles; ii++, ft++) { if (ft->f_index == -1) open_slots++; } open_slots += lmcb->maxfiles - lmcb->numfiles; if (new > open_slots) goto unavail; resp_size = sizeof(LR_DBOPEN) + (msg->nfiles - 1) * sizeof(short); response = psp_lmcAlloc(resp_size); /* We now know that all of the files can be added, go ahead and do it. */ filename[0] = lastname[0] = 0; for (names = msg->fnames, ii = 0; ii < msg->nfiles; ii++) { count = (short) *names++; vtstrcpy(filename, lastname); vtstrcpy(filename + count, names); vtstrcpy(lastname, filename); names += vtstrlen(names) + 1; if ((kk = fileid_add(lmcb->fidtab, filename)) == -1) goto unavail; avail = -1; for (ft = lmcb->filetab, jj = 0; jj < lmcb->numfiles; jj++, ft++) { if (kk == ft->f_index) break; else if (avail == -1 && ft->f_index == -1) avail = jj; } if (jj == lmcb->numfiles) { if (avail != -1) jj = avail; else lmcb->numfiles++; ft = &lmcb->filetab[jj]; ft->f_index = kk; ft->f_taf = ut->u_taf; ft->f_lockstat = msg->type == 'x' ? 'X' : 'f'; memset(ft->f_open, 0, lmcb->userbmbytes); memset(ft->f_lock, 0, lmcb->userbmbytes); DEBUG3(DB_TEXT("\tnew entry # %d, %s\n"), jj, filename) } else { DEBUG3(DB_TEXT("\told entry # %d, %s\n"), jj, filename); } response->frefs[ii] = jj; bit_set(ft->f_open, user); bit_set(ut->u_open, jj); } psp_lmcFree(msg); response->nusers = lmcb->taftab[ut->u_taf].t_nusers; reply_user(lmcb, user, response, resp_size, L_OKAY); return;unavail: psp_lmcFree(msg); reply_user(lmcb, user, NULL, 0, L_UNAVAIL);}static void l_dbclose( LMCB *lmcb, int user, LM_DBCLOSE *msg){ short ii; short *fref; USERTAB *ut = &lmcb->usertab[user]; FILETAB *ft = lmcb->filetab; DEBUG3(DB_TEXT("l_dbclose(user = %d, nfiles = %hd\n"), user, msg->nfiles) fref = msg->frefs; for (ii = 0; ii < msg->nfiles; ii++, fref++) { if (is_bit_set(ut->u_lock, *fref) && ft[*fref].f_lockstat == 'x') continue; freelock(lmcb, user, *fref); close_file(lmcb, user, *fref); } psp_lmcFree(msg); reply_user(lmcb, user, NULL, 0, L_OKAY);}static void l_lock( LMCB *lmcb, int user, LM_LOCK *msg){ int qptr; short ii; short locktype; DB_LOCKREQ *reqs; USERTAB *ut = &lmcb->usertab[user]; FILETAB *ft; QUEUETAB *qt; DEBUG3(DB_TEXT("l_lock(user = %d, nfiles = %hd\n"), user, msg->nfiles) if (chk_recover(lmcb, user, L_LOCK)) { psp_lmcFree(msg); return; } /* make sure there is room for these requests on the queue */ if (!room_q(lmcb, msg->nfiles)) { lmcb->locks_rejected += msg->nfiles; psp_lmcFree(msg); reply_user(lmcb, user, NULL, 0, L_QUEUEFULL); return; } /* Make sure all the file reference numbers are valid and that the request won't be rejected because of an upgrade conflict */ reqs = msg->locks; for (ii = 0; ii < msg->nfiles; ii++, reqs++) { if (reqs->fref < 0 || reqs->fref > lmcb->numfiles) { lmcb->locks_rejected += msg->nfiles; psp_lmcFree(msg); reply_user(lmcb, user, NULL, 0, L_SYSERR); return; } /* is this file already locked by this user? */ ft = &lmcb->filetab[reqs->fref]; if (!is_bit_set(ft->f_lock, user)) continue; /* is this an upgrade request? */ if (ft->f_lockstat != 'r' || reqs->type == 'r' || reqs->type == 'R') continue; /* This is an upgrade request. Has an upgrade request already been queued up by someone else? (Upgrade requests are capital letters */ if (ft->f_queue == -1) continue; locktype = lmcb->queuetab[ft->f_queue].q_locktype; if (locktype != 'W' && locktype != 'X') continue; /* Our worst fears. This upgrade request cannot be granted. This whole lock request must be rejected. */ DEBUG1(DB_TEXT("\tCannot grant upgrade request\n")) lmcb->locks_rejected += msg->nfiles; psp_lmcFree(msg); reply_user(lmcb, user, NULL, 0, L_UNAVAIL); return; } /* set the # of files that must be locked before the user can proceed */ ut->u_pending = msg->nfiles; reqs = msg->locks; for (ii = 0; ii < msg->nfiles; ii++, reqs++) { ft = &lmcb->filetab[reqs->fref]; DEBUG3(DB_TEXT("\treference # %d for '%c'"), reqs->fref, reqs->type) /* set the 'requested' bit */ bit_set(ut->u_req, reqs->fref); /* If this is an upgrade request */ if (is_bit_set(ft->f_lock, user) && ft->f_lockstat == 'r' && reqs->type != 'r' && reqs->type != 'R') { /* place request at head of the queue */ qt = &lmcb->queuetab[qptr = get_q(lmcb)]; qt->q_locktype = (short) toupper(reqs->type); qt->q_user = user; ins_head(lmcb, reqs->fref, qptr); DEBUG1(DB_TEXT("\tupgrade request queued\n")) } /* else if this is a downgrade request */ else if (is_bit_set(ft->f_lock, user) && (ft->f_lockstat == 'w' || ft->f_lockstat == 'R') && reqs->type == 'r') { /* it can be granted immediately */ ft->f_lockstat = 'r'; bit_set(ut->u_lock, reqs->fref); bit_set(ft->f_lock, user); --ut->u_pending; ++ut->u_waiting; DEBUG1(DB_TEXT("\tdowngrade request granted immediately\n")) } else { /* get a queue entry ready */ qt = &lmcb->queuetab[qptr = get_q(lmcb)]; qt->q_locktype = reqs->type; qt->q_user = user; /* if this is a Record lock request */ if (reqs->type == 'R') { /* place this request at the head of the queue, but following any existing 'R' requests */ ins_Record(lmcb, reqs->fref, qptr); DEBUG1(DB_TEXT("\tRecord lock request queued\n")) } else { /* else place this request at the end of the file's queue */ ins_tail(lmcb, reqs->fref, qptr); DEBUG1(DB_TEXT("\tlock request queued\n")) } } } psp_lmcFree(msg); /* lock whatever is lockable */ lock_all(lmcb); /* start the clock */ if (ut->u_timeout > 0) { while ((ut->u_timer = psp_timeMilliSecs()) == 0) ; } lock_reply(lmcb);}static void l_free( LMCB *lmcb, int user, LM_FREE *msg){ short ii; short *file; DEBUG3(DB_TEXT("l_free(user = %d, nfiles = %d)\n"), user, msg->nfiles) for (file = msg->frefs, ii = 0; ii < msg->nfiles; ii++, file++) freelock(lmcb, user, *file); psp_lmcFree(msg); /* lock any lockable files */ lock_all(lmcb); reply_user(lmcb, user, NULL, 0, L_OKAY); /* grant any locks that are now available */ lock_reply(lmcb);}static void l_trcommit( LMCB *lmcb, int user, LM_TRCOMMIT *msg){ long fid; USERTAB *ut = &lmcb->usertab[user]; DEBUG3(DB_TEXT("l_trcommit(user=%d, logfile=%s\n"), user, msg->logfile) fid = fileid_add(lmcb->fidtab, msg->logfile); psp_lmcFree(msg); if (fid == -1) { psp_lmcFree(msg); reply_user(lmcb, user, NULL, 0, L_UNAVAIL); return; } ut->u_logfile = fid; /* If the lock manager times out a user while file writes are taking place it can grant simultaneous rights to write to the file to another user. Do not allow timeouts to take place once transaction commit begins. */ ut->u_readlocksecs = 0; ut->u_writelocksecs = 0; reply_user(lmcb, user, NULL, 0, L_OKAY);}static void l_trend( LMCB *lmcb, int user, void *msg){ short ii; USERTAB *ut = &lmcb->usertab[user]; FILETAB *ft; DEBUG2(DB_TEXT("l_trend(user=%d\n"), user)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?