📄 tcl_lock.c
字号:
* defined above. */ if (Tcl_GetIndexFromObj(interp, objv[1], lkcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK) return (IS_HELP(objv[1])); switch ((enum lkcmds)cmdindex) { case LKPUT: _debug_check(); ret = env->lock_put(env, lock); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock put"); (void)Tcl_DeleteCommand(interp, lkip->i_name); _DeleteInfo(lkip); __os_free(env, lock); break; } return (result);}/* * tcl_LockVec -- * * PUBLIC: int tcl_LockVec __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); */inttcl_LockVec(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 *lvopts[] = { "-nowait", NULL }; enum lvopts { LVNOWAIT }; static char *lkops[] = { "get", "put", "put_all", "put_obj", "timeout", NULL }; enum lkops { LKGET, LKPUT, LKPUTALL, LKPUTOBJ, LKTIMEOUT }; DB_LOCK *lock; DB_LOCKREQ list; DBT obj; Tcl_Obj **myobjv, *res, *thisop; void *otmp; u_int32_t flag, lockid; int freeobj, i, myobjc, optindex, result, ret; char *lockname, msg[MSG_SIZE], newname[MSG_SIZE]; result = TCL_OK; memset(newname, 0, MSG_SIZE); flag = 0; freeobj = 0; /* * If -nowait is given, it MUST be first arg. */ if (Tcl_GetIndexFromObj(interp, objv[2], lvopts, "option", TCL_EXACT, &optindex) == TCL_OK) { switch ((enum lvopts)optindex) { case LVNOWAIT: flag |= DB_LOCK_NOWAIT; break; } i = 3; } else { if (IS_HELP(objv[2]) == TCL_OK) return (TCL_OK); Tcl_ResetResult(interp); i = 2; } /* * Our next arg MUST be the locker ID. */ result = _GetUInt32(interp, objv[i++], &lockid); if (result != TCL_OK) return (result); /* * All other remaining args are operation tuples. * Go through sequentially to decode, execute and build * up list of return values. */ res = Tcl_NewListObj(0, NULL); while (i < objc) { /* * Get the list of the tuple. */ lock = NULL; result = Tcl_ListObjGetElements(interp, objv[i], &myobjc, &myobjv); if (result == TCL_OK) i++; else break; /* * First we will set up the list of requests. * We will make a "second pass" after we get back * the results from the lock_vec call to create * the return list. */ if (Tcl_GetIndexFromObj(interp, myobjv[0], lkops, "option", TCL_EXACT, &optindex) != TCL_OK) { result = IS_HELP(myobjv[0]); goto error; } switch ((enum lkops)optindex) { case LKGET: if (myobjc != 3) { Tcl_WrongNumArgs(interp, 1, myobjv, "{get obj mode}"); result = TCL_ERROR; goto error; } result = _LockMode(interp, myobjv[2], &list.mode); if (result != TCL_OK) goto error; ret = _CopyObjBytes(interp, myobjv[1], &otmp, &obj.size, &freeobj); if (ret != 0) { result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock vec"); return (result); } obj.data = otmp; ret = _GetThisLock(interp, envp, lockid, flag, &obj, list.mode, newname); if (ret != 0) { result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock vec"); thisop = Tcl_NewIntObj(ret); (void)Tcl_ListObjAppendElement(interp, res, thisop); goto error; } thisop = Tcl_NewStringObj(newname, strlen(newname)); (void)Tcl_ListObjAppendElement(interp, res, thisop); if (freeobj) { (void)__os_free(envp, otmp); freeobj = 0; } continue; case LKPUT: if (myobjc != 2) { Tcl_WrongNumArgs(interp, 1, myobjv, "{put lock}"); result = TCL_ERROR; goto error; } list.op = DB_LOCK_PUT; lockname = Tcl_GetStringFromObj(myobjv[1], NULL); lock = NAME_TO_LOCK(lockname); if (lock == NULL) { snprintf(msg, MSG_SIZE, "Invalid lock: %s\n", lockname); Tcl_SetResult(interp, msg, TCL_VOLATILE); result = TCL_ERROR; goto error; } list.lock = *lock; break; case LKPUTALL: if (myobjc != 1) { Tcl_WrongNumArgs(interp, 1, myobjv, "{put_all}"); result = TCL_ERROR; goto error; } list.op = DB_LOCK_PUT_ALL; break; case LKPUTOBJ: if (myobjc != 2) { Tcl_WrongNumArgs(interp, 1, myobjv, "{put_obj obj}"); result = TCL_ERROR; goto error; } list.op = DB_LOCK_PUT_OBJ; ret = _CopyObjBytes(interp, myobjv[1], &otmp, &obj.size, &freeobj); if (ret != 0) { result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock vec"); return (result); } obj.data = otmp; list.obj = &obj; break; case LKTIMEOUT: list.op = DB_LOCK_TIMEOUT; break; } /* * We get here, we have set up our request, now call * lock_vec. */ _debug_check(); ret = envp->lock_vec(envp, lockid, flag, &list, 1, NULL); /* * Now deal with whether or not the operation succeeded. * Get's were done above, all these are only puts. */ thisop = Tcl_NewIntObj(ret); result = Tcl_ListObjAppendElement(interp, res, thisop); if (ret != 0 && result == TCL_OK) result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock put"); if (freeobj) { (void)__os_free(envp, otmp); freeobj = 0; } /* * We did a put of some kind. Since we did that, * we have to delete the commands associated with * any of the locks we just put. */ _LockPutInfo(interp, list.op, lock, lockid, &obj); } if (result == TCL_OK && res) Tcl_SetObjResult(interp, res);error: return (result);}static int_LockMode(interp, obj, mode) Tcl_Interp *interp; Tcl_Obj *obj; db_lockmode_t *mode;{ int optindex; if (Tcl_GetIndexFromObj(interp, obj, lkmode, "option", TCL_EXACT, &optindex) != TCL_OK) return (IS_HELP(obj)); switch ((enum lkmode)optindex) { case LK_NG: *mode = DB_LOCK_NG; break; case LK_READ: *mode = DB_LOCK_READ; break; case LK_WRITE: *mode = DB_LOCK_WRITE; break; case LK_IREAD: *mode = DB_LOCK_IREAD; break; case LK_IWRITE: *mode = DB_LOCK_IWRITE; break; case LK_IWR: *mode = DB_LOCK_IWR; break; } return (TCL_OK);}static void_LockPutInfo(interp, op, lock, lockid, objp) Tcl_Interp *interp; db_lockop_t op; DB_LOCK *lock; u_int32_t lockid; DBT *objp;{ DBTCL_INFO *p, *nextp; int found; for (p = LIST_FIRST(&__db_infohead); p != NULL; p = nextp) { found = 0; nextp = LIST_NEXT(p, entries); if ((op == DB_LOCK_PUT && (p->i_lock == lock)) || (op == DB_LOCK_PUT_ALL && p->i_locker == lockid) || (op == DB_LOCK_PUT_OBJ && p->i_lockobj.data && memcmp(p->i_lockobj.data, objp->data, objp->size) == 0)) found = 1; if (found) { (void)Tcl_DeleteCommand(interp, p->i_name); __os_free(NULL, p->i_lock); _DeleteInfo(p); } }}static int_GetThisLock(interp, envp, lockid, flag, objp, mode, newname) Tcl_Interp *interp; /* Interpreter */ DB_ENV *envp; /* Env handle */ u_int32_t lockid; /* Locker ID */ u_int32_t flag; /* Lock flag */ DBT *objp; /* Object to lock */ db_lockmode_t mode; /* Lock mode */ char *newname; /* New command name */{ DB_LOCK *lock; DBTCL_INFO *envip, *ip; int result, ret; result = TCL_OK; envip = _PtrToInfo((void *)envp); if (envip == NULL) { Tcl_SetResult(interp, "Could not find env info\n", TCL_STATIC); return (TCL_ERROR); } snprintf(newname, MSG_SIZE, "%s.lock%d", envip->i_name, envip->i_envlockid); ip = _NewInfo(interp, NULL, newname, I_LOCK); if (ip == NULL) { Tcl_SetResult(interp, "Could not set up info", TCL_STATIC); return (TCL_ERROR); } ret = __os_malloc(envp, sizeof(DB_LOCK), &lock); if (ret != 0) { Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC); return (TCL_ERROR); } _debug_check(); ret = envp->lock_get(envp, lockid, flag, objp, mode, lock); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock get"); if (result == TCL_ERROR) { __os_free(envp, lock); _DeleteInfo(ip); return (result); } /* * Success. Set up return. Set up new info * and command widget for this lock. */ ret = __os_malloc(envp, objp->size, &ip->i_lockobj.data); if (ret != 0) { Tcl_SetResult(interp, "Could not duplicate obj", TCL_STATIC); (void)envp->lock_put(envp, lock); __os_free(envp, lock); _DeleteInfo(ip); result = TCL_ERROR; goto error; } memcpy(ip->i_lockobj.data, objp->data, objp->size); ip->i_lockobj.size = objp->size; envip->i_envlockid++; ip->i_parent = envip; ip->i_locker = lockid; _SetInfoData(ip, lock); Tcl_CreateObjCommand(interp, newname, (Tcl_ObjCmdProc *)lock_Cmd, (ClientData)lock, NULL);error: return (result);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -