PageRenderTime 37ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/TclFrameWork/src/bDb/tcl_db_pkg.c

http://msg-pthreads.googlecode.com/
C | 2594 lines | 2247 code | 63 blank | 284 comment | 403 complexity | 8c4ecb63e7824257477023a00b15ef7f MD5 | raw file
  1. /*-
  2. * See the file LICENSE for redistribution information.
  3. * Copyright (c) 1999,2007 Oracle. All rights reserved.
  4. * $Id: tcl_db_pkg.c,v 12.51 2007/07/09 17:38:45 bostic Exp $
  5. */
  6. #include "db_config.h"
  7. #ifdef CONFIG_TEST
  8. #define DB_DBM_HSEARCH 1
  9. #endif
  10. #include "db_int.h"
  11. #ifdef HAVE_SYSTEM_INCLUDE_FILES
  12. #include <tcl.h>
  13. #endif
  14. #include "dbinc/db_page.h"
  15. #include "dbinc/hash.h"
  16. #include "dbinc/tcl_db.h"
  17. /* XXX we must declare global data in just one place */
  18. DBTCL_GLOBAL __dbtcl_global;
  19. /*
  20. * Prototypes for procedures defined later in this file:
  21. */
  22. static int berkdb_Cmd __P((ClientData, Tcl_Interp *, int,
  23. Tcl_Obj * CONST*));
  24. static int bdb_EnvOpen __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
  25. DBTCL_INFO *, DB_ENV **));
  26. static int bdb_DbOpen __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
  27. DBTCL_INFO *, DB **));
  28. static int bdb_DbRemove __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
  29. static int bdb_DbRename __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
  30. static int bdb_Version __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
  31. #ifdef HAVE_64BIT_TYPES
  32. static int bdb_SeqOpen __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
  33. DBTCL_INFO *, DB_SEQUENCE **));
  34. #endif
  35. #ifdef CONFIG_TEST
  36. static int bdb_DbUpgrade __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
  37. static int bdb_DbVerify __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
  38. static int bdb_GetConfig __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
  39. static int bdb_Handles __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
  40. static int bdb_MsgType __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
  41. static int tcl_bt_compare __P((DB *, const DBT *, const DBT *));
  42. static int tcl_compare_callback __P((DB *, const DBT *, const DBT *,
  43. Tcl_Obj *, char *));
  44. static void tcl_db_free __P((void *));
  45. static void * tcl_db_malloc __P((size_t));
  46. static void * tcl_db_realloc __P((void *, size_t));
  47. static int tcl_dup_compare __P((DB *, const DBT *, const DBT *));
  48. static u_int32_t tcl_h_hash __P((DB *, const void *, u_int32_t));
  49. #endif
  50. /* Db_tcl_Init --
  51. *
  52. * This is a package initialization procedure, which is called by Tcl when
  53. * this package is to be added to an interpreter. The name is based on the
  54. * name of the shared library, currently libdb_tcl-X.Y.so, which Tcl uses
  55. * to determine the name of this function.
  56. */
  57. int Db_tcl_Init(interp)
  58. Tcl_Interp *interp; /* Interpreter in which the package is
  59. * to be made available. */
  60. {
  61. int code;
  62. char pkg[12];
  63. snprintf(pkg, sizeof(pkg), "%d.%d", DB_VERSION_MAJOR, DB_VERSION_MINOR);
  64. code = Tcl_PkgProvide(interp, "Db_tcl", pkg);
  65. if (code != TCL_OK)
  66. return (code);
  67. (void)Tcl_CreateObjCommand(interp,
  68. "berkdb", (Tcl_ObjCmdProc *)berkdb_Cmd, (ClientData)0, NULL);
  69. /* Create shared global debugging variables */
  70. (void)Tcl_LinkVar(interp, "__debug_on", (char *)&__debug_on, TCL_LINK_INT);
  71. (void)Tcl_LinkVar(interp, "__debug_print", (char *)&__debug_print, TCL_LINK_INT);
  72. (void)Tcl_LinkVar(interp, "__debug_stop", (char *)&__debug_stop, TCL_LINK_INT);
  73. (void)Tcl_LinkVar(interp, "__debug_test", (char *)&__debug_test, TCL_LINK_INT);
  74. LIST_INIT(&__db_infohead);
  75. return (TCL_OK);
  76. }
  77. /* berkdb_cmd --
  78. * Implements the "berkdb" command.
  79. * This command supports three sub commands:
  80. * berkdb version - Returns a list {major minor patch}
  81. * berkdb env - Creates a new DB_ENV and returns a binding
  82. * to a new command of the form dbenvX, where X is an
  83. * integer starting at 0 (dbenv0, dbenv1, ...)
  84. * berkdb open - Creates a new DB (optionally within
  85. * the given environment. Returns a binding to a new
  86. * command of the form dbX, where X is an integer
  87. * starting at 0 (db0, db1, ...)
  88. */
  89. #ifdef BDB_ENV_FROM_APPS
  90. DB_ENV* glb_pDbEnv = NULL;
  91. #endif // BDB_ENV_FROM_APPS
  92. static int berkdb_Cmd(notused, interp, objc, objv)
  93. ClientData notused; /* Not used. */
  94. Tcl_Interp *interp; /* Interpreter */
  95. int objc; /* How many arguments? */
  96. Tcl_Obj *CONST objv[]; /* The argument objects */
  97. {
  98. static const char *berkdbcmds[] = {
  99. #ifdef CONFIG_TEST
  100. "dbverify",
  101. "getconfig",
  102. "handles",
  103. "msgtype",
  104. "upgrade",
  105. #endif
  106. "dbremove",
  107. "dbrename",
  108. "env",
  109. "envremove",
  110. "open",
  111. #ifdef HAVE_64BIT_TYPES
  112. "sequence",
  113. #endif
  114. "version",
  115. #ifdef CONFIG_TEST
  116. /* All below are compatibility functions */
  117. "hcreate", "hsearch", "hdestroy",
  118. "dbminit", "fetch", "store",
  119. "delete", "firstkey", "nextkey",
  120. "ndbm_open", "dbmclose",
  121. #endif
  122. /* All below are convenience functions */
  123. "rand", "random_int", "srand",
  124. "debug_check",
  125. NULL
  126. };
  127. /*
  128. * All commands enums below ending in X are compatibility
  129. */
  130. enum berkdbcmds {
  131. #ifdef CONFIG_TEST
  132. BDB_DBVERIFY,
  133. BDB_GETCONFIG,
  134. BDB_HANDLES,
  135. BDB_MSGTYPE,
  136. BDB_UPGRADE,
  137. #endif
  138. BDB_DBREMOVE,
  139. BDB_DBRENAME,
  140. BDB_ENV,
  141. BDB_ENVREMOVE,
  142. BDB_OPEN,
  143. #ifdef HAVE_64BIT_TYPES
  144. BDB_SEQUENCE,
  145. #endif
  146. BDB_VERSION,
  147. #ifdef CONFIG_TEST
  148. BDB_HCREATEX, BDB_HSEARCHX, BDB_HDESTROYX,
  149. BDB_DBMINITX, BDB_FETCHX, BDB_STOREX,
  150. BDB_DELETEX, BDB_FIRSTKEYX, BDB_NEXTKEYX,
  151. BDB_NDBMOPENX, BDB_DBMCLOSEX,
  152. #endif
  153. BDB_RANDX, BDB_RAND_INTX, BDB_SRANDX,
  154. BDB_DBGCKX
  155. };
  156. static int env_id = 0;
  157. static int db_id = 0;
  158. #ifdef HAVE_64BIT_TYPES
  159. static int seq_id = 0;
  160. #endif
  161. DB *dbp;
  162. #ifdef HAVE_64BIT_TYPES
  163. DB_SEQUENCE *seq;
  164. #endif
  165. #ifdef CONFIG_TEST
  166. DBM *ndbmp;
  167. static int ndbm_id = 0;
  168. #endif
  169. DBTCL_INFO *ip;
  170. DB_ENV *envp;
  171. Tcl_Obj *res;
  172. int cmdindex, result;
  173. char newname[MSG_SIZE];
  174. COMPQUIET(notused, NULL);
  175. Tcl_ResetResult(interp);
  176. memset(newname, 0, MSG_SIZE);
  177. result = TCL_OK;
  178. if (objc <= 1) {
  179. Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs");
  180. return (TCL_ERROR);
  181. }
  182. /* Get the command name index from the object based on the berkdbcmds
  183. * defined above. */
  184. if (Tcl_GetIndexFromObj(interp, objv[1], berkdbcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
  185. return (IS_HELP(objv[1]));
  186. res = NULL;
  187. switch ((enum berkdbcmds)cmdindex) {
  188. #ifdef CONFIG_TEST
  189. case BDB_DBVERIFY:
  190. result = bdb_DbVerify(interp, objc, objv);
  191. break;
  192. case BDB_GETCONFIG:
  193. result = bdb_GetConfig(interp, objc, objv);
  194. break;
  195. case BDB_HANDLES:
  196. result = bdb_Handles(interp, objc, objv);
  197. break;
  198. case BDB_MSGTYPE:
  199. result = bdb_MsgType(interp, objc, objv);
  200. break;
  201. case BDB_UPGRADE:
  202. result = bdb_DbUpgrade(interp, objc, objv);
  203. break;
  204. #endif
  205. case BDB_VERSION:
  206. _debug_check();
  207. result = bdb_Version(interp, objc, objv);
  208. break;
  209. case BDB_ENV:
  210. #ifdef BDB_ENV_FROM_APPS
  211. snprintf(newname, sizeof(newname), "env%d", env_id);
  212. ip = _NewInfo(interp, NULL, newname, I_ENV);
  213. if (ip) {
  214. if(glb_pDbEnv) {
  215. envp = glb_pDbEnv;
  216. ++env_id;
  217. (void)Tcl_CreateObjCommand(
  218. interp, newname, (Tcl_ObjCmdProc*)env_Cmd, (ClientData)envp, NULL);
  219. /* Use ip->i_name - newname is overwritten */
  220. res = NewStringObj(newname, strlen(newname));
  221. _SetInfoData(ip, envp);
  222. } else {
  223. result = bdb_EnvOpen(interp, objc, objv, ip, &envp);
  224. if (result == TCL_OK && envp != NULL) {
  225. ++env_id;
  226. (void)Tcl_CreateObjCommand(interp, newname,
  227. (Tcl_ObjCmdProc*)env_Cmd, (ClientData)envp, NULL);
  228. /* Use ip->i_name - newname is overwritten */
  229. res = NewStringObj(newname, strlen(newname));
  230. _SetInfoData(ip, envp);
  231. } else
  232. _DeleteInfo(ip);
  233. }
  234. } else {
  235. Tcl_SetResult(interp, "Could not set up info", TCL_STATIC);
  236. result = TCL_ERROR;
  237. }
  238. #else // BDB_ENV_FROM_APPS
  239. snprintf(newname, sizeof(newname), "env%d", env_id);
  240. ip = _NewInfo(interp, NULL, newname, I_ENV);
  241. if (ip != NULL) {
  242. result = bdb_EnvOpen(interp, objc, objv, ip, &envp);
  243. if (result == TCL_OK && envp != NULL) {
  244. ++env_id;
  245. (void)Tcl_CreateObjCommand(interp, newname,
  246. (Tcl_ObjCmdProc*)env_Cmd, (ClientData)envp, NULL);
  247. /* Use ip->i_name - newname is overwritten */
  248. res = NewStringObj(newname, strlen(newname));
  249. _SetInfoData(ip, envp);
  250. } else
  251. _DeleteInfo(ip);
  252. } else {
  253. Tcl_SetResult(interp, "Could not set up info", TCL_STATIC);
  254. result = TCL_ERROR;
  255. }
  256. #endif // BDB_ENV_FROM_APPS
  257. break;
  258. case BDB_DBREMOVE:
  259. result = bdb_DbRemove(interp, objc, objv);
  260. break;
  261. case BDB_DBRENAME:
  262. result = bdb_DbRename(interp, objc, objv);
  263. break;
  264. case BDB_ENVREMOVE:
  265. result = tcl_EnvRemove(interp, objc, objv, NULL, NULL);
  266. break;
  267. case BDB_OPEN:
  268. snprintf(newname, sizeof(newname), "db%d", db_id);
  269. ip = _NewInfo(interp, NULL, newname, I_DB);
  270. if (ip != NULL) {
  271. result = bdb_DbOpen(interp, objc, objv, ip, &dbp);
  272. if (result == TCL_OK && dbp != NULL) {
  273. db_id++;
  274. (void)Tcl_CreateObjCommand(interp, newname,
  275. (Tcl_ObjCmdProc *)db_Cmd,
  276. (ClientData)dbp, NULL);
  277. /* Use ip->i_name - newname is overwritten */
  278. res = NewStringObj(newname, strlen(newname));
  279. _SetInfoData(ip, dbp);
  280. } else
  281. _DeleteInfo(ip);
  282. } else {
  283. Tcl_SetResult(interp, "Could not set up info",
  284. TCL_STATIC);
  285. result = TCL_ERROR;
  286. }
  287. break;
  288. #ifdef HAVE_64BIT_TYPES
  289. case BDB_SEQUENCE:
  290. snprintf(newname, sizeof(newname), "seq%d", seq_id);
  291. ip = _NewInfo(interp, NULL, newname, I_SEQ);
  292. if (ip != NULL) {
  293. result = bdb_SeqOpen(interp, objc, objv, ip, &seq);
  294. if (result == TCL_OK && seq != NULL) {
  295. seq_id++;
  296. (void)Tcl_CreateObjCommand(interp, newname, (Tcl_ObjCmdProc*)seq_Cmd,
  297. (ClientData)seq, NULL);
  298. /* Use ip->i_name - newname is overwritten */
  299. res = NewStringObj(newname, strlen(newname));
  300. _SetInfoData(ip, seq);
  301. } else
  302. _DeleteInfo(ip);
  303. } else {
  304. Tcl_SetResult(interp, "Could not set up info", TCL_STATIC);
  305. result = TCL_ERROR;
  306. }
  307. break;
  308. #endif
  309. #ifdef CONFIG_TEST
  310. case BDB_HCREATEX:
  311. case BDB_HSEARCHX:
  312. case BDB_HDESTROYX:
  313. result = bdb_HCommand(interp, objc, objv);
  314. break;
  315. case BDB_DBMINITX:
  316. case BDB_DBMCLOSEX:
  317. case BDB_FETCHX:
  318. case BDB_STOREX:
  319. case BDB_DELETEX:
  320. case BDB_FIRSTKEYX:
  321. case BDB_NEXTKEYX:
  322. result = bdb_DbmCommand(interp, objc, objv, DBTCL_DBM, NULL);
  323. break;
  324. case BDB_NDBMOPENX:
  325. snprintf(newname, sizeof(newname), "ndbm%d", ndbm_id);
  326. ip = _NewInfo(interp, NULL, newname, I_NDBM);
  327. if (ip != NULL) {
  328. result = bdb_NdbmOpen(interp, objc, objv, &ndbmp);
  329. if (result == TCL_OK) {
  330. ndbm_id++;
  331. (void)Tcl_CreateObjCommand(interp, newname, (Tcl_ObjCmdProc*)ndbm_Cmd,
  332. (ClientData)ndbmp, NULL);
  333. /* Use ip->i_name - newname is overwritten */
  334. res = NewStringObj(newname, strlen(newname));
  335. _SetInfoData(ip, ndbmp);
  336. } else
  337. _DeleteInfo(ip);
  338. } else {
  339. Tcl_SetResult(interp, "Could not set up info", TCL_STATIC);
  340. result = TCL_ERROR;
  341. }
  342. break;
  343. #endif
  344. case BDB_RANDX:
  345. case BDB_RAND_INTX:
  346. case BDB_SRANDX:
  347. result = bdb_RandCommand(interp, objc, objv);
  348. break;
  349. case BDB_DBGCKX:
  350. _debug_check();
  351. res = Tcl_NewIntObj(0);
  352. break;
  353. }
  354. /* For each different arg call different function to create
  355. * new commands (or if version, get/return it).
  356. */
  357. if (result == TCL_OK && res != NULL)
  358. Tcl_SetObjResult(interp, res);
  359. return (result);
  360. }
  361. /* bdb_EnvOpen -
  362. * Implements the environment open command.
  363. * There are many, many options to the open command.
  364. * Here is the general flow:
  365. *
  366. * 1. Call db_env_create to create the env handle.
  367. * 2. Parse args tracking options.
  368. * 3. Make any pre-open setup calls necessary.
  369. * 4. Call DB_ENV->open to open the env.
  370. * 5. Return env widget handle to user.
  371. */
  372. static int bdb_EnvOpen(interp, objc, objv, ip, env)
  373. Tcl_Interp *interp; /* Interpreter */
  374. int objc; /* How many arguments? */
  375. Tcl_Obj *CONST objv[]; /* The argument objects */
  376. DBTCL_INFO *ip; /* Our internal info */
  377. DB_ENV **env; /* Environment pointer */
  378. {
  379. static const char *envopen[] = {
  380. #ifdef CONFIG_TEST
  381. "-alloc",
  382. "-auto_commit",
  383. "-cdb",
  384. "-cdb_alldb",
  385. "-client_timeout",
  386. "-event",
  387. "-lock",
  388. "-lock_conflict",
  389. "-lock_detect",
  390. "-lock_max_locks",
  391. "-lock_max_lockers",
  392. "-lock_max_objects",
  393. "-lock_timeout",
  394. "-log",
  395. "-log_filemode",
  396. "-log_buffer",
  397. "-log_inmemory",
  398. "-log_max",
  399. "-log_regionmax",
  400. "-log_remove",
  401. "-mpool_max_openfd",
  402. "-mpool_max_write",
  403. "-mpool_mmap_size",
  404. "-mpool_nommap",
  405. "-multiversion",
  406. "-overwrite",
  407. "-region_init",
  408. "-rep",
  409. "-rep_client",
  410. "-rep_lease",
  411. "-rep_master",
  412. "-rep_transport",
  413. "-server",
  414. "-server_timeout",
  415. "-set_intermediate_dir",
  416. "-snapshot",
  417. "-thread",
  418. "-time_notgranted",
  419. "-txn_nowait",
  420. "-txn_timeout",
  421. "-txn_timestamp",
  422. "-verbose",
  423. "-wrnosync",
  424. #endif
  425. "-cachesize",
  426. "-cache_max",
  427. "-create",
  428. "-data_dir",
  429. "-encryptaes",
  430. "-encryptany",
  431. "-errfile",
  432. "-errpfx",
  433. "-home",
  434. "-log_dir",
  435. "-mode",
  436. "-private",
  437. "-recover",
  438. "-recover_fatal",
  439. "-register",
  440. "-shm_key",
  441. "-system_mem",
  442. "-tmp_dir",
  443. "-txn",
  444. "-txn_max",
  445. "-use_environ",
  446. "-use_environ_root",
  447. NULL
  448. };
  449. /*
  450. * !!!
  451. * These have to be in the same order as the above,
  452. * which is close to but not quite alphabetical.
  453. */
  454. enum envopen {
  455. #ifdef CONFIG_TEST
  456. ENV_ALLOC,
  457. ENV_AUTO_COMMIT,
  458. ENV_CDB,
  459. ENV_CDB_ALLDB,
  460. ENV_CLIENT_TO,
  461. ENV_EVENT,
  462. ENV_LOCK,
  463. ENV_CONFLICT,
  464. ENV_DETECT,
  465. ENV_LOCK_MAX_LOCKS,
  466. ENV_LOCK_MAX_LOCKERS,
  467. ENV_LOCK_MAX_OBJECTS,
  468. ENV_LOCK_TIMEOUT,
  469. ENV_LOG,
  470. ENV_LOG_FILEMODE,
  471. ENV_LOG_BUFFER,
  472. ENV_LOG_INMEMORY,
  473. ENV_LOG_MAX,
  474. ENV_LOG_REGIONMAX,
  475. ENV_LOG_REMOVE,
  476. ENV_MPOOL_MAX_OPENFD,
  477. ENV_MPOOL_MAX_WRITE,
  478. ENV_MPOOL_MMAP_SIZE,
  479. ENV_MPOOL_NOMMAP,
  480. ENV_MULTIVERSION,
  481. ENV_OVERWRITE,
  482. ENV_REGION_INIT,
  483. ENV_REP,
  484. ENV_REP_CLIENT,
  485. ENV_REP_LEASE,
  486. ENV_REP_MASTER,
  487. ENV_REP_TRANSPORT,
  488. ENV_SERVER,
  489. ENV_SERVER_TO,
  490. ENV_SET_INTERMEDIATE_DIR,
  491. ENV_SNAPSHOT,
  492. ENV_THREAD,
  493. ENV_TIME_NOTGRANTED,
  494. ENV_TXN_NOWAIT,
  495. ENV_TXN_TIMEOUT,
  496. ENV_TXN_TIME,
  497. ENV_VERBOSE,
  498. ENV_WRNOSYNC,
  499. #endif
  500. ENV_CACHESIZE,
  501. ENV_CACHE_MAX,
  502. ENV_CREATE,
  503. ENV_DATA_DIR,
  504. ENV_ENCRYPT_AES,
  505. ENV_ENCRYPT_ANY,
  506. ENV_ERRFILE,
  507. ENV_ERRPFX,
  508. ENV_HOME,
  509. ENV_LOG_DIR,
  510. ENV_MODE,
  511. ENV_PRIVATE,
  512. ENV_RECOVER,
  513. ENV_RECOVER_FATAL,
  514. ENV_REGISTER,
  515. ENV_SHM_KEY,
  516. ENV_SYSTEM_MEM,
  517. ENV_TMP_DIR,
  518. ENV_TXN,
  519. ENV_TXN_MAX,
  520. ENV_USE_ENVIRON,
  521. ENV_USE_ENVIRON_ROOT
  522. };
  523. Tcl_Obj **myobjv;
  524. u_int32_t cr_flags, gbytes, bytes, logbufset, logmaxset;
  525. u_int32_t open_flags, rep_flags, set_flags, uintarg;
  526. int i, mode, myobjc, ncaches, optindex, result, ret;
  527. long client_to, server_to, shm;
  528. char *arg, *home, *passwd, *server;
  529. #ifdef CONFIG_TEST
  530. Tcl_Obj **myobjv1;
  531. time_t timestamp;
  532. long v;
  533. u_int32_t detect;
  534. u_int8_t *conflicts;
  535. int intarg, intarg2, j, nmodes, temp;
  536. #endif
  537. result = TCL_OK;
  538. mode = 0;
  539. rep_flags = set_flags = cr_flags = 0;
  540. home = NULL;
  541. /* XXX
  542. * If/when our Tcl interface becomes thread-safe, we should enable
  543. * DB_THREAD here in all cases. For now, we turn it on later in this
  544. * function, and only when we're in testing and we specify the
  545. * -thread flag, so that we can exercise MUTEX_THREAD_LOCK cases.
  546. *
  547. * In order to become truly thread-safe, we need to look at making sure
  548. * DBTCL_INFO structs are safe to share across threads (they're not
  549. * mutex-protected) before we declare the Tcl interface thread-safe.
  550. * Meanwhile, there's no strong reason to enable DB_THREAD when not
  551. * testing. */
  552. open_flags = 0;
  553. logmaxset = logbufset = 0;
  554. if (objc <= 2) {
  555. Tcl_WrongNumArgs(interp, 2, objv, "?args?");
  556. return (TCL_ERROR);
  557. }
  558. /* Server code must go before the call to db_env_create. */
  559. server = NULL;
  560. server_to = client_to = 0;
  561. i = 2;
  562. while (i < objc) {
  563. if (Tcl_GetIndexFromObj(interp, objv[i++], envopen, "option",
  564. TCL_EXACT, &optindex) != TCL_OK) {
  565. Tcl_ResetResult(interp);
  566. continue;
  567. }
  568. #ifdef CONFIG_TEST
  569. switch ((enum envopen)optindex) {
  570. case ENV_SERVER:
  571. if (i >= objc) {
  572. Tcl_WrongNumArgs(interp, 2, objv,
  573. "?-server hostname");
  574. result = TCL_ERROR;
  575. break;
  576. }
  577. FLD_SET(cr_flags, DB_RPCCLIENT);
  578. server = Tcl_GetStringFromObj(objv[i++], NULL);
  579. break;
  580. case ENV_SERVER_TO:
  581. if (i >= objc) {
  582. Tcl_WrongNumArgs(interp, 2, objv,
  583. "?-server_to secs");
  584. result = TCL_ERROR;
  585. break;
  586. }
  587. FLD_SET(cr_flags, DB_RPCCLIENT);
  588. result = Tcl_GetLongFromObj(interp, objv[i++],
  589. &server_to);
  590. break;
  591. case ENV_CLIENT_TO:
  592. if (i >= objc) {
  593. Tcl_WrongNumArgs(interp, 2, objv,
  594. "?-client_to secs");
  595. result = TCL_ERROR;
  596. break;
  597. }
  598. FLD_SET(cr_flags, DB_RPCCLIENT);
  599. result = Tcl_GetLongFromObj(interp, objv[i++],
  600. &client_to);
  601. break;
  602. default:
  603. break;
  604. }
  605. #endif
  606. }
  607. if (result != TCL_OK)
  608. return (TCL_ERROR);
  609. ret = db_env_create(env, cr_flags);
  610. if (ret)
  611. return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  612. "db_env_create"));
  613. /*
  614. * From here on we must 'goto error' in order to clean up the
  615. * env from db_env_create.
  616. */
  617. (*env)->set_errpfx((*env), ip->i_name);
  618. (*env)->set_errcall((*env), _ErrorFunc);
  619. if (server != NULL &&
  620. (ret = (*env)->set_rpc_server((*env), NULL, server,
  621. client_to, server_to, 0)) != 0) {
  622. result = TCL_ERROR;
  623. goto error;
  624. }
  625. /* Hang our info pointer on the env handle, so we can do callbacks. */
  626. (*env)->app_private = ip;
  627. /*
  628. * Get the command name index from the object based on the bdbcmds
  629. * defined above.
  630. */
  631. i = 2;
  632. while (i < objc) {
  633. Tcl_ResetResult(interp);
  634. if (Tcl_GetIndexFromObj(interp, objv[i], envopen, "option",
  635. TCL_EXACT, &optindex) != TCL_OK) {
  636. result = IS_HELP(objv[i]);
  637. goto error;
  638. }
  639. i++;
  640. switch ((enum envopen)optindex) {
  641. #ifdef CONFIG_TEST
  642. case ENV_SERVER:
  643. case ENV_SERVER_TO:
  644. case ENV_CLIENT_TO:
  645. /*
  646. * Already handled these, skip them and their arg.
  647. */
  648. i++;
  649. break;
  650. case ENV_ALLOC:
  651. /*
  652. * Use a Tcl-local alloc and free function so that
  653. * we're sure to test whether we use umalloc/ufree in
  654. * the right places.
  655. */
  656. (void)(*env)->set_alloc(*env,
  657. tcl_db_malloc, tcl_db_realloc, tcl_db_free);
  658. break;
  659. case ENV_AUTO_COMMIT:
  660. FLD_SET(set_flags, DB_AUTO_COMMIT);
  661. break;
  662. case ENV_CDB:
  663. FLD_SET(open_flags, DB_INIT_CDB | DB_INIT_MPOOL);
  664. break;
  665. case ENV_CDB_ALLDB:
  666. FLD_SET(set_flags, DB_CDB_ALLDB);
  667. break;
  668. case ENV_LOCK:
  669. FLD_SET(open_flags, DB_INIT_LOCK | DB_INIT_MPOOL);
  670. break;
  671. case ENV_CONFLICT:
  672. /*
  673. * Get conflict list. List is:
  674. * {nmodes {matrix}}
  675. *
  676. * Where matrix must be nmodes*nmodes big.
  677. * Set up conflicts array to pass.
  678. */
  679. result = Tcl_ListObjGetElements(interp, objv[i],
  680. &myobjc, &myobjv);
  681. if (result == TCL_OK)
  682. i++;
  683. else
  684. break;
  685. if (myobjc != 2) {
  686. Tcl_WrongNumArgs(interp, 2, objv,
  687. "?-lock_conflict {nmodes {matrix}}?");
  688. result = TCL_ERROR;
  689. break;
  690. }
  691. result = Tcl_GetIntFromObj(interp, myobjv[0], &nmodes);
  692. if (result != TCL_OK)
  693. break;
  694. result = Tcl_ListObjGetElements(interp, myobjv[1],
  695. &myobjc, &myobjv1);
  696. if (myobjc != (nmodes * nmodes)) {
  697. Tcl_WrongNumArgs(interp, 2, objv,
  698. "?-lock_conflict {nmodes {matrix}}?");
  699. result = TCL_ERROR;
  700. break;
  701. }
  702. ret = __os_malloc(*env, sizeof(u_int8_t) *
  703. (size_t)nmodes * (size_t)nmodes, &conflicts);
  704. if (ret != 0) {
  705. result = TCL_ERROR;
  706. break;
  707. }
  708. for (j = 0; j < myobjc; j++) {
  709. result = Tcl_GetIntFromObj(interp, myobjv1[j],
  710. &temp);
  711. conflicts[j] = temp;
  712. if (result != TCL_OK) {
  713. __os_free(NULL, conflicts);
  714. break;
  715. }
  716. }
  717. _debug_check();
  718. ret = (*env)->set_lk_conflicts(*env,
  719. (u_int8_t *)conflicts, nmodes);
  720. __os_free(NULL, conflicts);
  721. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  722. "set_lk_conflicts");
  723. break;
  724. case ENV_DETECT:
  725. if (i >= objc) {
  726. Tcl_WrongNumArgs(interp, 2, objv,
  727. "?-lock_detect policy?");
  728. result = TCL_ERROR;
  729. break;
  730. }
  731. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  732. if (strcmp(arg, "default") == 0)
  733. detect = DB_LOCK_DEFAULT;
  734. else if (strcmp(arg, "expire") == 0)
  735. detect = DB_LOCK_EXPIRE;
  736. else if (strcmp(arg, "maxlocks") == 0)
  737. detect = DB_LOCK_MAXLOCKS;
  738. else if (strcmp(arg, "maxwrites") == 0)
  739. detect = DB_LOCK_MAXWRITE;
  740. else if (strcmp(arg, "minlocks") == 0)
  741. detect = DB_LOCK_MINLOCKS;
  742. else if (strcmp(arg, "minwrites") == 0)
  743. detect = DB_LOCK_MINWRITE;
  744. else if (strcmp(arg, "oldest") == 0)
  745. detect = DB_LOCK_OLDEST;
  746. else if (strcmp(arg, "youngest") == 0)
  747. detect = DB_LOCK_YOUNGEST;
  748. else if (strcmp(arg, "random") == 0)
  749. detect = DB_LOCK_RANDOM;
  750. else {
  751. Tcl_AddErrorInfo(interp,
  752. "lock_detect: illegal policy");
  753. result = TCL_ERROR;
  754. break;
  755. }
  756. _debug_check();
  757. ret = (*env)->set_lk_detect(*env, detect);
  758. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  759. "lock_detect");
  760. break;
  761. case ENV_EVENT:
  762. if (i >= objc) {
  763. Tcl_WrongNumArgs(interp, 2, objv,
  764. "-event eventproc");
  765. result = TCL_ERROR;
  766. break;
  767. }
  768. result = tcl_EventNotify(interp, *env, objv[i++], ip);
  769. break;
  770. case ENV_LOCK_MAX_LOCKS:
  771. case ENV_LOCK_MAX_LOCKERS:
  772. case ENV_LOCK_MAX_OBJECTS:
  773. if (i >= objc) {
  774. Tcl_WrongNumArgs(interp, 2, objv,
  775. "?-lock_max max?");
  776. result = TCL_ERROR;
  777. break;
  778. }
  779. result = _GetUInt32(interp, objv[i++], &uintarg);
  780. if (result == TCL_OK) {
  781. _debug_check();
  782. switch ((enum envopen)optindex) {
  783. case ENV_LOCK_MAX_LOCKS:
  784. ret = (*env)->set_lk_max_locks(*env,
  785. uintarg);
  786. break;
  787. case ENV_LOCK_MAX_LOCKERS:
  788. ret = (*env)->set_lk_max_lockers(*env,
  789. uintarg);
  790. break;
  791. case ENV_LOCK_MAX_OBJECTS:
  792. ret = (*env)->set_lk_max_objects(*env,
  793. uintarg);
  794. break;
  795. default:
  796. break;
  797. }
  798. result = _ReturnSetup(interp, ret,
  799. DB_RETOK_STD(ret), "lock_max");
  800. }
  801. break;
  802. case ENV_TXN_NOWAIT:
  803. FLD_SET(set_flags, DB_TXN_NOWAIT);
  804. break;
  805. case ENV_TXN_TIME:
  806. case ENV_TXN_TIMEOUT:
  807. case ENV_LOCK_TIMEOUT:
  808. if (i >= objc) {
  809. Tcl_WrongNumArgs(interp, 2, objv,
  810. "?-txn_timestamp time?");
  811. result = TCL_ERROR;
  812. break;
  813. }
  814. if ((result = Tcl_GetLongFromObj(
  815. interp, objv[i++], &v)) != TCL_OK)
  816. break;
  817. timestamp = (time_t)v;
  818. _debug_check();
  819. if ((enum envopen)optindex == ENV_TXN_TIME)
  820. ret =
  821. (*env)->set_tx_timestamp(*env, &timestamp);
  822. else
  823. ret = (*env)->set_timeout(*env,
  824. (db_timeout_t)timestamp,
  825. (enum envopen)optindex == ENV_TXN_TIMEOUT ?
  826. DB_SET_TXN_TIMEOUT : DB_SET_LOCK_TIMEOUT);
  827. result = _ReturnSetup(interp, ret,
  828. DB_RETOK_STD(ret), "txn_timestamp");
  829. break;
  830. case ENV_LOG:
  831. FLD_SET(open_flags, DB_INIT_LOG | DB_INIT_MPOOL);
  832. break;
  833. case ENV_LOG_BUFFER:
  834. if (i >= objc) {
  835. Tcl_WrongNumArgs(interp, 2, objv,
  836. "?-log_buffer size?");
  837. result = TCL_ERROR;
  838. break;
  839. }
  840. result = _GetUInt32(interp, objv[i++], &uintarg);
  841. if (result == TCL_OK) {
  842. _debug_check();
  843. ret = (*env)->set_lg_bsize(*env, uintarg);
  844. result = _ReturnSetup(interp, ret,
  845. DB_RETOK_STD(ret), "log_bsize");
  846. logbufset = 1;
  847. if (logmaxset) {
  848. _debug_check();
  849. ret = (*env)->set_lg_max(*env,
  850. logmaxset);
  851. result = _ReturnSetup(interp, ret,
  852. DB_RETOK_STD(ret), "log_max");
  853. logmaxset = 0;
  854. logbufset = 0;
  855. }
  856. }
  857. break;
  858. case ENV_LOG_FILEMODE:
  859. if (i >= objc) {
  860. Tcl_WrongNumArgs(interp, 2, objv,
  861. "?-log_filemode mode?");
  862. result = TCL_ERROR;
  863. break;
  864. }
  865. result = _GetUInt32(interp, objv[i++], &uintarg);
  866. if (result == TCL_OK) {
  867. _debug_check();
  868. ret =
  869. (*env)->set_lg_filemode(*env, (int)uintarg);
  870. result = _ReturnSetup(interp, ret,
  871. DB_RETOK_STD(ret), "log_filemode");
  872. }
  873. break;
  874. case ENV_LOG_INMEMORY:
  875. FLD_SET(set_flags, DB_LOG_INMEMORY);
  876. break;
  877. case ENV_LOG_MAX:
  878. if (i >= objc) {
  879. Tcl_WrongNumArgs(interp, 2, objv,
  880. "?-log_max max?");
  881. result = TCL_ERROR;
  882. break;
  883. }
  884. result = _GetUInt32(interp, objv[i++], &uintarg);
  885. if (result == TCL_OK && logbufset) {
  886. _debug_check();
  887. ret = (*env)->set_lg_max(*env, uintarg);
  888. result = _ReturnSetup(interp, ret,
  889. DB_RETOK_STD(ret), "log_max");
  890. logbufset = 0;
  891. } else
  892. logmaxset = uintarg;
  893. break;
  894. case ENV_LOG_REGIONMAX:
  895. if (i >= objc) {
  896. Tcl_WrongNumArgs(interp, 2, objv,
  897. "?-log_regionmax size?");
  898. result = TCL_ERROR;
  899. break;
  900. }
  901. result = _GetUInt32(interp, objv[i++], &uintarg);
  902. if (result == TCL_OK) {
  903. _debug_check();
  904. ret = (*env)->set_lg_regionmax(*env, uintarg);
  905. result =
  906. _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  907. "log_regionmax");
  908. }
  909. break;
  910. case ENV_LOG_REMOVE:
  911. FLD_SET(set_flags, DB_LOG_AUTOREMOVE);
  912. break;
  913. case ENV_MPOOL_MAX_OPENFD:
  914. if (i >= objc) {
  915. Tcl_WrongNumArgs(interp, 2, objv,
  916. "?-mpool_max_openfd fd_count?");
  917. result = TCL_ERROR;
  918. break;
  919. }
  920. result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
  921. if (result == TCL_OK) {
  922. _debug_check();
  923. ret = (*env)->set_mp_max_openfd(*env, intarg);
  924. result = _ReturnSetup(interp, ret,
  925. DB_RETOK_STD(ret), "mpool_max_openfd");
  926. }
  927. break;
  928. case ENV_MPOOL_MAX_WRITE:
  929. result = Tcl_ListObjGetElements(interp, objv[i],
  930. &myobjc, &myobjv);
  931. if (result == TCL_OK)
  932. i++;
  933. else
  934. break;
  935. if (myobjc != 2) {
  936. Tcl_WrongNumArgs(interp, 2, objv,
  937. "?-mpool_max_write {nwrite nsleep}?");
  938. result = TCL_ERROR;
  939. break;
  940. }
  941. result = Tcl_GetIntFromObj(interp, myobjv[0], &intarg);
  942. if (result != TCL_OK)
  943. break;
  944. result = Tcl_GetIntFromObj(interp, myobjv[1], &intarg2);
  945. if (result != TCL_OK)
  946. break;
  947. _debug_check();
  948. ret = (*env)->set_mp_max_write(
  949. *env, intarg, (db_timeout_t)intarg2);
  950. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  951. "set_mp_max_write");
  952. break;
  953. case ENV_MPOOL_MMAP_SIZE:
  954. if (i >= objc) {
  955. Tcl_WrongNumArgs(interp, 2, objv,
  956. "?-mpool_mmap_size size?");
  957. result = TCL_ERROR;
  958. break;
  959. }
  960. result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
  961. if (result == TCL_OK) {
  962. _debug_check();
  963. ret = (*env)->set_mp_mmapsize(*env,
  964. (size_t)intarg);
  965. result = _ReturnSetup(interp, ret,
  966. DB_RETOK_STD(ret), "mpool_mmap_size");
  967. }
  968. break;
  969. case ENV_MPOOL_NOMMAP:
  970. FLD_SET(set_flags, DB_NOMMAP);
  971. break;
  972. case ENV_MULTIVERSION:
  973. FLD_SET(set_flags, DB_MULTIVERSION);
  974. break;
  975. case ENV_OVERWRITE:
  976. FLD_SET(set_flags, DB_OVERWRITE);
  977. break;
  978. case ENV_REGION_INIT:
  979. _debug_check();
  980. ret = (*env)->set_flags(*env, DB_REGION_INIT, 1);
  981. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  982. "region_init");
  983. break;
  984. case ENV_SET_INTERMEDIATE_DIR:
  985. if (i >= objc) {
  986. Tcl_WrongNumArgs(interp,
  987. 2, objv, "?-set_intermediate_dir mode?");
  988. result = TCL_ERROR;
  989. break;
  990. }
  991. result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
  992. if (result == TCL_OK) {
  993. _debug_check();
  994. ret = (*env)->
  995. set_intermediate_dir(*env, intarg, 0);
  996. result = _ReturnSetup(interp, ret,
  997. DB_RETOK_STD(ret), "set_intermediate_dir");
  998. }
  999. break;
  1000. case ENV_REP:
  1001. FLD_SET(open_flags, DB_INIT_REP);
  1002. break;
  1003. case ENV_REP_CLIENT:
  1004. rep_flags = DB_REP_CLIENT;
  1005. FLD_SET(open_flags, DB_INIT_REP);
  1006. break;
  1007. case ENV_REP_MASTER:
  1008. rep_flags = DB_REP_MASTER;
  1009. FLD_SET(open_flags, DB_INIT_REP);
  1010. break;
  1011. case ENV_REP_LEASE:
  1012. if (i >= objc) {
  1013. Tcl_WrongNumArgs(interp, 2, objv,
  1014. "-rep_lease {nsites timeout clockskew}");
  1015. result = TCL_ERROR;
  1016. break;
  1017. }
  1018. result = Tcl_ListObjGetElements(interp, objv[i],
  1019. &myobjc, &myobjv);
  1020. if (result == TCL_OK)
  1021. i++;
  1022. else
  1023. break;
  1024. result = tcl_RepLease(interp, myobjc, myobjv, *env);
  1025. if (result == TCL_OK)
  1026. FLD_SET(open_flags, DB_INIT_REP);
  1027. break;
  1028. case ENV_REP_TRANSPORT:
  1029. if (i >= objc) {
  1030. Tcl_WrongNumArgs(interp, 2, objv,
  1031. "-rep_transport {envid sendproc}");
  1032. result = TCL_ERROR;
  1033. break;
  1034. }
  1035. result = Tcl_ListObjGetElements(interp, objv[i],
  1036. &myobjc, &myobjv);
  1037. if (result == TCL_OK)
  1038. i++;
  1039. else
  1040. break;
  1041. result = tcl_RepTransport(interp, myobjc, myobjv,
  1042. *env, ip);
  1043. if (result == TCL_OK)
  1044. FLD_SET(open_flags, DB_INIT_REP);
  1045. break;
  1046. case ENV_SNAPSHOT:
  1047. FLD_SET(set_flags, DB_TXN_SNAPSHOT);
  1048. break;
  1049. case ENV_THREAD:
  1050. /* Enable DB_THREAD when specified in testing. */
  1051. FLD_SET(open_flags, DB_THREAD);
  1052. break;
  1053. case ENV_TIME_NOTGRANTED:
  1054. FLD_SET(set_flags, DB_TIME_NOTGRANTED);
  1055. break;
  1056. case ENV_VERBOSE:
  1057. result = Tcl_ListObjGetElements(interp, objv[i],
  1058. &myobjc, &myobjv);
  1059. if (result == TCL_OK)
  1060. i++;
  1061. else
  1062. break;
  1063. if (myobjc != 2) {
  1064. Tcl_WrongNumArgs(interp, 2, objv,
  1065. "?-verbose {which on|off}?");
  1066. result = TCL_ERROR;
  1067. break;
  1068. }
  1069. result = tcl_EnvVerbose(interp, *env,
  1070. myobjv[0], myobjv[1]);
  1071. break;
  1072. case ENV_WRNOSYNC:
  1073. FLD_SET(set_flags, DB_TXN_WRITE_NOSYNC);
  1074. break;
  1075. #endif
  1076. case ENV_TXN:
  1077. FLD_SET(open_flags, DB_INIT_LOCK |
  1078. DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN);
  1079. /* Make sure we have an arg to check against! */
  1080. while (i < objc) {
  1081. arg = Tcl_GetStringFromObj(objv[i], NULL);
  1082. if (strcmp(arg, "nosync") == 0) {
  1083. FLD_SET(set_flags, DB_TXN_NOSYNC);
  1084. i++;
  1085. } else if (strcmp(arg, "snapshot") == 0) {
  1086. FLD_SET(set_flags, DB_TXN_SNAPSHOT);
  1087. i++;
  1088. } else
  1089. break;
  1090. }
  1091. break;
  1092. case ENV_CREATE:
  1093. FLD_SET(open_flags, DB_CREATE | DB_INIT_MPOOL);
  1094. break;
  1095. case ENV_ENCRYPT_AES:
  1096. /* Make sure we have an arg to check against! */
  1097. if (i >= objc) {
  1098. Tcl_WrongNumArgs(interp, 2, objv,
  1099. "?-encryptaes passwd?");
  1100. result = TCL_ERROR;
  1101. break;
  1102. }
  1103. passwd = Tcl_GetStringFromObj(objv[i++], NULL);
  1104. _debug_check();
  1105. ret = (*env)->set_encrypt(*env, passwd, DB_ENCRYPT_AES);
  1106. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1107. "set_encrypt");
  1108. break;
  1109. case ENV_ENCRYPT_ANY:
  1110. /* Make sure we have an arg to check against! */
  1111. if (i >= objc) {
  1112. Tcl_WrongNumArgs(interp, 2, objv,
  1113. "?-encryptany passwd?");
  1114. result = TCL_ERROR;
  1115. break;
  1116. }
  1117. passwd = Tcl_GetStringFromObj(objv[i++], NULL);
  1118. _debug_check();
  1119. ret = (*env)->set_encrypt(*env, passwd, 0);
  1120. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1121. "set_encrypt");
  1122. break;
  1123. case ENV_HOME:
  1124. /* Make sure we have an arg to check against! */
  1125. if (i >= objc) {
  1126. Tcl_WrongNumArgs(interp, 2, objv,
  1127. "?-home dir?");
  1128. result = TCL_ERROR;
  1129. break;
  1130. }
  1131. home = Tcl_GetStringFromObj(objv[i++], NULL);
  1132. break;
  1133. case ENV_MODE:
  1134. if (i >= objc) {
  1135. Tcl_WrongNumArgs(interp, 2, objv,
  1136. "?-mode mode?");
  1137. result = TCL_ERROR;
  1138. break;
  1139. }
  1140. /*
  1141. * Don't need to check result here because
  1142. * if TCL_ERROR, the error message is already
  1143. * set up, and we'll bail out below. If ok,
  1144. * the mode is set and we go on.
  1145. */
  1146. result = Tcl_GetIntFromObj(interp, objv[i++], &mode);
  1147. break;
  1148. case ENV_PRIVATE:
  1149. FLD_SET(open_flags, DB_PRIVATE | DB_INIT_MPOOL);
  1150. break;
  1151. case ENV_RECOVER:
  1152. FLD_SET(open_flags, DB_RECOVER);
  1153. break;
  1154. case ENV_RECOVER_FATAL:
  1155. FLD_SET(open_flags, DB_RECOVER_FATAL);
  1156. break;
  1157. case ENV_REGISTER:
  1158. FLD_SET(open_flags, DB_REGISTER);
  1159. break;
  1160. case ENV_SYSTEM_MEM:
  1161. FLD_SET(open_flags, DB_SYSTEM_MEM);
  1162. break;
  1163. case ENV_USE_ENVIRON_ROOT:
  1164. FLD_SET(open_flags, DB_USE_ENVIRON_ROOT);
  1165. break;
  1166. case ENV_USE_ENVIRON:
  1167. FLD_SET(open_flags, DB_USE_ENVIRON);
  1168. break;
  1169. case ENV_CACHESIZE:
  1170. result = Tcl_ListObjGetElements(interp, objv[i],
  1171. &myobjc, &myobjv);
  1172. if (result == TCL_OK)
  1173. i++;
  1174. else
  1175. break;
  1176. if (myobjc != 3) {
  1177. Tcl_WrongNumArgs(interp, 2, objv,
  1178. "?-cachesize {gbytes bytes ncaches}?");
  1179. result = TCL_ERROR;
  1180. break;
  1181. }
  1182. result = _GetUInt32(interp, myobjv[0], &gbytes);
  1183. if (result != TCL_OK)
  1184. break;
  1185. result = _GetUInt32(interp, myobjv[1], &bytes);
  1186. if (result != TCL_OK)
  1187. break;
  1188. result = Tcl_GetIntFromObj(interp, myobjv[2], &ncaches);
  1189. if (result != TCL_OK)
  1190. break;
  1191. _debug_check();
  1192. ret = (*env)->set_cachesize(*env, gbytes, bytes,
  1193. ncaches);
  1194. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1195. "set_cachesize");
  1196. break;
  1197. case ENV_CACHE_MAX:
  1198. result = Tcl_ListObjGetElements(interp, objv[i],
  1199. &myobjc, &myobjv);
  1200. if (result == TCL_OK)
  1201. i++;
  1202. else
  1203. break;
  1204. if (myobjc != 2) {
  1205. Tcl_WrongNumArgs(interp, 2, objv,
  1206. "?-cache_max {gbytes bytes}?");
  1207. result = TCL_ERROR;
  1208. break;
  1209. }
  1210. result = _GetUInt32(interp, myobjv[0], &gbytes);
  1211. if (result != TCL_OK)
  1212. break;
  1213. result = _GetUInt32(interp, myobjv[1], &bytes);
  1214. if (result != TCL_OK)
  1215. break;
  1216. _debug_check();
  1217. ret = (*env)->set_cache_max(*env, gbytes, bytes);
  1218. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1219. "set_cache_max");
  1220. break;
  1221. case ENV_SHM_KEY:
  1222. if (i >= objc) {
  1223. Tcl_WrongNumArgs(interp, 2, objv,
  1224. "?-shm_key key?");
  1225. result = TCL_ERROR;
  1226. break;
  1227. }
  1228. result = Tcl_GetLongFromObj(interp, objv[i++], &shm);
  1229. if (result == TCL_OK) {
  1230. _debug_check();
  1231. ret = (*env)->set_shm_key(*env, shm);
  1232. result = _ReturnSetup(interp, ret,
  1233. DB_RETOK_STD(ret), "shm_key");
  1234. }
  1235. break;
  1236. case ENV_TXN_MAX:
  1237. if (i >= objc) {
  1238. Tcl_WrongNumArgs(interp, 2, objv,
  1239. "?-txn_max max?");
  1240. result = TCL_ERROR;
  1241. break;
  1242. }
  1243. result = _GetUInt32(interp, objv[i++], &uintarg);
  1244. if (result == TCL_OK) {
  1245. _debug_check();
  1246. ret = (*env)->set_tx_max(*env, uintarg);
  1247. result = _ReturnSetup(interp, ret,
  1248. DB_RETOK_STD(ret), "txn_max");
  1249. }
  1250. break;
  1251. case ENV_ERRFILE:
  1252. if (i >= objc) {
  1253. Tcl_WrongNumArgs(interp, 2, objv,
  1254. "-errfile file");
  1255. result = TCL_ERROR;
  1256. break;
  1257. }
  1258. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  1259. tcl_EnvSetErrfile(interp, *env, ip, arg);
  1260. break;
  1261. case ENV_ERRPFX:
  1262. if (i >= objc) {
  1263. Tcl_WrongNumArgs(interp, 2, objv,
  1264. "-errpfx prefix");
  1265. result = TCL_ERROR;
  1266. break;
  1267. }
  1268. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  1269. _debug_check();
  1270. result = tcl_EnvSetErrpfx(interp, *env, ip, arg);
  1271. break;
  1272. case ENV_DATA_DIR:
  1273. if (i >= objc) {
  1274. Tcl_WrongNumArgs(interp, 2, objv,
  1275. "-data_dir dir");
  1276. result = TCL_ERROR;
  1277. break;
  1278. }
  1279. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  1280. _debug_check();
  1281. ret = (*env)->set_data_dir(*env, arg);
  1282. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1283. "set_data_dir");
  1284. break;
  1285. case ENV_LOG_DIR:
  1286. if (i >= objc) {
  1287. Tcl_WrongNumArgs(interp, 2, objv,
  1288. "-log_dir dir");
  1289. result = TCL_ERROR;
  1290. break;
  1291. }
  1292. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  1293. _debug_check();
  1294. ret = (*env)->set_lg_dir(*env, arg);
  1295. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1296. "set_lg_dir");
  1297. break;
  1298. case ENV_TMP_DIR:
  1299. if (i >= objc) {
  1300. Tcl_WrongNumArgs(interp, 2, objv,
  1301. "-tmp_dir dir");
  1302. result = TCL_ERROR;
  1303. break;
  1304. }
  1305. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  1306. _debug_check();
  1307. ret = (*env)->set_tmp_dir(*env, arg);
  1308. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1309. "set_tmp_dir");
  1310. break;
  1311. }
  1312. /*
  1313. * If, at any time, parsing the args we get an error,
  1314. * bail out and return.
  1315. */
  1316. if (result != TCL_OK)
  1317. goto error;
  1318. }
  1319. /*
  1320. * We have to check this here. We want to set the log buffer
  1321. * size first, if it is specified. So if the user did so,
  1322. * then we took care of it above. But, if we get out here and
  1323. * logmaxset is non-zero, then they set the log_max without
  1324. * resetting the log buffer size, so we now have to do the
  1325. * call to set_lg_max, since we didn't do it above.
  1326. */
  1327. if (logmaxset) {
  1328. _debug_check();
  1329. ret = (*env)->set_lg_max(*env, (u_int32_t)logmaxset);
  1330. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1331. "log_max");
  1332. }
  1333. if (result != TCL_OK)
  1334. goto error;
  1335. if (set_flags) {
  1336. ret = (*env)->set_flags(*env, set_flags, 1);
  1337. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1338. "set_flags");
  1339. if (result == TCL_ERROR)
  1340. goto error;
  1341. /*
  1342. * If we are successful, clear the result so that the
  1343. * return from set_flags isn't part of the result.
  1344. */
  1345. Tcl_ResetResult(interp);
  1346. }
  1347. /*
  1348. * When we get here, we have already parsed all of our args
  1349. * and made all our calls to set up the environment. Everything
  1350. * is okay so far, no errors, if we get here.
  1351. *
  1352. * Now open the environment.
  1353. */
  1354. _debug_check();
  1355. ret = (*env)->open(*env, home, open_flags, mode);
  1356. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env open");
  1357. if (rep_flags != 0 && result == TCL_OK) {
  1358. _debug_check();
  1359. ret = (*env)->rep_start(*env, NULL, rep_flags);
  1360. result = _ReturnSetup(interp,
  1361. ret, DB_RETOK_STD(ret), "rep_start");
  1362. }
  1363. error: if (result == TCL_ERROR) {
  1364. if (ip->i_err && ip->i_err != stdout && ip->i_err != stderr) {
  1365. (void)fclose(ip->i_err);
  1366. ip->i_err = NULL;
  1367. }
  1368. (void)(*env)->close(*env, 0);
  1369. *env = NULL;
  1370. }
  1371. return (result);
  1372. }
  1373. /*
  1374. * bdb_DbOpen --
  1375. * Implements the "db_create/db_open" command.
  1376. * There are many, many options to the open command.
  1377. * Here is the general flow:
  1378. *
  1379. * 0. Preparse args to determine if we have -env.
  1380. * 1. Call db_create to create the db handle.
  1381. * 2. Parse args tracking options.
  1382. * 3. Make any pre-open setup calls necessary.
  1383. * 4. Call DB->open to open the database.
  1384. * 5. Return db widget handle to user.
  1385. */
  1386. static int
  1387. bdb_DbOpen(interp, objc, objv, ip, dbp)
  1388. Tcl_Interp *interp; /* Interpreter */
  1389. int objc; /* How many arguments? */
  1390. Tcl_Obj *CONST objv[]; /* The argument objects */
  1391. DBTCL_INFO *ip; /* Our internal info */
  1392. DB **dbp; /* DB handle */
  1393. {
  1394. static const char *bdbenvopen[] = {
  1395. "-env", NULL
  1396. };
  1397. enum bdbenvopen {
  1398. TCL_DB_ENV0
  1399. };
  1400. static const char *bdbopen[] = {
  1401. #ifdef CONFIG_TEST
  1402. "-btcompare",
  1403. "-dupcompare",
  1404. "-hashcompare",
  1405. "-hashproc",
  1406. "-lorder",
  1407. "-minkey",
  1408. "-nommap",
  1409. "-notdurable",
  1410. "-read_uncommitted",
  1411. "-revsplitoff",
  1412. "-test",
  1413. "-thread",
  1414. #endif
  1415. "-auto_commit",
  1416. "-btree",
  1417. "-cachesize",
  1418. "-chksum",
  1419. "-create",
  1420. "-delim",
  1421. "-dup",
  1422. "-dupsort",
  1423. "-encrypt",
  1424. "-encryptaes",
  1425. "-encryptany",
  1426. "-env",
  1427. "-errfile",
  1428. "-errpfx",
  1429. "-excl",
  1430. "-extent",
  1431. "-ffactor",
  1432. "-hash",
  1433. "-inorder",
  1434. "-len",
  1435. "-maxsize",
  1436. "-mode",
  1437. "-multiversion",
  1438. "-nelem",
  1439. "-pad",
  1440. "-pagesize",
  1441. "-queue",
  1442. "-rdonly",
  1443. "-recno",
  1444. "-recnum",
  1445. "-renumber",
  1446. "-snapshot",
  1447. "-source",
  1448. "-truncate",
  1449. "-txn",
  1450. "-unknown",
  1451. "--",
  1452. NULL
  1453. };
  1454. enum bdbopen {
  1455. #ifdef CONFIG_TEST
  1456. TCL_DB_BTCOMPARE,
  1457. TCL_DB_DUPCOMPARE,
  1458. TCL_DB_HASHCOMPARE,
  1459. TCL_DB_HASHPROC,
  1460. TCL_DB_LORDER,
  1461. TCL_DB_MINKEY,
  1462. TCL_DB_NOMMAP,
  1463. TCL_DB_NOTDURABLE,
  1464. TCL_DB_READ_UNCOMMITTED,
  1465. TCL_DB_REVSPLIT,
  1466. TCL_DB_TEST,
  1467. TCL_DB_THREAD,
  1468. #endif
  1469. TCL_DB_AUTO_COMMIT,
  1470. TCL_DB_BTREE,
  1471. TCL_DB_CACHESIZE,
  1472. TCL_DB_CHKSUM,
  1473. TCL_DB_CREATE,
  1474. TCL_DB_DELIM,
  1475. TCL_DB_DUP,
  1476. TCL_DB_DUPSORT,
  1477. TCL_DB_ENCRYPT,
  1478. TCL_DB_ENCRYPT_AES,
  1479. TCL_DB_ENCRYPT_ANY,
  1480. TCL_DB_ENV,
  1481. TCL_DB_ERRFILE,
  1482. TCL_DB_ERRPFX,
  1483. TCL_DB_EXCL,
  1484. TCL_DB_EXTENT,
  1485. TCL_DB_FFACTOR,
  1486. TCL_DB_HASH,
  1487. TCL_DB_INORDER,
  1488. TCL_DB_LEN,
  1489. TCL_DB_MAXSIZE,
  1490. TCL_DB_MODE,
  1491. TCL_DB_MULTIVERSION,
  1492. TCL_DB_NELEM,
  1493. TCL_DB_PAD,
  1494. TCL_DB_PAGESIZE,
  1495. TCL_DB_QUEUE,
  1496. TCL_DB_RDONLY,
  1497. TCL_DB_RECNO,
  1498. TCL_DB_RECNUM,
  1499. TCL_DB_RENUMBER,
  1500. TCL_DB_SNAPSHOT,
  1501. TCL_DB_SOURCE,
  1502. TCL_DB_TRUNCATE,
  1503. TCL_DB_TXN,
  1504. TCL_DB_UNKNOWN,
  1505. TCL_DB_ENDARG
  1506. };
  1507. DBTCL_INFO *envip, *errip;
  1508. DB_TXN *txn;
  1509. DBTYPE type;
  1510. DB_ENV *envp;
  1511. Tcl_Obj **myobjv;
  1512. u_int32_t gbytes, bytes, open_flags, set_flags, uintarg;
  1513. int endarg, i, intarg, mode, myobjc, ncaches;
  1514. int optindex, result, ret, set_err, set_pfx, subdblen;
  1515. u_char *subdbtmp;
  1516. char *arg, *db, *passwd, *subdb, msg[MSG_SIZE];
  1517. type = DB_UNKNOWN;
  1518. endarg = mode = set_err = set_flags = set_pfx = 0;
  1519. result = TCL_OK;
  1520. subdbtmp = NULL;
  1521. db = subdb = NULL;
  1522. /*
  1523. * XXX
  1524. * If/when our Tcl interface becomes thread-safe, we should enable
  1525. * DB_THREAD here in all cases. For now, we turn it on later in this
  1526. * function, and only when we're in testing and we specify the
  1527. * -thread flag, so that we can exercise MUTEX_THREAD_LOCK cases.
  1528. *
  1529. * In order to become truly thread-safe, we need to look at making sure
  1530. * DBTCL_INFO structs are safe to share across threads (they're not
  1531. * mutex-protected) before we declare the Tcl interface thread-safe.
  1532. * Meanwhile, there's no strong reason to enable DB_THREAD when not
  1533. * testing.
  1534. */
  1535. open_flags = 0;
  1536. envp = NULL;
  1537. txn = NULL;
  1538. if (objc < 2) {
  1539. Tcl_WrongNumArgs(interp, 2, objv, "?args?");
  1540. return (TCL_ERROR);
  1541. }
  1542. /*
  1543. * We must first parse for the environment flag, since that
  1544. * is needed for db_create. Then create the db handle.
  1545. */
  1546. i = 2;
  1547. while (i < objc) {
  1548. if (Tcl_GetIndexFromObj(interp, objv[i++], bdbenvopen,
  1549. "option", TCL_EXACT, &optindex) != TCL_OK) {
  1550. /*
  1551. * Reset the result so we don't get
  1552. * an errant error message if there is another error.
  1553. */
  1554. Tcl_ResetResult(interp);
  1555. continue;
  1556. }
  1557. switch ((enum bdbenvopen)optindex) {
  1558. case TCL_DB_ENV0:
  1559. arg = Tcl_GetStringFromObj(objv[i], NULL);
  1560. envp = NAME_TO_ENV(arg);
  1561. if (envp == NULL) {
  1562. Tcl_SetResult(interp,
  1563. "db open: illegal environment", TCL_STATIC);
  1564. return (TCL_ERROR);
  1565. }
  1566. }
  1567. break;
  1568. }
  1569. /*
  1570. * Create the db handle before parsing the args
  1571. * since we'll be modifying the database options as we parse.
  1572. */
  1573. ret = db_create(dbp, envp, 0);
  1574. if (ret)
  1575. return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1576. "db_create"));
  1577. /* Hang our info pointer on the DB handle, so we can do callbacks. */
  1578. (*dbp)->api_internal = ip;
  1579. /*
  1580. * XXX
  1581. * Remove restriction if error handling not tied to env.
  1582. *
  1583. * The DB->set_err* functions overwrite the environment. So, if
  1584. * we are using an env, don't overwrite it; if not using an env,
  1585. * then configure error handling.
  1586. */
  1587. if (envp == NULL) {
  1588. (*dbp)->set_errpfx((*dbp), ip->i_name);
  1589. (*dbp)->set_errcall((*dbp), _ErrorFunc);
  1590. }
  1591. envip = _PtrToInfo(envp); /* XXX */
  1592. /*
  1593. * If we are using an env, we keep track of err info in the env's ip.
  1594. * Otherwise use the DB's ip.
  1595. */
  1596. if (envip)
  1597. errip = envip;
  1598. else
  1599. errip = ip;
  1600. /*
  1601. * Get the option name index from the object based on the args
  1602. * defined above.
  1603. */
  1604. i = 2;
  1605. while (i < objc) {
  1606. Tcl_ResetResult(interp);
  1607. if (Tcl_GetIndexFromObj(interp, objv[i], bdbopen, "option",
  1608. TCL_EXACT, &optindex) != TCL_OK) {
  1609. arg = Tcl_GetStringFromObj(objv[i], NULL);
  1610. if (arg[0] == '-') {
  1611. result = IS_HELP(objv[i]);
  1612. goto error;
  1613. } else
  1614. Tcl_ResetResult(interp);
  1615. break;
  1616. }
  1617. i++;
  1618. switch ((enum bdbopen)optindex) {
  1619. #ifdef CONFIG_TEST
  1620. case TCL_DB_BTCOMPARE:
  1621. if (i >= objc) {
  1622. Tcl_WrongNumArgs(interp, 2, objv,
  1623. "-btcompare compareproc");
  1624. result = TCL_ERROR;
  1625. break;
  1626. }
  1627. /*
  1628. * Store the object containing the procedure name.
  1629. * We don't need to crack it out now--we'll want
  1630. * to bundle it up to pass into Tcl_EvalObjv anyway.
  1631. * Tcl's object refcounting will--I hope--take care
  1632. * of the memory management here.
  1633. */
  1634. ip->i_compare = objv[i++];
  1635. Tcl_IncrRefCount(ip->i_compare);
  1636. _debug_check();
  1637. ret = (*dbp)->set_bt_compare(*dbp, tcl_bt_compare);
  1638. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1639. "set_bt_compare");
  1640. break;
  1641. case TCL_DB_DUPCOMPARE:
  1642. if (i >= objc) {
  1643. Tcl_WrongNumArgs(interp, 2, objv,
  1644. "-dupcompare compareproc");
  1645. result = TCL_ERROR;
  1646. break;
  1647. }
  1648. /*
  1649. * Store the object containing the procedure name.
  1650. * See TCL_DB_BTCOMPARE.
  1651. */
  1652. ip->i_dupcompare = objv[i++];
  1653. Tcl_IncrRefCount(ip->i_dupcompare);
  1654. _debug_check();
  1655. ret = (*dbp)->set_dup_compare(*dbp, tcl_dup_compare);
  1656. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1657. "set_dup_compare");
  1658. break;
  1659. case TCL_DB_HASHCOMPARE:
  1660. if (i >= objc) {
  1661. Tcl_WrongNumArgs(interp, 2, objv,
  1662. "-hashcompare compareproc");
  1663. result = TCL_ERROR;
  1664. break;
  1665. }
  1666. /*
  1667. * Store the object containing the procedure name.
  1668. * We don't need to crack it out now--we'll want
  1669. * to bundle it up to pass into Tcl_EvalObjv anyway.
  1670. * Tcl's object refcounting will--I hope--take care
  1671. * of the memory management here.
  1672. */
  1673. ip->i_compare = objv[i++];
  1674. Tcl_IncrRefCount(ip->i_compare);
  1675. _debug_check();
  1676. ret = (*dbp)->set_h_compare(*dbp, tcl_bt_compare);
  1677. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1678. "set_h_compare");
  1679. break;
  1680. case TCL_DB_HASHPROC:
  1681. if (i >= objc) {
  1682. Tcl_WrongNumArgs(interp, 2, objv,
  1683. "-hashproc hashproc");
  1684. result = TCL_ERROR;
  1685. break;
  1686. }
  1687. /*
  1688. * Store the object containing the procedure name.
  1689. * See TCL_DB_BTCOMPARE.
  1690. */
  1691. ip->i_hashproc = objv[i++];
  1692. Tcl_IncrRefCount(ip->i_hashproc);
  1693. _debug_check();
  1694. ret = (*dbp)->set_h_hash(*dbp, tcl_h_hash);
  1695. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1696. "set_h_hash");
  1697. break;
  1698. case TCL_DB_LORDER:
  1699. if (i >= objc) {
  1700. Tcl_WrongNumArgs(interp, 2, objv,
  1701. "-lorder 1234|4321");
  1702. result = TCL_ERROR;
  1703. break;
  1704. }
  1705. result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
  1706. if (result == TCL_OK) {
  1707. _debug_check();
  1708. ret = (*dbp)->set_lorder(*dbp, intarg);
  1709. result = _ReturnSetup(interp, ret,
  1710. DB_RETOK_STD(ret), "set_lorder");
  1711. }
  1712. break;
  1713. case TCL_DB_MINKEY:
  1714. if (i >= objc) {
  1715. Tcl_WrongNumArgs(interp, 2, objv,
  1716. "-minkey minkey");
  1717. result = TCL_ERROR;
  1718. break;
  1719. }
  1720. result = _GetUInt32(interp, objv[i++], &uintarg);
  1721. if (result == TCL_OK) {
  1722. _debug_check();
  1723. ret = (*dbp)->set_bt_minkey(*dbp, uintarg);
  1724. result = _ReturnSetup(interp, ret,
  1725. DB_RETOK_STD(ret), "set_bt_minkey");
  1726. }
  1727. break;
  1728. case TCL_DB_NOMMAP:
  1729. open_flags |= DB_NOMMAP;
  1730. break;
  1731. case TCL_DB_NOTDURABLE:
  1732. set_flags |= DB_TXN_NOT_DURABLE;
  1733. break;
  1734. case TCL_DB_READ_UNCOMMITTED:
  1735. open_flags |= DB_READ_UNCOMMITTED;
  1736. break;
  1737. case TCL_DB_REVSPLIT:
  1738. set_flags |= DB_REVSPLITOFF;
  1739. break;
  1740. case TCL_DB_TEST:
  1741. ret = (*dbp)->set_h_hash(*dbp, __ham_test);
  1742. result = _ReturnSetup(interp, ret,
  1743. DB_RETOK_STD(ret), "set_h_hash");
  1744. break;
  1745. case TCL_DB_THREAD:
  1746. /* Enable DB_THREAD when specified in testing. */
  1747. open_flags |= DB_THREAD;
  1748. break;
  1749. #endif
  1750. case TCL_DB_AUTO_COMMIT:
  1751. open_flags |= DB_AUTO_COMMIT;
  1752. break;
  1753. case TCL_DB_ENV:
  1754. /*
  1755. * Already parsed this, skip it and the env pointer.
  1756. */
  1757. i++;
  1758. continue;
  1759. case TCL_DB_TXN:
  1760. if (i > (objc - 1)) {
  1761. Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
  1762. result = TCL_ERROR;
  1763. break;
  1764. }
  1765. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  1766. txn = NAME_TO_TXN(arg);
  1767. if (txn == NULL) {
  1768. snprintf(msg, MSG_SIZE,
  1769. "Open: Invalid txn: %s\n", arg);
  1770. Tcl_SetResult(interp, msg, TCL_VOLATILE);
  1771. result = TCL_ERROR;
  1772. }
  1773. break;
  1774. case TCL_DB_BTREE:
  1775. if (type != DB_UNKNOWN) {
  1776. Tcl_SetResult(interp,
  1777. "Too many DB types specified", TCL_STATIC);
  1778. result = TCL_ERROR;
  1779. goto error;
  1780. }
  1781. type = DB_BTREE;
  1782. break;
  1783. case TCL_DB_HASH:
  1784. if (type != DB_UNKNOWN) {
  1785. Tcl_SetResult(interp,
  1786. "Too many DB types specified", TCL_STATIC);
  1787. result = TCL_ERROR;
  1788. goto error;
  1789. }
  1790. type = DB_HASH;
  1791. break;
  1792. case TCL_DB_RECNO:
  1793. if (type != DB_UNKNOWN) {
  1794. Tcl_SetResult(interp,
  1795. "Too many DB types specified", TCL_STATIC);
  1796. result = TCL_ERROR;
  1797. goto error;
  1798. }
  1799. type = DB_RECNO;
  1800. break;
  1801. case TCL_DB_QUEUE:
  1802. if (type != DB_UNKNOWN) {
  1803. Tcl_SetResult(interp,
  1804. "Too many DB types specified", TCL_STATIC);
  1805. result = TCL_ERROR;
  1806. goto error;
  1807. }
  1808. type = DB_QUEUE;
  1809. break;
  1810. case TCL_DB_UNKNOWN:
  1811. if (type != DB_UNKNOWN) {
  1812. Tcl_SetResult(interp,
  1813. "Too many DB types specified", TCL_STATIC);
  1814. result = TCL_ERROR;
  1815. goto error;
  1816. }
  1817. break;
  1818. case TCL_DB_CREATE:
  1819. open_flags |= DB_CREATE;
  1820. break;
  1821. case TCL_DB_EXCL:
  1822. open_flags |= DB_EXCL;
  1823. break;
  1824. case TCL_DB_RDONLY:
  1825. open_flags |= DB_RDONLY;
  1826. break;
  1827. case TCL_DB_TRUNCATE:
  1828. open_flags |= DB_TRUNCATE;
  1829. break;
  1830. case TCL_DB_MODE:
  1831. if (i >= objc) {
  1832. Tcl_WrongNumArgs(interp, 2, objv,
  1833. "?-mode mode?");
  1834. result = TCL_ERROR;
  1835. break;
  1836. }
  1837. /*
  1838. * Don't need to check result here because
  1839. * if TCL_ERROR, the error message is already
  1840. * set up, and we'll bail out below. If ok,
  1841. * the mode is set and we go on.
  1842. */
  1843. result = Tcl_GetIntFromObj(interp, objv[i++], &mode);
  1844. break;
  1845. case TCL_DB_DUP:
  1846. set_flags |= DB_DUP;
  1847. break;
  1848. case TCL_DB_DUPSORT:
  1849. set_flags |= DB_DUPSORT;
  1850. break;
  1851. case TCL_DB_INORDER:
  1852. set_flags |= DB_INORDER;
  1853. break;
  1854. case TCL_DB_RECNUM:
  1855. set_flags |= DB_RECNUM;
  1856. break;
  1857. case TCL_DB_RENUMBER:
  1858. set_flags |= DB_RENUMBER;
  1859. break;
  1860. case TCL_DB_SNAPSHOT:
  1861. set_flags |= DB_SNAPSHOT;
  1862. break;
  1863. case TCL_DB_CHKSUM:
  1864. set_flags |= DB_CHKSUM;
  1865. break;
  1866. case TCL_DB_ENCRYPT:
  1867. set_flags |= DB_ENCRYPT;
  1868. break;
  1869. case TCL_DB_ENCRYPT_AES:
  1870. /* Make sure we have an arg to check against! */
  1871. if (i >= objc) {
  1872. Tcl_WrongNumArgs(interp, 2, objv,
  1873. "?-encryptaes passwd?");
  1874. result = TCL_ERROR;
  1875. break;
  1876. }
  1877. passwd = Tcl_GetStringFromObj(objv[i++], NULL);
  1878. _debug_check();
  1879. ret = (*dbp)->set_encrypt(*dbp, passwd, DB_ENCRYPT_AES);
  1880. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1881. "set_encrypt");
  1882. break;
  1883. case TCL_DB_ENCRYPT_ANY:
  1884. /* Make sure we have an arg to check against! */
  1885. if (i >= objc) {
  1886. Tcl_WrongNumArgs(interp, 2, objv,
  1887. "?-encryptany passwd?");
  1888. result = TCL_ERROR;
  1889. break;
  1890. }
  1891. passwd = Tcl_GetStringFromObj(objv[i++], NULL);
  1892. _debug_check();
  1893. ret = (*dbp)->set_encrypt(*dbp, passwd, 0);
  1894. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  1895. "set_encrypt");
  1896. break;
  1897. case TCL_DB_FFACTOR:
  1898. if (i >= objc) {
  1899. Tcl_WrongNumArgs(interp, 2, objv,
  1900. "-ffactor density");
  1901. result = TCL_ERROR;
  1902. break;
  1903. }
  1904. result = _GetUInt32(interp, objv[i++], &uintarg);
  1905. if (result == TCL_OK) {
  1906. _debug_check();
  1907. ret = (*dbp)->set_h_ffactor(*dbp, uintarg);
  1908. result = _ReturnSetup(interp, ret,
  1909. DB_RETOK_STD(ret), "set_h_ffactor");
  1910. }
  1911. break;
  1912. case TCL_DB_MULTIVERSION:
  1913. open_flags |= DB_MULTIVERSION;
  1914. break;
  1915. case TCL_DB_NELEM:
  1916. if (i >= objc) {
  1917. Tcl_WrongNumArgs(interp, 2, objv,
  1918. "-nelem nelem");
  1919. result = TCL_ERROR;
  1920. break;
  1921. }
  1922. result = _GetUInt32(interp, objv[i++], &uintarg);
  1923. if (result == TCL_OK) {
  1924. _debug_check();
  1925. ret = (*dbp)->set_h_nelem(*dbp, uintarg);
  1926. result = _ReturnSetup(interp, ret,
  1927. DB_RETOK_STD(ret), "set_h_nelem");
  1928. }
  1929. break;
  1930. case TCL_DB_DELIM:
  1931. if (i >= objc) {
  1932. Tcl_WrongNumArgs(interp, 2, objv,
  1933. "-delim delim");
  1934. result = TCL_ERROR;
  1935. break;
  1936. }
  1937. result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
  1938. if (result == TCL_OK) {
  1939. _debug_check();
  1940. ret = (*dbp)->set_re_delim(*dbp, intarg);
  1941. result = _ReturnSetup(interp, ret,
  1942. DB_RETOK_STD(ret), "set_re_delim");
  1943. }
  1944. break;
  1945. case TCL_DB_LEN:
  1946. if (i >= objc) {
  1947. Tcl_WrongNumArgs(interp, 2, objv,
  1948. "-len length");
  1949. result = TCL_ERROR;
  1950. break;
  1951. }
  1952. result = _GetUInt32(interp, objv[i++], &uintarg);
  1953. if (result == TCL_OK) {
  1954. _debug_check();
  1955. ret = (*dbp)->set_re_len(*dbp, uintarg);
  1956. result = _ReturnSetup(interp, ret,
  1957. DB_RETOK_STD(ret), "set_re_len");
  1958. }
  1959. break;
  1960. case TCL_DB_MAXSIZE:
  1961. if (i >= objc) {
  1962. Tcl_WrongNumArgs(interp, 2, objv,
  1963. "-len length");
  1964. result = TCL_ERROR;
  1965. break;
  1966. }
  1967. result = _GetUInt32(interp, objv[i++], &uintarg);
  1968. if (result == TCL_OK) {
  1969. _debug_check();
  1970. ret = (*dbp)->mpf->set_maxsize(
  1971. (*dbp)->mpf, 0, uintarg);
  1972. result = _ReturnSetup(interp, ret,
  1973. DB_RETOK_STD(ret), "set_re_len");
  1974. }
  1975. break;
  1976. case TCL_DB_PAD:
  1977. if (i >= objc) {
  1978. Tcl_WrongNumArgs(interp, 2, objv,
  1979. "-pad pad");
  1980. result = TCL_ERROR;
  1981. break;
  1982. }
  1983. result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
  1984. if (result == TCL_OK) {
  1985. _debug_check();
  1986. ret = (*dbp)->set_re_pad(*dbp, intarg);
  1987. result = _ReturnSetup(interp, ret,
  1988. DB_RETOK_STD(ret), "set_re_pad");
  1989. }
  1990. break;
  1991. case TCL_DB_SOURCE:
  1992. if (i >= objc) {
  1993. Tcl_WrongNumArgs(interp, 2, objv,
  1994. "-source file");
  1995. result = TCL_ERROR;
  1996. break;
  1997. }
  1998. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  1999. _debug_check();
  2000. ret = (*dbp)->set_re_source(*dbp, arg);
  2001. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  2002. "set_re_source");
  2003. break;
  2004. case TCL_DB_EXTENT:
  2005. if (i >= objc) {
  2006. Tcl_WrongNumArgs(interp, 2, objv,
  2007. "-extent size");
  2008. result = TCL_ERROR;
  2009. break;
  2010. }
  2011. result = _GetUInt32(interp, objv[i++], &uintarg);
  2012. if (result == TCL_OK) {
  2013. _debug_check();
  2014. ret = (*dbp)->set_q_extentsize(*dbp, uintarg);
  2015. result = _ReturnSetup(interp, ret,
  2016. DB_RETOK_STD(ret), "set_q_extentsize");
  2017. }
  2018. break;
  2019. case TCL_DB_CACHESIZE:
  2020. result = Tcl_ListObjGetElements(interp, objv[i++],
  2021. &myobjc, &myobjv);
  2022. if (result != TCL_OK)
  2023. break;
  2024. if (myobjc != 3) {
  2025. Tcl_WrongNumArgs(interp, 2, objv,
  2026. "?-cachesize {gbytes bytes ncaches}?");
  2027. result = TCL_ERROR;
  2028. break;
  2029. }
  2030. result = _GetUInt32(interp, myobjv[0], &gbytes);
  2031. if (result != TCL_OK)
  2032. break;
  2033. result = _GetUInt32(interp, myobjv[1], &bytes);
  2034. if (result != TCL_OK)
  2035. break;
  2036. result = Tcl_GetIntFromObj(interp, myobjv[2], &ncaches);
  2037. if (result != TCL_OK)
  2038. break;
  2039. _debug_check();
  2040. ret = (*dbp)->set_cachesize(*dbp, gbytes, bytes,
  2041. ncaches);
  2042. result = _ReturnSetup(interp, ret,
  2043. DB_RETOK_STD(ret), "set_cachesize");
  2044. break;
  2045. case TCL_DB_PAGESIZE:
  2046. if (i >= objc) {
  2047. Tcl_WrongNumArgs(interp, 2, objv,
  2048. "?-pagesize size?");
  2049. result = TCL_ERROR;
  2050. break;
  2051. }
  2052. result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
  2053. if (result == TCL_OK) {
  2054. _debug_check();
  2055. ret = (*dbp)->set_pagesize(*dbp,
  2056. (size_t)intarg);
  2057. result = _ReturnSetup(interp, ret,
  2058. DB_RETOK_STD(ret), "set pagesize");
  2059. }
  2060. break;
  2061. case TCL_DB_ERRFILE:
  2062. if (i >= objc) {
  2063. Tcl_WrongNumArgs(interp, 2, objv,
  2064. "-errfile file");
  2065. result = TCL_ERROR;
  2066. break;
  2067. }
  2068. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  2069. /*
  2070. * If the user already set one, close it.
  2071. */
  2072. if (errip->i_err != NULL &&
  2073. errip->i_err != stdout && errip->i_err != stderr)
  2074. (void)fclose(errip->i_err);
  2075. if (strcmp(arg, "/dev/stdout") == 0)
  2076. errip->i_err = stdout;
  2077. else if (strcmp(arg, "/dev/stderr") == 0)
  2078. errip->i_err = stderr;
  2079. else
  2080. errip->i_err = fopen(arg, "a");
  2081. if (errip->i_err != NULL) {
  2082. _debug_check();
  2083. (*dbp)->set_errfile(*dbp, errip->i_err);
  2084. set_err = 1;
  2085. }
  2086. break;
  2087. case TCL_DB_ERRPFX:
  2088. if (i >= objc) {
  2089. Tcl_WrongNumArgs(interp, 2, objv,
  2090. "-errpfx prefix");
  2091. result = TCL_ERROR;
  2092. break;
  2093. }
  2094. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  2095. /*
  2096. * If the user already set one, free it.
  2097. */
  2098. if (errip->i_errpfx != NULL)
  2099. __os_free(NULL, errip->i_errpfx);
  2100. if ((ret = __os_strdup((*dbp)->dbenv,
  2101. arg, &errip->i_errpfx)) != 0) {
  2102. result = _ReturnSetup(interp, ret,
  2103. DB_RETOK_STD(ret), "__os_strdup");
  2104. break;
  2105. }
  2106. if (errip->i_errpfx != NULL) {
  2107. _debug_check();
  2108. (*dbp)->set_errpfx(*dbp, errip->i_errpfx);
  2109. set_pfx = 1;
  2110. }
  2111. break;
  2112. case TCL_DB_ENDARG:
  2113. endarg = 1;
  2114. break;
  2115. } /* switch */
  2116. /*
  2117. * If, at any time, parsing the args we get an error,
  2118. * bail out and return.
  2119. */
  2120. if (result != TCL_OK)
  2121. goto error;
  2122. if (endarg)
  2123. break;
  2124. }
  2125. if (result != TCL_OK)
  2126. goto error;
  2127. /*
  2128. * Any args we have left, (better be 0, 1 or 2 left) are
  2129. * file names. If we have 0, then an in-memory db. If
  2130. * there is 1, a db name, if 2 a db and subdb name.
  2131. */
  2132. if (i != objc) {
  2133. /*
  2134. * Dbs must be NULL terminated file names, but subdbs can
  2135. * be anything. Use Strings for the db name and byte
  2136. * arrays for the subdb.
  2137. */
  2138. db = Tcl_GetStringFromObj(objv[i++], NULL);
  2139. if (strcmp(db, "") == 0)
  2140. db = NULL;
  2141. if (i != objc) {
  2142. subdbtmp =
  2143. Tcl_GetByteArrayFromObj(objv[i++], &subdblen);
  2144. if ((ret = __os_malloc(envp,
  2145. (size_t)subdblen + 1, &subdb)) != 0) {
  2146. Tcl_SetResult(interp, db_strerror(ret),
  2147. TCL_STATIC);
  2148. return (0);
  2149. }
  2150. memcpy(subdb, subdbtmp, (size_t)subdblen);
  2151. subdb[subdblen] = '\0';
  2152. }
  2153. }
  2154. if (set_flags) {
  2155. ret = (*dbp)->set_flags(*dbp, set_flags);
  2156. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
  2157. "set_flags");
  2158. if (result == TCL_ERROR)
  2159. goto error;
  2160. /*
  2161. * If we are successful, clear the result so that the
  2162. * return from set_flags isn't part of the result.
  2163. */
  2164. Tcl_ResetResult(interp);
  2165. }
  2166. /*
  2167. * When we get here, we have already parsed all of our args and made
  2168. * all our calls to set up the database. Everything is okay so far,
  2169. * no errors, if we get here.
  2170. */
  2171. _debug_check();
  2172. /* Open the database. */
  2173. ret = (*dbp)->open(*dbp, txn, db, subdb, type, open_flags, mode);
  2174. result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db open");
  2175. error:
  2176. if (subdb)
  2177. __os_free(envp, subdb);
  2178. if (result == TCL_ERROR) {
  2179. (void)(*dbp)->close(*dbp, 0);
  2180. /*
  2181. * If we opened and set up the error file in the environment
  2182. * on this open, but we failed for some other reason, clean
  2183. * up and close the file.
  2184. *
  2185. * XXX when err stuff isn't tied to env, change to use ip,
  2186. * instead of envip. Also, set_err is irrelevant when that
  2187. * happens. It will just read:
  2188. * if (ip->i_err)
  2189. * fclose(ip->i_err);
  2190. */
  2191. if (set_err && errip && errip->i_err != NULL &&
  2192. errip->i_err != stdout && errip->i_err != stderr) {
  2193. (void)fclose(errip->i_err);
  2194. errip->i_err = NULL;
  2195. }
  2196. if (set_pfx && errip && errip->i_errpfx != NULL) {
  2197. __os_free(envp, errip->i_errpfx);
  2198. errip->i_errpfx = NULL;
  2199. }
  2200. *dbp = NULL;
  2201. }
  2202. return (result);
  2203. }
  2204. #ifdef HAVE_64BIT_TYPES
  2205. /*
  2206. * bdb_SeqOpen --
  2207. * Implements the "Seq_create/Seq_open" command.
  2208. */
  2209. static int
  2210. bdb_SeqOpen(interp, objc, objv, ip, seqp)
  2211. Tcl_Interp *interp; /* Interpreter */
  2212. int objc; /* How many arguments? */
  2213. Tcl_Obj *CONST objv[]; /* The argument objects */
  2214. DBTCL_INFO *ip; /* Our internal info */
  2215. DB_SEQUENCE **seqp; /* DB_SEQUENCE handle */
  2216. {
  2217. static const char *seqopen[] = {
  2218. "-cachesize",
  2219. "-create",
  2220. "-inc",
  2221. "-init",
  2222. "-dec",
  2223. "-max",
  2224. "-min",
  2225. "-thread",
  2226. "-txn",
  2227. "-wrap",
  2228. "--",
  2229. NULL
  2230. } ;
  2231. enum seqopen {
  2232. TCL_SEQ_CACHESIZE,
  2233. TCL_SEQ_CREATE,
  2234. TCL_SEQ_INC,
  2235. TCL_SEQ_INIT,
  2236. TCL_SEQ_DEC,
  2237. TCL_SEQ_MAX,
  2238. TCL_SEQ_MIN,
  2239. TCL_SEQ_THREAD,
  2240. TCL_SEQ_TXN,
  2241. TCL_SEQ_WRAP,
  2242. TCL_SEQ_ENDARG
  2243. };
  2244. DB *dbp;
  2245. DBT key;
  2246. DBTYPE type;
  2247. DB_TXN *txn;
  2248. db_recno_t recno;
  2249. db_seq_t min, max, value;
  2250. Tcl_WideInt tcl_value;
  2251. u_int32_t flags, oflags;
  2252. int cache, endarg, i, optindex, result, ret, setrange, setvalue, v;
  2253. char *arg, *db, msg[MSG_SIZE];
  2254. COMPQUIET(ip, NULL);
  2255. COMPQUIET(value, 0);
  2256. *seqp = NULL;
  2257. if (objc < 2) {
  2258. Tcl_WrongNumArgs(interp, 2, objv, "?args?");
  2259. return (TCL_ERROR);
  2260. }
  2261. txn = NULL;
  2262. endarg = 0;
  2263. flags = oflags = 0;
  2264. setrange = setvalue = 0;
  2265. min = INT64_MIN;
  2266. max = INT64_MAX;
  2267. cache = 0;
  2268. for (i = 2; i < objc;) {
  2269. Tcl_ResetResult(interp);
  2270. if (Tcl_GetIndexFromObj(interp, objv[i], seqopen, "option",
  2271. TCL_EXACT, &optindex) != TCL_OK) {
  2272. arg = Tcl_GetStringFromObj(objv[i], NULL);
  2273. if (arg[0] == '-') {
  2274. result = IS_HELP(objv[i]);
  2275. goto error;
  2276. } else
  2277. Tcl_ResetResult(interp);
  2278. break;
  2279. }
  2280. i++;
  2281. result = TCL_OK;
  2282. switch ((enum seqopen)optindex) {
  2283. case TCL_SEQ_CREATE:
  2284. oflags |= DB_CREATE;
  2285. break;
  2286. case TCL_SEQ_INC:
  2287. LF_SET(DB_SEQ_INC);
  2288. break;
  2289. case TCL_SEQ_CACHESIZE:
  2290. if (i >= objc) {
  2291. Tcl_WrongNumArgs(interp, 2, objv,
  2292. "?-cachesize value?");
  2293. result = TCL_ERROR;
  2294. break;
  2295. }
  2296. result = Tcl_GetIntFromObj(interp, objv[i++], &cache);
  2297. break;
  2298. case TCL_SEQ_INIT:
  2299. if (i >= objc) {
  2300. Tcl_WrongNumArgs(interp, 2, objv,
  2301. "?-init value?");
  2302. result = TCL_ERROR;
  2303. break;
  2304. }
  2305. result =
  2306. Tcl_GetWideIntFromObj(
  2307. interp, objv[i++], &tcl_value);
  2308. value = tcl_value;
  2309. setvalue = 1;
  2310. break;
  2311. case TCL_SEQ_DEC:
  2312. LF_SET(DB_SEQ_DEC);
  2313. break;
  2314. case TCL_SEQ_MAX:
  2315. if (i >= objc) {
  2316. Tcl_WrongNumArgs(interp, 2, objv,
  2317. "?-max value?");
  2318. result = TCL_ERROR;
  2319. break;
  2320. }
  2321. if ((result =
  2322. Tcl_GetWideIntFromObj(interp,
  2323. objv[i++], &tcl_value)) != TCL_OK)
  2324. goto error;
  2325. max = tcl_value;
  2326. setrange = 1;
  2327. break;
  2328. case TCL_SEQ_MIN:
  2329. if (i >= objc) {
  2330. Tcl_WrongNumArgs(interp, 2, objv,
  2331. "?-min value?");
  2332. result = TCL_ERROR;
  2333. break;
  2334. }
  2335. if ((result =
  2336. Tcl_GetWideIntFromObj(interp,
  2337. objv[i++], &tcl_value)) != TCL_OK)
  2338. goto error;
  2339. min = tcl_value;
  2340. setrange = 1;
  2341. break;
  2342. case TCL_SEQ_THREAD:
  2343. oflags |= DB_THREAD;
  2344. break;
  2345. case TCL_SEQ_TXN:
  2346. if (i > (objc - 1)) {
  2347. Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
  2348. result = TCL_ERROR;
  2349. break;
  2350. }
  2351. arg = Tcl_GetStringFromObj(objv[i++], NULL);
  2352. txn = NAME_TO_TXN(arg);
  2353. if (txn == NULL) {
  2354. snprintf(msg, MSG_SIZE,
  2355. "Sequence: Invalid txn: %s\n", arg);
  2356. Tcl_SetResult(interp, msg, TCL_VOLATILE);
  2357. result = TCL_ERROR;
  2358. }
  2359. break;
  2360. case TCL_SEQ_WRAP:
  2361. LF_SET(DB_SEQ_WRAP);
  2362. break;
  2363. case TCL_SEQ_ENDARG:
  2364. endarg = 1;
  2365. break;
  2366. }
  2367. /*
  2368. * If, at any time, parsing the args we get an error,
  2369. * bail out and return.
  2370. */
  2371. if (result != TCL_OK)
  2372. goto error;
  2373. if (endarg)
  2374. break;
  2375. }
  2376. if (objc - i != 2) {
  2377. Tcl_WrongNumArgs(interp, 2, objv, "?args?");
  2378. return (TCL_ERROR);
  2379. }
  2380. /*
  2381. * The db must be a string but the sequence key may
  2382. * be anything.
  2383. */
  2384. db = Tcl_GetStringFromObj(objv[i++], NULL);
  2385. if ((dbp = NAME_TO_DB(db)) == NULL) {
  2386. Tcl_SetResult(interp, "No such dbp", TCL_STATIC);
  2387. return (TCL_ERROR);
  2388. }
  2389. (void)dbp->get_type(dbp, &type);
  2390. if (type == DB_QUEUE || type == DB_RECNO) {
  2391. result = _GetUInt32(interp, objv[i++], &recno);
  2392. if (result != TCL_OK)
  2393. return (result);
  2394. DB_INIT_DBT(key, &recno, sizeof(recno));
  2395. } else
  2396. DB_INIT_DBT(key, Tcl_GetByteArrayFromObj(objv[i++], &v), v);
  2397. ret = db_sequence_create(seqp, dbp, 0);
  2398. if ((result = _ReturnSetup(interp,
  2399. ret, DB_RETOK_STD(ret), "sequence create")) != TCL_OK) {
  2400. *seqp = NULL;
  2401. return (result);
  2402. }
  2403. ret = (*seqp)->set_flags(*seqp, flags);
  2404. if ((result = _ReturnSetup(interp,
  2405. ret, DB_RETOK_STD(ret), "sequence set_flags")) != TCL_OK)
  2406. goto error;
  2407. if (setrange) {
  2408. ret = (*seqp)->set_range(*seqp, min, max);
  2409. if ((result = _ReturnSetup(interp,
  2410. ret, DB_RETOK_STD(ret), "sequence set_range")) != TCL_OK)
  2411. goto error;
  2412. }
  2413. if (cache) {
  2414. ret = (*seqp)->set_cachesize(*seqp, cache);
  2415. if ((result = _ReturnSetup(interp,
  2416. ret, DB_RETOK_STD(ret), "sequence cachesize")) != TCL_OK)
  2417. goto error;
  2418. }
  2419. if (setvalue) {
  2420. ret = (*seqp)->initial_value(*seqp, value);
  2421. if ((result = _ReturnSetup(interp,
  2422. ret, DB_RETOK_STD(ret), "sequence init")) != TCL_OK)
  2423. goto error;
  2424. }
  2425. ret = (*seqp)->open(*seqp, txn, &key, oflags);
  2426. if ((result = _ReturnSetup(interp,
  2427. ret, DB_RETOK_STD(ret), "sequence open")) != TCL_OK)
  2428. goto error;
  2429. if (0) {
  2430. error: if (*seqp != NULL)
  2431. (void)(*seqp)->close(*seqp, 0);
  2432. *seqp = NULL;
  2433. }
  2434. return (result);
  2435. }
  2436. #endif
  2437. /*
  2438. * bdb_DbRemove --
  2439. * Implements the DB_ENV->remove and DB->remove command.
  2440. */
  2441. static int
  2442. bdb_DbRemove(interp, objc, objv)
  2443. Tcl_Interp *interp; /* Interpreter */
  2444. int objc; /* How many arguments? */
  2445. Tcl_Obj *CONST objv[]; /* The argument objects */
  2446. {
  2447. static const char *bdbrem[] = {
  2448. "-auto_commit",
  2449. "-encrypt",
  2450. "-encryptaes",
  2451. "-encryptany",
  2452. "-env",
  2453. "-txn",
  2454. "--",
  2455. NULL
  2456. };
  2457. enum bdbrem {
  2458. TCL_DBREM_AUTOCOMMIT,
  2459. TCL_DBREM_ENCRYPT,
  2460. TCL_DBREM_ENCRYPT_AES,
  2461. TCL_DBREM_ENCRYPT_ANY,
  2462. TCL_DBREM_ENV,
  2463. TCL_DBREM_TXN,
  2464. TCL_DBREM_ENDARG
  2465. };
  2466. DB *dbp;
  2467. DB_ENV *envp;
  2468. DB_TXN *txn;
  2469. int endarg, i, optindex, result, ret, subdblen;
  2470. u_int32_t enc_flag, iflags, set_flags;
  2471. u_char *subdbtmp;
  2472. char *arg, *db, msg[MSG_SIZE], *passwd, *subdb;
  2473. db = subdb = NULL;
  2474. dbp = NULL;
  2475. endarg = 0;
  2476. envp = NULL;
  2477. iflags = enc_flag = set_flags = 0;
  2478. passwd = NULL;
  2479. result = TCL_OK;
  2480. subdbtmp = NULL;
  2481. txn = NULL;
  2482. if (objc < 2) {
  2483. Tcl_WrongNumArgs(interp, 2, objv, "?args? filename ?database?");
  2484. return (TCL_ERROR);
  2485. }
  2486. /*
  2487. * We must first parse for the environment flag, since that
  2488. * is needed for db_create. Then create the db handle.
  2489. */
  2490. i = 2;
  2491. while (i < objc) {
  2492. if (Tcl_GetIndexFromObj(interp, objv[i], bdbrem,
  2493. "option", TCL_EXACT, &optindex) != TCL_OK) {
  2494. arg = Tcl_GetStringFromObj(objv[i], NULL);
  2495. if (arg[0] == '-') {
  2496. result = IS_HELP(objv[i]);
  2497. goto error;
  2498. } else
  2499. Tcl_ResetResult(interp);
  2500. break;
  2501. }
  2502. i++;
  2503. switch ((enum bdbrem)optindex) {
  2504. case TCL_DBREM_AUTOCOMMIT:
  2505. iflags |= DB_AUTO_COMMIT;
  2506. _debug_check();
  2507. break;
  2508. case TCL_DBREM_ENCRYPT:
  2509. set_flags |= DB_ENCRYPT;
  2510. _debug_check();
  2511. break;
  2512. case TCL_DBREM_ENCRYPT_AES:
  2513. /* Make sure we have an arg to check against! */
  2514. if (i >= objc) {
  2515. Tcl_WrongNumArgs(interp, 2, objv,
  2516. "?-encryptaes passwd?");
  2517. result = TCL_ERROR;
  2518. break;
  2519. }
  2520. passwd = Tcl_GetStringFromObj(objv[i++], NULL);
  2521. enc_flag = DB_ENCRYPT_AES;
  2522. break;
  2523. case TCL_DBREM_ENCRYPT_ANY:
  2524. /* Make sure we have an arg to check against! */
  2525. if (i >= objc) {
  2526. Tcl_WrongNumArgs(interp, 2, objv,
  2527. "?-encryptany passwd?");
  2528. result = TCL_ERROR;
  2529. break;
  2530. }
  2531. passwd = Tcl_GetStringFromObj(objv[i