PageRenderTime 59ms 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

Large files files are truncated, but you can click here to view the full 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 =

Large files files are truncated, but you can click here to view the full file