📄 tcl_lock.c
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1999-2001 * Sleepycat Software. All rights reserved. */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: tcl_lock.c,v 11.47 2002/08/08 15:27:10 bostic Exp $";#endif /* not lint */#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <stdlib.h>#include <string.h>#include <tcl.h>#endif#include "db_int.h"#include "dbinc/tcl_db.h"/* * Prototypes for procedures defined later in this file: */static int lock_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));static int _LockMode __P((Tcl_Interp *, Tcl_Obj *, db_lockmode_t *));static int _GetThisLock __P((Tcl_Interp *, DB_ENV *, u_int32_t, u_int32_t, DBT *, db_lockmode_t, char *));static void _LockPutInfo __P((Tcl_Interp *, db_lockop_t, DB_LOCK *, u_int32_t, DBT *));#if CONFIG_TESTstatic char *lkmode[] = { "ng", "read", "write", "iwrite", "iread", "iwr", NULL};enum lkmode { LK_NG, LK_READ, LK_WRITE, LK_IWRITE, LK_IREAD, LK_IWR};/* * tcl_LockDetect -- * * PUBLIC: int tcl_LockDetect __P((Tcl_Interp *, int, * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); */inttcl_LockDetect(interp, objc, objv, envp) Tcl_Interp *interp; /* Interpreter */ int objc; /* How many arguments? */ Tcl_Obj *CONST objv[]; /* The argument objects */ DB_ENV *envp; /* Environment pointer */{ static char *ldopts[] = { "expire", "default", "maxlocks", "minlocks", "minwrites", "oldest", "random", "youngest", NULL }; enum ldopts { LD_EXPIRE, LD_DEFAULT, LD_MAXLOCKS, LD_MINLOCKS, LD_MINWRITES, LD_OLDEST, LD_RANDOM, LD_YOUNGEST }; u_int32_t flag, policy; int i, optindex, result, ret; result = TCL_OK; flag = policy = 0; i = 2; while (i < objc) { if (Tcl_GetIndexFromObj(interp, objv[i], ldopts, "option", TCL_EXACT, &optindex) != TCL_OK) return (IS_HELP(objv[i])); i++; switch ((enum ldopts)optindex) { case LD_EXPIRE: FLAG_CHECK(policy); policy = DB_LOCK_EXPIRE; break; case LD_DEFAULT: FLAG_CHECK(policy); policy = DB_LOCK_DEFAULT; break; case LD_MAXLOCKS: FLAG_CHECK(policy); policy = DB_LOCK_MAXLOCKS; break; case LD_MINWRITES: FLAG_CHECK(policy); policy = DB_LOCK_MINWRITE; break; case LD_MINLOCKS: FLAG_CHECK(policy); policy = DB_LOCK_MINLOCKS; break; case LD_OLDEST: FLAG_CHECK(policy); policy = DB_LOCK_OLDEST; break; case LD_YOUNGEST: FLAG_CHECK(policy); policy = DB_LOCK_YOUNGEST; break; case LD_RANDOM: FLAG_CHECK(policy); policy = DB_LOCK_RANDOM; break; } } _debug_check(); ret = envp->lock_detect(envp, flag, policy, NULL); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock detect"); return (result);}/* * tcl_LockGet -- * * PUBLIC: int tcl_LockGet __P((Tcl_Interp *, int, * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); */inttcl_LockGet(interp, objc, objv, envp) Tcl_Interp *interp; /* Interpreter */ int objc; /* How many arguments? */ Tcl_Obj *CONST objv[]; /* The argument objects */ DB_ENV *envp; /* Environment pointer */{ static char *lgopts[] = { "-nowait", NULL }; enum lgopts { LGNOWAIT }; DBT obj; Tcl_Obj *res; void *otmp; db_lockmode_t mode; u_int32_t flag, lockid; int freeobj, optindex, result, ret; char newname[MSG_SIZE]; result = TCL_OK; freeobj = 0; memset(newname, 0, MSG_SIZE); if (objc != 5 && objc != 6) { Tcl_WrongNumArgs(interp, 2, objv, "?-nowait? mode id obj"); return (TCL_ERROR); } /* * Work back from required args. * Last arg is obj. * Second last is lock id. * Third last is lock mode. */ memset(&obj, 0, sizeof(obj)); if ((result = _GetUInt32(interp, objv[objc-2], &lockid)) != TCL_OK) return (result); ret = _CopyObjBytes(interp, objv[objc-1], &otmp, &obj.size, &freeobj); if (ret != 0) { result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock get"); return (result); } obj.data = otmp; if ((result = _LockMode(interp, objv[(objc - 3)], &mode)) != TCL_OK) goto out; /* * Any left over arg is the flag. */ flag = 0; if (objc == 6) { if (Tcl_GetIndexFromObj(interp, objv[(objc - 4)], lgopts, "option", TCL_EXACT, &optindex) != TCL_OK) return (IS_HELP(objv[(objc - 4)])); switch ((enum lgopts)optindex) { case LGNOWAIT: flag |= DB_LOCK_NOWAIT; break; } } result = _GetThisLock(interp, envp, lockid, flag, &obj, mode, newname); if (result == TCL_OK) { res = Tcl_NewStringObj(newname, strlen(newname)); Tcl_SetObjResult(interp, res); }out: if (freeobj) (void)__os_free(envp, otmp); return (result);}/* * tcl_LockStat -- * * PUBLIC: int tcl_LockStat __P((Tcl_Interp *, int, * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); */inttcl_LockStat(interp, objc, objv, envp) Tcl_Interp *interp; /* Interpreter */ int objc; /* How many arguments? */ Tcl_Obj *CONST objv[]; /* The argument objects */ DB_ENV *envp; /* Environment pointer */{ DB_LOCK_STAT *sp; Tcl_Obj *res; int result, ret; result = TCL_OK; /* * No args for this. Error if there are some. */ if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return (TCL_ERROR); } _debug_check(); ret = envp->lock_stat(envp, &sp, 0); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock stat"); if (result == TCL_ERROR) return (result); /* * Have our stats, now construct the name value * list pairs and free up the memory. */ res = Tcl_NewObj(); /* * MAKE_STAT_LIST assumes 'res' and 'error' label. */ MAKE_STAT_LIST("Region size", sp->st_regsize); MAKE_STAT_LIST("Last allocated locker ID", sp->st_id); MAKE_STAT_LIST("Current maximum unused locker ID", sp->st_cur_maxid); MAKE_STAT_LIST("Maximum locks", sp->st_maxlocks); MAKE_STAT_LIST("Maximum lockers", sp->st_maxlockers); MAKE_STAT_LIST("Maximum objects", sp->st_maxobjects); MAKE_STAT_LIST("Lock modes", sp->st_nmodes); MAKE_STAT_LIST("Current number of locks", sp->st_nlocks); MAKE_STAT_LIST("Maximum number of locks so far", sp->st_maxnlocks); MAKE_STAT_LIST("Current number of lockers", sp->st_nlockers); MAKE_STAT_LIST("Maximum number of lockers so far", sp->st_maxnlockers); MAKE_STAT_LIST("Current number of objects", sp->st_nobjects); MAKE_STAT_LIST("Maximum number of objects so far", sp->st_maxnobjects); MAKE_STAT_LIST("Number of conflicts", sp->st_nconflicts); MAKE_STAT_LIST("Lock requests", sp->st_nrequests); MAKE_STAT_LIST("Lock releases", sp->st_nreleases); MAKE_STAT_LIST("Lock requests that would have waited", sp->st_nnowaits); MAKE_STAT_LIST("Deadlocks detected", sp->st_ndeadlocks); MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait); MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait); MAKE_STAT_LIST("Lock timeout value", sp->st_locktimeout); MAKE_STAT_LIST("Number of lock timeouts", sp->st_nlocktimeouts); MAKE_STAT_LIST("Transaction timeout value", sp->st_txntimeout); MAKE_STAT_LIST("Number of transaction timeouts", sp->st_ntxntimeouts); Tcl_SetObjResult(interp, res);error: free(sp); return (result);}/* * tcl_LockTimeout -- * * PUBLIC: int tcl_LockTimeout __P((Tcl_Interp *, int, * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); */inttcl_LockTimeout(interp, objc, objv, envp) Tcl_Interp *interp; /* Interpreter */ int objc; /* How many arguments? */ Tcl_Obj *CONST objv[]; /* The argument objects */ DB_ENV *envp; /* Environment pointer */{ long timeout; int result, ret; /* * One arg, the timeout. */ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "?timeout?"); return (TCL_ERROR); } result = Tcl_GetLongFromObj(interp, objv[2], &timeout); if (result != TCL_OK) return (result); _debug_check(); ret = envp->set_timeout(envp, (u_int32_t)timeout, DB_SET_LOCK_TIMEOUT); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock timeout"); return (result);}/* * lock_Cmd -- * Implements the "lock" widget. */static intlock_Cmd(clientData, interp, objc, objv) ClientData clientData; /* Lock handle */ Tcl_Interp *interp; /* Interpreter */ int objc; /* How many arguments? */ Tcl_Obj *CONST objv[]; /* The argument objects */{ static char *lkcmds[] = { "put", NULL }; enum lkcmds { LKPUT }; DB_ENV *env; DB_LOCK *lock; DBTCL_INFO *lkip; int cmdindex, result, ret; Tcl_ResetResult(interp); lock = (DB_LOCK *)clientData; lkip = _PtrToInfo((void *)lock); result = TCL_OK; if (lock == NULL) { Tcl_SetResult(interp, "NULL lock", TCL_STATIC); return (TCL_ERROR); } if (lkip == NULL) { Tcl_SetResult(interp, "NULL lock info pointer", TCL_STATIC); return (TCL_ERROR); } env = NAME_TO_ENV(lkip->i_parent->i_name); /* * No args for this. Error if there are some. */ if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return (TCL_ERROR); } /* * Get the command name index from the object based on the dbcmds
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -