tcl_lock.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:17k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1999-2001
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: tcl_lock.c,v 11.47 2002/08/08 15:27:10 bostic Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <tcl.h>
  16. #endif
  17. #include "db_int.h"
  18. #include "dbinc/tcl_db.h"
  19. /*
  20.  * Prototypes for procedures defined later in this file:
  21.  */
  22. static int      lock_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
  23. static int _LockMode __P((Tcl_Interp *, Tcl_Obj *, db_lockmode_t *));
  24. static int _GetThisLock __P((Tcl_Interp *, DB_ENV *, u_int32_t,
  25.      u_int32_t, DBT *, db_lockmode_t, char *));
  26. static void _LockPutInfo __P((Tcl_Interp *, db_lockop_t, DB_LOCK *,
  27.      u_int32_t, DBT *));
  28. #if CONFIG_TEST
  29. static char *lkmode[] = {
  30. "ng",
  31. "read",
  32. "write",
  33. "iwrite",
  34. "iread",
  35. "iwr",
  36.  NULL
  37. };
  38. enum lkmode {
  39. LK_NG,
  40. LK_READ,
  41. LK_WRITE,
  42. LK_IWRITE,
  43. LK_IREAD,
  44. LK_IWR
  45. };
  46. /*
  47.  * tcl_LockDetect --
  48.  *
  49.  * PUBLIC: int tcl_LockDetect __P((Tcl_Interp *, int,
  50.  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
  51.  */
  52. int
  53. tcl_LockDetect(interp, objc, objv, envp)
  54. Tcl_Interp *interp; /* Interpreter */
  55. int objc; /* How many arguments? */
  56. Tcl_Obj *CONST objv[]; /* The argument objects */
  57. DB_ENV *envp; /* Environment pointer */
  58. {
  59. static char *ldopts[] = {
  60. "expire",
  61. "default",
  62. "maxlocks",
  63. "minlocks",
  64. "minwrites",
  65. "oldest",
  66. "random",
  67. "youngest",
  68.  NULL
  69. };
  70. enum ldopts {
  71. LD_EXPIRE,
  72. LD_DEFAULT,
  73. LD_MAXLOCKS,
  74. LD_MINLOCKS,
  75. LD_MINWRITES,
  76. LD_OLDEST,
  77. LD_RANDOM,
  78. LD_YOUNGEST
  79. };
  80. u_int32_t flag, policy;
  81. int i, optindex, result, ret;
  82. result = TCL_OK;
  83. flag = policy = 0;
  84. i = 2;
  85. while (i < objc) {
  86. if (Tcl_GetIndexFromObj(interp, objv[i],
  87.     ldopts, "option", TCL_EXACT, &optindex) != TCL_OK)
  88. return (IS_HELP(objv[i]));
  89. i++;
  90. switch ((enum ldopts)optindex) {
  91. case LD_EXPIRE:
  92. FLAG_CHECK(policy);
  93. policy = DB_LOCK_EXPIRE;
  94. break;
  95. case LD_DEFAULT:
  96. FLAG_CHECK(policy);
  97. policy = DB_LOCK_DEFAULT;
  98. break;
  99. case LD_MAXLOCKS:
  100. FLAG_CHECK(policy);
  101. policy = DB_LOCK_MAXLOCKS;
  102. break;
  103. case LD_MINWRITES:
  104. FLAG_CHECK(policy);
  105. policy = DB_LOCK_MINWRITE;
  106. break;
  107. case LD_MINLOCKS:
  108. FLAG_CHECK(policy);
  109. policy = DB_LOCK_MINLOCKS;
  110. break;
  111. case LD_OLDEST:
  112. FLAG_CHECK(policy);
  113. policy = DB_LOCK_OLDEST;
  114. break;
  115. case LD_YOUNGEST:
  116. FLAG_CHECK(policy);
  117. policy = DB_LOCK_YOUNGEST;
  118. break;
  119. case LD_RANDOM:
  120. FLAG_CHECK(policy);
  121. policy = DB_LOCK_RANDOM;
  122. break;
  123. }
  124. }
  125. _debug_check();
  126. ret = envp->lock_detect(envp, flag, policy, NULL);
  127. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock detect");
  128. return (result);
  129. }
  130. /*
  131.  * tcl_LockGet --
  132.  *
  133.  * PUBLIC: int tcl_LockGet __P((Tcl_Interp *, int,
  134.  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
  135.  */
  136. int
  137. tcl_LockGet(interp, objc, objv, envp)
  138. Tcl_Interp *interp; /* Interpreter */
  139. int objc; /* How many arguments? */
  140. Tcl_Obj *CONST objv[]; /* The argument objects */
  141. DB_ENV *envp; /* Environment pointer */
  142. {
  143. static char *lgopts[] = {
  144. "-nowait",
  145.  NULL
  146. };
  147. enum lgopts {
  148. LGNOWAIT
  149. };
  150. DBT obj;
  151. Tcl_Obj *res;
  152. void *otmp;
  153. db_lockmode_t mode;
  154. u_int32_t flag, lockid;
  155. int freeobj, optindex, result, ret;
  156. char newname[MSG_SIZE];
  157. result = TCL_OK;
  158. freeobj = 0;
  159. memset(newname, 0, MSG_SIZE);
  160. if (objc != 5 && objc != 6) {
  161. Tcl_WrongNumArgs(interp, 2, objv, "?-nowait? mode id obj");
  162. return (TCL_ERROR);
  163. }
  164. /*
  165.  * Work back from required args.
  166.  * Last arg is obj.
  167.  * Second last is lock id.
  168.  * Third last is lock mode.
  169.  */
  170. memset(&obj, 0, sizeof(obj));
  171. if ((result =
  172.     _GetUInt32(interp, objv[objc-2], &lockid)) != TCL_OK)
  173. return (result);
  174. ret = _CopyObjBytes(interp, objv[objc-1], &otmp,
  175.     &obj.size, &freeobj);
  176. if (ret != 0) {
  177. result = _ReturnSetup(interp, ret,
  178.     DB_RETOK_STD(ret), "lock get");
  179. return (result);
  180. }
  181. obj.data = otmp;
  182. if ((result = _LockMode(interp, objv[(objc - 3)], &mode)) != TCL_OK)
  183. goto out;
  184. /*
  185.  * Any left over arg is the flag.
  186.  */
  187. flag = 0;
  188. if (objc == 6) {
  189. if (Tcl_GetIndexFromObj(interp, objv[(objc - 4)],
  190.     lgopts, "option", TCL_EXACT, &optindex) != TCL_OK)
  191. return (IS_HELP(objv[(objc - 4)]));
  192. switch ((enum lgopts)optindex) {
  193. case LGNOWAIT:
  194. flag |= DB_LOCK_NOWAIT;
  195. break;
  196. }
  197. }
  198. result = _GetThisLock(interp, envp, lockid, flag, &obj, mode, newname);
  199. if (result == TCL_OK) {
  200. res = Tcl_NewStringObj(newname, strlen(newname));
  201. Tcl_SetObjResult(interp, res);
  202. }
  203. out:
  204. if (freeobj)
  205. (void)__os_free(envp, otmp);
  206. return (result);
  207. }
  208. /*
  209.  * tcl_LockStat --
  210.  *
  211.  * PUBLIC: int tcl_LockStat __P((Tcl_Interp *, int,
  212.  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
  213.  */
  214. int
  215. tcl_LockStat(interp, objc, objv, envp)
  216. Tcl_Interp *interp; /* Interpreter */
  217. int objc; /* How many arguments? */
  218. Tcl_Obj *CONST objv[]; /* The argument objects */
  219. DB_ENV *envp; /* Environment pointer */
  220. {
  221. DB_LOCK_STAT *sp;
  222. Tcl_Obj *res;
  223. int result, ret;
  224. result = TCL_OK;
  225. /*
  226.  * No args for this.  Error if there are some.
  227.  */
  228. if (objc != 2) {
  229. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  230. return (TCL_ERROR);
  231. }
  232. _debug_check();
  233. ret = envp->lock_stat(envp, &sp, 0);
  234. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock stat");
  235. if (result == TCL_ERROR)
  236. return (result);
  237. /*
  238.  * Have our stats, now construct the name value
  239.  * list pairs and free up the memory.
  240.  */
  241. res = Tcl_NewObj();
  242. /*
  243.  * MAKE_STAT_LIST assumes 'res' and 'error' label.
  244.  */
  245. MAKE_STAT_LIST("Region size", sp->st_regsize);
  246. MAKE_STAT_LIST("Last allocated locker ID", sp->st_id);
  247. MAKE_STAT_LIST("Current maximum unused locker ID", sp->st_cur_maxid);
  248. MAKE_STAT_LIST("Maximum locks", sp->st_maxlocks);
  249. MAKE_STAT_LIST("Maximum lockers", sp->st_maxlockers);
  250. MAKE_STAT_LIST("Maximum objects", sp->st_maxobjects);
  251. MAKE_STAT_LIST("Lock modes", sp->st_nmodes);
  252. MAKE_STAT_LIST("Current number of locks", sp->st_nlocks);
  253. MAKE_STAT_LIST("Maximum number of locks so far", sp->st_maxnlocks);
  254. MAKE_STAT_LIST("Current number of lockers", sp->st_nlockers);
  255. MAKE_STAT_LIST("Maximum number of lockers so far", sp->st_maxnlockers);
  256. MAKE_STAT_LIST("Current number of objects", sp->st_nobjects);
  257. MAKE_STAT_LIST("Maximum number of objects so far", sp->st_maxnobjects);
  258. MAKE_STAT_LIST("Number of conflicts", sp->st_nconflicts);
  259. MAKE_STAT_LIST("Lock requests", sp->st_nrequests);
  260. MAKE_STAT_LIST("Lock releases", sp->st_nreleases);
  261. MAKE_STAT_LIST("Lock requests that would have waited", sp->st_nnowaits);
  262. MAKE_STAT_LIST("Deadlocks detected", sp->st_ndeadlocks);
  263. MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait);
  264. MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait);
  265. MAKE_STAT_LIST("Lock timeout value", sp->st_locktimeout);
  266. MAKE_STAT_LIST("Number of lock timeouts", sp->st_nlocktimeouts);
  267. MAKE_STAT_LIST("Transaction timeout value", sp->st_txntimeout);
  268. MAKE_STAT_LIST("Number of transaction timeouts", sp->st_ntxntimeouts);
  269. Tcl_SetObjResult(interp, res);
  270. error:
  271. free(sp);
  272. return (result);
  273. }
  274. /*
  275.  * tcl_LockTimeout --
  276.  *
  277.  * PUBLIC: int tcl_LockTimeout __P((Tcl_Interp *, int,
  278.  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
  279.  */
  280. int
  281. tcl_LockTimeout(interp, objc, objv, envp)
  282. Tcl_Interp *interp; /* Interpreter */
  283. int objc; /* How many arguments? */
  284. Tcl_Obj *CONST objv[]; /* The argument objects */
  285. DB_ENV *envp; /* Environment pointer */
  286. {
  287. long timeout;
  288. int result, ret;
  289. /*
  290.  * One arg, the timeout.
  291.  */
  292. if (objc != 3) {
  293. Tcl_WrongNumArgs(interp, 2, objv, "?timeout?");
  294. return (TCL_ERROR);
  295. }
  296. result = Tcl_GetLongFromObj(interp, objv[2], &timeout);
  297. if (result != TCL_OK)
  298. return (result);
  299. _debug_check();
  300. ret = envp->set_timeout(envp, (u_int32_t)timeout, DB_SET_LOCK_TIMEOUT);
  301. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock timeout");
  302. return (result);
  303. }
  304. /*
  305.  * lock_Cmd --
  306.  * Implements the "lock" widget.
  307.  */
  308. static int
  309. lock_Cmd(clientData, interp, objc, objv)
  310. ClientData clientData; /* Lock handle */
  311. Tcl_Interp *interp; /* Interpreter */
  312. int objc; /* How many arguments? */
  313. Tcl_Obj *CONST objv[]; /* The argument objects */
  314. {
  315. static char *lkcmds[] = {
  316. "put",
  317. NULL
  318. };
  319. enum lkcmds {
  320. LKPUT
  321. };
  322. DB_ENV *env;
  323. DB_LOCK *lock;
  324. DBTCL_INFO *lkip;
  325. int cmdindex, result, ret;
  326. Tcl_ResetResult(interp);
  327. lock = (DB_LOCK *)clientData;
  328. lkip = _PtrToInfo((void *)lock);
  329. result = TCL_OK;
  330. if (lock == NULL) {
  331. Tcl_SetResult(interp, "NULL lock", TCL_STATIC);
  332. return (TCL_ERROR);
  333. }
  334. if (lkip == NULL) {
  335. Tcl_SetResult(interp, "NULL lock info pointer", TCL_STATIC);
  336. return (TCL_ERROR);
  337. }
  338. env = NAME_TO_ENV(lkip->i_parent->i_name);
  339. /*
  340.  * No args for this.  Error if there are some.
  341.  */
  342. if (objc != 2) {
  343. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  344. return (TCL_ERROR);
  345. }
  346. /*
  347.  * Get the command name index from the object based on the dbcmds
  348.  * defined above.
  349.  */
  350. if (Tcl_GetIndexFromObj(interp,
  351.     objv[1], lkcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
  352. return (IS_HELP(objv[1]));
  353. switch ((enum lkcmds)cmdindex) {
  354. case LKPUT:
  355. _debug_check();
  356. ret = env->lock_put(env, lock);
  357. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  358.     "lock put");
  359. (void)Tcl_DeleteCommand(interp, lkip->i_name);
  360. _DeleteInfo(lkip);
  361. __os_free(env, lock);
  362. break;
  363. }
  364. return (result);
  365. }
  366. /*
  367.  * tcl_LockVec --
  368.  *
  369.  * PUBLIC: int tcl_LockVec __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
  370.  */
  371. int
  372. tcl_LockVec(interp, objc, objv, envp)
  373. Tcl_Interp *interp; /* Interpreter */
  374. int objc; /* How many arguments? */
  375. Tcl_Obj *CONST objv[]; /* The argument objects */
  376. DB_ENV *envp; /* environment pointer */
  377. {
  378. static char *lvopts[] = {
  379. "-nowait",
  380.  NULL
  381. };
  382. enum lvopts {
  383. LVNOWAIT
  384. };
  385. static char *lkops[] = {
  386. "get",
  387. "put",
  388. "put_all",
  389. "put_obj",
  390. "timeout",
  391.  NULL
  392. };
  393. enum lkops {
  394. LKGET,
  395. LKPUT,
  396. LKPUTALL,
  397. LKPUTOBJ,
  398. LKTIMEOUT
  399. };
  400. DB_LOCK *lock;
  401. DB_LOCKREQ list;
  402. DBT obj;
  403. Tcl_Obj **myobjv, *res, *thisop;
  404. void *otmp;
  405. u_int32_t flag, lockid;
  406. int freeobj, i, myobjc, optindex, result, ret;
  407. char *lockname, msg[MSG_SIZE], newname[MSG_SIZE];
  408. result = TCL_OK;
  409. memset(newname, 0, MSG_SIZE);
  410. flag = 0;
  411. freeobj = 0;
  412. /*
  413.  * If -nowait is given, it MUST be first arg.
  414.  */
  415. if (Tcl_GetIndexFromObj(interp, objv[2],
  416.     lvopts, "option", TCL_EXACT, &optindex) == TCL_OK) {
  417. switch ((enum lvopts)optindex) {
  418. case LVNOWAIT:
  419. flag |= DB_LOCK_NOWAIT;
  420. break;
  421. }
  422. i = 3;
  423. } else {
  424. if (IS_HELP(objv[2]) == TCL_OK)
  425. return (TCL_OK);
  426. Tcl_ResetResult(interp);
  427. i = 2;
  428. }
  429. /*
  430.  * Our next arg MUST be the locker ID.
  431.  */
  432. result = _GetUInt32(interp, objv[i++], &lockid);
  433. if (result != TCL_OK)
  434. return (result);
  435. /*
  436.  * All other remaining args are operation tuples.
  437.  * Go through sequentially to decode, execute and build
  438.  * up list of return values.
  439.  */
  440. res = Tcl_NewListObj(0, NULL);
  441. while (i < objc) {
  442. /*
  443.  * Get the list of the tuple.
  444.  */
  445. lock = NULL;
  446. result = Tcl_ListObjGetElements(interp, objv[i],
  447.     &myobjc, &myobjv);
  448. if (result == TCL_OK)
  449. i++;
  450. else
  451. break;
  452. /*
  453.  * First we will set up the list of requests.
  454.  * We will make a "second pass" after we get back
  455.  * the results from the lock_vec call to create
  456.  * the return list.
  457.  */
  458. if (Tcl_GetIndexFromObj(interp, myobjv[0],
  459.     lkops, "option", TCL_EXACT, &optindex) != TCL_OK) {
  460. result = IS_HELP(myobjv[0]);
  461. goto error;
  462. }
  463. switch ((enum lkops)optindex) {
  464. case LKGET:
  465. if (myobjc != 3) {
  466. Tcl_WrongNumArgs(interp, 1, myobjv,
  467.     "{get obj mode}");
  468. result = TCL_ERROR;
  469. goto error;
  470. }
  471. result = _LockMode(interp, myobjv[2], &list.mode);
  472. if (result != TCL_OK)
  473. goto error;
  474. ret = _CopyObjBytes(interp, myobjv[1], &otmp,
  475.     &obj.size, &freeobj);
  476. if (ret != 0) {
  477. result = _ReturnSetup(interp, ret,
  478.     DB_RETOK_STD(ret), "lock vec");
  479. return (result);
  480. }
  481. obj.data = otmp;
  482. ret = _GetThisLock(interp, envp, lockid, flag,
  483.     &obj, list.mode, newname);
  484. if (ret != 0) {
  485. result = _ReturnSetup(interp, ret,
  486.     DB_RETOK_STD(ret), "lock vec");
  487. thisop = Tcl_NewIntObj(ret);
  488. (void)Tcl_ListObjAppendElement(interp, res,
  489.     thisop);
  490. goto error;
  491. }
  492. thisop = Tcl_NewStringObj(newname, strlen(newname));
  493. (void)Tcl_ListObjAppendElement(interp, res, thisop);
  494. if (freeobj) {
  495. (void)__os_free(envp, otmp);
  496. freeobj = 0;
  497. }
  498. continue;
  499. case LKPUT:
  500. if (myobjc != 2) {
  501. Tcl_WrongNumArgs(interp, 1, myobjv,
  502.     "{put lock}");
  503. result = TCL_ERROR;
  504. goto error;
  505. }
  506. list.op = DB_LOCK_PUT;
  507. lockname = Tcl_GetStringFromObj(myobjv[1], NULL);
  508. lock = NAME_TO_LOCK(lockname);
  509. if (lock == NULL) {
  510. snprintf(msg, MSG_SIZE, "Invalid lock: %sn",
  511.     lockname);
  512. Tcl_SetResult(interp, msg, TCL_VOLATILE);
  513. result = TCL_ERROR;
  514. goto error;
  515. }
  516. list.lock = *lock;
  517. break;
  518. case LKPUTALL:
  519. if (myobjc != 1) {
  520. Tcl_WrongNumArgs(interp, 1, myobjv,
  521.     "{put_all}");
  522. result = TCL_ERROR;
  523. goto error;
  524. }
  525. list.op = DB_LOCK_PUT_ALL;
  526. break;
  527. case LKPUTOBJ:
  528. if (myobjc != 2) {
  529. Tcl_WrongNumArgs(interp, 1, myobjv,
  530.     "{put_obj obj}");
  531. result = TCL_ERROR;
  532. goto error;
  533. }
  534. list.op = DB_LOCK_PUT_OBJ;
  535. ret = _CopyObjBytes(interp, myobjv[1], &otmp,
  536.     &obj.size, &freeobj);
  537. if (ret != 0) {
  538. result = _ReturnSetup(interp, ret,
  539.     DB_RETOK_STD(ret), "lock vec");
  540. return (result);
  541. }
  542. obj.data = otmp;
  543. list.obj = &obj;
  544. break;
  545. case LKTIMEOUT:
  546. list.op = DB_LOCK_TIMEOUT;
  547. break;
  548. }
  549. /*
  550.  * We get here, we have set up our request, now call
  551.  * lock_vec.
  552.  */
  553. _debug_check();
  554. ret = envp->lock_vec(envp, lockid, flag, &list, 1, NULL);
  555. /*
  556.  * Now deal with whether or not the operation succeeded.
  557.  * Get's were done above, all these are only puts.
  558.  */
  559. thisop = Tcl_NewIntObj(ret);
  560. result = Tcl_ListObjAppendElement(interp, res, thisop);
  561. if (ret != 0 && result == TCL_OK)
  562. result = _ReturnSetup(interp, ret,
  563.     DB_RETOK_STD(ret), "lock put");
  564. if (freeobj) {
  565. (void)__os_free(envp, otmp);
  566. freeobj = 0;
  567. }
  568. /*
  569.  * We did a put of some kind.  Since we did that,
  570.  * we have to delete the commands associated with
  571.  * any of the locks we just put.
  572.  */
  573. _LockPutInfo(interp, list.op, lock, lockid, &obj);
  574. }
  575. if (result == TCL_OK && res)
  576. Tcl_SetObjResult(interp, res);
  577. error:
  578. return (result);
  579. }
  580. static int
  581. _LockMode(interp, obj, mode)
  582. Tcl_Interp *interp;
  583. Tcl_Obj *obj;
  584. db_lockmode_t *mode;
  585. {
  586. int optindex;
  587. if (Tcl_GetIndexFromObj(interp, obj, lkmode, "option",
  588.     TCL_EXACT, &optindex) != TCL_OK)
  589. return (IS_HELP(obj));
  590. switch ((enum lkmode)optindex) {
  591. case LK_NG:
  592. *mode = DB_LOCK_NG;
  593. break;
  594. case LK_READ:
  595. *mode = DB_LOCK_READ;
  596. break;
  597. case LK_WRITE:
  598. *mode = DB_LOCK_WRITE;
  599. break;
  600. case LK_IREAD:
  601. *mode = DB_LOCK_IREAD;
  602. break;
  603. case LK_IWRITE:
  604. *mode = DB_LOCK_IWRITE;
  605. break;
  606. case LK_IWR:
  607. *mode = DB_LOCK_IWR;
  608. break;
  609. }
  610. return (TCL_OK);
  611. }
  612. static void
  613. _LockPutInfo(interp, op, lock, lockid, objp)
  614. Tcl_Interp *interp;
  615. db_lockop_t op;
  616. DB_LOCK *lock;
  617. u_int32_t lockid;
  618. DBT *objp;
  619. {
  620. DBTCL_INFO *p, *nextp;
  621. int found;
  622. for (p = LIST_FIRST(&__db_infohead); p != NULL; p = nextp) {
  623. found = 0;
  624. nextp = LIST_NEXT(p, entries);
  625. if ((op == DB_LOCK_PUT && (p->i_lock == lock)) ||
  626.     (op == DB_LOCK_PUT_ALL && p->i_locker == lockid) ||
  627.     (op == DB_LOCK_PUT_OBJ && p->i_lockobj.data &&
  628. memcmp(p->i_lockobj.data, objp->data, objp->size) == 0))
  629. found = 1;
  630. if (found) {
  631. (void)Tcl_DeleteCommand(interp, p->i_name);
  632. __os_free(NULL, p->i_lock);
  633. _DeleteInfo(p);
  634. }
  635. }
  636. }
  637. static int
  638. _GetThisLock(interp, envp, lockid, flag, objp, mode, newname)
  639. Tcl_Interp *interp; /* Interpreter */
  640. DB_ENV *envp; /* Env handle */
  641. u_int32_t lockid; /* Locker ID */
  642. u_int32_t flag; /* Lock flag */
  643. DBT *objp; /* Object to lock */
  644. db_lockmode_t mode; /* Lock mode */
  645. char *newname; /* New command name */
  646. {
  647. DB_LOCK *lock;
  648. DBTCL_INFO *envip, *ip;
  649. int result, ret;
  650. result = TCL_OK;
  651. envip = _PtrToInfo((void *)envp);
  652. if (envip == NULL) {
  653. Tcl_SetResult(interp, "Could not find env infon", TCL_STATIC);
  654. return (TCL_ERROR);
  655. }
  656. snprintf(newname, MSG_SIZE, "%s.lock%d",
  657.     envip->i_name, envip->i_envlockid);
  658. ip = _NewInfo(interp, NULL, newname, I_LOCK);
  659. if (ip == NULL) {
  660. Tcl_SetResult(interp, "Could not set up info",
  661.     TCL_STATIC);
  662. return (TCL_ERROR);
  663. }
  664. ret = __os_malloc(envp, sizeof(DB_LOCK), &lock);
  665. if (ret != 0) {
  666. Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
  667. return (TCL_ERROR);
  668. }
  669. _debug_check();
  670. ret = envp->lock_get(envp, lockid, flag, objp, mode, lock);
  671. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock get");
  672. if (result == TCL_ERROR) {
  673. __os_free(envp, lock);
  674. _DeleteInfo(ip);
  675. return (result);
  676. }
  677. /*
  678.  * Success.  Set up return.  Set up new info
  679.  * and command widget for this lock.
  680.  */
  681. ret = __os_malloc(envp, objp->size, &ip->i_lockobj.data);
  682. if (ret != 0) {
  683. Tcl_SetResult(interp, "Could not duplicate obj",
  684.     TCL_STATIC);
  685. (void)envp->lock_put(envp, lock);
  686. __os_free(envp, lock);
  687. _DeleteInfo(ip);
  688. result = TCL_ERROR;
  689. goto error;
  690. }
  691. memcpy(ip->i_lockobj.data, objp->data, objp->size);
  692. ip->i_lockobj.size = objp->size;
  693. envip->i_envlockid++;
  694. ip->i_parent = envip;
  695. ip->i_locker = lockid;
  696. _SetInfoData(ip, lock);
  697. Tcl_CreateObjCommand(interp, newname,
  698.     (Tcl_ObjCmdProc *)lock_Cmd, (ClientData)lock, NULL);
  699. error:
  700. return (result);
  701. }
  702. #endif