📄 tcl_txn.c
字号:
MAKE_STAT_LSN("LSN of last checkpoint", &sp->st_last_ckp); MAKE_STAT_LIST("Time of last checkpoint", sp->st_time_ckp); MAKE_STAT_LIST("Last txn ID allocated", sp->st_last_txnid); MAKE_STAT_LIST("Max Txns", sp->st_maxtxns); MAKE_STAT_LIST("Number aborted txns", sp->st_naborts); MAKE_STAT_LIST("Number active txns", sp->st_nactive); MAKE_STAT_LIST("Maximum active txns", sp->st_maxnactive); MAKE_STAT_LIST("Number txns begun", sp->st_nbegins); MAKE_STAT_LIST("Number committed txns", sp->st_ncommits); MAKE_STAT_LIST("Number restored txns", sp->st_nrestores); MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait); MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait); for (i = 0, p = sp->st_txnarray; i < sp->st_nactive; i++, p++) for (ip = LIST_FIRST(&__db_infohead); ip != NULL; ip = LIST_NEXT(ip, entries)) { if (ip->i_type != I_TXN) continue; if (ip->i_type == I_TXN && (ip->i_txnp->id(ip->i_txnp) == p->txnid)) { MAKE_STAT_LSN(ip->i_name, &p->lsn); if (p->parentid != 0) MAKE_STAT_STRLIST("Parent", ip->i_parent->i_name); else MAKE_STAT_LIST("Parent", 0); break; } } Tcl_SetObjResult(interp, res);error: free(sp); return (result);}/* * tcl_TxnTimeout -- * * PUBLIC: int tcl_TxnTimeout __P((Tcl_Interp *, int, * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); */inttcl_TxnTimeout(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_TXN_TIMEOUT); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock timeout"); return (result);}/* * txn_Cmd -- * Implements the "txn" widget. */static inttxn_Cmd(clientData, interp, objc, objv) ClientData clientData; /* Txn handle */ Tcl_Interp *interp; /* Interpreter */ int objc; /* How many arguments? */ Tcl_Obj *CONST objv[]; /* The argument objects */{ static char *txncmds[] = {#if CONFIG_TEST "discard", "id", "prepare",#endif "abort", "commit", NULL }; enum txncmds {#if CONFIG_TEST TXNDISCARD, TXNID, TXNPREPARE,#endif TXNABORT, TXNCOMMIT }; DBTCL_INFO *txnip; DB_TXN *txnp; Tcl_Obj *res; int cmdindex, result, ret; u_int8_t *gid; Tcl_ResetResult(interp); txnp = (DB_TXN *)clientData; txnip = _PtrToInfo((void *)txnp); result = TCL_OK; if (txnp == NULL) { Tcl_SetResult(interp, "NULL txn pointer", TCL_STATIC); return (TCL_ERROR); } if (txnip == NULL) { Tcl_SetResult(interp, "NULL txn info pointer", TCL_STATIC); return (TCL_ERROR); } /* * Get the command name index from the object based on the dbcmds * defined above. */ if (Tcl_GetIndexFromObj(interp, objv[1], txncmds, "command", TCL_EXACT, &cmdindex) != TCL_OK) return (IS_HELP(objv[1])); res = NULL; switch ((enum txncmds)cmdindex) {#if CONFIG_TEST case TXNDISCARD: if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return (TCL_ERROR); } _debug_check(); ret = txnp->discard(txnp, 0); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "txn discard"); _TxnInfoDelete(interp, txnip); (void)Tcl_DeleteCommand(interp, txnip->i_name); _DeleteInfo(txnip); break; case TXNID: if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return (TCL_ERROR); } _debug_check(); ret = txnp->id(txnp); res = Tcl_NewIntObj(ret); break; case TXNPREPARE: if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return (TCL_ERROR); } _debug_check(); gid = (u_int8_t *)Tcl_GetByteArrayFromObj(objv[2], NULL); ret = txnp->prepare(txnp, gid); /* * !!! * DB_TXN->prepare commits all outstanding children. But it * does NOT destroy the current txn handle. So, we must call * _TxnInfoDelete to recursively remove all nested txn handles, * we do not call _DeleteInfo on ourselves. */ _TxnInfoDelete(interp, txnip); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "txn prepare"); break;#endif case TXNABORT: if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return (TCL_ERROR); } _debug_check(); ret = txnp->abort(txnp); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "txn abort"); _TxnInfoDelete(interp, txnip); (void)Tcl_DeleteCommand(interp, txnip->i_name); _DeleteInfo(txnip); break; case TXNCOMMIT: result = tcl_TxnCommit(interp, objc, objv, txnp, txnip); _TxnInfoDelete(interp, txnip); (void)Tcl_DeleteCommand(interp, txnip->i_name); _DeleteInfo(txnip); break; } /* * Only set result if we have a res. Otherwise, lower * functions have already done so. */ if (result == TCL_OK && res) Tcl_SetObjResult(interp, res); return (result);}static inttcl_TxnCommit(interp, objc, objv, txnp, txnip) Tcl_Interp *interp; /* Interpreter */ int objc; /* How many arguments? */ Tcl_Obj *CONST objv[]; /* The argument objects */ DB_TXN *txnp; /* Transaction pointer */ DBTCL_INFO *txnip; /* Info pointer */{ static char *commitopt[] = { "-nosync", "-sync", NULL }; enum commitopt { COMSYNC, COMNOSYNC }; u_int32_t flag; int optindex, result, ret; COMPQUIET(txnip, NULL); result = TCL_OK; flag = 0; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return (TCL_ERROR); } if (objc == 3) { if (Tcl_GetIndexFromObj(interp, objv[2], commitopt, "option", TCL_EXACT, &optindex) != TCL_OK) return (IS_HELP(objv[2])); switch ((enum commitopt)optindex) { case COMSYNC: FLAG_CHECK(flag); flag = DB_TXN_SYNC; break; case COMNOSYNC: FLAG_CHECK(flag); flag = DB_TXN_NOSYNC; break; } } _debug_check(); ret = txnp->commit(txnp, flag); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "txn commit"); return (result);}#if CONFIG_TEST/* * tcl_TxnRecover -- * * PUBLIC: int tcl_TxnRecover __P((Tcl_Interp *, int, * PUBLIC: Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *)); */inttcl_TxnRecover(interp, objc, objv, envp, envip) Tcl_Interp *interp; /* Interpreter */ int objc; /* How many arguments? */ Tcl_Obj *CONST objv[]; /* The argument objects */ DB_ENV *envp; /* Environment pointer */ DBTCL_INFO *envip; /* Info pointer */{#define DO_PREPLIST(count) \for (i = 0; i < count; i++) { \ snprintf(newname, sizeof(newname), "%s.txn%d", \ envip->i_name, envip->i_envtxnid); \ ip = _NewInfo(interp, NULL, newname, I_TXN); \ if (ip == NULL) { \ Tcl_SetResult(interp, "Could not set up info", \ TCL_STATIC); \ return (TCL_ERROR); \ } \ envip->i_envtxnid++; \ ip->i_parent = envip; \ p = &prep[i]; \ _SetInfoData(ip, p->txn); \ Tcl_CreateObjCommand(interp, newname, \ (Tcl_ObjCmdProc *)txn_Cmd, (ClientData)p->txn, NULL); \ result = _SetListElem(interp, res, newname, strlen(newname), \ p->gid, DB_XIDDATASIZE); \ if (result != TCL_OK) \ goto error; \} DBTCL_INFO *ip; DB_PREPLIST prep[DBTCL_PREP], *p; Tcl_Obj *res; long count, i; int result, ret; char newname[MSG_SIZE]; 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->txn_recover(envp, prep, DBTCL_PREP, &count, DB_FIRST); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "txn recover"); if (result == TCL_ERROR) return (result); res = Tcl_NewObj(); DO_PREPLIST(count); /* * If count returned is the maximum size we have, then there * might be more. Keep going until we get them all. */ while (count == DBTCL_PREP) { ret = envp->txn_recover( envp, prep, DBTCL_PREP, &count, DB_NEXT); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "txn recover"); if (result == TCL_ERROR) return (result); DO_PREPLIST(count); } Tcl_SetObjResult(interp, res);error: return (result);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -