lmcore.c

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

C
1,370
字号
/*************************************************************************** *                                                                         * * 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 "lm.h"static void l_dbopen(LMCB *, int, LM_DBOPEN *);static void l_dbclose(LMCB *, int, LM_DBCLOSE *);static void l_lock(LMCB *, int, LM_LOCK *);static void l_free(LMCB *, int, LM_FREE *);static void l_trcommit(LMCB *, int, LM_TRCOMMIT *);static void l_trend(LMCB *, int, void *);static void l_settime(LMCB *, int, LM_SETTIME *);static void l_recdone(LMCB *, int, void *);static void l_recfail(LMCB *, int, void *);static void l_login(LMCB *, int, LM_LOGIN *);static void l_logout(LMCB *, int, void *);static void l_terminate(LMCB *, int, void *);static void l_options(LMCB *, int, LM_OPTIONS *);static void l_verifyuser(LMCB *, int, void *);static void l_clearuser(LMCB *, int, LM_USERID *);static void l_status(LMCB *, int, LM_STATUS *);typedef struct {    LM_FCN *fcn;    int     user_check;} LM_FCNS;static LM_FCNS fcns[] = {    { (LM_FCN *) NULL,           0 },    { (LM_FCN *) &l_dbopen,      1 },    { (LM_FCN *) &l_dbclose,     1 },    { (LM_FCN *) &l_lock,        1 },    { (LM_FCN *) &l_free,        1 },    { (LM_FCN *) &l_trcommit,    1 },    { (LM_FCN *) &l_trend,       1 },    { (LM_FCN *) &l_settime,     1 },    { (LM_FCN *) &l_recdone,     1 },    { (LM_FCN *) &l_recfail,     1 },    { (LM_FCN *) &l_login,       0 },    { (LM_FCN *) &l_logout,      1 },    { (LM_FCN *) &l_terminate,   0 },    { (LM_FCN *) &l_options,     1 },    { (LM_FCN *) &l_verifyuser,  0 },    { (LM_FCN *) &l_clearuser,   0 },    { (LM_FCN *) &l_status,      0 }};static DB_TCHAR *get_filename(LMCB *, int, short);static void      l_status_genstat(LMCB *, int);static void      l_status_tables(LMCB *, int, TABSIZE *);static void      l_status_userinfo(LMCB *, int, TABSIZE *, int);static void      l_status_fileinfo(LMCB *, int, TABSIZE *, int);static void      l_status_userstat(LMCB *, int, DB_TCHAR *);static void      l_status_taftab(LMCB *, int, TABSIZE *);static int term_flag = 0;int lm_init(    LM            *lm,    short          maxusers,    short          maxfiles,    short          maxqueues,    LM_REPLY_FCN  *send,    LM_DISCON_FCN *discon,    LM_INFO_FCN   *info){    short     ii;    int       maxids;    size_t    userbmbytes;    size_t    filebmbytes;    size_t    bitmapsize;    LMCB     *lmcb;    USERTAB  *ut;    FILETAB  *ft;    TAFTAB   *tt;    QUEUETAB *qt;    DB_BYTE  *b;    if (!maxusers || !maxfiles || !maxqueues || !send || !discon || !info)        return LM_INVPARM;    userbmbytes = (maxusers - 1) / BITS_PER_BYTE + 1;    filebmbytes = (maxfiles - 1) / BITS_PER_BYTE + 1;    bitmapsize = userbmbytes * 2 * maxfiles + filebmbytes * 3 * maxusers;    if ((lmcb = psp_cGetMemory(sizeof(LMCB), 0)) == NULL)        return LM_NOMEMORY;    lmcb->maxusers  = maxusers;    lmcb->maxfiles  = maxfiles;    lmcb->maxqueues = maxqueues;    lmcb->filebmbytes = filebmbytes;    lmcb->userbmbytes = userbmbytes;    lmcb->usertab  = psp_cGetMemory(sizeof(USERTAB) * maxusers, 0);    lmcb->filetab  = psp_cGetMemory(sizeof(FILETAB) * maxfiles, 0);    lmcb->taftab   = psp_cGetMemory(sizeof(TAFTAB) * maxusers, 0);    lmcb->queuetab = psp_cGetMemory(sizeof(QUEUETAB) * maxqueues, 0);    lmcb->bitmaps  = psp_cGetMemory(bitmapsize, 0);    maxids = maxusers + maxfiles + maxqueues;    if (fileid_init(&lmcb->fidtab, maxids, 20 * maxids) != L_OKAY ||            !lmcb->usertab || !lmcb->filetab || !lmcb->taftab ||            !lmcb->queuetab || !lmcb->bitmaps) {        if (lmcb->usertab)            psp_freeMemory(lmcb->usertab, 0);        if (lmcb->filetab)            psp_freeMemory(lmcb->filetab, 0);        if (lmcb->taftab)            psp_freeMemory(lmcb->taftab, 0);        if (lmcb->queuetab)            psp_freeMemory(lmcb->queuetab, 0);        if (lmcb->bitmaps)            psp_freeMemory(lmcb->bitmaps, 0);        psp_freeMemory(lmcb, 0);        return LM_NOMEMORY;    }    lmcb->send = send;    lmcb->discon = discon;    lmcb->info = info;    ut = lmcb->usertab;    tt = lmcb->taftab;    b = lmcb->bitmaps;    for (ii = 0; ii < maxusers; ii++, ut++, tt++) {        ut->u_taf = -1;        ut->u_open = b;        ut->u_lock = b + filebmbytes;        ut->u_req  = b + 2 * filebmbytes;        ut->u_timeout = DEFAULT_TIMEOUT;        ut->u_recuser = -1;        ut->u_logfile = -1;        b += 3 * filebmbytes;        tt->t_index = -1;        tt->t_recuser = -1;    }    for (ft = lmcb->filetab, ii = 0; ii < maxfiles; ii++, ft++) {        ft->f_index = -1;        ft->f_lockstat = 'f';        ft->f_open = b;        ft->f_lock = b + userbmbytes;        ft->f_queue = -1;        b += 2 * userbmbytes;    }    for (qt = lmcb->queuetab, ii = 0; ii < maxqueues - 1; ii++, qt++) {        qt->q_locktype = 'f';        qt->q_user = -1;        qt->q_next = ii + 1;    }    qt->q_next = -1;    *lm = (LM) lmcb;        return LM_OKAY;}void lm_term(    LM lm){    LMCB *lmcb = (LMCB *) lm;    fileid_deinit(lmcb->fidtab);    psp_freeMemory(lmcb->queuetab, 0);    psp_freeMemory(lmcb->taftab, 0);    psp_freeMemory(lmcb->filetab, 0);    psp_freeMemory(lmcb->usertab, 0);    psp_freeMemory(lmcb->bitmaps, 0);    psp_freeMemory(lmcb, 0);}int lm_crank(    LM lm){    short    ii;    LMCB    *lmcb = (LMCB *) lm;    USERTAB *ut;    long     curr = psp_timeMilliSecs();    for (ut = lmcb->usertab, ii = 0; ii < lmcb->numusers; ii++, ut++) {        if (!ut->u_name[0])            continue;        if (ut->u_pending && ut->u_timeout > 0 && ut->u_timer != 0) {            if ((curr - ut->u_timer) / 1000 >= ut->u_timeout)                ut->u_timer = 0; /* timeout */        }    }    lock_reply(lmcb);    return LM_OKAY;}int lm_process(    LM     lm,    int    user,    int    conn,    int    type,    void  *msg){    LMCB *lmcb = (LMCB *) lm;    if (type < 0 || type > L_LAST) {        psp_lmcFree(msg);        return LM_INVTYPE;    }    if (fcns[type].user_check && (user < 0 || user > lmcb->maxusers ||            lmcb->usertab[user].u_status == U_EMPTY)) {        psp_lmcFree(msg);        return LM_INVUSER;    }    if (type)        (*fcns[type].fcn)(lmcb, fcns[type].user_check ? user : conn, msg);    if (term_flag)        return LM_TERMINATE;    return lm_crank(lm);}int lm_dead_user(    LM  lm,    int user){    LMCB *lmcb = (LMCB *) lm;    dead_user(lm, user, 0);    return LM_OKAY;}int lm_find_user(    LM    lm,    void *conn){    short    ii;    LMCB    *lmcb = (LMCB *) lm;    USERTAB *ut;    for (ut = lmcb->usertab, ii = 0; ii < lmcb->numusers; ii++, ut++) {        if (ut->u_conn == conn)            return ii;    }    return -1;}void reply_user(    LMCB  *lmcb,    int    user,    void  *msg,    size_t size,    int    status){    USERTAB *ut = &lmcb->usertab[user];    if ((*lmcb->send)(ut->u_conn, msg, size, status) != LM_OKAY)        dead_user(lmcb, user, 0);    if (msg)        psp_lmcFree(msg);}void reply_non_user(    LMCB  *lmcb,    int    conn,    void  *msg,    size_t size,    int    status){    (*lmcb->send)((void *) conn, msg, size, status);    if (msg)        psp_lmcFree(msg);}static void l_login(    LMCB     *lmcb,    int       user,    LM_LOGIN *msg){    short     ii;    short     taf;    int       fid;    DB_TCHAR *userid;    USERTAB  *ut;    TAFTAB   *tt = NULL;#if 0  /* TBD */    if (msg->version != (MSGVER | UNICODE_FLAG)) {        DEBUG1(DB_TEXT("\tInvalid message version\n"))        goto unavail;    }#endif    DEBUG3(DB_TEXT("l_login(dbuserid = %s, taffile = %s)\n"), msg->dbuserid, msg->taffile)    taf = -1;    if ((fid = fileid_fnd(lmcb->fidtab, msg->taffile)) != -1) {        tt = lmcb->taftab;        for (ii = 0; ii < lmcb->numtafs; ii++, tt++) {            if (fid == tt->t_index) {                taf = ii;                break;            }        }    }    if (taf != -1 && tt->t_status == REC_EXTERNAL) {        DEBUG1(DB_TEXT("\tUnavailable due to external recover in progress\n"))        goto unavail;    }    userid = msg->dbuserid;    ut = lmcb->usertab;    for (ii = 0; ii < lmcb->numusers; ii++, ut++) {        if (vtstrcmp(ut->u_name, userid) == 0) {            psp_lmcFree(msg);            switch (ut->u_status) {                /* This happens when the same userid is used by two different                   clients.  It is an error and the second user is denied                   access. */                case U_LIVE:                    reply_non_user(lmcb, user, NULL, 0, L_DUPUSER);                    break;                /* The user died during a previous session, so we check for a                   recovery in progress.  If not, we assign the recovery to                   this user for him to do. */                case U_DEAD:                    ut->u_conn = (void *) user;                    reply_user(lmcb, user, NULL, 0, L_OKAY);                    if (ut->u_logfile != -1) {                        ut->u_status = U_REC_MYSELF;                        ut->u_recuser = ii;                    }                    if (ut->u_taf != -1) {                        lmcb->taftab[ut->u_taf].t_status = REC_NEEDED;                        lmcb->taftab[ut->u_taf].t_recuser = ii;                    }                    break;                /* since this user's files are being recovered by another                   user this login must be denied.  If this user held                   exclusive locks then he must be able to regain the same                   usertab entry, and cannot until the recover is complete.                   If this user did not hold exclusive locks, he must wait                   for the recovery to complete because he might destroy the                   logfile while it is being used for recovery. */                case U_BEING_REC:                    DEBUG1(DB_TEXT("\tUnavailable because user is being recovered\n"))                    goto unavail;                /* The same user is logging in after having died holding                   exclusive locks; give him the same entry */                case U_HOLDING_X:                    ut->u_conn = (void *) user;                    reply_user(lmcb, user, NULL, 0, L_OKAY);                    ut->u_status = U_LIVE;                    break;                default:                    break;            }            return;        }         }    /* The user name does not already exist in the user table so add him */    ut = lmcb->usertab;    for (ii = 0; ii < lmcb->numusers; ii++, ut++) {        if (*ut->u_name == '\0')            break;    }    if (ii == lmcb->numusers) {        if (lmcb->numusers == lmcb->maxusers) {            DEBUG1(DB_TEXT("!\tuser table is full\n"))            goto unavail;        }        ii = lmcb->numusers++;    }    if (taf == -1) {        if (lmcb->numtafs == lmcb->maxusers) {            DEBUG1(DB_TEXT("!\ttaf table is full\n"))            if (ii == lmcb->numusers - 1) /* did we just increment numusers */                lmcb->numusers--;            goto unavail;        }        taf = lmcb->numtafs++;        tt = &lmcb->taftab[taf];    }    if (tt->t_nusers++ == 0) {        if ((fid = fileid_add(lmcb->fidtab, msg->taffile)) == -1) {            tt->t_nusers = 0;            if (taf == lmcb->numtafs - 1)                lmcb->numtafs--;            if (ii == lmcb->numusers - 1)                lmcb->numusers--;            DEBUG1(DB_TEXT("\tout of memory for fileid table\n"))            goto unavail;        }        tt->t_index = fid;        tt->t_status = REC_EXTERNAL;        tt->t_recuser = ii;    }    vtstrcpy(ut->u_name, msg->dbuserid);    ut->u_taf = taf;    ut->u_conn = (void *) user;    memset(ut->u_open, 0, lmcb->filebmbytes);    memset(ut->u_lock, 0, lmcb->filebmbytes);    memset(ut->u_req, 0, lmcb->filebmbytes);    ut->u_pending = 0;    ut->u_waiting = 0;    ut->u_timeout = DEFAULT_TIMEOUT;    ut->u_timer   = 0;    ut->u_status  = U_LIVE;    ut->u_recuser = -1;    ut->u_logfile = -1;

⌨️ 快捷键说明

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