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

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1999-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: tcl_env.c,v 11.84 2002/08/06 06:21:03 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 void _EnvInfoDelete __P((Tcl_Interp *, DBTCL_INFO *));
  23. static int  env_DbRemove __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
  24. static int  env_DbRename __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
  25. /*
  26.  * PUBLIC: int env_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
  27.  *
  28.  * env_Cmd --
  29.  * Implements the "env" command.
  30.  */
  31. int
  32. env_Cmd(clientData, interp, objc, objv)
  33. ClientData clientData; /* Env handle */
  34. Tcl_Interp *interp; /* Interpreter */
  35. int objc; /* How many arguments? */
  36. Tcl_Obj *CONST objv[]; /* The argument objects */
  37. {
  38. static char *envcmds[] = {
  39. #if CONFIG_TEST
  40. "attributes",
  41. "lock_detect",
  42. "lock_id",
  43. "lock_id_free",
  44. "lock_id_set",
  45. "lock_get",
  46. "lock_stat",
  47. "lock_timeout",
  48. "lock_vec",
  49. "log_archive",
  50. "log_compare",
  51. "log_cursor",
  52. "log_file",
  53. "log_flush",
  54. "log_get",
  55. "log_put",
  56. "log_stat",
  57. "mpool",
  58. "mpool_stat",
  59. "mpool_sync",
  60. "mpool_trickle",
  61. "mutex",
  62. "rep_elect",
  63. "rep_flush",
  64. "rep_limit",
  65. "rep_process_message",
  66. "rep_request",
  67. "rep_start",
  68. "rep_stat",
  69. "rpcid",
  70. "test",
  71. "txn_checkpoint",
  72. "txn_id_set",
  73. "txn_recover",
  74. "txn_stat",
  75. "txn_timeout",
  76. "verbose",
  77. #endif
  78. "close",
  79. "dbremove",
  80. "dbrename",
  81. "txn",
  82. NULL
  83. };
  84. enum envcmds {
  85. #if CONFIG_TEST
  86. ENVATTR,
  87. ENVLKDETECT,
  88. ENVLKID,
  89. ENVLKFREEID,
  90. ENVLKSETID,
  91. ENVLKGET,
  92. ENVLKSTAT,
  93. ENVLKTIMEOUT,
  94. ENVLKVEC,
  95. ENVLOGARCH,
  96. ENVLOGCMP,
  97. ENVLOGCURSOR,
  98. ENVLOGFILE,
  99. ENVLOGFLUSH,
  100. ENVLOGGET,
  101. ENVLOGPUT,
  102. ENVLOGSTAT,
  103. ENVMP,
  104. ENVMPSTAT,
  105. ENVMPSYNC,
  106. ENVTRICKLE,
  107. ENVMUTEX,
  108. ENVREPELECT,
  109. ENVREPFLUSH,
  110. ENVREPLIMIT,
  111. ENVREPPROCMESS,
  112. ENVREPREQUEST,
  113. ENVREPSTART,
  114. ENVREPSTAT,
  115. ENVRPCID,
  116. ENVTEST,
  117. ENVTXNCKP,
  118. ENVTXNSETID,
  119. ENVTXNRECOVER,
  120. ENVTXNSTAT,
  121. ENVTXNTIMEOUT,
  122. ENVVERB,
  123. #endif
  124. ENVCLOSE,
  125. ENVDBREMOVE,
  126. ENVDBRENAME,
  127. ENVTXN
  128. };
  129. DBTCL_INFO *envip, *logcip;
  130. DB_ENV *dbenv;
  131. DB_LOGC *logc;
  132. Tcl_Obj *res;
  133. char newname[MSG_SIZE];
  134. int cmdindex, result, ret;
  135. u_int32_t newval;
  136. #if CONFIG_TEST
  137. u_int32_t otherval;
  138. #endif
  139. Tcl_ResetResult(interp);
  140. dbenv = (DB_ENV *)clientData;
  141. envip = _PtrToInfo((void *)dbenv);
  142. result = TCL_OK;
  143. memset(newname, 0, MSG_SIZE);
  144. if (objc <= 1) {
  145. Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs");
  146. return (TCL_ERROR);
  147. }
  148. if (dbenv == NULL) {
  149. Tcl_SetResult(interp, "NULL env pointer", TCL_STATIC);
  150. return (TCL_ERROR);
  151. }
  152. if (envip == NULL) {
  153. Tcl_SetResult(interp, "NULL env info pointer", TCL_STATIC);
  154. return (TCL_ERROR);
  155. }
  156. /*
  157.  * Get the command name index from the object based on the berkdbcmds
  158.  * defined above.
  159.  */
  160. if (Tcl_GetIndexFromObj(interp, objv[1], envcmds, "command",
  161.     TCL_EXACT, &cmdindex) != TCL_OK)
  162. return (IS_HELP(objv[1]));
  163. res = NULL;
  164. switch ((enum envcmds)cmdindex) {
  165. #if CONFIG_TEST
  166. case ENVLKDETECT:
  167. result = tcl_LockDetect(interp, objc, objv, dbenv);
  168. break;
  169. case ENVLKSTAT:
  170. result = tcl_LockStat(interp, objc, objv, dbenv);
  171. break;
  172. case ENVLKTIMEOUT:
  173. result = tcl_LockTimeout(interp, objc, objv, dbenv);
  174. break;
  175. case ENVLKID:
  176. /*
  177.  * No args for this.  Error if there are some.
  178.  */
  179. if (objc > 2) {
  180. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  181. return (TCL_ERROR);
  182. }
  183. _debug_check();
  184. ret = dbenv->lock_id(dbenv, &newval);
  185. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  186.     "lock_id");
  187. if (result == TCL_OK)
  188. res = Tcl_NewLongObj((long)newval);
  189. break;
  190. case ENVLKFREEID:
  191. if (objc != 3) {
  192. Tcl_WrongNumArgs(interp, 3, objv, NULL);
  193. return (TCL_ERROR);
  194. }
  195. result = Tcl_GetLongFromObj(interp, objv[2], (long *)&newval);
  196. if (result != TCL_OK)
  197. return (result);
  198. ret = dbenv->lock_id_free(dbenv, newval);
  199. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  200.     "lock id_free");
  201. break;
  202. case ENVLKSETID:
  203. if (objc != 4) {
  204. Tcl_WrongNumArgs(interp, 4, objv, "current max");
  205. return (TCL_ERROR);
  206. }
  207. result = Tcl_GetLongFromObj(interp, objv[2], (long *)&newval);
  208. if (result != TCL_OK)
  209. return (result);
  210. result = Tcl_GetLongFromObj(interp, objv[3], (long *)&otherval);
  211. if (result != TCL_OK)
  212. return (result);
  213. ret = dbenv->lock_id_set(dbenv, newval, otherval);
  214. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  215.     "lock id_free");
  216. break;
  217. case ENVLKGET:
  218. result = tcl_LockGet(interp, objc, objv, dbenv);
  219. break;
  220. case ENVLKVEC:
  221. result = tcl_LockVec(interp, objc, objv, dbenv);
  222. break;
  223. case ENVLOGARCH:
  224. result = tcl_LogArchive(interp, objc, objv, dbenv);
  225. break;
  226. case ENVLOGCMP:
  227. result = tcl_LogCompare(interp, objc, objv);
  228. break;
  229. case ENVLOGCURSOR:
  230. snprintf(newname, sizeof(newname),
  231.     "%s.logc%d", envip->i_name, envip->i_envlogcid);
  232. logcip = _NewInfo(interp, NULL, newname, I_LOGC);
  233. if (logcip != NULL) {
  234. ret = dbenv->log_cursor(dbenv, &logc, 0);
  235. if (ret == 0) {
  236. result = TCL_OK;
  237. envip->i_envlogcid++;
  238. /*
  239.  * We do NOT want to set i_parent to
  240.  * envip here because log cursors are
  241.  * not "tied" to the env.  That is, they
  242.  * are NOT closed if the env is closed.
  243.  */
  244. Tcl_CreateObjCommand(interp, newname,
  245.     (Tcl_ObjCmdProc *)logc_Cmd,
  246.     (ClientData)logc, NULL);
  247. res =
  248.     Tcl_NewStringObj(newname, strlen(newname));
  249. _SetInfoData(logcip, logc);
  250. } else {
  251. _DeleteInfo(logcip);
  252. result = _ErrorSetup(interp, ret, "log cursor");
  253. }
  254. } else {
  255. Tcl_SetResult(interp,
  256.     "Could not set up info", TCL_STATIC);
  257. result = TCL_ERROR;
  258. }
  259. break;
  260. case ENVLOGFILE:
  261. result = tcl_LogFile(interp, objc, objv, dbenv);
  262. break;
  263. case ENVLOGFLUSH:
  264. result = tcl_LogFlush(interp, objc, objv, dbenv);
  265. break;
  266. case ENVLOGGET:
  267. result = tcl_LogGet(interp, objc, objv, dbenv);
  268. break;
  269. case ENVLOGPUT:
  270. result = tcl_LogPut(interp, objc, objv, dbenv);
  271. break;
  272. case ENVLOGSTAT:
  273. result = tcl_LogStat(interp, objc, objv, dbenv);
  274. break;
  275. case ENVMPSTAT:
  276. result = tcl_MpStat(interp, objc, objv, dbenv);
  277. break;
  278. case ENVMPSYNC:
  279. result = tcl_MpSync(interp, objc, objv, dbenv);
  280. break;
  281. case ENVTRICKLE:
  282. result = tcl_MpTrickle(interp, objc, objv, dbenv);
  283. break;
  284. case ENVMP:
  285. result = tcl_Mp(interp, objc, objv, dbenv, envip);
  286. break;
  287. case ENVREPELECT:
  288. result = tcl_RepElect(interp, objc, objv, dbenv);
  289. break;
  290. case ENVREPFLUSH:
  291. result = tcl_RepFlush(interp, objc, objv, dbenv);
  292. break;
  293. case ENVREPLIMIT:
  294. result = tcl_RepLimit(interp, objc, objv, dbenv);
  295. break;
  296. case ENVREPPROCMESS:
  297. result = tcl_RepProcessMessage(interp, objc, objv, dbenv);
  298. break;
  299. case ENVREPREQUEST:
  300. result = tcl_RepRequest(interp, objc, objv, dbenv);
  301. break;
  302. case ENVREPSTART:
  303. result = tcl_RepStart(interp, objc, objv, dbenv);
  304. break;
  305. case ENVREPSTAT:
  306. result = tcl_RepStat(interp, objc, objv, dbenv);
  307. break;
  308. case ENVRPCID:
  309. /*
  310.  * No args for this.  Error if there are some.
  311.  */
  312. if (objc > 2) {
  313. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  314. return (TCL_ERROR);
  315. }
  316. /*
  317.  * !!! Retrieve the client ID from the dbp handle directly.
  318.  * This is for testing purposes only.  It is dbp-private data.
  319.  */
  320. res = Tcl_NewLongObj(dbenv->cl_id);
  321. break;
  322. case ENVTXNCKP:
  323. result = tcl_TxnCheckpoint(interp, objc, objv, dbenv);
  324. break;
  325. case ENVTXNSETID:
  326. if (objc != 4) {
  327. Tcl_WrongNumArgs(interp, 4, objv, "current max");
  328. return (TCL_ERROR);
  329. }
  330. result = Tcl_GetLongFromObj(interp, objv[2], (long *)&newval);
  331. if (result != TCL_OK)
  332. return (result);
  333. result = Tcl_GetLongFromObj(interp, objv[3], (long *)&otherval);
  334. if (result != TCL_OK)
  335. return (result);
  336. ret = dbenv->txn_id_set(dbenv, newval, otherval);
  337. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  338.     "lock id_free");
  339. break;
  340. case ENVTXNRECOVER:
  341. result = tcl_TxnRecover(interp, objc, objv, dbenv, envip);
  342. break;
  343. case ENVTXNSTAT:
  344. result = tcl_TxnStat(interp, objc, objv, dbenv);
  345. break;
  346. case ENVTXNTIMEOUT:
  347. result = tcl_TxnTimeout(interp, objc, objv, dbenv);
  348. break;
  349. case ENVMUTEX:
  350. result = tcl_Mutex(interp, objc, objv, dbenv, envip);
  351. break;
  352. case ENVATTR:
  353. result = tcl_EnvAttr(interp, objc, objv, dbenv);
  354. break;
  355. case ENVTEST:
  356. result = tcl_EnvTest(interp, objc, objv, dbenv);
  357. break;
  358. case ENVVERB:
  359. /*
  360.  * Two args for this.  Error if different.
  361.  */
  362. if (objc != 4) {
  363. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  364. return (TCL_ERROR);
  365. }
  366. result = tcl_EnvVerbose(interp, dbenv, objv[2], objv[3]);
  367. break;
  368. #endif
  369. case ENVCLOSE:
  370. /*
  371.  * No args for this.  Error if there are some.
  372.  */
  373. if (objc > 2) {
  374. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  375. return (TCL_ERROR);
  376. }
  377. /*
  378.  * Any transactions will be aborted, and an mpools
  379.  * closed automatically.  We must delete any txn
  380.  * and mp widgets we have here too for this env.
  381.  * NOTE: envip is freed when we come back from
  382.  * this function.  Set it to NULL to make sure no
  383.  * one tries to use it later.
  384.  */
  385. _debug_check();
  386. ret = dbenv->close(dbenv, 0);
  387. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  388.     "env close");
  389. _EnvInfoDelete(interp, envip);
  390. envip = NULL;
  391. break;
  392. case ENVDBREMOVE:
  393. result = env_DbRemove(interp, objc, objv, dbenv);
  394. break;
  395. case ENVDBRENAME:
  396. result = env_DbRename(interp, objc, objv, dbenv);
  397. break;
  398. case ENVTXN:
  399. result = tcl_Txn(interp, objc, objv, dbenv, envip);
  400. break;
  401. }
  402. /*
  403.  * Only set result if we have a res.  Otherwise, lower
  404.  * functions have already done so.
  405.  */
  406. if (result == TCL_OK && res)
  407. Tcl_SetObjResult(interp, res);
  408. return (result);
  409. }
  410. /*
  411.  * PUBLIC: int tcl_EnvRemove __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
  412.  * PUBLIC:      DB_ENV *, DBTCL_INFO *));
  413.  *
  414.  * tcl_EnvRemove --
  415.  */
  416. int
  417. tcl_EnvRemove(interp, objc, objv, dbenv, envip)
  418. Tcl_Interp *interp; /* Interpreter */
  419. int objc; /* How many arguments? */
  420. Tcl_Obj *CONST objv[]; /* The argument objects */
  421. DB_ENV *dbenv; /* Env pointer */
  422. DBTCL_INFO *envip; /* Info pointer */
  423. {
  424. static char *envremopts[] = {
  425. #if CONFIG_TEST
  426. "-overwrite",
  427. "-server",
  428. #endif
  429. "-data_dir",
  430. "-encryptaes",
  431. "-encryptany",
  432. "-force",
  433. "-home",
  434. "-log_dir",
  435. "-tmp_dir",
  436. "-use_environ",
  437. "-use_environ_root",
  438. NULL
  439. };
  440. enum envremopts {
  441. #if CONFIG_TEST
  442. ENVREM_OVERWRITE,
  443. ENVREM_SERVER,
  444. #endif
  445. ENVREM_DATADIR,
  446. ENVREM_ENCRYPT_AES,
  447. ENVREM_ENCRYPT_ANY,
  448. ENVREM_FORCE,
  449. ENVREM_HOME,
  450. ENVREM_LOGDIR,
  451. ENVREM_TMPDIR,
  452. ENVREM_USE_ENVIRON,
  453. ENVREM_USE_ENVIRON_ROOT
  454. };
  455. DB_ENV *e;
  456. u_int32_t cflag, enc_flag, flag, forceflag, sflag;
  457. int i, optindex, result, ret;
  458. char *datadir, *home, *logdir, *passwd, *server, *tmpdir;
  459. result = TCL_OK;
  460. cflag = flag = forceflag = sflag = 0;
  461. home = NULL;
  462. passwd = NULL;
  463. datadir = logdir = tmpdir = NULL;
  464. server = NULL;
  465. enc_flag = 0;
  466. if (objc < 2) {
  467. Tcl_WrongNumArgs(interp, 2, objv, "?args?");
  468. return (TCL_ERROR);
  469. }
  470. i = 2;
  471. while (i < objc) {
  472. if (Tcl_GetIndexFromObj(interp, objv[i], envremopts, "option",
  473.     TCL_EXACT, &optindex) != TCL_OK) {
  474. result = IS_HELP(objv[i]);
  475. goto error;
  476. }
  477. i++;
  478. switch ((enum envremopts)optindex) {
  479. #if CONFIG_TEST
  480. case ENVREM_SERVER:
  481. /* Make sure we have an arg to check against! */
  482. if (i >= objc) {
  483. Tcl_WrongNumArgs(interp, 2, objv,
  484.     "?-server name?");
  485. result = TCL_ERROR;
  486. break;
  487. }
  488. server = Tcl_GetStringFromObj(objv[i++], NULL);
  489. cflag = DB_CLIENT;
  490. break;
  491. #endif
  492. case ENVREM_ENCRYPT_AES:
  493. /* Make sure we have an arg to check against! */
  494. if (i >= objc) {
  495. Tcl_WrongNumArgs(interp, 2, objv,
  496.     "?-encryptaes passwd?");
  497. result = TCL_ERROR;
  498. break;
  499. }
  500. passwd = Tcl_GetStringFromObj(objv[i++], NULL);
  501. enc_flag = DB_ENCRYPT_AES;
  502. break;
  503. case ENVREM_ENCRYPT_ANY:
  504. /* Make sure we have an arg to check against! */
  505. if (i >= objc) {
  506. Tcl_WrongNumArgs(interp, 2, objv,
  507.     "?-encryptany passwd?");
  508. result = TCL_ERROR;
  509. break;
  510. }
  511. passwd = Tcl_GetStringFromObj(objv[i++], NULL);
  512. enc_flag = 0;
  513. break;
  514. case ENVREM_FORCE:
  515. forceflag |= DB_FORCE;
  516. break;
  517. case ENVREM_HOME:
  518. /* Make sure we have an arg to check against! */
  519. if (i >= objc) {
  520. Tcl_WrongNumArgs(interp, 2, objv,
  521.     "?-home dir?");
  522. result = TCL_ERROR;
  523. break;
  524. }
  525. home = Tcl_GetStringFromObj(objv[i++], NULL);
  526. break;
  527. #if CONFIG_TEST
  528. case ENVREM_OVERWRITE:
  529. sflag |= DB_OVERWRITE;
  530. break;
  531. #endif
  532. case ENVREM_USE_ENVIRON:
  533. flag |= DB_USE_ENVIRON;
  534. break;
  535. case ENVREM_USE_ENVIRON_ROOT:
  536. flag |= DB_USE_ENVIRON_ROOT;
  537. break;
  538. case ENVREM_DATADIR:
  539. if (i >= objc) {
  540. Tcl_WrongNumArgs(interp, 2, objv,
  541.     "-data_dir dir");
  542. result = TCL_ERROR;
  543. break;
  544. }
  545. datadir = Tcl_GetStringFromObj(objv[i++], NULL);
  546. break;
  547. case ENVREM_LOGDIR:
  548. if (i >= objc) {
  549. Tcl_WrongNumArgs(interp, 2, objv,
  550.     "-log_dir dir");
  551. result = TCL_ERROR;
  552. break;
  553. }
  554. logdir = Tcl_GetStringFromObj(objv[i++], NULL);
  555. break;
  556. case ENVREM_TMPDIR:
  557. if (i >= objc) {
  558. Tcl_WrongNumArgs(interp, 2, objv,
  559.     "-tmp_dir dir");
  560. result = TCL_ERROR;
  561. break;
  562. }
  563. tmpdir = Tcl_GetStringFromObj(objv[i++], NULL);
  564. break;
  565. }
  566. /*
  567.  * If, at any time, parsing the args we get an error,
  568.  * bail out and return.
  569.  */
  570. if (result != TCL_OK)
  571. goto error;
  572. }
  573. /*
  574.  * If dbenv is NULL, we don't have an open env and we need to open
  575.  * one of the user.  Don't bother with the info stuff.
  576.  */
  577. if (dbenv == NULL) {
  578. if ((ret = db_env_create(&e, cflag)) != 0) {
  579. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  580.     "db_env_create");
  581. goto error;
  582. }
  583. if (server != NULL) {
  584. _debug_check();
  585. ret = e->set_rpc_server(e, NULL, server, 0, 0, 0);
  586. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  587.     "set_rpc_server");
  588. if (result != TCL_OK)
  589. goto error;
  590. }
  591. if (datadir != NULL) {
  592. _debug_check();
  593. ret = e->set_data_dir(e, datadir);
  594. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  595.     "set_data_dir");
  596. if (result != TCL_OK)
  597. goto error;
  598. }
  599. if (logdir != NULL) {
  600. _debug_check();
  601. ret = e->set_lg_dir(e, logdir);
  602. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  603.     "set_log_dir");
  604. if (result != TCL_OK)
  605. goto error;
  606. }
  607. if (tmpdir != NULL) {
  608. _debug_check();
  609. ret = e->set_tmp_dir(e, tmpdir);
  610. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  611.     "set_tmp_dir");
  612. if (result != TCL_OK)
  613. goto error;
  614. }
  615. if (passwd != NULL) {
  616. ret = e->set_encrypt(e, passwd, enc_flag);
  617. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  618.     "set_encrypt");
  619. }
  620. if (sflag != 0 && (ret = e->set_flags(e, sflag, 1)) != 0) {
  621. _debug_check();
  622. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  623.     "set_flags");
  624. if (result != TCL_OK)
  625. goto error;
  626. }
  627. } else {
  628. /*
  629.  * We have to clean up any info associated with this env,
  630.  * regardless of the result of the remove so do it first.
  631.  * NOTE: envip is freed when we come back from this function.
  632.  */
  633. _EnvInfoDelete(interp, envip);
  634. envip = NULL;
  635. e = dbenv;
  636. }
  637. flag |= forceflag;
  638. /*
  639.  * When we get here we have parsed all the args.  Now remove
  640.  * the environment.
  641.  */
  642. _debug_check();
  643. ret = e->remove(e, home, flag);
  644. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  645.     "env remove");
  646. error:
  647. return (result);
  648. }
  649. static void
  650. _EnvInfoDelete(interp, envip)
  651. Tcl_Interp *interp; /* Tcl Interpreter */
  652. DBTCL_INFO *envip; /* Info for env */
  653. {
  654. DBTCL_INFO *nextp, *p;
  655. /*
  656.  * Before we can delete the environment info, we must close
  657.  * any open subsystems in this env.  We will:
  658.  * 1.  Abort any transactions (which aborts any nested txns).
  659.  * 2.  Close any mpools (which will put any pages itself).
  660.  * 3.  Put any locks and close log cursors.
  661.  * 4.  Close the error file.
  662.  */
  663. for (p = LIST_FIRST(&__db_infohead); p != NULL; p = nextp) {
  664. /*
  665.  * Check if this info structure "belongs" to this
  666.  * env.  If so, remove its commands and info structure.
  667.  * We do not close/abort/whatever here, because we
  668.  * don't want to replicate DB behavior.
  669.  *
  670.  * NOTE:  Only those types that can nest need to be
  671.  * itemized in the switch below.  That is txns and mps.
  672.  * Other types like log cursors and locks will just
  673.  * get cleaned up here.
  674.  */
  675.  if (p->i_parent == envip) {
  676. switch (p->i_type) {
  677. case I_TXN:
  678. _TxnInfoDelete(interp, p);
  679. break;
  680. case I_MP:
  681. _MpInfoDelete(interp, p);
  682. break;
  683. default:
  684. Tcl_SetResult(interp,
  685.     "_EnvInfoDelete: bad info type",
  686.     TCL_STATIC);
  687. break;
  688. }
  689. nextp = LIST_NEXT(p, entries);
  690. (void)Tcl_DeleteCommand(interp, p->i_name);
  691. _DeleteInfo(p);
  692. } else
  693. nextp = LIST_NEXT(p, entries);
  694. }
  695. (void)Tcl_DeleteCommand(interp, envip->i_name);
  696. _DeleteInfo(envip);
  697. }
  698. #if CONFIG_TEST
  699. /*
  700.  * PUBLIC: int tcl_EnvVerbose __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *,
  701.  * PUBLIC:    Tcl_Obj *));
  702.  *
  703.  * tcl_EnvVerbose --
  704.  */
  705. int
  706. tcl_EnvVerbose(interp, dbenv, which, onoff)
  707. Tcl_Interp *interp; /* Interpreter */
  708. DB_ENV *dbenv; /* Env pointer */
  709. Tcl_Obj *which; /* Which subsystem */
  710. Tcl_Obj *onoff; /* On or off */
  711. {
  712. static char *verbwhich[] = {
  713. "chkpt",
  714. "deadlock",
  715. "recovery",
  716. "rep",
  717. "wait",
  718. NULL
  719. };
  720. enum verbwhich {
  721. ENVVERB_CHK,
  722. ENVVERB_DEAD,
  723. ENVVERB_REC,
  724. ENVVERB_REP,
  725. ENVVERB_WAIT
  726. };
  727. static char *verbonoff[] = {
  728. "off",
  729. "on",
  730. NULL
  731. };
  732. enum verbonoff {
  733. ENVVERB_OFF,
  734. ENVVERB_ON
  735. };
  736. int on, optindex, ret;
  737. u_int32_t wh;
  738. if (Tcl_GetIndexFromObj(interp, which, verbwhich, "option",
  739.     TCL_EXACT, &optindex) != TCL_OK)
  740. return (IS_HELP(which));
  741. switch ((enum verbwhich)optindex) {
  742. case ENVVERB_CHK:
  743. wh = DB_VERB_CHKPOINT;
  744. break;
  745. case ENVVERB_DEAD:
  746. wh = DB_VERB_DEADLOCK;
  747. break;
  748. case ENVVERB_REC:
  749. wh = DB_VERB_RECOVERY;
  750. break;
  751. case ENVVERB_REP:
  752. wh = DB_VERB_REPLICATION;
  753. break;
  754. case ENVVERB_WAIT:
  755. wh = DB_VERB_WAITSFOR;
  756. break;
  757. default:
  758. return (TCL_ERROR);
  759. }
  760. if (Tcl_GetIndexFromObj(interp, onoff, verbonoff, "option",
  761.     TCL_EXACT, &optindex) != TCL_OK)
  762. return (IS_HELP(onoff));
  763. switch ((enum verbonoff)optindex) {
  764. case ENVVERB_OFF:
  765. on = 0;
  766. break;
  767. case ENVVERB_ON:
  768. on = 1;
  769. break;
  770. default:
  771. return (TCL_ERROR);
  772. }
  773. ret = dbenv->set_verbose(dbenv, wh, on);
  774. return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  775.     "env set verbose"));
  776. }
  777. #endif
  778. #if CONFIG_TEST
  779. /*
  780.  * PUBLIC: int tcl_EnvAttr __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
  781.  *
  782.  * tcl_EnvAttr --
  783.  * Return a list of the env's attributes
  784.  */
  785. int
  786. tcl_EnvAttr(interp, objc, objv, dbenv)
  787. Tcl_Interp *interp; /* Interpreter */
  788. int objc; /* How many arguments? */
  789. Tcl_Obj *CONST objv[]; /* The argument objects */
  790. DB_ENV *dbenv; /* Env pointer */
  791. {
  792. int result;
  793. Tcl_Obj *myobj, *retlist;
  794. result = TCL_OK;
  795. if (objc > 2) {
  796. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  797. return (TCL_ERROR);
  798. }
  799. retlist = Tcl_NewListObj(0, NULL);
  800. /*
  801.  * XXX
  802.  * We peek at the dbenv to determine what subsystems
  803.  * we have available in this env.
  804.  */
  805. myobj = Tcl_NewStringObj("-home", strlen("-home"));
  806. if ((result = Tcl_ListObjAppendElement(interp,
  807.     retlist, myobj)) != TCL_OK)
  808. goto err;
  809. myobj = Tcl_NewStringObj(dbenv->db_home, strlen(dbenv->db_home));
  810. if ((result = Tcl_ListObjAppendElement(interp,
  811.     retlist, myobj)) != TCL_OK)
  812. goto err;
  813. if (CDB_LOCKING(dbenv)) {
  814. myobj = Tcl_NewStringObj("-cdb", strlen("-cdb"));
  815. if ((result = Tcl_ListObjAppendElement(interp,
  816.     retlist, myobj)) != TCL_OK)
  817. goto err;
  818. }
  819. if (CRYPTO_ON(dbenv)) {
  820. myobj = Tcl_NewStringObj("-crypto", strlen("-crypto"));
  821. if ((result = Tcl_ListObjAppendElement(interp,
  822.     retlist, myobj)) != TCL_OK)
  823. goto err;
  824. }
  825. if (LOCKING_ON(dbenv)) {
  826. myobj = Tcl_NewStringObj("-lock", strlen("-lock"));
  827. if ((result = Tcl_ListObjAppendElement(interp,
  828.     retlist, myobj)) != TCL_OK)
  829. goto err;
  830. }
  831. if (LOGGING_ON(dbenv)) {
  832. myobj = Tcl_NewStringObj("-log", strlen("-log"));
  833. if ((result = Tcl_ListObjAppendElement(interp,
  834.     retlist, myobj)) != TCL_OK)
  835. goto err;
  836. }
  837. if (MPOOL_ON(dbenv)) {
  838. myobj = Tcl_NewStringObj("-mpool", strlen("-mpool"));
  839. if ((result = Tcl_ListObjAppendElement(interp,
  840.     retlist, myobj)) != TCL_OK)
  841. goto err;
  842. }
  843. if (RPC_ON(dbenv)) {
  844. myobj = Tcl_NewStringObj("-rpc", strlen("-rpc"));
  845. if ((result = Tcl_ListObjAppendElement(interp,
  846.     retlist, myobj)) != TCL_OK)
  847. goto err;
  848. }
  849. if (TXN_ON(dbenv)) {
  850. myobj = Tcl_NewStringObj("-txn", strlen("-txn"));
  851. if ((result = Tcl_ListObjAppendElement(interp,
  852.     retlist, myobj)) != TCL_OK)
  853. goto err;
  854. }
  855. Tcl_SetObjResult(interp, retlist);
  856. err:
  857. return (result);
  858. }
  859. /*
  860.  * PUBLIC: int tcl_EnvTest __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
  861.  *
  862.  * tcl_EnvTest --
  863.  */
  864. int
  865. tcl_EnvTest(interp, objc, objv, dbenv)
  866. Tcl_Interp *interp; /* Interpreter */
  867. int objc; /* How many arguments? */
  868. Tcl_Obj *CONST objv[]; /* The argument objects */
  869. DB_ENV *dbenv; /* Env pointer */
  870. {
  871. static char *envtestcmd[] = {
  872. "abort",
  873. "copy",
  874. NULL
  875. };
  876. enum envtestcmd {
  877. ENVTEST_ABORT,
  878. ENVTEST_COPY
  879. };
  880. static char *envtestat[] = {
  881. "electinit",
  882. "electsend",
  883. "electvote1",
  884. "electvote2",
  885. "electwait1",
  886. "electwait2",
  887. "none",
  888. "predestroy",
  889. "preopen",
  890. "postdestroy",
  891. "postlog",
  892. "postlogmeta",
  893. "postopen",
  894. "postsync",
  895. "subdb_lock",
  896. NULL
  897. };
  898. enum envtestat {
  899. ENVTEST_ELECTINIT,
  900. ENVTEST_ELECTSEND,
  901. ENVTEST_ELECTVOTE1,
  902. ENVTEST_ELECTVOTE2,
  903. ENVTEST_ELECTWAIT1,
  904. ENVTEST_ELECTWAIT2,
  905. ENVTEST_NONE,
  906. ENVTEST_PREDESTROY,
  907. ENVTEST_PREOPEN,
  908. ENVTEST_POSTDESTROY,
  909. ENVTEST_POSTLOG,
  910. ENVTEST_POSTLOGMETA,
  911. ENVTEST_POSTOPEN,
  912. ENVTEST_POSTSYNC,
  913. ENVTEST_SUBDB_LOCKS
  914. };
  915. int *loc, optindex, result, testval;
  916. result = TCL_OK;
  917. loc = NULL;
  918. if (objc != 4) {
  919. Tcl_WrongNumArgs(interp, 2, objv, "abort|copy location");
  920. return (TCL_ERROR);
  921. }
  922. /*
  923.  * This must be the "copy" or "abort" portion of the command.
  924.  */
  925. if (Tcl_GetIndexFromObj(interp, objv[2], envtestcmd, "command",
  926.     TCL_EXACT, &optindex) != TCL_OK) {
  927. result = IS_HELP(objv[2]);
  928. return (result);
  929. }
  930. switch ((enum envtestcmd)optindex) {
  931. case ENVTEST_ABORT:
  932. loc = &dbenv->test_abort;
  933. break;
  934. case ENVTEST_COPY:
  935. loc = &dbenv->test_copy;
  936. break;
  937. default:
  938. Tcl_SetResult(interp, "Illegal store location", TCL_STATIC);
  939. return (TCL_ERROR);
  940. }
  941. /*
  942.  * This must be the location portion of the command.
  943.  */
  944. if (Tcl_GetIndexFromObj(interp, objv[3], envtestat, "location",
  945.     TCL_EXACT, &optindex) != TCL_OK) {
  946. result = IS_HELP(objv[3]);
  947. return (result);
  948. }
  949. switch ((enum envtestat)optindex) {
  950. case ENVTEST_ELECTINIT:
  951. DB_ASSERT(loc == &dbenv->test_abort);
  952. testval = DB_TEST_ELECTINIT;
  953. break;
  954. case ENVTEST_ELECTSEND:
  955. DB_ASSERT(loc == &dbenv->test_abort);
  956. testval = DB_TEST_ELECTSEND;
  957. break;
  958. case ENVTEST_ELECTVOTE1:
  959. DB_ASSERT(loc == &dbenv->test_abort);
  960. testval = DB_TEST_ELECTVOTE1;
  961. break;
  962. case ENVTEST_ELECTVOTE2:
  963. DB_ASSERT(loc == &dbenv->test_abort);
  964. testval = DB_TEST_ELECTVOTE2;
  965. break;
  966. case ENVTEST_ELECTWAIT1:
  967. DB_ASSERT(loc == &dbenv->test_abort);
  968. testval = DB_TEST_ELECTWAIT1;
  969. break;
  970. case ENVTEST_ELECTWAIT2:
  971. DB_ASSERT(loc == &dbenv->test_abort);
  972. testval = DB_TEST_ELECTWAIT2;
  973. break;
  974. case ENVTEST_NONE:
  975. testval = 0;
  976. break;
  977. case ENVTEST_PREOPEN:
  978. testval = DB_TEST_PREOPEN;
  979. break;
  980. case ENVTEST_PREDESTROY:
  981. testval = DB_TEST_PREDESTROY;
  982. break;
  983. case ENVTEST_POSTLOG:
  984. testval = DB_TEST_POSTLOG;
  985. break;
  986. case ENVTEST_POSTLOGMETA:
  987. testval = DB_TEST_POSTLOGMETA;
  988. break;
  989. case ENVTEST_POSTOPEN:
  990. testval = DB_TEST_POSTOPEN;
  991. break;
  992. case ENVTEST_POSTDESTROY:
  993. testval = DB_TEST_POSTDESTROY;
  994. break;
  995. case ENVTEST_POSTSYNC:
  996. testval = DB_TEST_POSTSYNC;
  997. break;
  998. case ENVTEST_SUBDB_LOCKS:
  999. DB_ASSERT(loc == &dbenv->test_abort);
  1000. testval = DB_TEST_SUBDB_LOCKS;
  1001. break;
  1002. default:
  1003. Tcl_SetResult(interp, "Illegal test location", TCL_STATIC);
  1004. return (TCL_ERROR);
  1005. }
  1006. *loc = testval;
  1007. Tcl_SetResult(interp, "0", TCL_STATIC);
  1008. return (result);
  1009. }
  1010. #endif
  1011. /*
  1012.  * env_DbRemove --
  1013.  * Implements the ENV->dbremove command.
  1014.  */
  1015. static int
  1016. env_DbRemove(interp, objc, objv, dbenv)
  1017. Tcl_Interp *interp; /* Interpreter */
  1018. int objc; /* How many arguments? */
  1019. Tcl_Obj *CONST objv[]; /* The argument objects */
  1020. DB_ENV *dbenv;
  1021. {
  1022. static char *envdbrem[] = {
  1023. "-auto_commit",
  1024. "-txn",
  1025. "--",
  1026. NULL
  1027. };
  1028. enum envdbrem {
  1029. TCL_EDBREM_COMMIT,
  1030. TCL_EDBREM_TXN,
  1031. TCL_EDBREM_ENDARG
  1032. };
  1033. DB_TXN *txn;
  1034. u_int32_t flag;
  1035. int endarg, i, optindex, result, ret, subdblen;
  1036. u_char *subdbtmp;
  1037. char *arg, *db, *subdb, msg[MSG_SIZE];
  1038. txn = NULL;
  1039. result = TCL_OK;
  1040. subdbtmp = NULL;
  1041. db = subdb = NULL;
  1042. endarg = 0;
  1043. flag = 0;
  1044. if (objc < 2) {
  1045. Tcl_WrongNumArgs(interp, 2, objv, "?args? filename ?database?");
  1046. return (TCL_ERROR);
  1047. }
  1048. /*
  1049.  * We must first parse for the environment flag, since that
  1050.  * is needed for db_create.  Then create the db handle.
  1051.  */
  1052. i = 2;
  1053. while (i < objc) {
  1054. if (Tcl_GetIndexFromObj(interp, objv[i], envdbrem,
  1055.     "option", TCL_EXACT, &optindex) != TCL_OK) {
  1056. arg = Tcl_GetStringFromObj(objv[i], NULL);
  1057. if (arg[0] == '-') {
  1058. result = IS_HELP(objv[i]);
  1059. goto error;
  1060. } else
  1061. Tcl_ResetResult(interp);
  1062. break;
  1063. }
  1064. i++;
  1065. switch ((enum envdbrem)optindex) {
  1066. case TCL_EDBREM_COMMIT:
  1067. flag |= DB_AUTO_COMMIT;
  1068. break;
  1069. case TCL_EDBREM_TXN:
  1070. if (i >= objc) {
  1071. Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
  1072. result = TCL_ERROR;
  1073. break;
  1074. }
  1075. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  1076. txn = NAME_TO_TXN(arg);
  1077. if (txn == NULL) {
  1078. snprintf(msg, MSG_SIZE,
  1079.     "env dbremove: Invalid txn %sn", arg);
  1080. Tcl_SetResult(interp, msg, TCL_VOLATILE);
  1081. return (TCL_ERROR);
  1082. }
  1083. break;
  1084. case TCL_EDBREM_ENDARG:
  1085. endarg = 1;
  1086. break;
  1087. }
  1088. /*
  1089.  * If, at any time, parsing the args we get an error,
  1090.  * bail out and return.
  1091.  */
  1092. if (result != TCL_OK)
  1093. goto error;
  1094. if (endarg)
  1095. break;
  1096. }
  1097. if (result != TCL_OK)
  1098. goto error;
  1099. /*
  1100.  * Any args we have left, (better be 1 or 2 left) are
  1101.  * file names. If there is 1, a db name, if 2 a db and subdb name.
  1102.  */
  1103. if ((i != (objc - 1)) || (i != (objc - 2))) {
  1104. /*
  1105.  * Dbs must be NULL terminated file names, but subdbs can
  1106.  * be anything.  Use Strings for the db name and byte
  1107.  * arrays for the subdb.
  1108.  */
  1109. db = Tcl_GetStringFromObj(objv[i++], NULL);
  1110. if (i != objc) {
  1111. subdbtmp =
  1112.     Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
  1113. if ((ret = __os_malloc(dbenv, subdblen + 1,
  1114.     &subdb)) != 0) {
  1115. Tcl_SetResult(interp,
  1116.     db_strerror(ret), TCL_STATIC);
  1117. return (0);
  1118. }
  1119. memcpy(subdb, subdbtmp, subdblen);
  1120. subdb[subdblen] = '';
  1121. }
  1122. } else {
  1123. Tcl_WrongNumArgs(interp, 2, objv, "?args? filename ?database?");
  1124. result = TCL_ERROR;
  1125. goto error;
  1126. }
  1127. ret = dbenv->dbremove(dbenv, txn, db, subdb, flag);
  1128. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1129.     "env dbremove");
  1130. error:
  1131. if (subdb)
  1132. __os_free(dbenv, subdb);
  1133. return (result);
  1134. }
  1135. /*
  1136.  * env_DbRename --
  1137.  * Implements the ENV->dbrename command.
  1138.  */
  1139. static int
  1140. env_DbRename(interp, objc, objv, dbenv)
  1141. Tcl_Interp *interp; /* Interpreter */
  1142. int objc; /* How many arguments? */
  1143. Tcl_Obj *CONST objv[]; /* The argument objects */
  1144. DB_ENV *dbenv;
  1145. {
  1146. static char *envdbmv[] = {
  1147. "-auto_commit",
  1148. "-txn",
  1149. "--",
  1150. NULL
  1151. };
  1152. enum envdbmv {
  1153. TCL_EDBMV_COMMIT,
  1154. TCL_EDBMV_TXN,
  1155. TCL_EDBMV_ENDARG
  1156. };
  1157. DB_TXN *txn;
  1158. u_int32_t flag;
  1159. int endarg, i, newlen, optindex, result, ret, subdblen;
  1160. u_char *subdbtmp;
  1161. char *arg, *db, *newname, *subdb, msg[MSG_SIZE];
  1162. txn = NULL;
  1163. result = TCL_OK;
  1164. subdbtmp = NULL;
  1165. db = newname = subdb = NULL;
  1166. endarg = 0;
  1167. flag = 0;
  1168. if (objc < 2) {
  1169. Tcl_WrongNumArgs(interp, 3, objv,
  1170.     "?args? filename ?database? ?newname?");
  1171. return (TCL_ERROR);
  1172. }
  1173. /*
  1174.  * We must first parse for the environment flag, since that
  1175.  * is needed for db_create.  Then create the db handle.
  1176.  */
  1177. i = 2;
  1178. while (i < objc) {
  1179. if (Tcl_GetIndexFromObj(interp, objv[i], envdbmv,
  1180.     "option", TCL_EXACT, &optindex) != TCL_OK) {
  1181. arg = Tcl_GetStringFromObj(objv[i], NULL);
  1182. if (arg[0] == '-') {
  1183. result = IS_HELP(objv[i]);
  1184. goto error;
  1185. } else
  1186. Tcl_ResetResult(interp);
  1187. break;
  1188. }
  1189. i++;
  1190. switch ((enum envdbmv)optindex) {
  1191. case TCL_EDBMV_COMMIT:
  1192. flag |= DB_AUTO_COMMIT;
  1193. break;
  1194. case TCL_EDBMV_TXN:
  1195. if (i >= objc) {
  1196. Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
  1197. result = TCL_ERROR;
  1198. break;
  1199. }
  1200. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  1201. txn = NAME_TO_TXN(arg);
  1202. if (txn == NULL) {
  1203. snprintf(msg, MSG_SIZE,
  1204.     "env dbrename: Invalid txn %sn", arg);
  1205. Tcl_SetResult(interp, msg, TCL_VOLATILE);
  1206. return (TCL_ERROR);
  1207. }
  1208. break;
  1209. case TCL_EDBMV_ENDARG:
  1210. endarg = 1;
  1211. break;
  1212. }
  1213. /*
  1214.  * If, at any time, parsing the args we get an error,
  1215.  * bail out and return.
  1216.  */
  1217. if (result != TCL_OK)
  1218. goto error;
  1219. if (endarg)
  1220. break;
  1221. }
  1222. if (result != TCL_OK)
  1223. goto error;
  1224. /*
  1225.  * Any args we have left, (better be 2 or 3 left) are
  1226.  * file names. If there is 2, a db name, if 3 a db and subdb name.
  1227.  */
  1228. if ((i != (objc - 2)) || (i != (objc - 3))) {
  1229. /*
  1230.  * Dbs must be NULL terminated file names, but subdbs can
  1231.  * be anything.  Use Strings for the db name and byte
  1232.  * arrays for the subdb.
  1233.  */
  1234. db = Tcl_GetStringFromObj(objv[i++], NULL);
  1235. if (i == objc - 2) {
  1236. subdbtmp =
  1237.     Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
  1238. if ((ret = __os_malloc(dbenv, subdblen + 1,
  1239.     &subdb)) != 0) {
  1240. Tcl_SetResult(interp,
  1241.     db_strerror(ret), TCL_STATIC);
  1242. return (0);
  1243. }
  1244. memcpy(subdb, subdbtmp, subdblen);
  1245. subdb[subdblen] = '';
  1246. }
  1247. subdbtmp =
  1248.     Tcl_GetByteArrayFromObj(objv[i++], &newlen);
  1249. if ((ret = __os_malloc(dbenv, newlen + 1,
  1250.     &newname)) != 0) {
  1251. Tcl_SetResult(interp,
  1252.     db_strerror(ret), TCL_STATIC);
  1253. return (0);
  1254. }
  1255. memcpy(newname, subdbtmp, newlen);
  1256. newname[newlen] = '';
  1257. } else {
  1258. Tcl_WrongNumArgs(interp, 3, objv,
  1259.     "?args? filename ?database? ?newname?");
  1260. result = TCL_ERROR;
  1261. goto error;
  1262. }
  1263. ret = dbenv->dbrename(dbenv, txn, db, subdb, newname, flag);
  1264. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1265.     "env dbrename");
  1266. error:
  1267. if (subdb)
  1268. __os_free(dbenv, subdb);
  1269. if (newname)
  1270. __os_free(dbenv, newname);
  1271. return (result);
  1272. }