tcl_env.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:15k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1999, 2000
  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.33 2001/01/11 18:19:55 bostic Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <stdlib.h>
  14. #include <tcl.h>
  15. #endif
  16. #include "db_int.h"
  17. #include "tcl_db.h"
  18. /*
  19.  * Prototypes for procedures defined later in this file:
  20.  */
  21. static void _EnvInfoDelete __P((Tcl_Interp *, DBTCL_INFO *));
  22. /*
  23.  * PUBLIC: int env_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
  24.  *
  25.  * env_Cmd --
  26.  * Implements the "env" command.
  27.  */
  28. int
  29. env_Cmd(clientData, interp, objc, objv)
  30. ClientData clientData;          /* Env handle */
  31. Tcl_Interp *interp;             /* Interpreter */
  32. int objc;                       /* How many arguments? */
  33. Tcl_Obj *CONST objv[];          /* The argument objects */
  34. {
  35. static char *envcmds[] = {
  36. "close",
  37. "lock_detect",
  38. "lock_id",
  39. "lock_get",
  40. "lock_stat",
  41. "lock_vec",
  42. "log_archive",
  43. "log_compare",
  44. "log_file",
  45. "log_flush",
  46. "log_get",
  47. "log_put",
  48. "log_register",
  49. "log_stat",
  50. "log_unregister",
  51. "mpool",
  52. "mpool_stat",
  53. "mpool_sync",
  54. "mpool_trickle",
  55. "mutex",
  56. #if CONFIG_TEST
  57. "test",
  58. #endif
  59. "txn",
  60. "txn_checkpoint",
  61. "txn_stat",
  62. "verbose",
  63. NULL
  64. };
  65. enum envcmds {
  66. ENVCLOSE,
  67. ENVLKDETECT,
  68. ENVLKID,
  69. ENVLKGET,
  70. ENVLKSTAT,
  71. ENVLKVEC,
  72. ENVLOGARCH,
  73. ENVLOGCMP,
  74. ENVLOGFILE,
  75. ENVLOGFLUSH,
  76. ENVLOGGET,
  77. ENVLOGPUT,
  78. ENVLOGREG,
  79. ENVLOGSTAT,
  80. ENVLOGUNREG,
  81. ENVMP,
  82. ENVMPSTAT,
  83. ENVMPSYNC,
  84. ENVTRICKLE,
  85. ENVMUTEX,
  86. #if CONFIG_TEST
  87. ENVTEST,
  88. #endif
  89. ENVTXN,
  90. ENVTXNCKP,
  91. ENVTXNSTAT,
  92. ENVVERB
  93. };
  94. DBTCL_INFO *envip;
  95. DB_ENV *envp;
  96. Tcl_Obj *res;
  97. u_int32_t newval;
  98. int cmdindex, result, ret;
  99. Tcl_ResetResult(interp);
  100. envp = (DB_ENV *)clientData;
  101. envip = _PtrToInfo((void *)envp);
  102. result = TCL_OK;
  103. if (objc <= 1) {
  104. Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs");
  105. return (TCL_ERROR);
  106. }
  107. if (envp == NULL) {
  108. Tcl_SetResult(interp, "NULL env pointer", TCL_STATIC);
  109. return (TCL_ERROR);
  110. }
  111. if (envip == NULL) {
  112. Tcl_SetResult(interp, "NULL env info pointer", TCL_STATIC);
  113. return (TCL_ERROR);
  114. }
  115. /*
  116.  * Get the command name index from the object based on the berkdbcmds
  117.  * defined above.
  118.  */
  119. if (Tcl_GetIndexFromObj(interp, objv[1], envcmds, "command",
  120.     TCL_EXACT, &cmdindex) != TCL_OK)
  121. return (IS_HELP(objv[1]));
  122. res = NULL;
  123. switch ((enum envcmds)cmdindex) {
  124. case ENVCLOSE:
  125. /*
  126.  * No args for this.  Error if there are some.
  127.  */
  128. if (objc > 2) {
  129. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  130. return (TCL_ERROR);
  131. }
  132. /*
  133.  * Any transactions will be aborted, and an mpools
  134.  * closed automatically.  We must delete any txn
  135.  * and mp widgets we have here too for this env.
  136.  * NOTE: envip is freed when we come back from
  137.  * this function.  Set it to NULL to make sure no
  138.  * one tries to use it later.
  139.  */
  140. _EnvInfoDelete(interp, envip);
  141. envip = NULL;
  142. _debug_check();
  143. ret = envp->close(envp, 0);
  144. result = _ReturnSetup(interp, ret, "env close");
  145. break;
  146. case ENVLKDETECT:
  147. result = tcl_LockDetect(interp, objc, objv, envp);
  148. break;
  149. case ENVLKSTAT:
  150. result = tcl_LockStat(interp, objc, objv, envp);
  151. break;
  152. case ENVLKID:
  153. /*
  154.  * No args for this.  Error if there are some.
  155.  */
  156. if (objc > 2) {
  157. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  158. return (TCL_ERROR);
  159. }
  160. _debug_check();
  161. ret = lock_id(envp, &newval);
  162. result = _ReturnSetup(interp, ret, "lock_id");
  163. if (result == TCL_OK)
  164. res = Tcl_NewIntObj((int)newval);
  165. break;
  166. case ENVLKGET:
  167. result = tcl_LockGet(interp, objc, objv, envp);
  168. break;
  169. case ENVLKVEC:
  170. result = tcl_LockVec(interp, objc, objv, envp);
  171. break;
  172. case ENVLOGARCH:
  173. result = tcl_LogArchive(interp, objc, objv, envp);
  174. break;
  175. case ENVLOGCMP:
  176. result = tcl_LogCompare(interp, objc, objv);
  177. break;
  178. case ENVLOGFILE:
  179. result = tcl_LogFile(interp, objc, objv, envp);
  180. break;
  181. case ENVLOGFLUSH:
  182. result = tcl_LogFlush(interp, objc, objv, envp);
  183. break;
  184. case ENVLOGGET:
  185. result = tcl_LogGet(interp, objc, objv, envp);
  186. break;
  187. case ENVLOGPUT:
  188. result = tcl_LogPut(interp, objc, objv, envp);
  189. break;
  190. case ENVLOGREG:
  191. result = tcl_LogRegister(interp, objc, objv, envp);
  192. break;
  193. case ENVLOGUNREG:
  194. result = tcl_LogUnregister(interp, objc, objv, envp);
  195. break;
  196. case ENVLOGSTAT:
  197. result = tcl_LogStat(interp, objc, objv, envp);
  198. break;
  199. case ENVMPSTAT:
  200. result = tcl_MpStat(interp, objc, objv, envp);
  201. break;
  202. case ENVMPSYNC:
  203. result = tcl_MpSync(interp, objc, objv, envp);
  204. break;
  205. case ENVTRICKLE:
  206. result = tcl_MpTrickle(interp, objc, objv, envp);
  207. break;
  208. case ENVMP:
  209. result = tcl_Mp(interp, objc, objv, envp, envip);
  210. break;
  211. case ENVTXNCKP:
  212. result = tcl_TxnCheckpoint(interp, objc, objv, envp);
  213. break;
  214. case ENVTXNSTAT:
  215. result = tcl_TxnStat(interp, objc, objv, envp);
  216. break;
  217. case ENVTXN:
  218. result = tcl_Txn(interp, objc, objv, envp, envip);
  219. break;
  220. case ENVMUTEX:
  221. result = tcl_Mutex(interp, objc, objv, envp, envip);
  222. break;
  223. #if CONFIG_TEST
  224. case ENVTEST:
  225. result = tcl_EnvTest(interp, objc, objv, envp);
  226. break;
  227. #endif
  228. case ENVVERB:
  229. /*
  230.  * Two args for this.  Error if different.
  231.  */
  232. if (objc != 4) {
  233. Tcl_WrongNumArgs(interp, 2, objv, NULL);
  234. return (TCL_ERROR);
  235. }
  236. result = tcl_EnvVerbose(interp, envp, objv[2], objv[3]);
  237. break;
  238. }
  239. /*
  240.  * Only set result if we have a res.  Otherwise, lower
  241.  * functions have already done so.
  242.  */
  243. if (result == TCL_OK && res)
  244. Tcl_SetObjResult(interp, res);
  245. return (result);
  246. }
  247. /*
  248.  * PUBLIC: int tcl_EnvRemove __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
  249.  * PUBLIC:      DB_ENV *, DBTCL_INFO *));
  250.  *
  251.  * tcl_EnvRemove --
  252.  */
  253. int
  254. tcl_EnvRemove(interp, objc, objv, envp, envip)
  255. Tcl_Interp *interp; /* Interpreter */
  256. int objc; /* How many arguments? */
  257. Tcl_Obj *CONST objv[]; /* The argument objects */
  258. DB_ENV *envp; /* Env pointer */
  259. DBTCL_INFO *envip; /* Info pointer */
  260. {
  261. static char *envremopts[] = {
  262. "-data_dir",
  263. "-force",
  264. "-home",
  265. "-log_dir",
  266. "-server",
  267. "-tmp_dir",
  268. "-use_environ",
  269. "-use_environ_root",
  270. NULL
  271. };
  272. enum envremopts {
  273. ENVREM_DATADIR,
  274. ENVREM_FORCE,
  275. ENVREM_HOME,
  276. ENVREM_LOGDIR,
  277. ENVREM_SERVER,
  278. ENVREM_TMPDIR,
  279. ENVREM_USE_ENVIRON,
  280. ENVREM_USE_ENVIRON_ROOT
  281. };
  282. DB_ENV *e;
  283. u_int32_t cflag, flag, forceflag;
  284. int i, optindex, result, ret;
  285. char *datadir, *home, *logdir, *server, *tmpdir;
  286. result = TCL_OK;
  287. cflag = flag = forceflag = 0;
  288. home = NULL;
  289. datadir = logdir = tmpdir = NULL;
  290. server = NULL;
  291. if (objc < 2) {
  292. Tcl_WrongNumArgs(interp, 2, objv, "?args?");
  293. return (TCL_ERROR);
  294. }
  295. i = 2;
  296. while (i < objc) {
  297. if (Tcl_GetIndexFromObj(interp, objv[i], envremopts, "option",
  298.     TCL_EXACT, &optindex) != TCL_OK) {
  299. result = IS_HELP(objv[i]);
  300. goto error;
  301. }
  302. i++;
  303. switch ((enum envremopts)optindex) {
  304. case ENVREM_FORCE:
  305. forceflag |= DB_FORCE;
  306. break;
  307. case ENVREM_HOME:
  308. /* Make sure we have an arg to check against! */
  309. if (i >= objc) {
  310. Tcl_WrongNumArgs(interp, 2, objv,
  311.     "?-home dir?");
  312. result = TCL_ERROR;
  313. break;
  314. }
  315. home = Tcl_GetStringFromObj(objv[i++], NULL);
  316. break;
  317. case ENVREM_SERVER:
  318. /* Make sure we have an arg to check against! */
  319. if (i >= objc) {
  320. Tcl_WrongNumArgs(interp, 2, objv,
  321.     "?-server name?");
  322. result = TCL_ERROR;
  323. break;
  324. }
  325. server = Tcl_GetStringFromObj(objv[i++], NULL);
  326. cflag = DB_CLIENT;
  327. break;
  328. case ENVREM_USE_ENVIRON:
  329. flag |= DB_USE_ENVIRON;
  330. break;
  331. case ENVREM_USE_ENVIRON_ROOT:
  332. flag |= DB_USE_ENVIRON_ROOT;
  333. break;
  334. case ENVREM_DATADIR:
  335. if (i >= objc) {
  336. Tcl_WrongNumArgs(interp, 2, objv,
  337.     "-data_dir dir");
  338. result = TCL_ERROR;
  339. break;
  340. }
  341. datadir = Tcl_GetStringFromObj(objv[i++], NULL);
  342. break;
  343. case ENVREM_LOGDIR:
  344. if (i >= objc) {
  345. Tcl_WrongNumArgs(interp, 2, objv,
  346.     "-log_dir dir");
  347. result = TCL_ERROR;
  348. break;
  349. }
  350. logdir = Tcl_GetStringFromObj(objv[i++], NULL);
  351. break;
  352. case ENVREM_TMPDIR:
  353. if (i >= objc) {
  354. Tcl_WrongNumArgs(interp, 2, objv,
  355.     "-tmp_dir dir");
  356. result = TCL_ERROR;
  357. break;
  358. }
  359. tmpdir = Tcl_GetStringFromObj(objv[i++], NULL);
  360. break;
  361. }
  362. /*
  363.  * If, at any time, parsing the args we get an error,
  364.  * bail out and return.
  365.  */
  366. if (result != TCL_OK)
  367. goto error;
  368. }
  369. /*
  370.  * If envp is NULL, we don't have an open env and we need to open
  371.  * one of the user.  Don't bother with the info stuff.
  372.  */
  373. if (envp == NULL) {
  374. if ((ret = db_env_create(&e, cflag)) != 0) {
  375. result = _ReturnSetup(interp, ret, "db_env_create");
  376. goto error;
  377. }
  378. if (server != NULL) {
  379. ret = e->set_server(e, server, 0, 0, 0);
  380. result = _ReturnSetup(interp, ret, "set_server");
  381. if (result != TCL_OK)
  382. goto error;
  383. }
  384. if (datadir != NULL) {
  385. _debug_check();
  386. ret = e->set_data_dir(e, datadir);
  387. result = _ReturnSetup(interp, ret, "set_data_dir");
  388. if (result != TCL_OK)
  389. goto error;
  390. }
  391. if (logdir != NULL) {
  392. _debug_check();
  393. ret = e->set_lg_dir(e, logdir);
  394. result = _ReturnSetup(interp, ret, "set_log_dir");
  395. if (result != TCL_OK)
  396. goto error;
  397. }
  398. if (tmpdir != NULL) {
  399. _debug_check();
  400. ret = e->set_tmp_dir(e, tmpdir);
  401. result = _ReturnSetup(interp, ret, "set_tmp_dir");
  402. if (result != TCL_OK)
  403. goto error;
  404. }
  405. } else {
  406. /*
  407.  * We have to clean up any info associated with this env,
  408.  * regardless of the result of the remove so do it first.
  409.  * NOTE: envip is freed when we come back from this function.
  410.  */
  411. _EnvInfoDelete(interp, envip);
  412. envip = NULL;
  413. e = envp;
  414. }
  415. flag |= forceflag;
  416. /*
  417.  * When we get here we have parsed all the args.  Now remove
  418.  * the environment.
  419.  */
  420. _debug_check();
  421. ret = e->remove(e, home, flag);
  422. result = _ReturnSetup(interp, ret, "env remove");
  423. error:
  424. return (result);
  425. }
  426. static void
  427. _EnvInfoDelete(interp, envip)
  428. Tcl_Interp *interp; /* Tcl Interpreter */
  429. DBTCL_INFO *envip; /* Info for env */
  430. {
  431. DBTCL_INFO *nextp, *p;
  432. /*
  433.  * Before we can delete the environment info, we must close
  434.  * any open subsystems in this env.  We will:
  435.  * 1.  Abort any transactions (which aborts any nested txns).
  436.  * 2.  Close any mpools (which will put any pages itself).
  437.  * 3.  Put any locks.
  438.  * 4.  Close the error file.
  439.  */
  440. for (p = LIST_FIRST(&__db_infohead); p != NULL; p = nextp) {
  441. /*
  442.  * Check if this info structure "belongs" to this
  443.  * env.  If so, remove its commands and info structure.
  444.  * We do not close/abort/whatever here, because we
  445.  * don't want to replicate DB behavior.
  446.  */
  447.  if (p->i_parent == envip) {
  448. switch (p->i_type) {
  449. case I_TXN:
  450. _TxnInfoDelete(interp, p);
  451. break;
  452. case I_MP:
  453. _MpInfoDelete(interp, p);
  454. break;
  455. default:
  456. Tcl_SetResult(interp,
  457.     "_EnvInfoDelete: bad info type",
  458.     TCL_STATIC);
  459. break;
  460. }
  461. nextp = LIST_NEXT(p, entries);
  462. (void)Tcl_DeleteCommand(interp, p->i_name);
  463. _DeleteInfo(p);
  464. } else
  465. nextp = LIST_NEXT(p, entries);
  466. }
  467. (void)Tcl_DeleteCommand(interp, envip->i_name);
  468. _DeleteInfo(envip);
  469. }
  470. /*
  471.  * PUBLIC: int tcl_EnvVerbose __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *,
  472.  * PUBLIC:    Tcl_Obj *));
  473.  *
  474.  * tcl_EnvVerbose --
  475.  */
  476. int
  477. tcl_EnvVerbose(interp, envp, which, onoff)
  478. Tcl_Interp *interp; /* Interpreter */
  479. DB_ENV *envp; /* Env pointer */
  480. Tcl_Obj *which; /* Which subsystem */
  481. Tcl_Obj *onoff; /* On or off */
  482. {
  483. static char *verbwhich[] = {
  484. "chkpt",
  485. "deadlock",
  486. "recovery",
  487. "wait",
  488. NULL
  489. };
  490. enum verbwhich {
  491. ENVVERB_CHK,
  492. ENVVERB_DEAD,
  493. ENVVERB_REC,
  494. ENVVERB_WAIT
  495. };
  496. static char *verbonoff[] = {
  497. "off",
  498. "on",
  499. NULL
  500. };
  501. enum verbonoff {
  502. ENVVERB_OFF,
  503. ENVVERB_ON
  504. };
  505. int on, optindex, ret;
  506. u_int32_t wh;
  507. if (Tcl_GetIndexFromObj(interp, which, verbwhich, "option",
  508.     TCL_EXACT, &optindex) != TCL_OK)
  509. return (IS_HELP(which));
  510. switch ((enum verbwhich)optindex) {
  511. case ENVVERB_CHK:
  512. wh = DB_VERB_CHKPOINT;
  513. break;
  514. case ENVVERB_DEAD:
  515. wh = DB_VERB_DEADLOCK;
  516. break;
  517. case ENVVERB_REC:
  518. wh = DB_VERB_RECOVERY;
  519. break;
  520. case ENVVERB_WAIT:
  521. wh = DB_VERB_WAITSFOR;
  522. break;
  523. default:
  524. return (TCL_ERROR);
  525. }
  526. if (Tcl_GetIndexFromObj(interp, onoff, verbonoff, "option",
  527.     TCL_EXACT, &optindex) != TCL_OK)
  528. return (IS_HELP(onoff));
  529. switch ((enum verbonoff)optindex) {
  530. case ENVVERB_OFF:
  531. on = 0;
  532. break;
  533. case ENVVERB_ON:
  534. on = 1;
  535. break;
  536. default:
  537. return (TCL_ERROR);
  538. }
  539. ret = envp->set_verbose(envp, wh, on);
  540. return (_ReturnSetup(interp, ret, "env set verbose"));
  541. }
  542. #if CONFIG_TEST
  543. /*
  544.  * PUBLIC: int tcl_EnvTest __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
  545.  *
  546.  * tcl_EnvTest --
  547.  */
  548. int
  549. tcl_EnvTest(interp, objc, objv, envp)
  550. Tcl_Interp *interp; /* Interpreter */
  551. int objc; /* How many arguments? */
  552. Tcl_Obj *CONST objv[]; /* The argument objects */
  553. DB_ENV *envp; /* Env pointer */
  554. {
  555. static char *envtestcmd[] = {
  556. "abort",
  557. "copy",
  558. NULL
  559. };
  560. enum envtestcmd {
  561. ENVTEST_ABORT,
  562. ENVTEST_COPY
  563. };
  564. static char *envtestat[] = {
  565. "none",
  566. "preopen",
  567. "prerename",
  568. "postlog",
  569. "postlogmeta",
  570. "postopen",
  571. "postrename",
  572. "postsync",
  573. NULL
  574. };
  575. enum envtestat {
  576. ENVTEST_NONE,
  577. ENVTEST_PREOPEN,
  578. ENVTEST_PRERENAME,
  579. ENVTEST_POSTLOG,
  580. ENVTEST_POSTLOGMETA,
  581. ENVTEST_POSTOPEN,
  582. ENVTEST_POSTRENAME,
  583. ENVTEST_POSTSYNC
  584. };
  585. int *loc, optindex, result, testval;
  586. result = TCL_OK;
  587. if (objc != 4) {
  588. Tcl_WrongNumArgs(interp, 2, objv, "abort|copy location");
  589. return (TCL_ERROR);
  590. }
  591. /*
  592.  * This must be the "copy" or "abort" portion of the command.
  593.  */
  594. if (Tcl_GetIndexFromObj(interp, objv[2], envtestcmd, "command",
  595.     TCL_EXACT, &optindex) != TCL_OK) {
  596. result = IS_HELP(objv[2]);
  597. return (result);
  598. }
  599. switch ((enum envtestcmd)optindex) {
  600. case ENVTEST_ABORT:
  601. loc = &envp->test_abort;
  602. break;
  603. case ENVTEST_COPY:
  604. loc = &envp->test_copy;
  605. break;
  606. default:
  607. Tcl_SetResult(interp, "Illegal store location", TCL_STATIC);
  608. return (TCL_ERROR);
  609. }
  610. /*
  611.  * This must be the location portion of the command.
  612.  */
  613. if (Tcl_GetIndexFromObj(interp, objv[3], envtestat, "location",
  614.     TCL_EXACT, &optindex) != TCL_OK) {
  615. result = IS_HELP(objv[3]);
  616. return (result);
  617. }
  618. switch ((enum envtestat)optindex) {
  619. case ENVTEST_NONE:
  620. testval = 0;
  621. break;
  622. case ENVTEST_PREOPEN:
  623. testval = DB_TEST_PREOPEN;
  624. break;
  625. case ENVTEST_PRERENAME:
  626. testval = DB_TEST_PRERENAME;
  627. break;
  628. case ENVTEST_POSTLOG:
  629. testval = DB_TEST_POSTLOG;
  630. break;
  631. case ENVTEST_POSTLOGMETA:
  632. testval = DB_TEST_POSTLOGMETA;
  633. break;
  634. case ENVTEST_POSTOPEN:
  635. testval = DB_TEST_POSTOPEN;
  636. break;
  637. case ENVTEST_POSTRENAME:
  638. testval = DB_TEST_POSTRENAME;
  639. break;
  640. case ENVTEST_POSTSYNC:
  641. testval = DB_TEST_POSTSYNC;
  642. break;
  643. default:
  644. Tcl_SetResult(interp, "Illegal test location", TCL_STATIC);
  645. return (TCL_ERROR);
  646. }
  647. *loc = testval;
  648. Tcl_SetResult(interp, "0", TCL_STATIC);
  649. return (result);
  650. }
  651. #endif