/TclFrameWork/src/bDb/tcl_db_pkg.c
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
- /*-
- * See the file LICENSE for redistribution information.
- * Copyright (c) 1999,2007 Oracle. All rights reserved.
- * $Id: tcl_db_pkg.c,v 12.51 2007/07/09 17:38:45 bostic Exp $
- */
- #include "db_config.h"
- #ifdef CONFIG_TEST
- #define DB_DBM_HSEARCH 1
- #endif
- #include "db_int.h"
- #ifdef HAVE_SYSTEM_INCLUDE_FILES
- #include <tcl.h>
- #endif
- #include "dbinc/db_page.h"
- #include "dbinc/hash.h"
- #include "dbinc/tcl_db.h"
- /* XXX we must declare global data in just one place */
- DBTCL_GLOBAL __dbtcl_global;
- /*
- * Prototypes for procedures defined later in this file:
- */
- static int berkdb_Cmd __P((ClientData, Tcl_Interp *, int,
- Tcl_Obj * CONST*));
- static int bdb_EnvOpen __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
- DBTCL_INFO *, DB_ENV **));
- static int bdb_DbOpen __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
- DBTCL_INFO *, DB **));
- static int bdb_DbRemove __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
- static int bdb_DbRename __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
- static int bdb_Version __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
- #ifdef HAVE_64BIT_TYPES
- static int bdb_SeqOpen __P((Tcl_Interp *, int, Tcl_Obj * CONST*,
- DBTCL_INFO *, DB_SEQUENCE **));
- #endif
- #ifdef CONFIG_TEST
- static int bdb_DbUpgrade __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
- static int bdb_DbVerify __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
- static int bdb_GetConfig __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
- static int bdb_Handles __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
- static int bdb_MsgType __P((Tcl_Interp *, int, Tcl_Obj * CONST*));
- static int tcl_bt_compare __P((DB *, const DBT *, const DBT *));
- static int tcl_compare_callback __P((DB *, const DBT *, const DBT *,
- Tcl_Obj *, char *));
- static void tcl_db_free __P((void *));
- static void * tcl_db_malloc __P((size_t));
- static void * tcl_db_realloc __P((void *, size_t));
- static int tcl_dup_compare __P((DB *, const DBT *, const DBT *));
- static u_int32_t tcl_h_hash __P((DB *, const void *, u_int32_t));
- #endif
- /* Db_tcl_Init --
- *
- * This is a package initialization procedure, which is called by Tcl when
- * this package is to be added to an interpreter. The name is based on the
- * name of the shared library, currently libdb_tcl-X.Y.so, which Tcl uses
- * to determine the name of this function.
- */
- int Db_tcl_Init(interp)
- Tcl_Interp *interp; /* Interpreter in which the package is
- * to be made available. */
- {
- int code;
- char pkg[12];
- snprintf(pkg, sizeof(pkg), "%d.%d", DB_VERSION_MAJOR, DB_VERSION_MINOR);
- code = Tcl_PkgProvide(interp, "Db_tcl", pkg);
- if (code != TCL_OK)
- return (code);
- (void)Tcl_CreateObjCommand(interp,
- "berkdb", (Tcl_ObjCmdProc *)berkdb_Cmd, (ClientData)0, NULL);
- /* Create shared global debugging variables */
- (void)Tcl_LinkVar(interp, "__debug_on", (char *)&__debug_on, TCL_LINK_INT);
- (void)Tcl_LinkVar(interp, "__debug_print", (char *)&__debug_print, TCL_LINK_INT);
- (void)Tcl_LinkVar(interp, "__debug_stop", (char *)&__debug_stop, TCL_LINK_INT);
- (void)Tcl_LinkVar(interp, "__debug_test", (char *)&__debug_test, TCL_LINK_INT);
- LIST_INIT(&__db_infohead);
- return (TCL_OK);
- }
- /* berkdb_cmd --
- * Implements the "berkdb" command.
- * This command supports three sub commands:
- * berkdb version - Returns a list {major minor patch}
- * berkdb env - Creates a new DB_ENV and returns a binding
- * to a new command of the form dbenvX, where X is an
- * integer starting at 0 (dbenv0, dbenv1, ...)
- * berkdb open - Creates a new DB (optionally within
- * the given environment. Returns a binding to a new
- * command of the form dbX, where X is an integer
- * starting at 0 (db0, db1, ...)
- */
- #ifdef BDB_ENV_FROM_APPS
- DB_ENV* glb_pDbEnv = NULL;
- #endif // BDB_ENV_FROM_APPS
- static int berkdb_Cmd(notused, interp, objc, objv)
- ClientData notused; /* Not used. */
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
- {
- static const char *berkdbcmds[] = {
- #ifdef CONFIG_TEST
- "dbverify",
- "getconfig",
- "handles",
- "msgtype",
- "upgrade",
- #endif
- "dbremove",
- "dbrename",
- "env",
- "envremove",
- "open",
- #ifdef HAVE_64BIT_TYPES
- "sequence",
- #endif
- "version",
- #ifdef CONFIG_TEST
- /* All below are compatibility functions */
- "hcreate", "hsearch", "hdestroy",
- "dbminit", "fetch", "store",
- "delete", "firstkey", "nextkey",
- "ndbm_open", "dbmclose",
- #endif
- /* All below are convenience functions */
- "rand", "random_int", "srand",
- "debug_check",
- NULL
- };
- /*
- * All commands enums below ending in X are compatibility
- */
- enum berkdbcmds {
- #ifdef CONFIG_TEST
- BDB_DBVERIFY,
- BDB_GETCONFIG,
- BDB_HANDLES,
- BDB_MSGTYPE,
- BDB_UPGRADE,
- #endif
- BDB_DBREMOVE,
- BDB_DBRENAME,
- BDB_ENV,
- BDB_ENVREMOVE,
- BDB_OPEN,
- #ifdef HAVE_64BIT_TYPES
- BDB_SEQUENCE,
- #endif
- BDB_VERSION,
- #ifdef CONFIG_TEST
- BDB_HCREATEX, BDB_HSEARCHX, BDB_HDESTROYX,
- BDB_DBMINITX, BDB_FETCHX, BDB_STOREX,
- BDB_DELETEX, BDB_FIRSTKEYX, BDB_NEXTKEYX,
- BDB_NDBMOPENX, BDB_DBMCLOSEX,
- #endif
- BDB_RANDX, BDB_RAND_INTX, BDB_SRANDX,
- BDB_DBGCKX
- };
- static int env_id = 0;
- static int db_id = 0;
- #ifdef HAVE_64BIT_TYPES
- static int seq_id = 0;
- #endif
- DB *dbp;
- #ifdef HAVE_64BIT_TYPES
- DB_SEQUENCE *seq;
- #endif
- #ifdef CONFIG_TEST
- DBM *ndbmp;
- static int ndbm_id = 0;
- #endif
- DBTCL_INFO *ip;
- DB_ENV *envp;
- Tcl_Obj *res;
- int cmdindex, result;
- char newname[MSG_SIZE];
- COMPQUIET(notused, NULL);
- Tcl_ResetResult(interp);
- memset(newname, 0, MSG_SIZE);
- result = TCL_OK;
- if (objc <= 1) {
- Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs");
- return (TCL_ERROR);
- }
- /* Get the command name index from the object based on the berkdbcmds
- * defined above. */
- if (Tcl_GetIndexFromObj(interp, objv[1], berkdbcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
- return (IS_HELP(objv[1]));
- res = NULL;
- switch ((enum berkdbcmds)cmdindex) {
- #ifdef CONFIG_TEST
- case BDB_DBVERIFY:
- result = bdb_DbVerify(interp, objc, objv);
- break;
- case BDB_GETCONFIG:
- result = bdb_GetConfig(interp, objc, objv);
- break;
- case BDB_HANDLES:
- result = bdb_Handles(interp, objc, objv);
- break;
- case BDB_MSGTYPE:
- result = bdb_MsgType(interp, objc, objv);
- break;
- case BDB_UPGRADE:
- result = bdb_DbUpgrade(interp, objc, objv);
- break;
- #endif
- case BDB_VERSION:
- _debug_check();
- result = bdb_Version(interp, objc, objv);
- break;
- case BDB_ENV:
- #ifdef BDB_ENV_FROM_APPS
- snprintf(newname, sizeof(newname), "env%d", env_id);
- ip = _NewInfo(interp, NULL, newname, I_ENV);
- if (ip) {
- if(glb_pDbEnv) {
- envp = glb_pDbEnv;
- ++env_id;
- (void)Tcl_CreateObjCommand(
- interp, newname, (Tcl_ObjCmdProc*)env_Cmd, (ClientData)envp, NULL);
- /* Use ip->i_name - newname is overwritten */
- res = NewStringObj(newname, strlen(newname));
- _SetInfoData(ip, envp);
- } else {
- result = bdb_EnvOpen(interp, objc, objv, ip, &envp);
- if (result == TCL_OK && envp != NULL) {
- ++env_id;
- (void)Tcl_CreateObjCommand(interp, newname,
- (Tcl_ObjCmdProc*)env_Cmd, (ClientData)envp, NULL);
- /* Use ip->i_name - newname is overwritten */
- res = NewStringObj(newname, strlen(newname));
- _SetInfoData(ip, envp);
- } else
- _DeleteInfo(ip);
- }
- } else {
- Tcl_SetResult(interp, "Could not set up info", TCL_STATIC);
- result = TCL_ERROR;
- }
- #else // BDB_ENV_FROM_APPS
- snprintf(newname, sizeof(newname), "env%d", env_id);
- ip = _NewInfo(interp, NULL, newname, I_ENV);
- if (ip != NULL) {
- result = bdb_EnvOpen(interp, objc, objv, ip, &envp);
- if (result == TCL_OK && envp != NULL) {
- ++env_id;
- (void)Tcl_CreateObjCommand(interp, newname,
- (Tcl_ObjCmdProc*)env_Cmd, (ClientData)envp, NULL);
- /* Use ip->i_name - newname is overwritten */
- res = NewStringObj(newname, strlen(newname));
- _SetInfoData(ip, envp);
- } else
- _DeleteInfo(ip);
- } else {
- Tcl_SetResult(interp, "Could not set up info", TCL_STATIC);
- result = TCL_ERROR;
- }
- #endif // BDB_ENV_FROM_APPS
- break;
- case BDB_DBREMOVE:
- result = bdb_DbRemove(interp, objc, objv);
- break;
- case BDB_DBRENAME:
- result = bdb_DbRename(interp, objc, objv);
- break;
- case BDB_ENVREMOVE:
- result = tcl_EnvRemove(interp, objc, objv, NULL, NULL);
- break;
- case BDB_OPEN:
- snprintf(newname, sizeof(newname), "db%d", db_id);
- ip = _NewInfo(interp, NULL, newname, I_DB);
- if (ip != NULL) {
- result = bdb_DbOpen(interp, objc, objv, ip, &dbp);
- if (result == TCL_OK && dbp != NULL) {
- db_id++;
- (void)Tcl_CreateObjCommand(interp, newname,
- (Tcl_ObjCmdProc *)db_Cmd,
- (ClientData)dbp, NULL);
- /* Use ip->i_name - newname is overwritten */
- res = NewStringObj(newname, strlen(newname));
- _SetInfoData(ip, dbp);
- } else
- _DeleteInfo(ip);
- } else {
- Tcl_SetResult(interp, "Could not set up info",
- TCL_STATIC);
- result = TCL_ERROR;
- }
- break;
- #ifdef HAVE_64BIT_TYPES
- case BDB_SEQUENCE:
- snprintf(newname, sizeof(newname), "seq%d", seq_id);
- ip = _NewInfo(interp, NULL, newname, I_SEQ);
- if (ip != NULL) {
- result = bdb_SeqOpen(interp, objc, objv, ip, &seq);
- if (result == TCL_OK && seq != NULL) {
- seq_id++;
- (void)Tcl_CreateObjCommand(interp, newname, (Tcl_ObjCmdProc*)seq_Cmd,
- (ClientData)seq, NULL);
- /* Use ip->i_name - newname is overwritten */
- res = NewStringObj(newname, strlen(newname));
- _SetInfoData(ip, seq);
- } else
- _DeleteInfo(ip);
- } else {
- Tcl_SetResult(interp, "Could not set up info", TCL_STATIC);
- result = TCL_ERROR;
- }
- break;
- #endif
- #ifdef CONFIG_TEST
- case BDB_HCREATEX:
- case BDB_HSEARCHX:
- case BDB_HDESTROYX:
- result = bdb_HCommand(interp, objc, objv);
- break;
- case BDB_DBMINITX:
- case BDB_DBMCLOSEX:
- case BDB_FETCHX:
- case BDB_STOREX:
- case BDB_DELETEX:
- case BDB_FIRSTKEYX:
- case BDB_NEXTKEYX:
- result = bdb_DbmCommand(interp, objc, objv, DBTCL_DBM, NULL);
- break;
- case BDB_NDBMOPENX:
- snprintf(newname, sizeof(newname), "ndbm%d", ndbm_id);
- ip = _NewInfo(interp, NULL, newname, I_NDBM);
- if (ip != NULL) {
- result = bdb_NdbmOpen(interp, objc, objv, &ndbmp);
- if (result == TCL_OK) {
- ndbm_id++;
- (void)Tcl_CreateObjCommand(interp, newname, (Tcl_ObjCmdProc*)ndbm_Cmd,
- (ClientData)ndbmp, NULL);
- /* Use ip->i_name - newname is overwritten */
- res = NewStringObj(newname, strlen(newname));
- _SetInfoData(ip, ndbmp);
- } else
- _DeleteInfo(ip);
- } else {
- Tcl_SetResult(interp, "Could not set up info", TCL_STATIC);
- result = TCL_ERROR;
- }
- break;
- #endif
- case BDB_RANDX:
- case BDB_RAND_INTX:
- case BDB_SRANDX:
- result = bdb_RandCommand(interp, objc, objv);
- break;
- case BDB_DBGCKX:
- _debug_check();
- res = Tcl_NewIntObj(0);
- break;
- }
- /* For each different arg call different function to create
- * new commands (or if version, get/return it).
- */
- if (result == TCL_OK && res != NULL)
- Tcl_SetObjResult(interp, res);
- return (result);
- }
- /* bdb_EnvOpen -
- * Implements the environment open command.
- * There are many, many options to the open command.
- * Here is the general flow:
- *
- * 1. Call db_env_create to create the env handle.
- * 2. Parse args tracking options.
- * 3. Make any pre-open setup calls necessary.
- * 4. Call DB_ENV->open to open the env.
- * 5. Return env widget handle to user.
- */
- static int bdb_EnvOpen(interp, objc, objv, ip, env)
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
- DBTCL_INFO *ip; /* Our internal info */
- DB_ENV **env; /* Environment pointer */
- {
- static const char *envopen[] = {
- #ifdef CONFIG_TEST
- "-alloc",
- "-auto_commit",
- "-cdb",
- "-cdb_alldb",
- "-client_timeout",
- "-event",
- "-lock",
- "-lock_conflict",
- "-lock_detect",
- "-lock_max_locks",
- "-lock_max_lockers",
- "-lock_max_objects",
- "-lock_timeout",
- "-log",
- "-log_filemode",
- "-log_buffer",
- "-log_inmemory",
- "-log_max",
- "-log_regionmax",
- "-log_remove",
- "-mpool_max_openfd",
- "-mpool_max_write",
- "-mpool_mmap_size",
- "-mpool_nommap",
- "-multiversion",
- "-overwrite",
- "-region_init",
- "-rep",
- "-rep_client",
- "-rep_lease",
- "-rep_master",
- "-rep_transport",
- "-server",
- "-server_timeout",
- "-set_intermediate_dir",
- "-snapshot",
- "-thread",
- "-time_notgranted",
- "-txn_nowait",
- "-txn_timeout",
- "-txn_timestamp",
- "-verbose",
- "-wrnosync",
- #endif
- "-cachesize",
- "-cache_max",
- "-create",
- "-data_dir",
- "-encryptaes",
- "-encryptany",
- "-errfile",
- "-errpfx",
- "-home",
- "-log_dir",
- "-mode",
- "-private",
- "-recover",
- "-recover_fatal",
- "-register",
- "-shm_key",
- "-system_mem",
- "-tmp_dir",
- "-txn",
- "-txn_max",
- "-use_environ",
- "-use_environ_root",
- NULL
- };
- /*
- * !!!
- * These have to be in the same order as the above,
- * which is close to but not quite alphabetical.
- */
- enum envopen {
- #ifdef CONFIG_TEST
- ENV_ALLOC,
- ENV_AUTO_COMMIT,
- ENV_CDB,
- ENV_CDB_ALLDB,
- ENV_CLIENT_TO,
- ENV_EVENT,
- ENV_LOCK,
- ENV_CONFLICT,
- ENV_DETECT,
- ENV_LOCK_MAX_LOCKS,
- ENV_LOCK_MAX_LOCKERS,
- ENV_LOCK_MAX_OBJECTS,
- ENV_LOCK_TIMEOUT,
- ENV_LOG,
- ENV_LOG_FILEMODE,
- ENV_LOG_BUFFER,
- ENV_LOG_INMEMORY,
- ENV_LOG_MAX,
- ENV_LOG_REGIONMAX,
- ENV_LOG_REMOVE,
- ENV_MPOOL_MAX_OPENFD,
- ENV_MPOOL_MAX_WRITE,
- ENV_MPOOL_MMAP_SIZE,
- ENV_MPOOL_NOMMAP,
- ENV_MULTIVERSION,
- ENV_OVERWRITE,
- ENV_REGION_INIT,
- ENV_REP,
- ENV_REP_CLIENT,
- ENV_REP_LEASE,
- ENV_REP_MASTER,
- ENV_REP_TRANSPORT,
- ENV_SERVER,
- ENV_SERVER_TO,
- ENV_SET_INTERMEDIATE_DIR,
- ENV_SNAPSHOT,
- ENV_THREAD,
- ENV_TIME_NOTGRANTED,
- ENV_TXN_NOWAIT,
- ENV_TXN_TIMEOUT,
- ENV_TXN_TIME,
- ENV_VERBOSE,
- ENV_WRNOSYNC,
- #endif
- ENV_CACHESIZE,
- ENV_CACHE_MAX,
- ENV_CREATE,
- ENV_DATA_DIR,
- ENV_ENCRYPT_AES,
- ENV_ENCRYPT_ANY,
- ENV_ERRFILE,
- ENV_ERRPFX,
- ENV_HOME,
- ENV_LOG_DIR,
- ENV_MODE,
- ENV_PRIVATE,
- ENV_RECOVER,
- ENV_RECOVER_FATAL,
- ENV_REGISTER,
- ENV_SHM_KEY,
- ENV_SYSTEM_MEM,
- ENV_TMP_DIR,
- ENV_TXN,
- ENV_TXN_MAX,
- ENV_USE_ENVIRON,
- ENV_USE_ENVIRON_ROOT
- };
- Tcl_Obj **myobjv;
- u_int32_t cr_flags, gbytes, bytes, logbufset, logmaxset;
- u_int32_t open_flags, rep_flags, set_flags, uintarg;
- int i, mode, myobjc, ncaches, optindex, result, ret;
- long client_to, server_to, shm;
- char *arg, *home, *passwd, *server;
- #ifdef CONFIG_TEST
- Tcl_Obj **myobjv1;
- time_t timestamp;
- long v;
- u_int32_t detect;
- u_int8_t *conflicts;
- int intarg, intarg2, j, nmodes, temp;
- #endif
- result = TCL_OK;
- mode = 0;
- rep_flags = set_flags = cr_flags = 0;
- home = NULL;
- /* XXX
- * If/when our Tcl interface becomes thread-safe, we should enable
- * DB_THREAD here in all cases. For now, we turn it on later in this
- * function, and only when we're in testing and we specify the
- * -thread flag, so that we can exercise MUTEX_THREAD_LOCK cases.
- *
- * In order to become truly thread-safe, we need to look at making sure
- * DBTCL_INFO structs are safe to share across threads (they're not
- * mutex-protected) before we declare the Tcl interface thread-safe.
- * Meanwhile, there's no strong reason to enable DB_THREAD when not
- * testing. */
- open_flags = 0;
- logmaxset = logbufset = 0;
- if (objc <= 2) {
- Tcl_WrongNumArgs(interp, 2, objv, "?args?");
- return (TCL_ERROR);
- }
- /* Server code must go before the call to db_env_create. */
- server = NULL;
- server_to = client_to = 0;
- i = 2;
- while (i < objc) {
- if (Tcl_GetIndexFromObj(interp, objv[i++], envopen, "option",
- TCL_EXACT, &optindex) != TCL_OK) {
- Tcl_ResetResult(interp);
- continue;
- }
- #ifdef CONFIG_TEST
- switch ((enum envopen)optindex) {
- case ENV_SERVER:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-server hostname");
- result = TCL_ERROR;
- break;
- }
- FLD_SET(cr_flags, DB_RPCCLIENT);
- server = Tcl_GetStringFromObj(objv[i++], NULL);
- break;
- case ENV_SERVER_TO:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-server_to secs");
- result = TCL_ERROR;
- break;
- }
- FLD_SET(cr_flags, DB_RPCCLIENT);
- result = Tcl_GetLongFromObj(interp, objv[i++],
- &server_to);
- break;
- case ENV_CLIENT_TO:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-client_to secs");
- result = TCL_ERROR;
- break;
- }
- FLD_SET(cr_flags, DB_RPCCLIENT);
- result = Tcl_GetLongFromObj(interp, objv[i++],
- &client_to);
- break;
- default:
- break;
- }
- #endif
- }
- if (result != TCL_OK)
- return (TCL_ERROR);
- ret = db_env_create(env, cr_flags);
- if (ret)
- return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "db_env_create"));
- /*
- * From here on we must 'goto error' in order to clean up the
- * env from db_env_create.
- */
- (*env)->set_errpfx((*env), ip->i_name);
- (*env)->set_errcall((*env), _ErrorFunc);
- if (server != NULL &&
- (ret = (*env)->set_rpc_server((*env), NULL, server,
- client_to, server_to, 0)) != 0) {
- result = TCL_ERROR;
- goto error;
- }
- /* Hang our info pointer on the env handle, so we can do callbacks. */
- (*env)->app_private = ip;
- /*
- * Get the command name index from the object based on the bdbcmds
- * defined above.
- */
- i = 2;
- while (i < objc) {
- Tcl_ResetResult(interp);
- if (Tcl_GetIndexFromObj(interp, objv[i], envopen, "option",
- TCL_EXACT, &optindex) != TCL_OK) {
- result = IS_HELP(objv[i]);
- goto error;
- }
- i++;
- switch ((enum envopen)optindex) {
- #ifdef CONFIG_TEST
- case ENV_SERVER:
- case ENV_SERVER_TO:
- case ENV_CLIENT_TO:
- /*
- * Already handled these, skip them and their arg.
- */
- i++;
- break;
- case ENV_ALLOC:
- /*
- * Use a Tcl-local alloc and free function so that
- * we're sure to test whether we use umalloc/ufree in
- * the right places.
- */
- (void)(*env)->set_alloc(*env,
- tcl_db_malloc, tcl_db_realloc, tcl_db_free);
- break;
- case ENV_AUTO_COMMIT:
- FLD_SET(set_flags, DB_AUTO_COMMIT);
- break;
- case ENV_CDB:
- FLD_SET(open_flags, DB_INIT_CDB | DB_INIT_MPOOL);
- break;
- case ENV_CDB_ALLDB:
- FLD_SET(set_flags, DB_CDB_ALLDB);
- break;
- case ENV_LOCK:
- FLD_SET(open_flags, DB_INIT_LOCK | DB_INIT_MPOOL);
- break;
- case ENV_CONFLICT:
- /*
- * Get conflict list. List is:
- * {nmodes {matrix}}
- *
- * Where matrix must be nmodes*nmodes big.
- * Set up conflicts array to pass.
- */
- result = Tcl_ListObjGetElements(interp, objv[i],
- &myobjc, &myobjv);
- if (result == TCL_OK)
- i++;
- else
- break;
- if (myobjc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-lock_conflict {nmodes {matrix}}?");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetIntFromObj(interp, myobjv[0], &nmodes);
- if (result != TCL_OK)
- break;
- result = Tcl_ListObjGetElements(interp, myobjv[1],
- &myobjc, &myobjv1);
- if (myobjc != (nmodes * nmodes)) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-lock_conflict {nmodes {matrix}}?");
- result = TCL_ERROR;
- break;
- }
- ret = __os_malloc(*env, sizeof(u_int8_t) *
- (size_t)nmodes * (size_t)nmodes, &conflicts);
- if (ret != 0) {
- result = TCL_ERROR;
- break;
- }
- for (j = 0; j < myobjc; j++) {
- result = Tcl_GetIntFromObj(interp, myobjv1[j],
- &temp);
- conflicts[j] = temp;
- if (result != TCL_OK) {
- __os_free(NULL, conflicts);
- break;
- }
- }
- _debug_check();
- ret = (*env)->set_lk_conflicts(*env,
- (u_int8_t *)conflicts, nmodes);
- __os_free(NULL, conflicts);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_lk_conflicts");
- break;
- case ENV_DETECT:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-lock_detect policy?");
- result = TCL_ERROR;
- break;
- }
- arg = Tcl_GetStringFromObj(objv[i++], NULL);
- if (strcmp(arg, "default") == 0)
- detect = DB_LOCK_DEFAULT;
- else if (strcmp(arg, "expire") == 0)
- detect = DB_LOCK_EXPIRE;
- else if (strcmp(arg, "maxlocks") == 0)
- detect = DB_LOCK_MAXLOCKS;
- else if (strcmp(arg, "maxwrites") == 0)
- detect = DB_LOCK_MAXWRITE;
- else if (strcmp(arg, "minlocks") == 0)
- detect = DB_LOCK_MINLOCKS;
- else if (strcmp(arg, "minwrites") == 0)
- detect = DB_LOCK_MINWRITE;
- else if (strcmp(arg, "oldest") == 0)
- detect = DB_LOCK_OLDEST;
- else if (strcmp(arg, "youngest") == 0)
- detect = DB_LOCK_YOUNGEST;
- else if (strcmp(arg, "random") == 0)
- detect = DB_LOCK_RANDOM;
- else {
- Tcl_AddErrorInfo(interp,
- "lock_detect: illegal policy");
- result = TCL_ERROR;
- break;
- }
- _debug_check();
- ret = (*env)->set_lk_detect(*env, detect);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "lock_detect");
- break;
- case ENV_EVENT:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-event eventproc");
- result = TCL_ERROR;
- break;
- }
- result = tcl_EventNotify(interp, *env, objv[i++], ip);
- break;
- case ENV_LOCK_MAX_LOCKS:
- case ENV_LOCK_MAX_LOCKERS:
- case ENV_LOCK_MAX_OBJECTS:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-lock_max max?");
- result = TCL_ERROR;
- break;
- }
- result = _GetUInt32(interp, objv[i++], &uintarg);
- if (result == TCL_OK) {
- _debug_check();
- switch ((enum envopen)optindex) {
- case ENV_LOCK_MAX_LOCKS:
- ret = (*env)->set_lk_max_locks(*env,
- uintarg);
- break;
- case ENV_LOCK_MAX_LOCKERS:
- ret = (*env)->set_lk_max_lockers(*env,
- uintarg);
- break;
- case ENV_LOCK_MAX_OBJECTS:
- ret = (*env)->set_lk_max_objects(*env,
- uintarg);
- break;
- default:
- break;
- }
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "lock_max");
- }
- break;
- case ENV_TXN_NOWAIT:
- FLD_SET(set_flags, DB_TXN_NOWAIT);
- break;
- case ENV_TXN_TIME:
- case ENV_TXN_TIMEOUT:
- case ENV_LOCK_TIMEOUT:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-txn_timestamp time?");
- result = TCL_ERROR;
- break;
- }
- if ((result = Tcl_GetLongFromObj(
- interp, objv[i++], &v)) != TCL_OK)
- break;
- timestamp = (time_t)v;
- _debug_check();
- if ((enum envopen)optindex == ENV_TXN_TIME)
- ret =
- (*env)->set_tx_timestamp(*env, ×tamp);
- else
- ret = (*env)->set_timeout(*env,
- (db_timeout_t)timestamp,
- (enum envopen)optindex == ENV_TXN_TIMEOUT ?
- DB_SET_TXN_TIMEOUT : DB_SET_LOCK_TIMEOUT);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "txn_timestamp");
- break;
- case ENV_LOG:
- FLD_SET(open_flags, DB_INIT_LOG | DB_INIT_MPOOL);
- break;
- case ENV_LOG_BUFFER:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-log_buffer size?");
- result = TCL_ERROR;
- break;
- }
- result = _GetUInt32(interp, objv[i++], &uintarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*env)->set_lg_bsize(*env, uintarg);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "log_bsize");
- logbufset = 1;
- if (logmaxset) {
- _debug_check();
- ret = (*env)->set_lg_max(*env,
- logmaxset);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "log_max");
- logmaxset = 0;
- logbufset = 0;
- }
- }
- break;
- case ENV_LOG_FILEMODE:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-log_filemode mode?");
- result = TCL_ERROR;
- break;
- }
- result = _GetUInt32(interp, objv[i++], &uintarg);
- if (result == TCL_OK) {
- _debug_check();
- ret =
- (*env)->set_lg_filemode(*env, (int)uintarg);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "log_filemode");
- }
- break;
- case ENV_LOG_INMEMORY:
- FLD_SET(set_flags, DB_LOG_INMEMORY);
- break;
- case ENV_LOG_MAX:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-log_max max?");
- result = TCL_ERROR;
- break;
- }
- result = _GetUInt32(interp, objv[i++], &uintarg);
- if (result == TCL_OK && logbufset) {
- _debug_check();
- ret = (*env)->set_lg_max(*env, uintarg);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "log_max");
- logbufset = 0;
- } else
- logmaxset = uintarg;
- break;
- case ENV_LOG_REGIONMAX:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-log_regionmax size?");
- result = TCL_ERROR;
- break;
- }
- result = _GetUInt32(interp, objv[i++], &uintarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*env)->set_lg_regionmax(*env, uintarg);
- result =
- _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "log_regionmax");
- }
- break;
- case ENV_LOG_REMOVE:
- FLD_SET(set_flags, DB_LOG_AUTOREMOVE);
- break;
- case ENV_MPOOL_MAX_OPENFD:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-mpool_max_openfd fd_count?");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*env)->set_mp_max_openfd(*env, intarg);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "mpool_max_openfd");
- }
- break;
- case ENV_MPOOL_MAX_WRITE:
- result = Tcl_ListObjGetElements(interp, objv[i],
- &myobjc, &myobjv);
- if (result == TCL_OK)
- i++;
- else
- break;
- if (myobjc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-mpool_max_write {nwrite nsleep}?");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetIntFromObj(interp, myobjv[0], &intarg);
- if (result != TCL_OK)
- break;
- result = Tcl_GetIntFromObj(interp, myobjv[1], &intarg2);
- if (result != TCL_OK)
- break;
- _debug_check();
- ret = (*env)->set_mp_max_write(
- *env, intarg, (db_timeout_t)intarg2);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_mp_max_write");
- break;
- case ENV_MPOOL_MMAP_SIZE:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-mpool_mmap_size size?");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*env)->set_mp_mmapsize(*env,
- (size_t)intarg);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "mpool_mmap_size");
- }
- break;
- case ENV_MPOOL_NOMMAP:
- FLD_SET(set_flags, DB_NOMMAP);
- break;
- case ENV_MULTIVERSION:
- FLD_SET(set_flags, DB_MULTIVERSION);
- break;
- case ENV_OVERWRITE:
- FLD_SET(set_flags, DB_OVERWRITE);
- break;
- case ENV_REGION_INIT:
- _debug_check();
- ret = (*env)->set_flags(*env, DB_REGION_INIT, 1);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "region_init");
- break;
- case ENV_SET_INTERMEDIATE_DIR:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp,
- 2, objv, "?-set_intermediate_dir mode?");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*env)->
- set_intermediate_dir(*env, intarg, 0);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "set_intermediate_dir");
- }
- break;
- case ENV_REP:
- FLD_SET(open_flags, DB_INIT_REP);
- break;
- case ENV_REP_CLIENT:
- rep_flags = DB_REP_CLIENT;
- FLD_SET(open_flags, DB_INIT_REP);
- break;
- case ENV_REP_MASTER:
- rep_flags = DB_REP_MASTER;
- FLD_SET(open_flags, DB_INIT_REP);
- break;
- case ENV_REP_LEASE:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-rep_lease {nsites timeout clockskew}");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_ListObjGetElements(interp, objv[i],
- &myobjc, &myobjv);
- if (result == TCL_OK)
- i++;
- else
- break;
- result = tcl_RepLease(interp, myobjc, myobjv, *env);
- if (result == TCL_OK)
- FLD_SET(open_flags, DB_INIT_REP);
- break;
- case ENV_REP_TRANSPORT:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-rep_transport {envid sendproc}");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_ListObjGetElements(interp, objv[i],
- &myobjc, &myobjv);
- if (result == TCL_OK)
- i++;
- else
- break;
- result = tcl_RepTransport(interp, myobjc, myobjv,
- *env, ip);
- if (result == TCL_OK)
- FLD_SET(open_flags, DB_INIT_REP);
- break;
- case ENV_SNAPSHOT:
- FLD_SET(set_flags, DB_TXN_SNAPSHOT);
- break;
- case ENV_THREAD:
- /* Enable DB_THREAD when specified in testing. */
- FLD_SET(open_flags, DB_THREAD);
- break;
- case ENV_TIME_NOTGRANTED:
- FLD_SET(set_flags, DB_TIME_NOTGRANTED);
- break;
- case ENV_VERBOSE:
- result = Tcl_ListObjGetElements(interp, objv[i],
- &myobjc, &myobjv);
- if (result == TCL_OK)
- i++;
- else
- break;
- if (myobjc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-verbose {which on|off}?");
- result = TCL_ERROR;
- break;
- }
- result = tcl_EnvVerbose(interp, *env,
- myobjv[0], myobjv[1]);
- break;
- case ENV_WRNOSYNC:
- FLD_SET(set_flags, DB_TXN_WRITE_NOSYNC);
- break;
- #endif
- case ENV_TXN:
- FLD_SET(open_flags, DB_INIT_LOCK |
- DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN);
- /* Make sure we have an arg to check against! */
- while (i < objc) {
- arg = Tcl_GetStringFromObj(objv[i], NULL);
- if (strcmp(arg, "nosync") == 0) {
- FLD_SET(set_flags, DB_TXN_NOSYNC);
- i++;
- } else if (strcmp(arg, "snapshot") == 0) {
- FLD_SET(set_flags, DB_TXN_SNAPSHOT);
- i++;
- } else
- break;
- }
- break;
- case ENV_CREATE:
- FLD_SET(open_flags, DB_CREATE | DB_INIT_MPOOL);
- break;
- case ENV_ENCRYPT_AES:
- /* Make sure we have an arg to check against! */
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-encryptaes passwd?");
- result = TCL_ERROR;
- break;
- }
- passwd = Tcl_GetStringFromObj(objv[i++], NULL);
- _debug_check();
- ret = (*env)->set_encrypt(*env, passwd, DB_ENCRYPT_AES);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_encrypt");
- break;
- case ENV_ENCRYPT_ANY:
- /* Make sure we have an arg to check against! */
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-encryptany passwd?");
- result = TCL_ERROR;
- break;
- }
- passwd = Tcl_GetStringFromObj(objv[i++], NULL);
- _debug_check();
- ret = (*env)->set_encrypt(*env, passwd, 0);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_encrypt");
- break;
- case ENV_HOME:
- /* Make sure we have an arg to check against! */
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-home dir?");
- result = TCL_ERROR;
- break;
- }
- home = Tcl_GetStringFromObj(objv[i++], NULL);
- break;
- case ENV_MODE:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-mode mode?");
- result = TCL_ERROR;
- break;
- }
- /*
- * Don't need to check result here because
- * if TCL_ERROR, the error message is already
- * set up, and we'll bail out below. If ok,
- * the mode is set and we go on.
- */
- result = Tcl_GetIntFromObj(interp, objv[i++], &mode);
- break;
- case ENV_PRIVATE:
- FLD_SET(open_flags, DB_PRIVATE | DB_INIT_MPOOL);
- break;
- case ENV_RECOVER:
- FLD_SET(open_flags, DB_RECOVER);
- break;
- case ENV_RECOVER_FATAL:
- FLD_SET(open_flags, DB_RECOVER_FATAL);
- break;
- case ENV_REGISTER:
- FLD_SET(open_flags, DB_REGISTER);
- break;
- case ENV_SYSTEM_MEM:
- FLD_SET(open_flags, DB_SYSTEM_MEM);
- break;
- case ENV_USE_ENVIRON_ROOT:
- FLD_SET(open_flags, DB_USE_ENVIRON_ROOT);
- break;
- case ENV_USE_ENVIRON:
- FLD_SET(open_flags, DB_USE_ENVIRON);
- break;
- case ENV_CACHESIZE:
- result = Tcl_ListObjGetElements(interp, objv[i],
- &myobjc, &myobjv);
- if (result == TCL_OK)
- i++;
- else
- break;
- if (myobjc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-cachesize {gbytes bytes ncaches}?");
- result = TCL_ERROR;
- break;
- }
- result = _GetUInt32(interp, myobjv[0], &gbytes);
- if (result != TCL_OK)
- break;
- result = _GetUInt32(interp, myobjv[1], &bytes);
- if (result != TCL_OK)
- break;
- result = Tcl_GetIntFromObj(interp, myobjv[2], &ncaches);
- if (result != TCL_OK)
- break;
- _debug_check();
- ret = (*env)->set_cachesize(*env, gbytes, bytes,
- ncaches);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_cachesize");
- break;
- case ENV_CACHE_MAX:
- result = Tcl_ListObjGetElements(interp, objv[i],
- &myobjc, &myobjv);
- if (result == TCL_OK)
- i++;
- else
- break;
- if (myobjc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-cache_max {gbytes bytes}?");
- result = TCL_ERROR;
- break;
- }
- result = _GetUInt32(interp, myobjv[0], &gbytes);
- if (result != TCL_OK)
- break;
- result = _GetUInt32(interp, myobjv[1], &bytes);
- if (result != TCL_OK)
- break;
- _debug_check();
- ret = (*env)->set_cache_max(*env, gbytes, bytes);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_cache_max");
- break;
- case ENV_SHM_KEY:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-shm_key key?");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetLongFromObj(interp, objv[i++], &shm);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*env)->set_shm_key(*env, shm);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "shm_key");
- }
- break;
- case ENV_TXN_MAX:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-txn_max max?");
- result = TCL_ERROR;
- break;
- }
- result = _GetUInt32(interp, objv[i++], &uintarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*env)->set_tx_max(*env, uintarg);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "txn_max");
- }
- break;
- case ENV_ERRFILE:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-errfile file");
- result = TCL_ERROR;
- break;
- }
- arg = Tcl_GetStringFromObj(objv[i++], NULL);
- tcl_EnvSetErrfile(interp, *env, ip, arg);
- break;
- case ENV_ERRPFX:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-errpfx prefix");
- result = TCL_ERROR;
- break;
- }
- arg = Tcl_GetStringFromObj(objv[i++], NULL);
- _debug_check();
- result = tcl_EnvSetErrpfx(interp, *env, ip, arg);
- break;
- case ENV_DATA_DIR:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-data_dir dir");
- result = TCL_ERROR;
- break;
- }
- arg = Tcl_GetStringFromObj(objv[i++], NULL);
- _debug_check();
- ret = (*env)->set_data_dir(*env, arg);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_data_dir");
- break;
- case ENV_LOG_DIR:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-log_dir dir");
- result = TCL_ERROR;
- break;
- }
- arg = Tcl_GetStringFromObj(objv[i++], NULL);
- _debug_check();
- ret = (*env)->set_lg_dir(*env, arg);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_lg_dir");
- break;
- case ENV_TMP_DIR:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-tmp_dir dir");
- result = TCL_ERROR;
- break;
- }
- arg = Tcl_GetStringFromObj(objv[i++], NULL);
- _debug_check();
- ret = (*env)->set_tmp_dir(*env, arg);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_tmp_dir");
- break;
- }
- /*
- * If, at any time, parsing the args we get an error,
- * bail out and return.
- */
- if (result != TCL_OK)
- goto error;
- }
- /*
- * We have to check this here. We want to set the log buffer
- * size first, if it is specified. So if the user did so,
- * then we took care of it above. But, if we get out here and
- * logmaxset is non-zero, then they set the log_max without
- * resetting the log buffer size, so we now have to do the
- * call to set_lg_max, since we didn't do it above.
- */
- if (logmaxset) {
- _debug_check();
- ret = (*env)->set_lg_max(*env, (u_int32_t)logmaxset);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "log_max");
- }
- if (result != TCL_OK)
- goto error;
- if (set_flags) {
- ret = (*env)->set_flags(*env, set_flags, 1);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_flags");
- if (result == TCL_ERROR)
- goto error;
- /*
- * If we are successful, clear the result so that the
- * return from set_flags isn't part of the result.
- */
- Tcl_ResetResult(interp);
- }
- /*
- * When we get here, we have already parsed all of our args
- * and made all our calls to set up the environment. Everything
- * is okay so far, no errors, if we get here.
- *
- * Now open the environment.
- */
- _debug_check();
- ret = (*env)->open(*env, home, open_flags, mode);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env open");
- if (rep_flags != 0 && result == TCL_OK) {
- _debug_check();
- ret = (*env)->rep_start(*env, NULL, rep_flags);
- result = _ReturnSetup(interp,
- ret, DB_RETOK_STD(ret), "rep_start");
- }
- error: if (result == TCL_ERROR) {
- if (ip->i_err && ip->i_err != stdout && ip->i_err != stderr) {
- (void)fclose(ip->i_err);
- ip->i_err = NULL;
- }
- (void)(*env)->close(*env, 0);
- *env = NULL;
- }
- return (result);
- }
- /*
- * bdb_DbOpen --
- * Implements the "db_create/db_open" command.
- * There are many, many options to the open command.
- * Here is the general flow:
- *
- * 0. Preparse args to determine if we have -env.
- * 1. Call db_create to create the db handle.
- * 2. Parse args tracking options.
- * 3. Make any pre-open setup calls necessary.
- * 4. Call DB->open to open the database.
- * 5. Return db widget handle to user.
- */
- static int
- bdb_DbOpen(interp, objc, objv, ip, dbp)
- Tcl_Interp *interp; /* Interpreter */
- int objc; /* How many arguments? */
- Tcl_Obj *CONST objv[]; /* The argument objects */
- DBTCL_INFO *ip; /* Our internal info */
- DB **dbp; /* DB handle */
- {
- static const char *bdbenvopen[] = {
- "-env", NULL
- };
- enum bdbenvopen {
- TCL_DB_ENV0
- };
- static const char *bdbopen[] = {
- #ifdef CONFIG_TEST
- "-btcompare",
- "-dupcompare",
- "-hashcompare",
- "-hashproc",
- "-lorder",
- "-minkey",
- "-nommap",
- "-notdurable",
- "-read_uncommitted",
- "-revsplitoff",
- "-test",
- "-thread",
- #endif
- "-auto_commit",
- "-btree",
- "-cachesize",
- "-chksum",
- "-create",
- "-delim",
- "-dup",
- "-dupsort",
- "-encrypt",
- "-encryptaes",
- "-encryptany",
- "-env",
- "-errfile",
- "-errpfx",
- "-excl",
- "-extent",
- "-ffactor",
- "-hash",
- "-inorder",
- "-len",
- "-maxsize",
- "-mode",
- "-multiversion",
- "-nelem",
- "-pad",
- "-pagesize",
- "-queue",
- "-rdonly",
- "-recno",
- "-recnum",
- "-renumber",
- "-snapshot",
- "-source",
- "-truncate",
- "-txn",
- "-unknown",
- "--",
- NULL
- };
- enum bdbopen {
- #ifdef CONFIG_TEST
- TCL_DB_BTCOMPARE,
- TCL_DB_DUPCOMPARE,
- TCL_DB_HASHCOMPARE,
- TCL_DB_HASHPROC,
- TCL_DB_LORDER,
- TCL_DB_MINKEY,
- TCL_DB_NOMMAP,
- TCL_DB_NOTDURABLE,
- TCL_DB_READ_UNCOMMITTED,
- TCL_DB_REVSPLIT,
- TCL_DB_TEST,
- TCL_DB_THREAD,
- #endif
- TCL_DB_AUTO_COMMIT,
- TCL_DB_BTREE,
- TCL_DB_CACHESIZE,
- TCL_DB_CHKSUM,
- TCL_DB_CREATE,
- TCL_DB_DELIM,
- TCL_DB_DUP,
- TCL_DB_DUPSORT,
- TCL_DB_ENCRYPT,
- TCL_DB_ENCRYPT_AES,
- TCL_DB_ENCRYPT_ANY,
- TCL_DB_ENV,
- TCL_DB_ERRFILE,
- TCL_DB_ERRPFX,
- TCL_DB_EXCL,
- TCL_DB_EXTENT,
- TCL_DB_FFACTOR,
- TCL_DB_HASH,
- TCL_DB_INORDER,
- TCL_DB_LEN,
- TCL_DB_MAXSIZE,
- TCL_DB_MODE,
- TCL_DB_MULTIVERSION,
- TCL_DB_NELEM,
- TCL_DB_PAD,
- TCL_DB_PAGESIZE,
- TCL_DB_QUEUE,
- TCL_DB_RDONLY,
- TCL_DB_RECNO,
- TCL_DB_RECNUM,
- TCL_DB_RENUMBER,
- TCL_DB_SNAPSHOT,
- TCL_DB_SOURCE,
- TCL_DB_TRUNCATE,
- TCL_DB_TXN,
- TCL_DB_UNKNOWN,
- TCL_DB_ENDARG
- };
- DBTCL_INFO *envip, *errip;
- DB_TXN *txn;
- DBTYPE type;
- DB_ENV *envp;
- Tcl_Obj **myobjv;
- u_int32_t gbytes, bytes, open_flags, set_flags, uintarg;
- int endarg, i, intarg, mode, myobjc, ncaches;
- int optindex, result, ret, set_err, set_pfx, subdblen;
- u_char *subdbtmp;
- char *arg, *db, *passwd, *subdb, msg[MSG_SIZE];
- type = DB_UNKNOWN;
- endarg = mode = set_err = set_flags = set_pfx = 0;
- result = TCL_OK;
- subdbtmp = NULL;
- db = subdb = NULL;
- /*
- * XXX
- * If/when our Tcl interface becomes thread-safe, we should enable
- * DB_THREAD here in all cases. For now, we turn it on later in this
- * function, and only when we're in testing and we specify the
- * -thread flag, so that we can exercise MUTEX_THREAD_LOCK cases.
- *
- * In order to become truly thread-safe, we need to look at making sure
- * DBTCL_INFO structs are safe to share across threads (they're not
- * mutex-protected) before we declare the Tcl interface thread-safe.
- * Meanwhile, there's no strong reason to enable DB_THREAD when not
- * testing.
- */
- open_flags = 0;
- envp = NULL;
- txn = NULL;
- if (objc < 2) {
- Tcl_WrongNumArgs(interp, 2, objv, "?args?");
- return (TCL_ERROR);
- }
- /*
- * We must first parse for the environment flag, since that
- * is needed for db_create. Then create the db handle.
- */
- i = 2;
- while (i < objc) {
- if (Tcl_GetIndexFromObj(interp, objv[i++], bdbenvopen,
- "option", TCL_EXACT, &optindex) != TCL_OK) {
- /*
- * Reset the result so we don't get
- * an errant error message if there is another error.
- */
- Tcl_ResetResult(interp);
- continue;
- }
- switch ((enum bdbenvopen)optindex) {
- case TCL_DB_ENV0:
- arg = Tcl_GetStringFromObj(objv[i], NULL);
- envp = NAME_TO_ENV(arg);
- if (envp == NULL) {
- Tcl_SetResult(interp,
- "db open: illegal environment", TCL_STATIC);
- return (TCL_ERROR);
- }
- }
- break;
- }
- /*
- * Create the db handle before parsing the args
- * since we'll be modifying the database options as we parse.
- */
- ret = db_create(dbp, envp, 0);
- if (ret)
- return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "db_create"));
- /* Hang our info pointer on the DB handle, so we can do callbacks. */
- (*dbp)->api_internal = ip;
- /*
- * XXX
- * Remove restriction if error handling not tied to env.
- *
- * The DB->set_err* functions overwrite the environment. So, if
- * we are using an env, don't overwrite it; if not using an env,
- * then configure error handling.
- */
- if (envp == NULL) {
- (*dbp)->set_errpfx((*dbp), ip->i_name);
- (*dbp)->set_errcall((*dbp), _ErrorFunc);
- }
- envip = _PtrToInfo(envp); /* XXX */
- /*
- * If we are using an env, we keep track of err info in the env's ip.
- * Otherwise use the DB's ip.
- */
- if (envip)
- errip = envip;
- else
- errip = ip;
- /*
- * Get the option name index from the object based on the args
- * defined above.
- */
- i = 2;
- while (i < objc) {
- Tcl_ResetResult(interp);
- if (Tcl_GetIndexFromObj(interp, objv[i], bdbopen, "option",
- TCL_EXACT, &optindex) != TCL_OK) {
- arg = Tcl_GetStringFromObj(objv[i], NULL);
- if (arg[0] == '-') {
- result = IS_HELP(objv[i]);
- goto error;
- } else
- Tcl_ResetResult(interp);
- break;
- }
- i++;
- switch ((enum bdbopen)optindex) {
- #ifdef CONFIG_TEST
- case TCL_DB_BTCOMPARE:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-btcompare compareproc");
- result = TCL_ERROR;
- break;
- }
- /*
- * Store the object containing the procedure name.
- * We don't need to crack it out now--we'll want
- * to bundle it up to pass into Tcl_EvalObjv anyway.
- * Tcl's object refcounting will--I hope--take care
- * of the memory management here.
- */
- ip->i_compare = objv[i++];
- Tcl_IncrRefCount(ip->i_compare);
- _debug_check();
- ret = (*dbp)->set_bt_compare(*dbp, tcl_bt_compare);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_bt_compare");
- break;
- case TCL_DB_DUPCOMPARE:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-dupcompare compareproc");
- result = TCL_ERROR;
- break;
- }
- /*
- * Store the object containing the procedure name.
- * See TCL_DB_BTCOMPARE.
- */
- ip->i_dupcompare = objv[i++];
- Tcl_IncrRefCount(ip->i_dupcompare);
- _debug_check();
- ret = (*dbp)->set_dup_compare(*dbp, tcl_dup_compare);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_dup_compare");
- break;
- case TCL_DB_HASHCOMPARE:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-hashcompare compareproc");
- result = TCL_ERROR;
- break;
- }
- /*
- * Store the object containing the procedure name.
- * We don't need to crack it out now--we'll want
- * to bundle it up to pass into Tcl_EvalObjv anyway.
- * Tcl's object refcounting will--I hope--take care
- * of the memory management here.
- */
- ip->i_compare = objv[i++];
- Tcl_IncrRefCount(ip->i_compare);
- _debug_check();
- ret = (*dbp)->set_h_compare(*dbp, tcl_bt_compare);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_h_compare");
- break;
- case TCL_DB_HASHPROC:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-hashproc hashproc");
- result = TCL_ERROR;
- break;
- }
- /*
- * Store the object containing the procedure name.
- * See TCL_DB_BTCOMPARE.
- */
- ip->i_hashproc = objv[i++];
- Tcl_IncrRefCount(ip->i_hashproc);
- _debug_check();
- ret = (*dbp)->set_h_hash(*dbp, tcl_h_hash);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_h_hash");
- break;
- case TCL_DB_LORDER:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-lorder 1234|4321");
- result = TCL_ERROR;
- break;
- }
- result = Tcl_GetIntFromObj(interp, objv[i++], &intarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*dbp)->set_lorder(*dbp, intarg);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "set_lorder");
- }
- break;
- case TCL_DB_MINKEY:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-minkey minkey");
- result = TCL_ERROR;
- break;
- }
- result = _GetUInt32(interp, objv[i++], &uintarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = (*dbp)->set_bt_minkey(*dbp, uintarg);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "set_bt_minkey");
- }
- break;
- case TCL_DB_NOMMAP:
- open_flags |= DB_NOMMAP;
- break;
- case TCL_DB_NOTDURABLE:
- set_flags |= DB_TXN_NOT_DURABLE;
- break;
- case TCL_DB_READ_UNCOMMITTED:
- open_flags |= DB_READ_UNCOMMITTED;
- break;
- case TCL_DB_REVSPLIT:
- set_flags |= DB_REVSPLITOFF;
- break;
- case TCL_DB_TEST:
- ret = (*dbp)->set_h_hash(*dbp, __ham_test);
- result = _ReturnSetup(interp, ret,
- DB_RETOK_STD(ret), "set_h_hash");
- break;
- case TCL_DB_THREAD:
- /* Enable DB_THREAD when specified in testing. */
- open_flags |= DB_THREAD;
- break;
- #endif
- case TCL_DB_AUTO_COMMIT:
- open_flags |= DB_AUTO_COMMIT;
- break;
- case TCL_DB_ENV:
- /*
- * Already parsed this, skip it and the env pointer.
- */
- i++;
- continue;
- case TCL_DB_TXN:
- if (i > (objc - 1)) {
- Tcl_WrongNumArgs(interp, 2, objv, "?-txn id?");
- result = TCL_ERROR;
- break;
- }
- arg = Tcl_GetStringFromObj(objv[i++], NULL);
- txn = NAME_TO_TXN(arg);
- if (txn == NULL) {
- snprintf(msg, MSG_SIZE,
- "Open: Invalid txn: %s\n", arg);
- Tcl_SetResult(interp, msg, TCL_VOLATILE);
- result = TCL_ERROR;
- }
- break;
- case TCL_DB_BTREE:
- if (type != DB_UNKNOWN) {
- Tcl_SetResult(interp,
- "Too many DB types specified", TCL_STATIC);
- result = TCL_ERROR;
- goto error;
- }
- type = DB_BTREE;
- break;
- case TCL_DB_HASH:
- if (type != DB_UNKNOWN) {
- Tcl_SetResult(interp,
- "Too many DB types specified", TCL_STATIC);
- result = TCL_ERROR;
- goto error;
- }
- type = DB_HASH;
- break;
- case TCL_DB_RECNO:
- if (type != DB_UNKNOWN) {
- Tcl_SetResult(interp,
- "Too many DB types specified", TCL_STATIC);
- result = TCL_ERROR;
- goto error;
- }
- type = DB_RECNO;
- break;
- case TCL_DB_QUEUE:
- if (type != DB_UNKNOWN) {
- Tcl_SetResult(interp,
- "Too many DB types specified", TCL_STATIC);
- result = TCL_ERROR;
- goto error;
- }
- type = DB_QUEUE;
- break;
- case TCL_DB_UNKNOWN:
- if (type != DB_UNKNOWN) {
- Tcl_SetResult(interp,
- "Too many DB types specified", TCL_STATIC);
- result = TCL_ERROR;
- goto error;
- }
- break;
- case TCL_DB_CREATE:
- open_flags |= DB_CREATE;
- break;
- case TCL_DB_EXCL:
- open_flags |= DB_EXCL;
- break;
- case TCL_DB_RDONLY:
- open_flags |= DB_RDONLY;
- break;
- case TCL_DB_TRUNCATE:
- open_flags |= DB_TRUNCATE;
- break;
- case TCL_DB_MODE:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-mode mode?");
- result = TCL_ERROR;
- break;
- }
- /*
- * Don't need to check result here because
- * if TCL_ERROR, the error message is already
- * set up, and we'll bail out below. If ok,
- * the mode is set and we go on.
- */
- result = Tcl_GetIntFromObj(interp, objv[i++], &mode);
- break;
- case TCL_DB_DUP:
- set_flags |= DB_DUP;
- break;
- case TCL_DB_DUPSORT:
- set_flags |= DB_DUPSORT;
- break;
- case TCL_DB_INORDER:
- set_flags |= DB_INORDER;
- break;
- case TCL_DB_RECNUM:
- set_flags |= DB_RECNUM;
- break;
- case TCL_DB_RENUMBER:
- set_flags |= DB_RENUMBER;
- break;
- case TCL_DB_SNAPSHOT:
- set_flags |= DB_SNAPSHOT;
- break;
- case TCL_DB_CHKSUM:
- set_flags |= DB_CHKSUM;
- break;
- case TCL_DB_ENCRYPT:
- set_flags |= DB_ENCRYPT;
- break;
- case TCL_DB_ENCRYPT_AES:
- /* Make sure we have an arg to check against! */
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-encryptaes passwd?");
- result = TCL_ERROR;
- break;
- }
- passwd = Tcl_GetStringFromObj(objv[i++], NULL);
- _debug_check();
- ret = (*dbp)->set_encrypt(*dbp, passwd, DB_ENCRYPT_AES);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_encrypt");
- break;
- case TCL_DB_ENCRYPT_ANY:
- /* Make sure we have an arg to check against! */
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "?-encryptany passwd?");
- result = TCL_ERROR;
- break;
- }
- passwd = Tcl_GetStringFromObj(objv[i++], NULL);
- _debug_check();
- ret = (*dbp)->set_encrypt(*dbp, passwd, 0);
- result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
- "set_encrypt");
- break;
- case TCL_DB_FFACTOR:
- if (i >= objc) {
- Tcl_WrongNumArgs(interp, 2, objv,
- "-ffactor density");
- result = TCL_ERROR;
- break;
- }
- result = _GetUInt32(interp, objv[i++], &uintarg);
- if (result == TCL_OK) {
- _debug_check();
- ret = …
Large files files are truncated, but you can click here to view the full file