diff options
Diffstat (limited to 'lang/tcl')
-rw-r--r-- | lang/tcl/docs/db.html | 2 | ||||
-rw-r--r-- | lang/tcl/docs/env.html | 2 | ||||
-rw-r--r-- | lang/tcl/docs/historic.html | 2 | ||||
-rw-r--r-- | lang/tcl/docs/index.html | 2 | ||||
-rw-r--r-- | lang/tcl/docs/library.html | 2 | ||||
-rw-r--r-- | lang/tcl/docs/lock.html | 2 | ||||
-rw-r--r-- | lang/tcl/docs/log.html | 2 | ||||
-rw-r--r-- | lang/tcl/docs/mpool.html | 2 | ||||
-rw-r--r-- | lang/tcl/docs/rep.html | 2 | ||||
-rw-r--r-- | lang/tcl/docs/sequence.html | 2 | ||||
-rw-r--r-- | lang/tcl/docs/test.html | 2 | ||||
-rw-r--r-- | lang/tcl/docs/txn.html | 2 | ||||
-rw-r--r-- | lang/tcl/tcl_compat.c | 2 | ||||
-rw-r--r-- | lang/tcl/tcl_db.c | 407 | ||||
-rw-r--r-- | lang/tcl/tcl_db_pkg.c | 560 | ||||
-rw-r--r-- | lang/tcl/tcl_dbcursor.c | 108 | ||||
-rw-r--r-- | lang/tcl/tcl_dbstream.c | 302 | ||||
-rw-r--r-- | lang/tcl/tcl_env.c | 578 | ||||
-rw-r--r-- | lang/tcl/tcl_internal.c | 9 | ||||
-rw-r--r-- | lang/tcl/tcl_lock.c | 38 | ||||
-rw-r--r-- | lang/tcl/tcl_log.c | 125 | ||||
-rw-r--r-- | lang/tcl/tcl_mp.c | 199 | ||||
-rw-r--r-- | lang/tcl/tcl_mutex.c | 41 | ||||
-rw-r--r-- | lang/tcl/tcl_rep.c | 106 | ||||
-rw-r--r-- | lang/tcl/tcl_seq.c | 27 | ||||
-rw-r--r-- | lang/tcl/tcl_txn.c | 36 | ||||
-rw-r--r-- | lang/tcl/tcl_util.c | 2 |
27 files changed, 2200 insertions, 364 deletions
diff --git a/lang/tcl/docs/db.html b/lang/tcl/docs/db.html index 6c5bcecf..77b4cc3a 100644 --- a/lang/tcl/docs/db.html +++ b/lang/tcl/docs/db.html @@ -1,4 +1,4 @@ -<!--Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved.--> +<!--Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved.--> <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> diff --git a/lang/tcl/docs/env.html b/lang/tcl/docs/env.html index f790cab0..506a4b39 100644 --- a/lang/tcl/docs/env.html +++ b/lang/tcl/docs/env.html @@ -1,4 +1,4 @@ -<!--Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved.--> +<!--Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved.--> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> diff --git a/lang/tcl/docs/historic.html b/lang/tcl/docs/historic.html index 9345208e..6d8e8e03 100644 --- a/lang/tcl/docs/historic.html +++ b/lang/tcl/docs/historic.html @@ -1,4 +1,4 @@ -<!--Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved.--> +<!--Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved.--> <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> diff --git a/lang/tcl/docs/index.html b/lang/tcl/docs/index.html index ad08b3ae..6faf388d 100644 --- a/lang/tcl/docs/index.html +++ b/lang/tcl/docs/index.html @@ -1,4 +1,4 @@ -<!--Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved.--> +<!--Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved.--> <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> diff --git a/lang/tcl/docs/library.html b/lang/tcl/docs/library.html index fab4ff2f..72f54f24 100644 --- a/lang/tcl/docs/library.html +++ b/lang/tcl/docs/library.html @@ -1,4 +1,4 @@ -<!--Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved.--> +<!--Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved.--> <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> diff --git a/lang/tcl/docs/lock.html b/lang/tcl/docs/lock.html index d9b7599c..ba3f5f5d 100644 --- a/lang/tcl/docs/lock.html +++ b/lang/tcl/docs/lock.html @@ -1,4 +1,4 @@ -<!--Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved.--> +<!--Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved.--> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> diff --git a/lang/tcl/docs/log.html b/lang/tcl/docs/log.html index 7df38f80..8451404b 100644 --- a/lang/tcl/docs/log.html +++ b/lang/tcl/docs/log.html @@ -1,4 +1,4 @@ -<!--Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved.--> +<!--Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved.--> <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> diff --git a/lang/tcl/docs/mpool.html b/lang/tcl/docs/mpool.html index 42d38e27..2ddb692f 100644 --- a/lang/tcl/docs/mpool.html +++ b/lang/tcl/docs/mpool.html @@ -1,4 +1,4 @@ -<!--Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved.--> +<!--Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved.--> <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> diff --git a/lang/tcl/docs/rep.html b/lang/tcl/docs/rep.html index 60c074e1..1a8ee5ca 100644 --- a/lang/tcl/docs/rep.html +++ b/lang/tcl/docs/rep.html @@ -1,4 +1,4 @@ -<!--Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved.--> +<!--Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved.--> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> diff --git a/lang/tcl/docs/sequence.html b/lang/tcl/docs/sequence.html index 8d608d31..3ea7cf2c 100644 --- a/lang/tcl/docs/sequence.html +++ b/lang/tcl/docs/sequence.html @@ -1,4 +1,4 @@ -<!--Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved.--> +<!--Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved.--> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> diff --git a/lang/tcl/docs/test.html b/lang/tcl/docs/test.html index ff591b7b..3eb7311a 100644 --- a/lang/tcl/docs/test.html +++ b/lang/tcl/docs/test.html @@ -1,4 +1,4 @@ -<!--Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved.--> +<!--Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved.--> <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> diff --git a/lang/tcl/docs/txn.html b/lang/tcl/docs/txn.html index 061a221a..9c7f2020 100644 --- a/lang/tcl/docs/txn.html +++ b/lang/tcl/docs/txn.html @@ -1,4 +1,4 @@ -<!--Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved.--> +<!--Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved.--> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> diff --git a/lang/tcl/tcl_compat.c b/lang/tcl/tcl_compat.c index 57c0b9bc..97900eef 100644 --- a/lang/tcl/tcl_compat.c +++ b/lang/tcl/tcl_compat.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/lang/tcl/tcl_db.c b/lang/tcl/tcl_db.c index afe431b8..7c0e1b65 100644 --- a/lang/tcl/tcl_db.c +++ b/lang/tcl/tcl_db.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -100,11 +100,11 @@ db_Cmd(clientData, interp, objc, objv) { static const char *dbcmds[] = { #ifdef CONFIG_TEST + "compact", + "compact_stat", "keyrange", "pget", "test", - "compact", - "compact_stat", #endif "associate", "associate_foreign", @@ -113,7 +113,11 @@ db_Cmd(clientData, interp, objc, objv) "cursor", "del", "get", + "get_blob_dir", + "get_blob_sub_dir", + "get_blob_threshold", "get_bt_minkey", + "get_byteswapped", "get_cachesize", "get_dbname", "get_encrypt_flags", @@ -121,9 +125,11 @@ db_Cmd(clientData, interp, objc, objv) "get_errpfx", "get_flags", "get_heap_regionsize", + "get_heapsize", "get_h_ffactor", "get_h_nelem", "get_join", + "get_lk_exclusive", "get_lorder", "get_open_flags", "get_pagesize", @@ -133,9 +139,9 @@ db_Cmd(clientData, interp, objc, objv) "get_re_pad", "get_re_source", "get_type", - "is_byteswapped", "join", - "get_lk_exclusive", + "msgfile", + "msgfile_close", "put", "stat", "stat_print", @@ -145,11 +151,11 @@ db_Cmd(clientData, interp, objc, objv) }; enum dbcmds { #ifdef CONFIG_TEST + DBCOMPACT, + DBCOMPACT_STAT, DBKEYRANGE, DBPGET, DBTEST, - DBCOMPACT, - DBCOMPACT_STAT, #endif DBASSOCIATE, DBASSOCFOREIGN, @@ -158,7 +164,11 @@ db_Cmd(clientData, interp, objc, objv) DBCURSOR, DBDELETE, DBGET, + DBGETBLOBDIR, + DBGETBLOBSUBDIR, + DBGETBLOBTHRESHOLD, DBGETBTMINKEY, + DBGETBYTESWAPPED, DBGETCACHESIZE, DBGETDBNAME, DBGETENCRYPTFLAGS, @@ -166,9 +176,11 @@ db_Cmd(clientData, interp, objc, objv) DBGETERRPFX, DBGETFLAGS, DBGETHEAPREGIONSIZE, + DBGETHEAPSIZE, DBGETHFFACTOR, DBGETHNELEM, DBGETJOIN, + DBGETLKEXCLUSIVE, DBGETLORDER, DBGETOPENFLAGS, DBGETPAGESIZE, @@ -178,9 +190,9 @@ db_Cmd(clientData, interp, objc, objv) DBGETREPAD, DBGETRESOURCE, DBGETTYPE, - DBSWAPPED, DBJOIN, - DBGETLKEXCLUSIVE, + DBMSGFILE, + DBMSGFILECLOSE, DBPUT, DBSTAT, DBSTATPRINT, @@ -195,8 +207,10 @@ db_Cmd(clientData, interp, objc, objv) Tcl_Obj *res, *myobjv[3]; int cmdindex, intval, ncache, result, ret, onoff, nowait; char newname[MSG_SIZE]; + char *strarg; u_int32_t bytes, gbytes, value; const char *strval, *filename, *dbname, *envid; + FILE *file; Tcl_ResetResult(interp); dbp = (DB *)clientData; @@ -227,6 +241,14 @@ db_Cmd(clientData, interp, objc, objv) res = NULL; switch ((enum dbcmds)cmdindex) { #ifdef CONFIG_TEST + case DBCOMPACT: + result = tcl_DbCompact(interp, objc, objv, dbp); + break; + + case DBCOMPACT_STAT: + result = tcl_DbCompactStat(interp, objc, objv, dbp); + break; + case DBKEYRANGE: result = tcl_DbKeyRange(interp, objc, objv, dbp); break; @@ -237,14 +259,6 @@ db_Cmd(clientData, interp, objc, objv) result = tcl_EnvTest(interp, objc, objv, dbp->dbenv); break; - case DBCOMPACT: - result = tcl_DbCompact(interp, objc, objv, dbp); - break; - - case DBCOMPACT_STAT: - result = tcl_DbCompactStat(interp, objc, objv, dbp); - break; - #endif case DBASSOCIATE: result = tcl_DbAssociate(interp, objc, objv, dbp); @@ -255,100 +269,9 @@ db_Cmd(clientData, interp, objc, objv) case DBCLOSE: result = tcl_DbClose(interp, objc, objv, dbp, dbip); break; - case DBDELETE: - result = tcl_DbDelete(interp, objc, objv, dbp); - break; - case DBGET: - result = tcl_DbGet(interp, objc, objv, dbp, 0); - break; - case DBPUT: - result = tcl_DbPut(interp, objc, objv, dbp); - break; case DBCOUNT: result = tcl_DbCount(interp, objc, objv, dbp); break; - case DBSWAPPED: - /* - * No args for this. Error if there are some. - */ - if (objc > 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - return (TCL_ERROR); - } - _debug_check(); - ret = dbp->get_byteswapped(dbp, &intval); - res = Tcl_NewIntObj(intval); - break; - case DBGETTYPE: - /* - * No args for this. Error if there are some. - */ - if (objc > 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - return (TCL_ERROR); - } - _debug_check(); - ret = dbp->get_type(dbp, &type); - if (type == DB_BTREE) - res = NewStringObj("btree", strlen("btree")); - else if (type == DB_HASH) - res = NewStringObj("hash", strlen("hash")); - else if (type == DB_RECNO) - res = NewStringObj("recno", strlen("recno")); - else if (type == DB_QUEUE) - res = NewStringObj("queue", strlen("queue")); - else if (type == DB_HEAP) - res = NewStringObj("heap", strlen("heap")); - else { - Tcl_SetResult(interp, - "db gettype: Returned unknown type\n", TCL_STATIC); - result = TCL_ERROR; - } - break; - case DBSTAT: - result = tcl_DbStat(interp, objc, objv, dbp); - break; - case DBSTATPRINT: - result = tcl_DbStatPrint(interp, objc, objv, dbp); - break; - case DBSYNC: - /* - * No args for this. Error if there are some. - */ - if (objc > 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - return (TCL_ERROR); - } - _debug_check(); - ret = dbp->sync(dbp, 0); - res = Tcl_NewIntObj(ret); - if (ret != 0) { - Tcl_SetObjResult(interp, res); - result = TCL_ERROR; - } - - /* If we are heap, we have more work to do. */ - ret = dbp->get_type(dbp, &type); - if (type == DB_HEAP) { - hrdbp = dbip->hrdbp; - hsdbp = dbip->hsdbp; - - /* sync the associated dbs also */ - ret = dbp->sync(hrdbp, 0); - res = Tcl_NewIntObj(ret); - if (ret != 0) { - Tcl_SetObjResult(interp, res); - result = TCL_ERROR; - } - - ret = dbp->sync(hsdbp, 0); - res = Tcl_NewIntObj(ret); - if (ret != 0) { - Tcl_SetObjResult(interp, res); - result = TCL_ERROR; - } - } - break; case DBCURSOR: snprintf(newname, sizeof(newname), "%s.c%d", dbip->i_name, dbip->i_dbdbcid); @@ -371,27 +294,43 @@ db_Cmd(clientData, interp, objc, objv) result = TCL_ERROR; } break; - case DBJOIN: - snprintf(newname, sizeof(newname), - "%s.c%d", dbip->i_name, dbip->i_dbdbcid); - ip = _NewInfo(interp, NULL, newname, I_DBC); - if (ip != NULL) { - result = tcl_DbJoin(interp, objc, objv, dbp, &dbc); - if (result == TCL_OK) { - dbip->i_dbdbcid++; - ip->i_parent = dbip; - (void)Tcl_CreateObjCommand(interp, newname, - (Tcl_ObjCmdProc *)dbc_Cmd, - (ClientData)dbc, NULL); - res = NewStringObj(newname, strlen(newname)); - _SetInfoData(ip, dbc); - } else - _DeleteInfo(ip); - } else { - Tcl_SetResult(interp, - "Could not set up info", TCL_STATIC); - result = TCL_ERROR; + case DBDELETE: + result = tcl_DbDelete(interp, objc, objv, dbp); + break; + case DBGET: + result = tcl_DbGet(interp, objc, objv, dbp, 0); + break; + case DBGETBLOBDIR: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); } + ret = dbp->get_blob_dir(dbp, &strval); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "db get_blob_dir")) == TCL_OK) + res = NewStringObj(strval, + strval != NULL ? strlen(strval) : 0); + break; + case DBGETBLOBSUBDIR: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = dbp->get_blob_sub_dir(dbp, &strval); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "db get_blob_sub_dir")) == TCL_OK) + res = NewStringObj(strval, + strval != NULL ? strlen(strval) : 0); + break; + case DBGETBLOBTHRESHOLD: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = dbp->get_blob_threshold(dbp, &value); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "db get_blob_threshold")) == TCL_OK) + res = Tcl_NewIntObj((int)value); break; case DBGETBTMINKEY: if (objc != 2) { @@ -403,6 +342,18 @@ db_Cmd(clientData, interp, objc, objv) "db get_bt_minkey")) == TCL_OK) res = Tcl_NewIntObj((int)value); break; + case DBGETBYTESWAPPED: + /* + * No args for this. Error if there are some. + */ + if (objc > 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return (TCL_ERROR); + } + _debug_check(); + ret = dbp->get_byteswapped(dbp, &intval); + res = Tcl_NewIntObj(intval); + break; case DBGETCACHESIZE: if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, NULL); @@ -468,6 +419,19 @@ db_Cmd(clientData, interp, objc, objv) "db get_heap_regionsize")) == TCL_OK) res = Tcl_NewIntObj((int)value); break; + case DBGETHEAPSIZE: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = dbp->get_heapsize(dbp, &gbytes, &bytes); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "db get_heapsize")) == TCL_OK) { + myobjv[0] = Tcl_NewIntObj((int)gbytes); + myobjv[1] = Tcl_NewIntObj((int)bytes); + res = Tcl_NewListObj(2, myobjv); + } + break; case DBGETHFFACTOR: if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, NULL); @@ -491,6 +455,19 @@ db_Cmd(clientData, interp, objc, objv) case DBGETJOIN: result = tcl_DbGetjoin(interp, objc, objv, dbp); break; + case DBGETLKEXCLUSIVE: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = dbp->get_lk_exclusive(dbp, &onoff, &nowait); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "db get_lk_exclusive")) == TCL_OK) { + myobjv[0] = Tcl_NewIntObj((int)onoff); + myobjv[1] = Tcl_NewIntObj((int)nowait); + res = Tcl_NewListObj(2, myobjv); + } + break; case DBGETLORDER: /* * No args for this. Error if there are some. @@ -566,17 +543,157 @@ db_Cmd(clientData, interp, objc, objv) "db get_re_source")) == TCL_OK) res = NewStringObj(strval, strlen(strval)); break; - case DBGETLKEXCLUSIVE: - if (objc != 2) { + case DBGETTYPE: + /* + * No args for this. Error if there are some. + */ + if (objc > 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return (TCL_ERROR); + } + _debug_check(); + ret = dbp->get_type(dbp, &type); + if (type == DB_BTREE) + res = NewStringObj("btree", strlen("btree")); + else if (type == DB_HASH) + res = NewStringObj("hash", strlen("hash")); + else if (type == DB_RECNO) + res = NewStringObj("recno", strlen("recno")); + else if (type == DB_QUEUE) + res = NewStringObj("queue", strlen("queue")); + else if (type == DB_HEAP) + res = NewStringObj("heap", strlen("heap")); + else { + Tcl_SetResult(interp, + "db gettype: Returned unknown type\n", TCL_STATIC); + result = TCL_ERROR; + } + break; + case DBJOIN: + snprintf(newname, sizeof(newname), + "%s.c%d", dbip->i_name, dbip->i_dbdbcid); + ip = _NewInfo(interp, NULL, newname, I_DBC); + if (ip != NULL) { + result = tcl_DbJoin(interp, objc, objv, dbp, &dbc); + if (result == TCL_OK) { + dbip->i_dbdbcid++; + ip->i_parent = dbip; + (void)Tcl_CreateObjCommand(interp, newname, + (Tcl_ObjCmdProc *)dbc_Cmd, + (ClientData)dbc, NULL); + res = NewStringObj(newname, strlen(newname)); + _SetInfoData(ip, dbc); + } else + _DeleteInfo(ip); + } else { + Tcl_SetResult(interp, + "Could not set up info", TCL_STATIC); + result = TCL_ERROR; + } + break; + case DBMSGFILE: + if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return (TCL_ERROR); } - ret = dbp->get_lk_exclusive(dbp, &onoff, &nowait); + strarg = Tcl_GetStringFromObj(objv[2], NULL); + dbenv = dbp->get_env(dbp); + if (dbenv != NULL && _PtrToInfo(dbenv) != NULL) { + ip = _PtrToInfo(dbenv); + } else { + ip = dbip; + } + if (ip->i_msg != NULL && ip->i_msg != stdout && + ip->i_msg != stderr) + (void)fclose(ip->i_msg); + if (strcmp(strarg, "NULL") == 0) + ip->i_msg = NULL; + else if (strcmp(strarg, "/dev/stdout") == 0) + ip->i_msg = stdout; + else if (strcmp(strarg, "/dev/stderr") == 0) + ip->i_msg = stderr; + else + ip->i_msg = fopen(strarg, "a"); + if (strcmp(strarg, "NULL") == 0 || ip->i_msg != NULL ) { + dbp->set_msgfile(dbp, ip->i_msg); + ret = TCL_OK; + } + else + ret = TCL_ERROR; if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), - "db get_lk_exclusive")) == TCL_OK) { - myobjv[0] = Tcl_NewIntObj((int)onoff); - myobjv[1] = Tcl_NewIntObj((int)nowait); - res = Tcl_NewListObj(2, myobjv); + "db set_msgfile")) == TCL_OK) + res = Tcl_NewIntObj(ret); + break; + case DBMSGFILECLOSE: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = TCL_OK; + dbenv = dbp->get_env(dbp); + if (dbenv != NULL && _PtrToInfo(dbenv) != NULL) { + ip = _PtrToInfo(dbenv); + } else { + ip = dbip; + } + dbp->get_msgfile(dbp, &file); + if (file != ip->i_msg) { + return (TCL_ERROR); + } + if (file != NULL && file != stdout && file != stderr) { + ret = fclose(file); + } + ip->i_msg = NULL; + dbp->set_msgfile(dbp, NULL); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "db close msgfile")) == TCL_OK) + res = Tcl_NewIntObj(ret); + break; + case DBPUT: + result = tcl_DbPut(interp, objc, objv, dbp); + break; + case DBSTAT: + result = tcl_DbStat(interp, objc, objv, dbp); + break; + case DBSTATPRINT: + result = tcl_DbStatPrint(interp, objc, objv, dbp); + break; + case DBSYNC: + /* + * No args for this. Error if there are some. + */ + if (objc > 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return (TCL_ERROR); + } + _debug_check(); + ret = dbp->sync(dbp, 0); + res = Tcl_NewIntObj(ret); + if (ret != 0) { + Tcl_SetObjResult(interp, res); + result = TCL_ERROR; + } + + /* If we are heap, we have more work to do. */ + ret = dbp->get_type(dbp, &type); + if (type == DB_HEAP) { + hrdbp = dbip->hrdbp; + hsdbp = dbip->hsdbp; + + /* sync the associated dbs also */ + ret = dbp->sync(hrdbp, 0); + res = Tcl_NewIntObj(ret); + if (ret != 0) { + Tcl_SetObjResult(interp, res); + result = TCL_ERROR; + } + + ret = dbp->sync(hsdbp, 0); + res = Tcl_NewIntObj(ret); + if (ret != 0) { + Tcl_SetObjResult(interp, res); + result = TCL_ERROR; + } } break; case DBTRUNCATE: @@ -703,6 +820,7 @@ tcl_DbStat(interp, objc, objv, dbp) MAKE_STAT_LIST("Number of records", hsp->hash_ndata); MAKE_STAT_LIST("Fill factor", hsp->hash_ffactor); MAKE_STAT_LIST("Buckets", hsp->hash_buckets); + MAKE_STAT_LIST("Number of blobs", hsp->hash_nblobs); if (flag != DB_FAST_STAT) { MAKE_STAT_LIST("Free pages", hsp->hash_free); MAKE_WSTAT_LIST("Bytes free", hsp->hash_bfree); @@ -727,6 +845,7 @@ tcl_DbStat(interp, objc, objv, dbp) MAKE_STAT_LIST("Number of regions", hpsp->heap_nregions); MAKE_STAT_LIST("Number of pages in a region", hpsp->heap_regionsize); + MAKE_STAT_LIST("Number of blobs", hpsp->heap_nblobs); } else if (type == DB_QUEUE) { qsp = (DB_QUEUE_STAT *)sp; MAKE_STAT_LIST("Magic", qsp->qs_magic); @@ -738,7 +857,7 @@ tcl_DbStat(interp, objc, objv, dbp) MAKE_STAT_LIST("Record length", qsp->qs_re_len); MAKE_STAT_LIST("Record pad", qsp->qs_re_pad); MAKE_STAT_LIST("First record number", qsp->qs_first_recno); - MAKE_STAT_LIST("Last record number", qsp->qs_cur_recno); + MAKE_STAT_LIST("Next available record number", qsp->qs_cur_recno); if (flag != DB_FAST_STAT) { MAKE_STAT_LIST("Number of pages", qsp->qs_pages); MAKE_WSTAT_LIST("Bytes free", qsp->qs_pgfree); @@ -749,6 +868,7 @@ tcl_DbStat(interp, objc, objv, dbp) MAKE_STAT_LIST("Version", bsp->bt_version); MAKE_STAT_LIST("Number of keys", bsp->bt_nkeys); MAKE_STAT_LIST("Number of records", bsp->bt_ndata); + MAKE_STAT_LIST("Number of blobs", bsp->bt_nblobs); MAKE_STAT_LIST("Minimum keys per page", bsp->bt_minkey); MAKE_STAT_LIST("Fixed record length", bsp->bt_re_len); MAKE_STAT_LIST("Record pad", bsp->bt_re_pad); @@ -981,6 +1101,7 @@ tcl_DbPut(interp, objc, objv, dbp) "-nodupdata", #endif "-append", + "-blob", "-multiple", "-multiple_key", "-nooverwrite", @@ -995,6 +1116,7 @@ tcl_DbPut(interp, objc, objv, dbp) DBGET_NODUPDATA, #endif DBPUT_APPEND, + DBPUT_BLOB, DBPUT_MULTIPLE, DBPUT_MULTIPLE_KEY, DBPUT_NOOVER, @@ -1104,6 +1226,9 @@ tcl_DbPut(interp, objc, objv, dbp) FLAG_CHECK(flag); flag = DB_APPEND; break; + case DBPUT_BLOB: + data.flags |= DB_DBT_BLOB; + break; case DBPUT_MULTIPLE: FLAG_CHECK(multiflag); multiflag = DB_MULTIPLE; @@ -2564,7 +2689,7 @@ tcl_DbDelete(interp, objc, objv, dbp) result = _ReturnSetup(interp, ret, DB_RETOK_DBPUT(ret), "db del heap bulk"); - goto out; + goto loopend; } DB_MULTIPLE_WRITE_NEXT(ptr, &key, hkey.data, hkey.size); @@ -2682,7 +2807,7 @@ tcl_DbDelete(interp, objc, objv, dbp) result = _ReturnSetup(interp, ret, DB_RETOK_DBPUT(ret), "db del heap bulk"); - goto out; + goto loopend; } DB_MULTIPLE_KEY_WRITE_NEXT(ptr, &key, hkey.data, hkey.size, @@ -3710,7 +3835,7 @@ tcl_DbGetFlags(interp, objc, objv, dbp) if (strlen(buf) > 0) (void)strncat(buf, " ", sizeof(buf)); (void)strncat( - buf, db_flags[i].arg, sizeof(buf)); + buf, db_flags[i].arg, sizeof(buf) - 1); } res = NewStringObj(buf, strlen(buf)); @@ -3766,7 +3891,7 @@ tcl_DbGetOpenFlags(interp, objc, objv, dbp) if (strlen(buf) > 0) (void)strncat(buf, " ", sizeof(buf)); (void)strncat( - buf, open_flags[i].arg, sizeof(buf)); + buf, open_flags[i].arg, sizeof(buf) - 1); } res = NewStringObj(buf, strlen(buf)); @@ -4216,7 +4341,7 @@ tcl_DbCompact(interp, objc, objv, dbp) key = &stop; key->data = &srecno; } - if (type == DB_RECNO || type == DB_QUEUE) { + if (type == DB_RECNO || type == DB_HASH) { result = _GetUInt32( interp, objv[i], key->data); if (result == TCL_OK) { diff --git a/lang/tcl/tcl_db_pkg.c b/lang/tcl/tcl_db_pkg.c index a190f9de..6de1e449 100644 --- a/lang/tcl/tcl_db_pkg.c +++ b/lang/tcl/tcl_db_pkg.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -47,16 +47,17 @@ 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_bt_compare __P((DB *, const DBT *, const DBT *, size_t *)); 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 int tcl_dup_compare __P((DB *, const DBT *, const DBT *, size_t *)); static u_int32_t tcl_h_hash __P((DB *, const void *, u_int32_t)); static int tcl_isalive __P((DB_ENV *, pid_t, db_threadid_t, u_int32_t)); static u_int32_t tcl_part_callback __P((DB *, DBT *)); +static int tcl_rep_view __P((DB_ENV *, const char *, int *, u_int32_t)); static int tcl_set_partition_dirs __P((Tcl_Interp *, DB *, Tcl_Obj *)); static int tcl_set_partition_keys @@ -219,6 +220,7 @@ berkdb_Cmd(notused, interp, objc, objv) COMPQUIET(hrip, NULL); COMPQUIET(hsdbp, NULL); COMPQUIET(hsip, NULL); + COMPQUIET(dbenv, NULL); Tcl_ResetResult(interp); memset(newname, 0, MSG_SIZE); @@ -476,9 +478,11 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) "-lock", "-lock_conflict", "-lock_detect", - "-lock_locks", "-lock_lockers", + "-lock_locks", + "-lock_logid", "-lock_objects", + "-lock_thread", "-lock_max_locks", "-lock_max_lockers", "-lock_max_objects", @@ -487,6 +491,7 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) "-lock_timeout", "-log", "-log_filemode", + "-log_blob", "-log_buffer", "-log_inmemory", "-log_max", @@ -499,6 +504,7 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) "-mpool_mutex_count", "-mpool_nommap", "-multiversion", + "-mutex_failchk_timeout", "-mutex_set_align", "-mutex_set_incr", "-mutex_set_init", @@ -511,11 +517,18 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) "-region_init", "-rep", "-rep_client", + "-rep_config", "-rep_inmem_files", "-rep_lease", + "-rep_limit", "-rep_master", "-rep_nsites", + "-rep_priority", + "-rep_request", + "-rep_timeout", "-rep_transport", + "-rep_view", + "-repmgr_ack_policy", "-set_intermediate_dir_mode", "-snapshot", "-tablesize", @@ -530,6 +543,8 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) "-zero_log", #endif "-add_dir", + "-blob_dir", + "-blob_threshold", "-cachesize", "-cache_max", "-create", @@ -574,9 +589,11 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) TCL_ENV_LOCK, TCL_ENV_CONFLICT, TCL_ENV_DETECT, - TCL_ENV_LOCK_LOCKS, TCL_ENV_LOCK_LOCKERS, + TCL_ENV_LOCK_LOCKS, + TCL_ENV_LOCK_LOGID, TCL_ENV_LOCK_OBJECTS, + TCL_ENV_LOCK_THREAD, TCL_ENV_LOCK_MAX_LOCKS, TCL_ENV_LOCK_MAX_LOCKERS, TCL_ENV_LOCK_MAX_OBJECTS, @@ -585,6 +602,7 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) TCL_ENV_LOCK_TIMEOUT, TCL_ENV_LOG, TCL_ENV_LOG_FILEMODE, + TCL_ENV_LOG_BLOB, TCL_ENV_LOG_BUFFER, TCL_ENV_LOG_INMEMORY, TCL_ENV_LOG_MAX, @@ -597,6 +615,7 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) TCL_ENV_MUTEXCOUNT, TCL_ENV_MPOOL_NOMMAP, TCL_ENV_MULTIVERSION, + TCL_ENV_MUT_FAILCHK_TIMEOUT, TCL_ENV_MUTSETALIGN, TCL_ENV_MUTSETINCR, TCL_ENV_MUTSETINIT, @@ -609,11 +628,18 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) TCL_ENV_REGION_INIT, TCL_ENV_REP, TCL_ENV_REP_CLIENT, + TCL_ENV_REP_CONFIG, TCL_ENV_REP_INMEM_FILES, TCL_ENV_REP_LEASE, + TCL_ENV_REP_LIMIT, TCL_ENV_REP_MASTER, TCL_ENV_REP_NSITES, + TCL_ENV_REP_PRIORITY, + TCL_ENV_REP_REQUEST, + TCL_ENV_REP_TIMEOUT, TCL_ENV_REP_TRANSPORT, + TCL_ENV_REP_VIEW, + TCL_ENV_REPMGR_ACK_POLICY, TCL_ENV_SET_INTERMEDIATE_DIR, TCL_ENV_SNAPSHOT, TCL_ENV_TABLESIZE, @@ -628,6 +654,8 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) TCL_ENV_ZEROLOG, #endif TCL_ENV_ADD_DIR, + TCL_ENV_BLOB_DIR, + TCL_ENV_BLOB_THRESHOLD, TCL_ENV_CACHESIZE, TCL_ENV_CACHE_MAX, TCL_ENV_CREATE, @@ -875,9 +903,11 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock_detect"); break; - case TCL_ENV_LOCK_LOCKS: case TCL_ENV_LOCK_LOCKERS: + case TCL_ENV_LOCK_LOCKS: + case TCL_ENV_LOCK_LOGID: case TCL_ENV_LOCK_OBJECTS: + case TCL_ENV_LOCK_THREAD: case TCL_ENV_LOCK_MAX_LOCKS: case TCL_ENV_LOCK_MAX_LOCKERS: case TCL_ENV_LOCK_MAX_OBJECTS: @@ -893,18 +923,26 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) if (result == TCL_OK) { _debug_check(); switch ((enum envopen)optindex) { + case TCL_ENV_LOCK_LOCKERS: + ret = dbenv->set_memory_init(dbenv, + DB_MEM_LOCKER, uintarg); + break; case TCL_ENV_LOCK_LOCKS: ret = dbenv->set_memory_init(dbenv, DB_MEM_LOCK, uintarg); break; - case TCL_ENV_LOCK_LOCKERS: + case TCL_ENV_LOCK_LOGID: ret = dbenv->set_memory_init(dbenv, - DB_MEM_LOCKER, uintarg); + DB_MEM_LOGID, uintarg); break; case TCL_ENV_LOCK_OBJECTS: ret = dbenv->set_memory_init(dbenv, DB_MEM_LOCKOBJECT, uintarg); break; + case TCL_ENV_LOCK_THREAD: + ret = dbenv->set_memory_init(dbenv, + DB_MEM_THREAD, uintarg); + break; case TCL_ENV_LOCK_MAX_LOCKS: ret = dbenv->set_lk_max_locks(dbenv, uintarg); @@ -971,6 +1009,7 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) case TCL_ENV_TXN_TIME: case TCL_ENV_TXN_TIMEOUT: case TCL_ENV_LOCK_TIMEOUT: + case TCL_ENV_MUT_FAILCHK_TIMEOUT: case TCL_ENV_REG_TIMEOUT: if (i >= objc) { Tcl_WrongNumArgs(interp, 2, objv, @@ -995,6 +1034,10 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) else if ((enum envopen)optindex == TCL_ENV_REG_TIMEOUT) time_flag = DB_SET_REG_TIMEOUT; + else if ((enum envopen)optindex == + TCL_ENV_MUT_FAILCHK_TIMEOUT) + time_flag = + DB_SET_MUTEX_FAILCHK_TIMEOUT; else time_flag = DB_SET_TXN_TIMEOUT; @@ -1007,6 +1050,12 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) case TCL_ENV_LOG: FLD_SET(open_flags, DB_INIT_LOG | DB_INIT_MPOOL); break; + case TCL_ENV_LOG_BLOB: + ret = + dbenv->log_set_config(dbenv, DB_LOG_BLOB, 1); + result = _ReturnSetup(interp, ret, + DB_RETOK_STD(ret), "log_blob"); + break; case TCL_ENV_LOG_BUFFER: if (i >= objc) { Tcl_WrongNumArgs(interp, 2, objv, @@ -1061,15 +1110,8 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) result = TCL_ERROR; break; } - result = _GetUInt32(interp, objv[i++], &uintarg); - if (result == TCL_OK && logbufset) { - _debug_check(); - ret = dbenv->set_lg_max(dbenv, uintarg); - result = _ReturnSetup(interp, ret, - DB_RETOK_STD(ret), "log_max"); - logbufset = 0; - } else - logmaxset = uintarg; + result = tcl_LogSetMax( + interp, dbenv, objv[i++], &logbufset, &logmaxset); break; case TCL_ENV_LOG_REGIONMAX: if (i >= objc) { @@ -1259,6 +1301,58 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) rep_flags = DB_REP_CLIENT; FLD_SET(open_flags, DB_INIT_REP); break; + case TCL_ENV_REP_CONFIG: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "-rep_config {which onoff}"); + result = TCL_ERROR; + break; + } + result = tcl_RepConfig(interp, dbenv, objv[i]); + if (result == TCL_OK) { + i++; + FLD_SET(open_flags, DB_INIT_REP); + } + break; + case TCL_ENV_REP_INMEM_FILES: + result = tcl_RepInmemFiles(interp,dbenv); + if (result == TCL_OK) + FLD_SET(open_flags, DB_INIT_REP); + break; + case TCL_ENV_REP_LEASE: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "-rep_lease {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, dbenv); + if (result == TCL_OK) + FLD_SET(open_flags, DB_INIT_REP); + break; + case TCL_ENV_REP_LIMIT: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "-rep_limit {gbytes bytes}"); + result = TCL_ERROR; + break; + } + result = Tcl_ListObjGetElements(interp, objv[i], + &myobjc, &myobjv); + if (result == TCL_OK) + i++; + else + break; + result = tcl_RepLimit(interp, myobjc, myobjv, dbenv); + if (result == TCL_OK) + FLD_SET(open_flags, DB_INIT_REP); + break; case TCL_ENV_REP_MASTER: rep_flags = DB_REP_MASTER; FLD_SET(open_flags, DB_INIT_REP); @@ -1280,15 +1374,27 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) if (result == TCL_OK) FLD_SET(open_flags, DB_INIT_REP); break; - case TCL_ENV_REP_INMEM_FILES: - result = tcl_RepInmemFiles(interp,dbenv); + case TCL_ENV_REP_PRIORITY: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "-rep_priority priority"); + result = TCL_ERROR; + break; + } + result = _GetUInt32(interp, objv[i++], &uintarg); + if (result == TCL_OK) { + _debug_check(); + ret = dbenv->rep_set_priority(dbenv, uintarg); + result = _ReturnSetup(interp, ret, + DB_RETOK_STD(ret), "rep_set_priority"); + } if (result == TCL_OK) FLD_SET(open_flags, DB_INIT_REP); break; - case TCL_ENV_REP_LEASE: + case TCL_ENV_REP_REQUEST: if (i >= objc) { Tcl_WrongNumArgs(interp, 2, objv, - "-rep_lease {timeout clockskew}"); + "-rep_request {minTime maxTime}"); result = TCL_ERROR; break; } @@ -1298,7 +1404,31 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) i++; else break; - result = tcl_RepLease(interp, myobjc, myobjv, dbenv); + result = tcl_RepRequest(interp, myobjc, myobjv, dbenv); + if (result == TCL_OK) + FLD_SET(open_flags, DB_INIT_REP); + break; + case TCL_ENV_REP_TIMEOUT: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "-rep_timout {which timeout}"); + result = TCL_ERROR; + break; + } + if ((result = Tcl_ListObjGetElements(interp, objv[i], + &myobjc, &myobjv)) != TCL_OK ) + break; + _debug_check(); + if ((result = + Tcl_GetIntFromObj(interp, myobjv[0], &intarg)) != TCL_OK) + break; + if ((result = + _GetUInt32(interp, myobjv[1], &uintarg)) != TCL_OK) + break; + i++; + ret = dbenv->rep_set_timeout(dbenv, intarg, uintarg); + result = _ReturnSetup(interp, ret, + DB_RETOK_STD(ret), "rep_set_timeout"); if (result == TCL_OK) FLD_SET(open_flags, DB_INIT_REP); break; @@ -1320,6 +1450,56 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) if (result == TCL_OK) FLD_SET(open_flags, DB_INIT_REP); break; + case TCL_ENV_REP_VIEW: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "-rep_view {viewproc}"); + result = TCL_ERROR; + break; + } + + /* + * We use a list here instead of just sending in the + * proc name so that an empty list can indicate to + * use the BDB default full view and we send in NULL. + */ + result = Tcl_ListObjGetElements(interp, objv[i], + &myobjc, &myobjv); + if (result == TCL_OK) + i++; + else + break; + if (myobjc == 0) { + ip->i_rep_view = NULL; + _debug_check(); + ret = dbenv->rep_set_view(dbenv, NULL); + } else { + ip->i_rep_view = myobjv[0]; + Tcl_IncrRefCount(ip->i_rep_view); + _debug_check(); + ret = dbenv->rep_set_view(dbenv, tcl_rep_view); + } + result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "rep_set_view"); + break; + case TCL_ENV_REPMGR_ACK_POLICY: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "-rep_ack_policy {ack_policy}"); + result = TCL_ERROR; + break; + } + result = Tcl_GetIntFromObj(interp, objv[i++], &intarg); + if (result == TCL_OK) { + _debug_check(); + ret = dbenv-> + repmgr_set_ack_policy(dbenv, intarg); + result = _ReturnSetup(interp, ret, + DB_RETOK_STD(ret), "repmgr_set_ack_policy"); + } + if (result == TCL_OK) + FLD_SET(open_flags, DB_INIT_REP); + break; case TCL_ENV_SNAPSHOT: FLD_SET(set_flags, DB_TXN_SNAPSHOT); break; @@ -1464,7 +1644,29 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) case TCL_ENV_USE_ENVIRON: FLD_SET(open_flags, DB_USE_ENVIRON); break; + case TCL_ENV_BLOB_THRESHOLD: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-blob_threshold bytes?"); + result = TCL_ERROR; + break; + } + result = _GetUInt32(interp, objv[i++], &bytes); + if (result == TCL_OK) { + _debug_check(); + ret = dbenv->set_blob_threshold(dbenv, + bytes, 0); + result = _ReturnSetup(interp, ret, + DB_RETOK_STD(ret), "set_blob_threshold"); + } + break; case TCL_ENV_CACHESIZE: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-cachesize {gbytes bytes ncaches}?"); + result = TCL_ERROR; + break; + } result = Tcl_ListObjGetElements(interp, objv[i], &myobjc, &myobjv); if (result == TCL_OK) @@ -1580,8 +1782,8 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) break; } arg = Tcl_GetStringFromObj(objv[i++], NULL); - tcl_EnvSetMsgfile(interp, dbenv, ip, arg); - break; + result = tcl_EnvSetMsgfile(interp, dbenv, ip, arg); + break; case TCL_ENV_ERRPFX: if (i >= objc) { Tcl_WrongNumArgs(interp, 2, objv, @@ -1593,9 +1795,10 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) _debug_check(); result = tcl_EnvSetErrpfx(interp, dbenv, ip, arg); break; - case TCL_ENV_DATA_DIR: case TCL_ENV_ADD_DIR: + case TCL_ENV_BLOB_DIR: case TCL_ENV_CREATE_DIR: + case TCL_ENV_DATA_DIR: if (i >= objc) { Tcl_WrongNumArgs(interp, 2, objv, "-xxx_dir dir"); @@ -1605,15 +1808,18 @@ bdb_EnvOpen(interp, objc, objv, ip, dbenvp) arg = Tcl_GetStringFromObj(objv[i++], NULL); _debug_check(); switch ((enum envopen)optindex) { - case TCL_ENV_DATA_DIR: - ret = dbenv->set_data_dir(dbenv, arg); - break; case TCL_ENV_ADD_DIR: ret = dbenv->add_data_dir(dbenv, arg); break; + case TCL_ENV_BLOB_DIR: + ret = dbenv->set_blob_dir(dbenv, arg); + break; case TCL_ENV_CREATE_DIR: ret = dbenv->set_create_dir(dbenv, arg); break; + case TCL_ENV_DATA_DIR: + ret = dbenv->set_data_dir(dbenv, arg); + break; default: break; } @@ -1785,6 +1991,8 @@ bdb_DbOpen(interp, objc, objv, ip, dbp) "-thread", #endif "-auto_commit", + "-blob_dir", + "-blob_threshold", "-btree", "-cachesize", "-chksum", @@ -1806,6 +2014,7 @@ bdb_DbOpen(interp, objc, objv, ip, dbp) "-hash", "-heap", "-heap_regionsize", + "-heapsize", "-inorder", "-len", "-lk_exclusive", @@ -1848,6 +2057,8 @@ bdb_DbOpen(interp, objc, objv, ip, dbp) TCL_DB_THREAD, #endif TCL_DB_AUTO_COMMIT, + TCL_DB_BLOB_DIR, + TCL_DB_BLOB_THRESHOLD, TCL_DB_BTREE, TCL_DB_CACHESIZE, TCL_DB_CHKSUM, @@ -1869,6 +2080,7 @@ bdb_DbOpen(interp, objc, objv, ip, dbp) TCL_DB_HASH, TCL_DB_HEAP, TCL_DB_HEAP_REGIONSIZE, + TCL_DB_HEAPSIZE, TCL_DB_INORDER, TCL_DB_LEN, TCL_DB_LK_EXCLUSIVE, @@ -1908,7 +2120,8 @@ bdb_DbOpen(interp, objc, objv, ip, dbp) size_t nlen; type = DB_UNKNOWN; - endarg = encenble = mode = nlen = set_err = set_msg = set_flags = 0; + endarg = encenble = mode = set_err = set_msg = set_flags = 0; + nlen = 0; set_pfx = 0; result = TCL_OK; subdbtmp = NULL; @@ -2122,6 +2335,34 @@ bdb_DbOpen(interp, objc, objv, ip, dbp) DB_RETOK_STD(ret), "set_heap_regionsize"); } break; + case TCL_DB_HEAPSIZE: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-heapsize {gbytes bytes}?"); + result = TCL_ERROR; + break; + } + result = Tcl_ListObjGetElements(interp, objv[i++], + &myobjc, &myobjv); + if (result != TCL_OK) + break; + if (myobjc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-heapsize {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 = (*dbp)->set_heapsize(*dbp, gbytes, bytes, 0); + result = _ReturnSetup(interp, ret, + DB_RETOK_STD(ret), "set_heapsize"); + break; case TCL_DB_LORDER: if (i >= objc) { Tcl_WrongNumArgs(interp, 2, objv, @@ -2533,6 +2774,37 @@ bdb_DbOpen(interp, objc, objv, ip, dbp) DB_RETOK_STD(ret), "set_q_extentsize"); } break; + case TCL_DB_BLOB_DIR: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-blob_threshold dir?"); + result = TCL_ERROR; + break; + } + arg = Tcl_GetStringFromObj(objv[i++], NULL); + if (arg != NULL && strlen(arg) != 0) { + _debug_check(); + ret = (*dbp)->set_blob_dir(*dbp, arg); + result = _ReturnSetup(interp, ret, + DB_RETOK_STD(ret), "set_blob_dir"); + } + break; + case TCL_DB_BLOB_THRESHOLD: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-blob_threshold bytes?"); + result = TCL_ERROR; + break; + } + result = _GetUInt32(interp, objv[i++], &bytes); + if (result == TCL_OK) { + _debug_check(); + ret = (*dbp)->set_blob_threshold(*dbp, + bytes, 0); + result = _ReturnSetup(interp, ret, + DB_RETOK_STD(ret), "set_blob_threshold"); + } + break; case TCL_DB_CACHESIZE: result = Tcl_ListObjGetElements(interp, objv[i++], &myobjc, &myobjv); @@ -2615,18 +2887,22 @@ bdb_DbOpen(interp, objc, objv, ip, dbp) if (errip->i_msg != NULL && errip->i_msg != stdout && errip->i_msg != stderr) (void)fclose(errip->i_msg); - if (strcmp(arg, "/dev/stdout") == 0) + if (strcmp(arg, "NULL") == 0) + errip->i_msg = NULL; + else if (strcmp(arg, "/dev/stdout") == 0) errip->i_msg = stdout; else if (strcmp(arg, "/dev/stderr") == 0) errip->i_msg = stderr; else errip->i_msg = fopen(arg, "a"); - if (errip->i_msg != NULL) { + if (strcmp(arg, "NULL") == 0 || errip->i_msg != NULL) { _debug_check(); (*dbp)->set_msgfile(*dbp, errip->i_msg); set_msg = 1; } - break; + else + set_msg = 0; + break; case TCL_DB_ERRPFX: if (i >= objc) { Tcl_WrongNumArgs(interp, 2, objv, @@ -2818,7 +3094,9 @@ bdb_DbOpen(interp, objc, objv, ip, dbp) dbr[nlen] = '2'; if (subdbr != NULL) subdbr[nlen] = '2'; - + + /* Disable blobs in case they are enabled environment wide. */ + (void)hsdbp->set_blob_threshold(hsdbp, 0, 0); /* * Use same flags as heap, note: heap does not use of * DB_AFTER/DB_BEFORE on cursor puts, but recno can. @@ -2968,8 +3246,8 @@ bdb_SeqOpen(interp, objc, objv, ip, seqp) db_recno_t recno; db_seq_t min, max, value; Tcl_WideInt tcl_value; - u_int32_t flags, oflags; - int cache, endarg, i, optindex, result, ret, setrange, setvalue, v; + u_int32_t cache, flags, oflags; + int endarg, i, optindex, result, ret, setrange, setvalue, v; char *arg, *db, msg[MSG_SIZE]; COMPQUIET(ip, NULL); @@ -3017,7 +3295,7 @@ bdb_SeqOpen(interp, objc, objv, ip, seqp) result = TCL_ERROR; break; } - result = Tcl_GetIntFromObj(interp, objv[i++], &cache); + result = _GetUInt32(interp, objv[i++], &cache); break; case TCL_SEQ_INIT: if (i >= objc) { @@ -3175,6 +3453,7 @@ bdb_DbRemove(interp, objc, objv) { static const char *bdbrem[] = { "-auto_commit", + "-blob_dir", "-encrypt", "-encryptaes", "-encryptany", @@ -3186,6 +3465,7 @@ bdb_DbRemove(interp, objc, objv) }; enum bdbrem { TCL_DBREM_AUTOCOMMIT, + TCL_DBREM_BLOBDIR, TCL_DBREM_ENCRYPT, TCL_DBREM_ENCRYPT_AES, TCL_DBREM_ENCRYPT_ANY, @@ -3201,18 +3481,19 @@ bdb_DbRemove(interp, objc, objv) u_int32_t enc_flag, iflags, set_flags; int endarg, i, optindex, result, ret, subdblen; u_char *subdbtmp; - char *arg, *db, *dbr, msg[MSG_SIZE], *passwd, *subdb, *subdbr; + char *arg, *bdir, *db, *dbr, msg[MSG_SIZE], *passwd, *subdb, *subdbr; size_t nlen; dbp = NULL; dbenv = NULL; txn = NULL; env = NULL; - enc_flag = iflags = set_flags = subdblen = 0; - endarg = nlen = 0; + enc_flag = iflags = set_flags = 0; + endarg = subdblen = 0; + nlen = 0; result = TCL_OK; subdbtmp = NULL; - db = dbr = passwd = subdb = subdbr = NULL; + bdir = db = dbr = passwd = subdb = subdbr = NULL; if (objc < 2) { Tcl_WrongNumArgs(interp, 2, objv, "?args? filename ?database?"); @@ -3241,6 +3522,16 @@ bdb_DbRemove(interp, objc, objv) iflags |= DB_AUTO_COMMIT; _debug_check(); break; + case TCL_DBREM_BLOBDIR: + /* Make sure we have an arg to check against! */ + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-blob_dir dir?"); + result = TCL_ERROR; + break; + } + bdir = Tcl_GetStringFromObj(objv[i++], NULL); + break; case TCL_DBREM_ENCRYPT: set_flags |= DB_ENCRYPT; _debug_check(); @@ -3372,6 +3663,14 @@ bdb_DbRemove(interp, objc, objv) result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "set_flags"); } + + if (bdir != NULL) { + ret = dbp->set_blob_dir(dbp, bdir); + result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "set_blob_dir"); + if (ret != 0) + goto error; + } } /* @@ -3922,6 +4221,7 @@ bdb_DbVerify(interp, objc, objv, ip) DBTCL_INFO *ip; /* Our internal info */ { static const char *bdbverify[] = { + "-blob_dir", "-btcompare", "-dupcompare", "-hashcompare", @@ -3940,6 +4240,7 @@ bdb_DbVerify(interp, objc, objv, ip) NULL }; enum bdbvrfy { + TCL_DBVRFY_BLOBDIR, TCL_DBVRFY_BTCOMPARE, TCL_DBVRFY_DUPCOMPARE, TCL_DBVRFY_HASHCOMPARE, @@ -3959,20 +4260,20 @@ bdb_DbVerify(interp, objc, objv, ip) DB_ENV *dbenv; DB *dbp; FILE *errf; - int (*bt_compare) __P((DB *, const DBT *, const DBT *)); - int (*dup_compare) __P((DB *, const DBT *, const DBT *)); - int (*h_compare) __P((DB *, const DBT *, const DBT *)); + int (*bt_compare) __P((DB *, const DBT *, const DBT *, size_t *)); + int (*dup_compare) __P((DB *, const DBT *, const DBT *, size_t *)); + int (*h_compare) __P((DB *, const DBT *, const DBT *, size_t *)); u_int32_t (*h_hash)__P((DB *, const void *, u_int32_t)); u_int32_t enc_flag, flags, set_flags; int endarg, i, optindex, result, ret, subdblen; - char *arg, *db, *errpfx, *passwd, *subdb; + char *arg, *bldir, *db, *errpfx, *passwd, *subdb; u_char *subdbtmp; dbenv = NULL; dbp = NULL; passwd = NULL; result = TCL_OK; - db = errpfx = subdb = NULL; + bldir = db = errpfx = subdb = NULL; errf = NULL; bt_compare = NULL; dup_compare = NULL; @@ -4004,6 +4305,27 @@ bdb_DbVerify(interp, objc, objv, ip) } i++; switch ((enum bdbvrfy)optindex) { + case TCL_DBVRFY_BLOBDIR: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "-blobdir dir"); + result = TCL_ERROR; + break; + } + arg = Tcl_GetStringFromObj(objv[i++], NULL); + /* + * If the user already set one, free it. + */ + if (bldir != NULL) + __os_free(dbenv != NULL ? + dbenv->env : NULL, bldir); + if ((ret = __os_strdup(NULL, arg, &bldir)) != 0) { + result = _ReturnSetup(interp, ret, + DB_RETOK_STD(ret), "__os_strdup"); + break; + } + _debug_check(); + break; case TCL_DBVRFY_BTCOMPARE: if (i >= objc) { Tcl_WrongNumArgs(interp, 2, objv, @@ -4222,6 +4544,13 @@ bdb_DbVerify(interp, objc, objv, ip) /* Hang our info pointer on the DB handle, so we can do callbacks. */ dbp->api_internal = ip; + if (bldir != NULL && dbenv == NULL && + (ret = dbp->set_blob_dir(dbp, bldir)) != 0) { + result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "set_blob_dir"); + goto error; + } + if (errf != NULL) dbp->set_errfile(dbp, errf); if (errpfx != NULL) @@ -4272,6 +4601,8 @@ bdb_DbVerify(interp, objc, objv, ip) result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db verify"); dbp = NULL; error: + if (bldir != NULL) + __os_free(dbenv != NULL ? dbenv->env : NULL, bldir); if (errf != NULL && errf != stdout && errf != stderr) (void)fclose(errf); if (errpfx != NULL) @@ -4405,6 +4736,9 @@ bdb_GetConfig(interp, objc, objv) #ifdef DIAGNOSTIC ADD_CONFIG_NAME("diagnostic"); #endif +#ifdef HAVE_FAILCHK_BROADCAST + ADD_CONFIG_NAME("failchk_broadcast"); +#endif #ifdef HAVE_PARTITION ADD_CONFIG_NAME("partition"); #endif @@ -4484,8 +4818,9 @@ bdb_MsgType(interp, objc, objv) * Add "no_type" for 0 so that we directly index. */ static const char *msgnames[] = { - "no_type", "alive", "alive_req", "all_req", - "bulk_log", "bulk_page", + "no_type", "alive", "alive_req", "all_req", "blob_all_req", + "blob_chunk", "blob_chunk_req", "blob_update", + "blob_update_req", "bulk_log", "bulk_page", "dupmaster", "file", "file_fail", "file_req", "lease_grant", "log", "log_more", "log_req", "master_req", "newclient", "newfile", "newmaster", "newsite", "page", @@ -4535,23 +4870,27 @@ bdb_DbUpgrade(interp, objc, objv) Tcl_Obj *CONST objv[]; /* The argument objects */ { static const char *bdbupg[] = { - "-dupsort", "-env", "--", NULL + "-dupsort", "-env", "-P", "--", NULL }; enum bdbupg { TCL_DBUPG_DUPSORT, TCL_DBUPG_ENV, + TCL_DBUPG_PASSWORD, TCL_DBUPG_ENDARG }; DB_ENV *dbenv; DB *dbp; + ENV *env; u_int32_t flags; int endarg, i, optindex, result, ret; - char *arg, *db; + char *arg, *db, *dbr, *passwd; + size_t nlen; dbenv = NULL; dbp = NULL; + env = NULL; result = TCL_OK; - db = NULL; + db = dbr = passwd = NULL; flags = endarg = 0; if (objc < 2) { @@ -4585,6 +4924,16 @@ bdb_DbUpgrade(interp, objc, objv) TCL_STATIC); return (TCL_ERROR); } + env = dbenv->env; + break; + case TCL_DBUPG_PASSWORD: + /* Make sure we have an arg to check against! */ + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-P passwd?"); + return (TCL_ERROR); + } + passwd = Tcl_GetStringFromObj(objv[i++], NULL); break; case TCL_DBUPG_ENDARG: endarg = 1; @@ -4630,11 +4979,40 @@ bdb_DbUpgrade(interp, objc, objv) dbp->set_errpfx(dbp, "DbUpgrade"); dbp->set_errcall(dbp, _ErrorFunc); } + if (passwd != NULL) { + if ((ret = dbp->set_encrypt( + dbp, passwd, DB_ENCRYPT_AES)) != 0 ) { + result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "set_encrypt"); + goto error; + } + } ret = dbp->upgrade(dbp, db, flags); - result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db upgrade"); + + if (ret == 0 && db != NULL) { + nlen = strlen(db); + if ((ret = __os_malloc(env, nlen + 2, &dbr)) != 0) { + Tcl_SetResult(interp, db_strerror(ret), + TCL_STATIC); + return (0); + } + memcpy(dbr, db, nlen); + dbr[nlen] = '1'; + dbr[nlen+1] = '\0'; + /* If the associated heap databases exist, upgrade them. */ + if (__os_exists(env, dbr, NULL) == 0) { + if ((ret = dbp->upgrade(dbp, dbr, flags)) != 0) + goto end; + dbr[nlen] = '2'; + ret = dbp->upgrade(dbp, dbr, flags); + } + } +end: result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "db upgrade"); error: if (dbp) (void)dbp->close(dbp, 0); + if (dbr) + __os_free(env, dbr); return (result); } @@ -4645,19 +5023,23 @@ error: * reporting and the Tcl_Obj representing their respective procs. */ static int -tcl_bt_compare(dbp, dbta, dbtb) +tcl_bt_compare(dbp, dbta, dbtb, locp) DB *dbp; const DBT *dbta, *dbtb; + size_t *locp; { + COMPQUIET(locp, NULL); return (tcl_compare_callback(dbp, dbta, dbtb, ((DBTCL_INFO *)dbp->api_internal)->i_compare, "bt_compare")); } static int -tcl_dup_compare(dbp, dbta, dbtb) +tcl_dup_compare(dbp, dbta, dbtb, locp) DB *dbp; const DBT *dbta, *dbtb; + size_t *locp; { + COMPQUIET(locp, NULL); return (tcl_compare_callback(dbp, dbta, dbtb, ((DBTCL_INFO *)dbp->api_internal)->i_dupcompare, "dup_compare")); } @@ -4771,6 +5153,10 @@ err: __db_errx(dbp->env, "Tcl h_hash callback failed"); return (0); } +/* + * We only support testing that the process is alive for now, because that + * seems easiest, and that's all we need for our tests for the moment. + */ static int tcl_isalive(dbenv, pid, tid, flags) DB_ENV *dbenv; @@ -4790,12 +5176,6 @@ tcl_isalive(dbenv, pid, tid, flags) if (mypid == pid && (LF_ISSET(DB_MUTEX_PROCESS_ONLY) || mytid == tid)) return (1); - /* - * We only support the PROCESS_ONLY case for now, because that seems - * easiest, and that's all we need for our tests for the moment. - */ - if (!LF_ISSET(DB_MUTEX_PROCESS_ONLY)) - return (1); ip = (DBTCL_INFO *)dbenv->app_private; interp = ip->i_interp; @@ -4971,6 +5351,64 @@ err: __db_errx(dbenv->env, return (ret); } + +static int +tcl_rep_view(dbenv, name, result, flags) + DB_ENV *dbenv; + const char *name; + int *result; + u_int32_t flags; +{ +#define TCLDB_VIEWITEMS 3 + ENV *env; + DBTCL_INFO *ip; + Tcl_Interp *interp; + Tcl_Obj *flags_o, *myobjv[TCLDB_MAXREPFLAGS], *objv[TCLDB_VIEWITEMS]; + int i, myobjc, res; + + COMPQUIET(flags, 0); + ip = (DBTCL_INFO *)dbenv->app_private; + interp = ip->i_interp; + myobjv[myobjc = 0] = NULL; + if (flags == 0) + myobjv[myobjc++] = NewStringObj("none", strlen("none")); + /* + * If we're given an unrecognized flag send "unknown". + */ + if (myobjc == 0) + myobjv[myobjc++] = NewStringObj("unknown", strlen("unknown")); + for (i = 0; i < myobjc; i++) + Tcl_IncrRefCount(myobjv[i]); + flags_o = Tcl_NewListObj(myobjc, myobjv); + + objv[0] = ip->i_rep_view; + objv[1] = NewStringObj(name, strlen(name)); + objv[2] = flags_o; /* Flags */ + Tcl_IncrRefCount(objv[1]); + Tcl_IncrRefCount(flags_o); + + res = Tcl_EvalObjv(interp, TCLDB_VIEWITEMS, objv, 0); + if (res != TCL_OK) + goto err; + Tcl_DecrRefCount(objv[1]); + for (i = 0; i < myobjc; i++) + Tcl_DecrRefCount(myobjv[i]); + Tcl_DecrRefCount(flags_o); + /* + * Put the result "do we replicate or not" into 'result'. + */ + res = Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), result); + if (res != TCL_OK) + goto err; + + return (0); + +err: env = dbenv->env; + __db_errx(env, "Tcl rep_view callback failed: %s", + Tcl_GetStringResult(interp)); + + return (1); +} #endif #ifdef CONFIG_TEST @@ -4994,7 +5432,7 @@ tcl_db_malloc(size) Tcl_SetObjLength(obj, (int)(size + sizeof(Tcl_Obj *))); buf = Tcl_GetString(obj); - memcpy(buf, &obj, sizeof(&obj)); + memcpy(buf, &obj, sizeof(Tcl_Obj *)); buf = (Tcl_Obj **)buf + 1; return (buf); @@ -5014,7 +5452,7 @@ tcl_db_realloc(ptr, size) Tcl_SetObjLength(obj, (int)(size + sizeof(Tcl_Obj *))); ptr = Tcl_GetString(obj); - memcpy(ptr, &obj, sizeof(&obj)); + memcpy(ptr, &obj, sizeof(Tcl_Obj *)); ptr = (Tcl_Obj **)ptr + 1; return (ptr); diff --git a/lang/tcl/tcl_dbcursor.c b/lang/tcl/tcl_dbcursor.c index a6df38dc..ebf0eaa9 100644 --- a/lang/tcl/tcl_dbcursor.c +++ b/lang/tcl/tcl_dbcursor.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -17,6 +17,8 @@ /* * Prototypes for procedures defined later in this file: */ +static int tcl_DbcDbstream __P((Tcl_Interp *, + int, Tcl_Obj * CONST*, DBC *, DB_STREAM **)); static int tcl_DbcDel __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *)); static int tcl_DbcDup __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *)); static int tcl_DbcCompare __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *)); @@ -43,6 +45,7 @@ dbc_Cmd(clientData, interp, objc, objv) #endif "close", "cmp", + "dbstream", "del", "dup", "get", @@ -55,18 +58,24 @@ dbc_Cmd(clientData, interp, objc, objv) #endif DBCCLOSE, DBCCOMPARE, + DBCDBSTREAM, DBCDELETE, DBCDUP, DBCGET, DBCPUT }; DBC *dbc; - DBTCL_INFO *dbip; + DB_STREAM *dbs; + DBTCL_INFO *dbip, *ip; + Tcl_Obj *res; + char newname[MSG_SIZE]; int cmdindex, result, ret; Tcl_ResetResult(interp); dbc = (DBC *)clientData; dbip = _PtrToInfo((void *)dbc); + res = NULL; + memset(newname, 0, MSG_SIZE); result = TCL_OK; if (objc <= 1) { @@ -120,6 +129,28 @@ dbc_Cmd(clientData, interp, objc, objv) _debug_check(); result = tcl_DbcCompare(interp, objc, objv, dbc); break; + case DBCDBSTREAM: + snprintf(newname, sizeof(newname), + "%s.dbs%d", dbip->i_name, dbip->i_dbcdbsid); + ip = _NewInfo(interp, NULL, newname, I_DBSTREAM); + if (ip != NULL) { + result = tcl_DbcDbstream(interp, objc, objv, dbc, &dbs); + if (result == TCL_OK) { + dbip->i_dbcdbsid++; + ip->i_parent = dbip; + (void)Tcl_CreateObjCommand(interp, newname, + (Tcl_ObjCmdProc *)dbstream_Cmd, + (ClientData)dbs, NULL); + res = NewStringObj(newname, strlen(newname)); + _SetInfoData(ip, dbs); + } else + _DeleteInfo(ip); + } else { + Tcl_SetResult(interp, + "Could not set up info", TCL_STATIC); + result = TCL_ERROR; + } + break; case DBCDELETE: result = tcl_DbcDel(interp, objc, objv, dbc); break; @@ -133,6 +164,13 @@ dbc_Cmd(clientData, interp, objc, objv) result = tcl_DbcPut(interp, objc, objv, dbc); break; } + + /* + * Only set result if we have a res. Otherwise, lower + * functions have already done so. + */ + if (result == TCL_OK && res) + Tcl_SetObjResult(interp, res); return (result); } @@ -200,6 +238,7 @@ tcl_DbcPut(interp, objc, objv, dbc) #endif "-after", "-before", + "-blob", "-current", "-keyfirst", "-keylast", @@ -213,6 +252,7 @@ tcl_DbcPut(interp, objc, objv, dbc) #endif DBCPUT_AFTER, DBCPUT_BEFORE, + DBCPUT_BLOB, DBCPUT_CURRENT, DBCPUT_KEYFIRST, DBCPUT_KEYLAST, @@ -281,6 +321,9 @@ tcl_DbcPut(interp, objc, objv, dbc) FLAG_CHECK(flag); flag = DB_BEFORE; break; + case DBCPUT_BLOB: + data.flags |= DB_DBT_BLOB; + break; case DBCPUT_CURRENT: FLAG_CHECK(flag); flag = DB_CURRENT; @@ -990,6 +1033,11 @@ tcl_DbcGet(interp, objc, objv, dbc, ispget) hkey.data = &rid; hkey.ulen = hkey.size = data.size; hkey.flags = DB_DBT_USERMEM; + if (data.data != NULL && + F_ISSET(&data, DB_DBT_MALLOC)) { + __os_ufree(dbc->env, data.data); + data.data = NULL; + } ret = phsdbp->pget(phsdbp, dbc->txn, &hkey, &data, &tmpdata, 0); } @@ -1336,3 +1384,59 @@ tcl_DbcDel(interp, objc, objv, dbc) out: return (result); } + +/* + * tcl_DbcDbstream -- + */ +static int +tcl_DbcDbstream(interp, objc, objv, dbc, dbsp) + Tcl_Interp *interp; /* Interpreter */ + int objc; /* How many arguments? */ + Tcl_Obj *CONST objv[]; /* The argument objects */ + DBC *dbc; /* Cursor pointer */ + DB_STREAM **dbsp; /* Return database stream pointer */ +{ + static const char *dbstreamopts[] = { + "-rdonly", + "-sync", + NULL + }; + enum dbstreamopts { + DBSTREAM_READ_ONLY, + DBSTREAM_SYNC + }; + u_int32_t flag; + int i, optindex, result, ret; + + result = TCL_OK; + flag = 0; + i = 2; + while (i < objc) { + if (Tcl_GetIndexFromObj(interp, objv[i], dbstreamopts, + "option", TCL_EXACT, &optindex) != TCL_OK) { + result = IS_HELP(objv[i]); + goto out; + } + i++; + switch ((enum dbstreamopts)optindex) { + case DBSTREAM_READ_ONLY: + flag |= DB_STREAM_READ; + break; + case DBSTREAM_SYNC: + flag |= DB_STREAM_SYNC_WRITE; + break; + } + if (result != TCL_OK) + break; + } + if (result != TCL_OK) + goto out; + + _debug_check(); + ret = dbc->db_stream(dbc, dbsp, flag); + if (ret != 0) + result = _ErrorSetup(interp, ret, "dbc db_stream"); +out: + return (result); +} + diff --git a/lang/tcl/tcl_dbstream.c b/lang/tcl/tcl_dbstream.c new file mode 100644 index 00000000..1acd06a8 --- /dev/null +++ b/lang/tcl/tcl_dbstream.c @@ -0,0 +1,302 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#ifdef HAVE_SYSTEM_INCLUDE_FILES +#include <tcl.h> +#endif +#include "dbinc/tcl_db.h" + +/* + * Prototypes for procedures defined later in this file: + */ +static int tcl_DbstreamRead __P((Tcl_Interp *, + int, Tcl_Obj * CONST*, DB_STREAM *)); +static int tcl_DbstreamWrite __P((Tcl_Interp *, + int, Tcl_Obj * CONST*, DB_STREAM *)); + +/* + * PUBLIC: int dbstream_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*)); + * + * dbstream_cmd -- + * Implements the database stream command. + */ +int +dbstream_Cmd(clientData, interp, objc, objv) + ClientData clientData; /* Database stream handle */ + Tcl_Interp *interp; /* Interpreter */ + int objc; /* How many arguments? */ + Tcl_Obj *CONST objv[]; /* The argument objects */ +{ + static const char *dbscmds[] = { + "close", + "read", + "size", + "write", + NULL + }; + enum dbscmds { + DBSTREAMCLOSE, + DBSTREAMREAD, + DBSTREAMSIZE, + DBSTREAMWRITE + }; + DB_STREAM *dbs; + Tcl_Obj *res; + DBTCL_INFO *dbip; + db_off_t size; + int cmdindex, result, ret; + + Tcl_ResetResult(interp); + dbs = (DB_STREAM *)clientData; + dbip = _PtrToInfo((void *)dbs); + size = 0; + ret = 0; + result = TCL_OK; + + if (objc <= 1) { + Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs"); + return (TCL_ERROR); + } + if (dbs == NULL) { + Tcl_SetResult(interp, "NULL dbstream pointer", TCL_STATIC); + return (TCL_ERROR); + } + if (dbip == NULL) { + Tcl_SetResult(interp, "NULL dbstream info pointer", TCL_STATIC); + return (TCL_ERROR); + } + + /* + * Get the command name index from the object based on the berkdbcmds + * defined above. + */ + if (Tcl_GetIndexFromObj(interp, objv[1], dbscmds, "command", + TCL_EXACT, &cmdindex) != TCL_OK) + return (IS_HELP(objv[1])); + switch ((enum dbscmds)cmdindex) { + case DBSTREAMCLOSE: + /* No args for this. Error if there are some. */ + if (objc > 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return (TCL_ERROR); + } + _debug_check(); + ret = dbs->close(dbs, 0); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "dbstream size")) == TCL_OK) { + (void)Tcl_DeleteCommand(interp, dbip->i_name); + _DeleteInfo(dbip); + } + break; + case DBSTREAMSIZE: + /* No args for this. Error if there are some. */ + if (objc > 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return (TCL_ERROR); + } + _debug_check(); + ret = dbs->size(dbs, &size, 0); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "dbstream size")) == TCL_OK) { + res = Tcl_NewWideIntObj((Tcl_WideInt)size); + Tcl_SetObjResult(interp, res); + } + break; + case DBSTREAMREAD: + result = tcl_DbstreamRead(interp, objc, objv, dbs); + break; + case DBSTREAMWRITE: + result = tcl_DbstreamWrite(interp, objc, objv, dbs); + break; + } + return (result); +} + +/* + * tcl_DbstreamRead -- + */ +static int +tcl_DbstreamRead(interp, objc, objv, dbs) + Tcl_Interp *interp; /* Interpreter */ + int objc; /* How many arguments? */ + Tcl_Obj *CONST objv[]; /* The argument objects */ + DB_STREAM *dbs; /* Database stream pointer */ +{ + static const char *dbsreadopts[] = { + "-offset", + "-size", + NULL + }; + enum dbsreadopts { + DBSTREAMREAD_OFFSET, + DBSTREAMREAD_SIZE + }; + Tcl_Obj *res; + Tcl_WideInt offtmp; + DBT data; + db_off_t offset; + u_int32_t size; + int i, optindex, result, ret; + + offtmp = 0; + memset(&data, 0, sizeof(DBT)); + offset = 0; + size = 0; + result = TCL_OK; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 2, objv, "?-args?"); + return (TCL_ERROR); + } + + /* + * Get the command name index from the object based on the options + * defined above. + */ + i = 2; + while (i < objc) { + if (Tcl_GetIndexFromObj(interp, objv[i], dbsreadopts, + "option", TCL_EXACT, &optindex) != TCL_OK) { + /* + * Reset the result so we don't get + * an errant error message if there is another error. + */ + if (IS_HELP(objv[i]) == TCL_OK) { + result = TCL_OK; + goto out; + } + Tcl_ResetResult(interp); + break; + } + i++; + switch ((enum dbsreadopts)optindex) { + case DBSTREAMREAD_OFFSET: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-offset offset?"); + result = TCL_ERROR; + goto out; + } + if ((result = Tcl_GetWideIntFromObj(interp, + objv[i++], &offtmp)) != TCL_OK) + goto out; + offset = (db_off_t)offtmp; + break; + case DBSTREAMREAD_SIZE: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-size bytes?"); + result = TCL_ERROR; + goto out; + } + if ((result = _GetUInt32(interp, + objv[i++], &size)) != TCL_OK) + goto out; + break; + } + } + _debug_check(); + data.flags = DB_DBT_MALLOC; + ret = dbs->read(dbs, &data, offset, size, 0); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "dbstream read")) == TCL_OK) { + res = NewStringObj(data.data, data.size); + Tcl_SetObjResult(interp, res); + } +out: if (data.data != NULL) + __os_ufree(dbs->dbc->env, data.data); + return (result); +} + +/* + * tcl_DbstreamWrite -- + */ +static int +tcl_DbstreamWrite(interp, objc, objv, dbs) + Tcl_Interp *interp; /* Interpreter */ + int objc; /* How many arguments? */ + Tcl_Obj *CONST objv[]; /* The argument objects */ + DB_STREAM *dbs; /* Database stream pointer */ +{ + static const char *dbsreadopts[] = { + "-offset", + NULL + }; + enum dbsreadopts { + DBSTREAMWRITE_OFFSET + }; + Tcl_WideInt offtmp; + DBT data; + db_off_t offset; + int freedata, i, optindex, result, ret; + + offtmp = 0; + memset(&data, 0, sizeof(DBT)); + offset = 0; + freedata = 0; + result = TCL_OK; + + if (objc != 3 && objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, "?-args? data"); + return (TCL_ERROR); + } + + /* + * Get the command name index from the object based on the options + * defined above. + */ + i = 2; + while (i < objc) { + if (Tcl_GetIndexFromObj(interp, objv[i], dbsreadopts, + "option", TCL_EXACT, &optindex) != TCL_OK) { + /* + * Reset the result so we don't get + * an errant error message if there is another error. + */ + if (IS_HELP(objv[i]) == TCL_OK) { + result = TCL_OK; + goto out; + } + Tcl_ResetResult(interp); + break; + } + i++; + switch ((enum dbsreadopts)optindex) { + case DBSTREAMWRITE_OFFSET: + if (i >= objc || objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-offset offset? data"); + result = TCL_ERROR; + goto out; + } + if ((result = Tcl_GetWideIntFromObj(interp, + objv[i++], &offtmp)) != TCL_OK) + goto out; + offset = (db_off_t)offtmp; + break; + } + } + _debug_check(); + ret = _CopyObjBytes(interp, objv[objc-1], + &data.data, &data.size, &freedata); + if (ret != 0) { + result = _ReturnSetup(interp, ret, + DB_RETOK_STD(ret), "dbstream write"); + goto out; + } + ret = dbs->write(dbs, &data, offset, 0); + result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "dbstream write"); + +out: if (freedata && data.data != NULL) + __os_free(NULL, data.data); + return (result); +} diff --git a/lang/tcl/tcl_env.c b/lang/tcl/tcl_env.c index e79ac2cf..7834e9ab 100644 --- a/lang/tcl/tcl_env.c +++ b/lang/tcl/tcl_env.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -23,12 +23,14 @@ static void _EnvInfoDelete __P((Tcl_Interp *, DBTCL_INFO *)); static int env_DbRemove __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); static int env_DbRename __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); static int env_EventInfo __P((Tcl_Interp *, - int, Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *)); + int, Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *)); +static int env_EventCount __P((Tcl_Interp *, + int, Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *)); static int env_GetFlags __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); -static int env_GetOpenFlag - __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); -static int env_GetLockDetect - __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +static int env_GetOpenFlag __P((Tcl_Interp *, + int, Tcl_Obj * CONST*, DB_ENV *)); +static int env_GetLockDetect __P((Tcl_Interp *, + int, Tcl_Obj * CONST*, DB_ENV *)); static int env_GetTimeout __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); static int env_GetVerbose __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); @@ -48,9 +50,12 @@ env_Cmd(clientData, interp, objc, objv) static const char *envcmds[] = { #ifdef CONFIG_TEST "attributes", + "backup", + "dbbackup", "errfile", "errpfx", "event_info", + "event_count", "failchk", "id_reset", "lock_detect", @@ -74,6 +79,7 @@ env_Cmd(clientData, interp, objc, objv) "log_put", "log_stat", "log_stat_print", + "log_verify", "lsn_reset", "mpool", "mpool_stat", @@ -81,10 +87,13 @@ env_Cmd(clientData, interp, objc, objv) "mpool_sync", "mpool_trickle", "msgfile", + "msgfile_close", "mutex", + "mutex_failchk_timeout", "mutex_free", "mutex_get_align", "mutex_get_incr", + "mutex_get_init", "mutex_get_max", "mutex_get_tas_spins", "mutex_lock", @@ -114,11 +123,15 @@ env_Cmd(clientData, interp, objc, objv) "rep_transport", "repmgr", "repmgr_get_ack_policy", + "repmgr_get_inqueue_max", + "repmgr_get_inqueue_redzone", + "repmgr_get_inqueue_fullevent", "repmgr_get_local_site", "repmgr_site_list", "repmgr_stat", "repmgr_stat_print", "set_flags", + "set_lg_max", "stat_print", "test", "txn_applied", @@ -133,6 +146,8 @@ env_Cmd(clientData, interp, objc, objv) "close", "dbremove", "dbrename", + "get_blob_dir", + "get_blob_threshold", "get_cachesize", "get_cache_max", "get_create_dir", @@ -149,20 +164,26 @@ env_Cmd(clientData, interp, objc, objv) "get_lk_detect", "get_lk_init_lockers", "get_lk_init_locks", + "get_lk_init_logid", "get_lk_init_objects", + "get_lk_init_thread", "get_lk_max_lockers", "get_lk_max_locks", "get_lk_max_objects", "get_lk_partitions", + "get_lk_tablesize", + "get_memory_max", "get_metadata_dir", "get_mp_max_openfd", "get_mp_max_write", "get_mp_mmapsize", "get_mp_mtxcount", "get_mp_pagesize", + "get_mp_tablesize", "get_open_flags", "get_shm_key", "get_tas_spins", + "get_thread_count", "get_timeout", "get_tmp_dir", "get_tx_init", @@ -170,6 +191,7 @@ env_Cmd(clientData, interp, objc, objv) "get_tx_timestamp", "get_verbose", "resize_cache", + "set_blob_threshold", "set_data_dir", "set_maxcache", "txn", @@ -179,9 +201,12 @@ env_Cmd(clientData, interp, objc, objv) enum envcmds { #ifdef CONFIG_TEST ENVATTR, + ENVBACKUP, + ENVDBBACKUP, ENVERRFILE, ENVERRPFX, ENVEVENTINFO, + ENVEVENTCOUNT, ENVFAILCHK, ENVIDRESET, ENVLKDETECT, @@ -205,6 +230,7 @@ env_Cmd(clientData, interp, objc, objv) ENVLOGPUT, ENVLOGSTAT, ENVLOGSTATPRT, + ENVLOGVERIFY, ENVLSNRESET, ENVMP, ENVMPSTAT, @@ -212,10 +238,13 @@ env_Cmd(clientData, interp, objc, objv) ENVMPSYNC, ENVTRICKLE, ENVMSGFILE, + ENVMSGFILECLOSE, ENVMUTEX, + ENVMUTFAILCHKTIMEOUT, ENVMUTFREE, ENVMUTGETALIGN, ENVMUTGETINCR, + ENVMUTGETINIT, ENVMUTGETMAX, ENVMUTGETTASSPINS, ENVMUTLOCK, @@ -245,11 +274,15 @@ env_Cmd(clientData, interp, objc, objv) ENVREPTRANSPORT, ENVREPMGR, ENVREPMGRGETACK, + ENVREPMGRGETINQUEUEMAX, + ENVREPMGRGETINQUEUEREDZONE, + ENVREPMGRGETINQUEUEFEVENT, ENVREPMGRGETLOCAL, ENVREPMGRSITELIST, ENVREPMGRSTAT, ENVREPMGRSTATPRT, ENVSETFLAGS, + ENVSETLOGMAX, ENVSTATPRT, ENVTEST, ENVTXNAPPLIED, @@ -264,6 +297,8 @@ env_Cmd(clientData, interp, objc, objv) ENVCLOSE, ENVDBREMOVE, ENVDBRENAME, + ENVGETBLOBDIR, + ENVGETBLOBTHRESHOLD, ENVGETCACHESIZE, ENVGETCACHEMAX, ENVGETCREATEDIR, @@ -280,20 +315,26 @@ env_Cmd(clientData, interp, objc, objv) ENVGETLKDETECT, ENVGETLKINITLOCKERS, ENVGETLKINITLOCKS, + ENVGETLKINITLOGID, ENVGETLKINITOBJECTS, + ENVGETLKINITTHREAD, ENVGETLKMAXLOCKERS, ENVGETLKMAXLOCKS, ENVGETLKMAXOBJECTS, ENVGETLKPARTITIONS, + ENVGETLKTABLESIZE, + ENVGETMEMORYMAX, ENVGETMETADATADIR, ENVGETMPMAXOPENFD, ENVGETMPMAXWRITE, ENVGETMPMMAPSIZE, ENVGETMPMTXCOUNT, ENVGETMPPAGESIZE, + ENVGETMPTABLESIZE, ENVGETOPENFLAG, ENVGETSHMKEY, ENVGETTASSPINS, + ENVGETTHREADCOUNT, ENVGETTIMEOUT, ENVGETTMPDIR, ENVGETTXINIT, @@ -301,6 +342,7 @@ env_Cmd(clientData, interp, objc, objv) ENVGETTXTIMESTAMP, ENVGETVERBOSE, ENVRESIZECACHE, + ENVSETBLOBTHRESHOLD, ENVSETDATADIR, ENVSETMAXCACHE, ENVTXN, @@ -353,9 +395,18 @@ env_Cmd(clientData, interp, objc, objv) res = NULL; switch ((enum envcmds)cmdindex) { #ifdef CONFIG_TEST + case ENVBACKUP: + result = tcl_EnvBackup(interp, objc, objv, dbenv); + break; + case ENVDBBACKUP: + result = tcl_EnvDbBackup(interp, objc, objv, dbenv); + break; case ENVEVENTINFO: result = env_EventInfo(interp, objc, objv, dbenv, envip); break; + case ENVEVENTCOUNT: + result = env_EventCount(interp, objc, objv, dbenv, envip); + break; case ENVFAILCHK: /* * No args for this. Error if there are some. @@ -442,7 +493,8 @@ env_Cmd(clientData, interp, objc, objv) if (result != TCL_OK) return (result); if (dbenv->env->lk_handle == NULL) { - Tcl_SetResult(interp, "env not configured for locking", NULL); + Tcl_SetResult(interp, + "env not configured for locking", NULL); return (TCL_ERROR); } ret = dbenv->set_lk_priority(dbenv, lockid, value); @@ -529,6 +581,9 @@ env_Cmd(clientData, interp, objc, objv) case ENVLOGSTATPRT: result = tcl_LogStatPrint(interp, objc, objv, dbenv); break; + case ENVLOGVERIFY: + result = tcl_LogVerify(interp, objc, objv, dbenv); + break; case ENVMPSTAT: result = tcl_MpStat(interp, objc, objv, dbenv); break; @@ -547,6 +602,9 @@ env_Cmd(clientData, interp, objc, objv) case ENVMUTEX: result = tcl_Mutex(interp, objc, objv, dbenv); break; + case ENVMUTFAILCHKTIMEOUT: + result = tcl_MutexFailchkTimeout(interp, objc, objv, dbenv); + break; case ENVMUTFREE: result = tcl_MutFree(interp, objc, objv, dbenv); break; @@ -556,6 +614,9 @@ env_Cmd(clientData, interp, objc, objv) case ENVMUTGETINCR: result = tcl_MutGet(interp, dbenv, DBTCL_MUT_INCR); break; + case ENVMUTGETINIT: + result = tcl_MutGet(interp, dbenv, DBTCL_MUT_INIT); + break; case ENVMUTGETMAX: result = tcl_MutGet(interp, dbenv, DBTCL_MUT_MAX); break; @@ -658,7 +719,7 @@ env_Cmd(clientData, interp, objc, objv) listobjc, listobjv, dbenv); break; case ENVREPLIMIT: - result = tcl_RepLimit(interp, objc, objv, dbenv); + result = tcl_RepLimit(interp, (objc-2), &objv[2], dbenv); break; case ENVREPNSITES: result = tcl_RepNSites(interp, objc, objv, dbenv); @@ -667,7 +728,7 @@ env_Cmd(clientData, interp, objc, objv) result = tcl_RepProcessMessage(interp, objc, objv, dbenv); break; case ENVREPREQUEST: - result = tcl_RepRequest(interp, objc, objv, dbenv); + result = tcl_RepRequest(interp, (objc-2), &objv[2], dbenv); break; case ENVREPSTART: result = tcl_RepStart(interp, objc, objv, dbenv); @@ -698,6 +759,22 @@ env_Cmd(clientData, interp, objc, objv) case ENVREPMGRGETACK: result = tcl_RepGetAckPolicy(interp, objc, objv, dbenv); break; + case ENVREPMGRGETINQUEUEMAX: + result = tcl_RepGetTwo(interp, dbenv, DBTCL_GETINQUEUE_MAX); + break; + case ENVREPMGRGETINQUEUEREDZONE: + result = tcl_RepGetTwo(interp, dbenv, DBTCL_GETINQUEUE_REDZONE); + break; + case ENVREPMGRGETINQUEUEFEVENT: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = __repmgr_get_incoming_queue_fullevent(dbenv, &intvalue); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "env repmgr_get_inqueue_fullevent")) == TCL_OK) + res = Tcl_NewIntObj(intvalue); + break; case ENVREPMGRGETLOCAL: result = tcl_RepGetLocalSite(interp, objc, objv, dbenv); break; @@ -710,6 +787,9 @@ env_Cmd(clientData, interp, objc, objv) case ENVREPMGRSTATPRT: result = tcl_RepMgrStatPrint(interp, objc, objv, dbenv); break; + case ENVSETLOGMAX: + result = tcl_LogSetMax(interp, dbenv, objv[2], NULL, NULL); + break; case ENVTXNAPPLIED: result = tcl_RepApplied(interp, objc, objv, dbenv); break; @@ -746,7 +826,7 @@ env_Cmd(clientData, interp, objc, objv) break; case ENVERRFILE: /* - * One args for this. Error if different. + * One arg for this. Error if different. */ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "errfile"); @@ -758,7 +838,7 @@ env_Cmd(clientData, interp, objc, objv) break; case ENVERRPFX: /* - * One args for this. Error if different. + * One arg for this. Error if different. */ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "pfx"); @@ -769,15 +849,27 @@ env_Cmd(clientData, interp, objc, objv) break; case ENVMSGFILE: /* - * One args for this. Error if different. + * One arg for this. Error if different. */ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "msgfile"); return (TCL_ERROR); } strarg = Tcl_GetStringFromObj(objv[2], NULL); - tcl_EnvSetMsgfile(interp, dbenv, envip, strarg); - result = TCL_OK; + ret = tcl_EnvSetMsgfile(interp, dbenv, envip, strarg); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "env set_msgfile")) == TCL_OK) + res = Tcl_NewIntObj(ret); + break; + case ENVMSGFILECLOSE: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, "msgfile_close"); + return (TCL_ERROR); + } + ret = tcl_EnvCloseMsgfile(interp, dbenv, envip); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "env close msgfile")) == TCL_OK) + res = Tcl_NewIntObj(ret); break; case ENVSETFLAGS: /* @@ -818,6 +910,27 @@ env_Cmd(clientData, interp, objc, objv) case ENVDBRENAME: result = env_DbRename(interp, objc, objv, dbenv); break; + case ENVGETBLOBDIR: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = dbenv->get_blob_dir(dbenv, &strval); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "env get_blob_dir")) == TCL_OK) + res = NewStringObj(strval, + strval != NULL ? strlen(strval) : 0); + break; + case ENVGETBLOBTHRESHOLD: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = dbenv->get_blob_threshold(dbenv, &value); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "env get_blob_threshold")) == TCL_OK) + res = Tcl_NewLongObj((long)value); + break; case ENVGETCACHESIZE: if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, NULL); @@ -853,7 +966,8 @@ env_Cmd(clientData, interp, objc, objv) ret = dbenv->get_create_dir(dbenv, &strval); if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "env get_create_dir")) == TCL_OK) - res = NewStringObj(strval, strlen(strval)); + res = NewStringObj(strval, + strval != NULL ? strlen(strval) : 0); break; case ENVGETDATADIRS: if (objc != 2) { @@ -866,7 +980,8 @@ env_Cmd(clientData, interp, objc, objv) res = Tcl_NewListObj(0, NULL); for (i = 0; result == TCL_OK && dirs[i] != NULL; i++) result = Tcl_ListObjAppendElement(interp, res, - NewStringObj(dirs[i], strlen(dirs[i]))); + NewStringObj(dirs[i], + dirs[i] != NULL ? strlen(dirs[i]) : 0)); } break; case ENVGETENCRYPTFLAGS: @@ -966,6 +1081,16 @@ env_Cmd(clientData, interp, objc, objv) "env get_lk_init_locks")) == TCL_OK) res = Tcl_NewLongObj((long)value); break; + case ENVGETLKINITLOGID: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = dbenv->get_memory_init(dbenv, DB_MEM_LOGID, &value); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "env get_lk_init_logid")) == TCL_OK) + res = Tcl_NewLongObj((long)value); + break; case ENVGETLKINITOBJECTS: if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, NULL); @@ -976,6 +1101,16 @@ env_Cmd(clientData, interp, objc, objv) "env get_lk_init_objects")) == TCL_OK) res = Tcl_NewLongObj((long)value); break; + case ENVGETLKINITTHREAD: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = dbenv->get_memory_init(dbenv, DB_MEM_THREAD, &value); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "env get_lk_init_thread")) == TCL_OK) + res = Tcl_NewLongObj((long)value); + break; case ENVGETLKMAXLOCKERS: if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, NULL); @@ -1016,6 +1151,29 @@ env_Cmd(clientData, interp, objc, objv) "env get_lk_partitions")) == TCL_OK) res = Tcl_NewLongObj((long)value); break; + case ENVGETLKTABLESIZE: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = dbenv->get_lk_tablesize(dbenv, &value); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "env get_lk_tablesize")) == TCL_OK) + res = Tcl_NewLongObj((long)value); + break; + case ENVGETMEMORYMAX: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = dbenv->get_memory_max(dbenv, &gbytes, &bytes); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "env get_memory_max")) == TCL_OK) { + myobjv[0] = Tcl_NewLongObj((long)gbytes); + myobjv[1] = Tcl_NewLongObj((long)bytes); + res = Tcl_NewListObj(2, myobjv); + } + break; case ENVGETMETADATADIR: if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, NULL); @@ -1079,6 +1237,16 @@ env_Cmd(clientData, interp, objc, objv) "env get_mp_pagesize")) == TCL_OK) res = Tcl_NewLongObj((long)value); break; + case ENVGETMPTABLESIZE: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = dbenv->get_mp_tablesize(dbenv, &value); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "env get_mp_tablesize")) == TCL_OK) + res = Tcl_NewLongObj((long)value); + break; case ENVGETOPENFLAG: result = env_GetOpenFlag(interp, objc, objv, dbenv); break; @@ -1102,6 +1270,16 @@ env_Cmd(clientData, interp, objc, objv) "env get_tas_spins")) == TCL_OK) res = Tcl_NewLongObj((long)value); break; + case ENVGETTHREADCOUNT: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = dbenv->get_thread_count(dbenv, &value); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "env get_thread_count")) == TCL_OK) + res = Tcl_NewLongObj((long)value); + break; case ENVGETTIMEOUT: result = env_GetTimeout(interp, objc, objv, dbenv); break; @@ -1174,9 +1352,21 @@ env_Cmd(clientData, interp, objc, objv) result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "resize_cache"); break; + case ENVSETBLOBTHRESHOLD: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-set_blob_threshold bytes?"); + result = TCL_ERROR; + break; + } + result = _GetUInt32(interp, objv[2], &bytes); + ret = dbenv->set_blob_threshold(dbenv, bytes, 0); + result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "env set_blob_threshold"); + break; case ENVSETDATADIR: /* - * One args for this. Error if different. + * One arg for this. Error if different. */ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "pfx"); @@ -1490,6 +1680,7 @@ _EnvInfoDelete(interp, envip) case I_AUX: case I_DB: case I_DBC: + case I_DBSTREAM: case I_ENV: case I_LOCK: case I_LOGC: @@ -1577,6 +1768,144 @@ tcl_EnvClose(interp, objc, objv, dbenv, envip) #ifdef CONFIG_TEST /* + * PUBLIC: int tcl_EnvBackup __P((Tcl_Interp *, int, Tcl_Obj * CONST*, + * PUBLIC: DB_ENV *)); + * + * tcl_EnvBackup -- + * Implements the ENV->backup command. + */ +int +tcl_EnvBackup(interp, objc, objv, dbenv) + Tcl_Interp *interp; /* Interpreter */ + int objc; /* arg count */ + Tcl_Obj * CONST* objv; /* args */ + DB_ENV *dbenv; /* Database pointer */ +{ + static const char *buwhich[] = { + "-clean", + "-create", + "-excl", + "-files", + "-no_logs", + "-single_dir", + "-update", + "-verbose", + NULL + }; + enum buwhich { + BKUPCLEAN, + BKUPCREATE, + BKUPEXCL, + BKUPFILES, + BKUPNOLOGS, + BKUPSINGLEDIR, + BKUPUPDATE, + BKUPVERBOSE + }; + int i, optindex, result, ret; + u_int32_t flags; + char *targetdir; + + result = TCL_OK; + flags = 0; + i = 2; + Tcl_SetResult(interp, "0", TCL_STATIC); + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?args? target"); + return (TCL_ERROR); + } + while (i < (objc - 1)) { + if (Tcl_GetIndexFromObj(interp, objv[i], buwhich, "option", + TCL_EXACT, &optindex) != TCL_OK) + return (IS_HELP(objv[i])); + i++; + switch ((enum buwhich)optindex) { + case BKUPCLEAN: + flags |= DB_BACKUP_CLEAN; + break; + case BKUPCREATE: + flags |= DB_CREATE; + break; + case BKUPEXCL: + flags |= DB_EXCL; + break; + case BKUPFILES: + flags |= DB_BACKUP_FILES; + break; + case BKUPNOLOGS: + flags |= DB_BACKUP_NO_LOGS; + break; + case BKUPSINGLEDIR: + flags |= DB_BACKUP_SINGLE_DIR; + break; + case BKUPUPDATE: + flags |= DB_BACKUP_UPDATE; + break; + case BKUPVERBOSE: + flags |= DB_VERB_BACKUP; + break; + } + } + targetdir = Tcl_GetStringFromObj(objv[i], NULL); + ret = dbenv->backup(dbenv, targetdir, flags); + result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "backup"); + return (result); +} + +/* + * PUBLIC: int tcl_EnvDbBackup __P((Tcl_Interp *, int, Tcl_Obj * CONST*, + * PUBLIC: DB_ENV *)); + * + * tcl_EnvDbBackup -- + * Implements the ENV->dbbackup command. + */ +int +tcl_EnvDbBackup(interp, objc, objv, dbenv) + Tcl_Interp *interp; /* Interpreter */ + int objc; /* arg count */ + Tcl_Obj * CONST* objv; /* args */ + DB_ENV *dbenv; /* Database pointer */ +{ + static const char *dbbuwhich[] = { + "-excl", + NULL + }; + enum dbbuwhich { + DBBKUPEXCL + }; + int i, optindex, result, ret; + u_int32_t flags; + char *srcfile, *targetdir; + + result = TCL_OK; + flags = 0; + i = 2; + Tcl_SetResult(interp, "0", TCL_STATIC); + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2, objv, "?args? file targetdir"); + return (TCL_ERROR); + } else if (objc > 4) { + /* + * If there is an arg, make sure it is the right one. + */ + if (Tcl_GetIndexFromObj(interp, objv[2], dbbuwhich, "option", + TCL_EXACT, &optindex) != TCL_OK) + return (IS_HELP(objv[2])); + switch ((enum dbbuwhich)optindex) { + case DBBKUPEXCL: + flags |= DB_EXCL; + break; + } + i = 4; + } + srcfile = Tcl_GetStringFromObj(objv[i++], NULL); + targetdir = Tcl_GetStringFromObj(objv[i], NULL); + ret = dbenv->dbbackup(dbenv, srcfile, targetdir, flags); + result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "dbbackup"); + return (result); +} + +/* * PUBLIC: int tcl_EnvIdReset __P((Tcl_Interp *, int, Tcl_Obj * CONST*, * PUBLIC: DB_ENV *)); * @@ -1699,6 +2028,7 @@ tcl_EnvVerbose(interp, dbenv, which, onoff) "deadlock", "fileops", "fileops_all", + "mvcc", "recovery", "register", "rep", @@ -1719,6 +2049,7 @@ tcl_EnvVerbose(interp, dbenv, which, onoff) ENVVERB_DEADLOCK, ENVVERB_FILEOPS, ENVVERB_FILEOPS_ALL, + ENVVERB_MVCC, ENVVERB_RECOVERY, ENVVERB_REGISTER, ENVVERB_REPLICATION, @@ -1762,6 +2093,9 @@ tcl_EnvVerbose(interp, dbenv, which, onoff) case ENVVERB_FILEOPS_ALL: wh = DB_VERB_FILEOPS_ALL; break; + case ENVVERB_MVCC: + wh = DB_VERB_MVCC; + break; case ENVVERB_RECOVERY: wh = DB_VERB_RECOVERY; break; @@ -1909,6 +2243,36 @@ err: return (result); } +static const struct { + u_int32_t flag; + char *name; +} event_names[] = { + { DB_EVENT_PANIC, "panic" }, + { DB_EVENT_REG_ALIVE, "reg_alive" }, + { DB_EVENT_REG_PANIC, "reg_panic" }, + { DB_EVENT_REP_AUTOTAKEOVER_FAILED, "autotakeover_failed" }, + { DB_EVENT_REP_CLIENT, "client" }, + { DB_EVENT_REP_CONNECT_BROKEN, "connection_broken" }, + { DB_EVENT_REP_CONNECT_ESTD, "connection_established" }, + { DB_EVENT_REP_CONNECT_TRY_FAILED, "connection_retry_failed" }, + { DB_EVENT_REP_DUPMASTER, "dupmaster" }, + { DB_EVENT_REP_ELECTED, "elected" }, + { DB_EVENT_REP_ELECTION_FAILED, "election_failed" }, + { DB_EVENT_REP_INQUEUE_FULL, "incoming_queue_full" }, + { DB_EVENT_REP_JOIN_FAILURE, "join_failure" }, + { DB_EVENT_REP_LOCAL_SITE_REMOVED, "local_site_removed" }, + { DB_EVENT_REP_MASTER, "master" }, + { DB_EVENT_REP_MASTER_FAILURE, "master_failure" }, + { DB_EVENT_REP_NEWMASTER, "newmaster" }, + { DB_EVENT_REP_PERM_FAILED, "perm_failed" }, + { DB_EVENT_REP_SITE_ADDED, "site_added" }, + { DB_EVENT_REP_SITE_REMOVED, "site_removed" }, + { DB_EVENT_REP_STARTUPDONE, "startupdone" }, + { DB_EVENT_REP_WOULD_ROLLBACK, "would_rollback" }, + { DB_EVENT_WRITE_FAILED, "write_failed" }, + { DB_EVENT_NO_SUCH_EVENT, NULL } +}; + /* * env_EventInfo -- * Implements the ENV->event_info command. @@ -1933,33 +2297,6 @@ env_EventInfo(interp, objc, objv, dbenv, ip) int clear, enc, i, ret, t_ret; u_int32_t bit_flag; - static const struct { - u_int32_t flag; - char *name; - } event_names[] = { - { DB_EVENT_PANIC, "panic" }, - { DB_EVENT_REG_ALIVE, "reg_alive" }, - { DB_EVENT_REG_PANIC, "reg_panic" }, - { DB_EVENT_REP_CLIENT, "client" }, - { DB_EVENT_REP_CONNECT_BROKEN, "connection_broken" }, - { DB_EVENT_REP_CONNECT_ESTD, "connection_established" }, - { DB_EVENT_REP_CONNECT_TRY_FAILED, "connection_retry_failed" }, - { DB_EVENT_REP_DUPMASTER, "dupmaster" }, - { DB_EVENT_REP_ELECTED, "elected" }, - { DB_EVENT_REP_ELECTION_FAILED, "election_failed" }, - { DB_EVENT_REP_JOIN_FAILURE, "join_failure" }, - { DB_EVENT_REP_LOCAL_SITE_REMOVED, "local_site_removed" }, - { DB_EVENT_REP_MASTER, "master" }, - { DB_EVENT_REP_MASTER_FAILURE, "master_failure" }, - { DB_EVENT_REP_NEWMASTER, "newmaster" }, - { DB_EVENT_REP_PERM_FAILED, "perm_failed" }, - { DB_EVENT_REP_SITE_ADDED, "site_added" }, - { DB_EVENT_REP_SITE_REMOVED, "site_removed" }, - { DB_EVENT_REP_STARTUPDONE, "startupdone" }, - { DB_EVENT_REP_WOULD_ROLLBACK, "would_rollback" }, - { DB_EVENT_WRITE_FAILED, "write_failed" }, - { DB_EVENT_NO_SUCH_EVENT, NULL } - }; /* * Note that when this list grows to more than 32 event types, the code * below (the shift operation) will be broken. @@ -2078,12 +2415,87 @@ env_EventInfo(interp, objc, objv, dbenv, ip) "mutex unlock")); Tcl_SetObjResult(interp, res); - if (clear) + if (clear) { ip->i_event_info->events = 0; + memset(ip->i_event_info->count, 0, + sizeof(ip->i_event_info->count)); + } return (TCL_OK); } /* + * env_EventCount -- + * Implements the 'env event_count' command. + */ +static int +env_EventCount(interp, objc, objv, dbenv, ip) + Tcl_Interp *interp; /* Interpreter */ + int objc; /* How many arguments? */ + Tcl_Obj *CONST objv[]; /* The argument objects */ + DB_ENV *dbenv; + DBTCL_INFO *ip; +{ + int result, ret, unused; + size_t count, i, names_cnt; + const char *name, **names; + Tcl_Obj *res; + + names = NULL; + res = NULL; + names_cnt = sizeof(event_names) / sizeof(event_names[0]); + + if(ip->i_event_info == NULL) { + /* Script needs "-event" in "berkdb env" cmd. */ + Tcl_SetResult(interp, + "event collection not enabled on this env", TCL_STATIC); + return (TCL_ERROR); + } + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "event_name"); + return (TCL_ERROR); + } + + /* + * Set up the event names array, then Tcl_GetIndexFromObj will + * check the name passed-in to see whether it is valid, and print + * hints when it is invalid. + */ + ret = __os_malloc(dbenv->env, + names_cnt * sizeof(char *), (void *)&names); + if (ret != 0) { + Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC); + return (TCL_ERROR); + } + + for (i = 0; i < names_cnt; i++) + names[i] = event_names[i].name; + + if (Tcl_GetIndexFromObj(interp, objv[2], names, "event_name", + TCL_EXACT, &unused) != TCL_OK) { + result = (IS_HELP(objv[2])); + goto err; + } + + name = Tcl_GetStringFromObj(objv[2], NULL); + for (i = 0; event_names[i].flag != DB_EVENT_NO_SUCH_EVENT; i++) + if (strcmp(event_names[i].name, name) == 0) + break; + DB_ASSERT(dbenv->env, event_names[i].flag != DB_EVENT_NO_SUCH_EVENT); + DB_ASSERT(dbenv->env, i < names_cnt); + count = ip->i_event_info->count[event_names[i].flag]; + res = Tcl_NewLongObj((long)count); + Tcl_SetObjResult(interp, res); + + result = TCL_OK; +err: + if (names != NULL) + __os_free(dbenv->env, (void *)names); + + return (result); +} + +/* * PUBLIC: int tcl_EnvSetFlags __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *, * PUBLIC: Tcl_Obj *)); * @@ -2260,6 +2672,7 @@ tcl_EnvTest(interp, objc, objv, dbenv) "postsync", "repmgr_perm", "subdb_lock", + "repmgr_heartbeat", NULL }; enum envtestat { @@ -2275,7 +2688,8 @@ tcl_EnvTest(interp, objc, objv, dbenv) ENVTEST_POSTOPEN, ENVTEST_POSTSYNC, ENVTEST_REPMGR_PERM, - ENVTEST_SUBDB_LOCKS + ENVTEST_SUBDB_LOCKS, + ENVTEST_REPMGR_HEARTBEAT }; static const char *envtestforce[] = { "noarchive_timeout", @@ -2390,6 +2804,10 @@ tcl_EnvTest(interp, objc, objv, dbenv) DB_ASSERT(env, loc == &env->test_abort); testval = DB_TEST_SUBDB_LOCKS; break; + case ENVTEST_REPMGR_HEARTBEAT: + DB_ASSERT(env, loc == &env->test_abort); + testval = DB_TEST_REPMGR_HEARTBEAT; + break; default: Tcl_SetResult(interp, "Illegal test location", TCL_STATIC); return (TCL_ERROR); @@ -2436,8 +2854,9 @@ env_DbRemove(interp, objc, objv, dbenv) result = TCL_OK; subdbtmp = NULL; db = dbr = subdb = subdbr = NULL; - endarg = nlen = subdblen = 0; + endarg = subdblen = 0; flag = 0; + nlen = 0; if (objc < 2) { Tcl_WrongNumArgs(interp, 2, objv, "?args? filename ?database?"); @@ -2538,7 +2957,7 @@ env_DbRemove(interp, objc, objv, dbenv) * try the dbremove and ignore ENOENT. */ if ((db != NULL || subdb != NULL) && ret == 0) { - /* set up file name for associated recno db for heap*/ + /* Set up file name for associated recno db for heap. */ if (db != NULL) { nlen = strlen(db); if ((ret = __os_malloc( @@ -2628,8 +3047,9 @@ env_DbRename(interp, objc, objv, dbenv) result = TCL_OK; subdbtmp = NULL; db = dbr = newname = newnamer = subdb = subdbr = NULL; - endarg = nlen = subdblen = 0; + endarg = subdblen = 0; flag = 0; + nlen = 0; if (objc < 2) { Tcl_WrongNumArgs(interp, 3, objv, @@ -2738,7 +3158,7 @@ env_DbRename(interp, objc, objv, dbenv) * try the dbrename and ignore ENOENT. */ if ((db != NULL || subdb != NULL) && ret == 0) { - /* set up file name for associated recno db for heap*/ + /* Set up file name for associated recno db for heap. */ if (db != NULL) { nlen = strlen(db); if ((ret = __os_malloc( @@ -2866,7 +3286,7 @@ env_GetFlags(interp, objc, objv, dbenv) if (strlen(buf) > 0) (void)strncat(buf, " ", sizeof(buf)); (void)strncat( - buf, open_flags[i].arg, sizeof(buf)); + buf, open_flags[i].arg, sizeof(buf) - 1); } res = NewStringObj(buf, strlen(buf)); @@ -2932,7 +3352,7 @@ env_GetOpenFlag(interp, objc, objv, dbenv) if (strlen(buf) > 0) (void)strncat(buf, " ", sizeof(buf)); (void)strncat( - buf, open_flags[i].arg, sizeof(buf)); + buf, open_flags[i].arg, sizeof(buf) - 1); } res = NewStringObj(buf, strlen(buf)); @@ -2984,7 +3404,7 @@ tcl_EnvGetEncryptFlags(interp, objc, objv, dbenv) if (strlen(buf) > 0) (void)strncat(buf, " ", sizeof(buf)); (void)strncat( - buf, encrypt_flags[i].arg, sizeof(buf)); + buf, encrypt_flags[i].arg, sizeof(buf) -1); } res = NewStringObj(buf, strlen(buf)); @@ -3060,6 +3480,7 @@ env_GetTimeout(interp, objc, objv, dbenv) char *arg; } timeout_flags[] = { { DB_SET_LOCK_TIMEOUT, "lock" }, + { DB_SET_MUTEX_FAILCHK_TIMEOUT, "mutex_failchk"}, { DB_SET_REG_TIMEOUT, "reg" }, { DB_SET_TXN_TIMEOUT, "txn" }, { 0, NULL } @@ -3196,13 +3617,13 @@ tcl_EnvSetErrfile(interp, dbenv, ip, errf) } /* - * PUBLIC: void tcl_EnvSetMsgfile __P((Tcl_Interp *, DB_ENV *, DBTCL_INFO *, + * PUBLIC: int tcl_EnvSetMsgfile __P((Tcl_Interp *, DB_ENV *, DBTCL_INFO *, * PUBLIC: char *)); * * tcl_EnvSetMsgfile -- * Implements the ENV->set_msgfile command. */ -void +int tcl_EnvSetMsgfile(interp, dbenv, ip, msgf) Tcl_Interp *interp; /* Interpreter */ DB_ENV *dbenv; /* Database pointer */ @@ -3216,14 +3637,52 @@ tcl_EnvSetMsgfile(interp, dbenv, ip, msgf) if (ip->i_msg != NULL && ip->i_msg != stdout && ip->i_msg != stderr) (void)fclose(ip->i_msg); - if (strcmp(msgf, "/dev/stdout") == 0) + if (strcmp(msgf, "NULL") == 0) + ip->i_msg = NULL; + else if (strcmp(msgf, "/dev/stdout") == 0) ip->i_msg = stdout; else if (strcmp(msgf, "/dev/stderr") == 0) ip->i_msg = stderr; else ip->i_msg = fopen(msgf, "a"); - if (ip->i_msg != NULL) + if (strcmp(msgf, "NULL") == 0 || ip->i_msg != NULL) { dbenv->set_msgfile(dbenv, ip->i_msg); + return (TCL_OK); + } + else + return (TCL_ERROR); +} + +/* + * PUBLIC: int tcl_EnvCloseMsgfile __P((Tcl_Interp *, DB_ENV *, DBTCL_INFO *)); + * + * tcl_EnvCloseMsgfile -- + * Implements the ENV->get_msgfile command. + */ +int +tcl_EnvCloseMsgfile(interp, dbenv, ip) + Tcl_Interp *interp; /* Interpreter */ + DB_ENV *dbenv; /* Database pointer */ + DBTCL_INFO *ip; /* Our internal info */ +{ + int ret; + FILE* msgfile; + COMPQUIET(interp, NULL); + /* + * If the user already set one, free it. + */ + ret = 0; + dbenv->get_msgfile(dbenv, &msgfile); + if (msgfile != ip->i_msg) { + return (TCL_ERROR); + } + if (msgfile != NULL && msgfile != stdout && + msgfile != stderr) { + ret = fclose(msgfile); + } + ip->i_msg = NULL; + dbenv->set_msgfile(dbenv, NULL); + return ret; } /* @@ -3281,12 +3740,14 @@ tcl_EnvStatPrint(interp, objc, objv, dbenv) { static const char *envstatprtopts[] = { "-all", + "-alloc", "-clear", "-subsystem", NULL }; enum envstatprtopts { ENVSTATPRTALL, + ENVSTATPRTALLOC, ENVSTATPRTCLEAR, ENVSTATPRTSUB }; @@ -3308,6 +3769,9 @@ tcl_EnvStatPrint(interp, objc, objv, dbenv) case ENVSTATPRTALL: flag |= DB_STAT_ALL; break; + case ENVSTATPRTALLOC: + flag |= DB_STAT_ALLOC; + break; case ENVSTATPRTCLEAR: flag |= DB_STAT_CLEAR; break; diff --git a/lang/tcl/tcl_internal.c b/lang/tcl/tcl_internal.c index a358ae99..25f2e48c 100644 --- a/lang/tcl/tcl_internal.c +++ b/lang/tcl/tcl_internal.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -165,6 +165,9 @@ _DeleteInfo(p) if (p->i_hashproc != NULL) { Tcl_DecrRefCount(p->i_hashproc); } + if (p->i_isalive != NULL) { + Tcl_DecrRefCount(p->i_isalive); + } if (p->i_part_callback != NULL) { Tcl_DecrRefCount(p->i_part_callback); } @@ -177,6 +180,9 @@ _DeleteInfo(p) if (p->i_rep_send != NULL) { Tcl_DecrRefCount(p->i_rep_send); } + if (p->i_rep_view != NULL) { + Tcl_DecrRefCount(p->i_rep_view); + } if (p->i_type == I_ENV && p->i_event_info != NULL) __os_free(NULL, p->i_event_info); @@ -609,6 +615,7 @@ _EventFunc(dbenv, event, info) /* Record the fact that this event occurred. */ bit_flag = 1 << event; ip->i_event_info->events |= bit_flag; + ip->i_event_info->count[event]++; /* * For events that have associated "info" (currently most don't), save diff --git a/lang/tcl/tcl_lock.c b/lang/tcl/tcl_lock.c index 5a06b1a0..847b8aef 100644 --- a/lang/tcl/tcl_lock.c +++ b/lang/tcl/tcl_lock.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -217,18 +217,31 @@ tcl_LockStat(interp, objc, objv, dbenv) { DB_LOCK_STAT *sp; Tcl_Obj *res; + u_int32_t flag; + char *arg; int result, ret; + flag = 0; result = TCL_OK; - /* - * No args for this. Error if there are some. - */ - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); + + if (objc > 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?-clear?"); return (TCL_ERROR); } + + if (objc == 3) { + arg = Tcl_GetStringFromObj(objv[2], NULL); + if (strcmp(arg, "-clear") == 0) + flag = DB_STAT_CLEAR; + else { + Tcl_SetResult(interp, + "db stat: unknown arg", TCL_STATIC); + return (TCL_ERROR); + } + } + _debug_check(); - ret = dbenv->lock_stat(dbenv, &sp, 0); + ret = dbenv->lock_stat(dbenv, &sp, flag); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock stat"); if (result == TCL_ERROR) return (result); @@ -237,7 +250,6 @@ tcl_LockStat(interp, objc, objv, dbenv) * list pairs and free up the memory. */ res = Tcl_NewObj(); -#ifdef HAVE_STATISTICS /* * MAKE_STAT_LIST assumes 'res' and 'error' label. */ @@ -266,6 +278,9 @@ tcl_LockStat(interp, objc, objv, dbenv) sp->st_maxlsteals); MAKE_STAT_LIST("Current number of lockers", sp->st_nlockers); MAKE_STAT_LIST("Maximum number of lockers so far", sp->st_maxnlockers); + MAKE_STAT_LIST("Number of hits in the thread locker cache", + sp->st_nlockers_hit); + MAKE_STAT_LIST("Total number of lockers reused", sp->st_nlockers_reused); MAKE_STAT_LIST("Current number of objects", sp->st_nobjects); MAKE_STAT_LIST("Maximum number of objects so far", sp->st_maxnobjects); MAKE_STAT_LIST("Maximum number of objects in any hash bucket", @@ -304,7 +319,7 @@ tcl_LockStat(interp, objc, objv, dbenv) sp->st_part_max_wait); MAKE_STAT_LIST("Maximum number nowaits on any lock partition mutex", sp->st_part_max_nowait); -#endif + Tcl_SetObjResult(interp, res); error: __os_ufree(dbenv->env, sp); @@ -326,6 +341,7 @@ tcl_LockStatPrint(interp, objc, objv, dbenv) { static const char *lkstatprtopts[] = { "-all", + "-alloc", "-clear", "-lk_conf", "-lk_lockers", @@ -335,6 +351,7 @@ tcl_LockStatPrint(interp, objc, objv, dbenv) }; enum lkstatprtopts { LKSTATPRTALL, + LKSTATPRTALLOC, LKSTATPRTCLEAR, LKSTATPRTCONF, LKSTATPRTLOCKERS, @@ -359,6 +376,9 @@ tcl_LockStatPrint(interp, objc, objv, dbenv) case LKSTATPRTALL: flag |= DB_STAT_ALL; break; + case LKSTATPRTALLOC: + flag |= DB_STAT_ALLOC; + break; case LKSTATPRTCLEAR: flag |= DB_STAT_CLEAR; break; diff --git a/lang/tcl/tcl_log.c b/lang/tcl/tcl_log.c index 3024f7b1..3331da16 100644 --- a/lang/tcl/tcl_log.c +++ b/lang/tcl/tcl_log.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -345,18 +345,31 @@ tcl_LogStat(interp, objc, objv, dbenv) { DB_LOG_STAT *sp; Tcl_Obj *res; + u_int32_t flag; + char *arg; int result, ret; + flag = 0; result = TCL_OK; - /* - * No args for this. Error if there are some. - */ - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); + + if (objc > 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?-clear?"); return (TCL_ERROR); } + + if (objc == 3) { + arg = Tcl_GetStringFromObj(objv[2], NULL); + if (strcmp(arg, "-clear") == 0) + flag = DB_STAT_CLEAR; + else { + Tcl_SetResult(interp, + "db stat: unknown arg", TCL_STATIC); + return (TCL_ERROR); + } + } + _debug_check(); - ret = dbenv->log_stat(dbenv, &sp, 0); + ret = dbenv->log_stat(dbenv, &sp, flag); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "log stat"); if (result == TCL_ERROR) return (result); @@ -369,7 +382,6 @@ tcl_LogStat(interp, objc, objv, dbenv) /* * MAKE_STAT_LIST assumes 'res' and 'error' label. */ -#ifdef HAVE_STATISTICS MAKE_STAT_LIST("Magic", sp->st_magic); MAKE_STAT_LIST("Log file Version", sp->st_version); MAKE_STAT_LIST("Region size", sp->st_regsize); @@ -398,7 +410,7 @@ tcl_LogStat(interp, objc, objv, dbenv) MAKE_STAT_LIST("Min commits in a log flush", sp->st_mincommitperflush); MAKE_WSTAT_LIST("Number of region lock waits", sp->st_region_wait); MAKE_WSTAT_LIST("Number of region lock nowaits", sp->st_region_nowait); -#endif + Tcl_SetObjResult(interp, res); error: __os_ufree(dbenv->env, sp); @@ -417,13 +429,16 @@ tcl_LogStatPrint(interp, objc, objv, dbenv) int objc; /* How many arguments? */ Tcl_Obj *CONST objv[]; /* The argument objects */ DB_ENV *dbenv; /* Environment pointer */ -{ static const char *logstatprtopts[] = { +{ + static const char *logstatprtopts[] = { "-all", + "-alloc", "-clear", NULL }; enum logstatprtopts { LOGSTATPRTALL, + LOGSTATPRTALLOC, LOGSTATPRTCLEAR }; u_int32_t flag; @@ -444,6 +459,9 @@ tcl_LogStatPrint(interp, objc, objv, dbenv) case LOGSTATPRTALL: flag |= DB_STAT_ALL; break; + case LOGSTATPRTALLOC: + flag |= DB_STAT_ALLOC; + break; case LOGSTATPRTCLEAR: flag |= DB_STAT_CLEAR; break; @@ -464,6 +482,33 @@ error: } /* + * tcl_LogVerify -- + * + * PUBLIC: int tcl_LogVerify __P((Tcl_Interp *, int, + * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); + */ +int +tcl_LogVerify(interp, objc, objv, dbenv) + Tcl_Interp *interp; /* Interpreter */ + int objc; /* How many arguments? */ + Tcl_Obj *CONST objv[]; /* The argument objects */ + DB_ENV *dbenv; /* Environment pointer */ +{ + DB_LOG_VERIFY_CONFIG lvc; + int result, ret; + + COMPQUIET(objc, 0); + COMPQUIET(objv, NULL); + result = TCL_OK; + memset(&lvc, 0, sizeof(lvc)); + _debug_check(); + ret = dbenv->log_verify(dbenv, &lvc); + result = _ReturnSetup(interp, + ret, DB_RETOK_STD(ret), "dbenv log_verify"); + return (result); + +} +/* * logc_Cmd -- * Implements the log cursor command. * @@ -691,17 +736,21 @@ memerr: if (res != NULL) { static const char *confwhich[] = { "autoremove", + "blob", "direct", "dsync", "inmemory", + "nosync", "zero", NULL }; enum logwhich { LOGCONF_AUTO, + LOGCONF_BLOB, LOGCONF_DIRECT, LOGCONF_DSYNC, LOGCONF_INMEMORY, + LOGCONF_NOSYNC, LOGCONF_ZERO }; @@ -739,6 +788,9 @@ tcl_LogConfig(interp, dbenv, which, onoff) case LOGCONF_AUTO: wh = DB_LOG_AUTO_REMOVE; break; + case LOGCONF_BLOB: + wh = DB_LOG_BLOB; + break; case LOGCONF_DIRECT: wh = DB_LOG_DIRECT; break; @@ -748,6 +800,9 @@ tcl_LogConfig(interp, dbenv, which, onoff) case LOGCONF_INMEMORY: wh = DB_LOG_IN_MEMORY; break; + case LOGCONF_NOSYNC: + wh = DB_LOG_NOSYNC; + break; case LOGCONF_ZERO: wh = DB_LOG_ZERO; break; @@ -769,7 +824,7 @@ tcl_LogConfig(interp, dbenv, which, onoff) } ret = dbenv->log_set_config(dbenv, wh, on); return (_ReturnSetup(interp, ret, DB_RETOK_STD(ret), - "env rep_config")); + "env log_config")); } /* @@ -798,6 +853,9 @@ tcl_LogGetConfig(interp, dbenv, which) case LOGCONF_AUTO: wh = DB_LOG_AUTO_REMOVE; break; + case LOGCONF_BLOB: + wh = DB_LOG_BLOB; + break; case LOGCONF_DIRECT: wh = DB_LOG_DIRECT; break; @@ -807,6 +865,9 @@ tcl_LogGetConfig(interp, dbenv, which) case LOGCONF_INMEMORY: wh = DB_LOG_IN_MEMORY; break; + case LOGCONF_NOSYNC: + wh = DB_LOG_NOSYNC; + break; case LOGCONF_ZERO: wh = DB_LOG_ZERO; break; @@ -821,4 +882,46 @@ tcl_LogGetConfig(interp, dbenv, which) } return (result); } + +/* + * tcl_LogSetMax -- + * Call DB_ENV->set_lg_max(). + * Also delay setting the maximum log if the log buffer size + * has already been set, this only applies when setting the + * maximum log when opening the environment. + * + * PUBLIC: int tcl_LogSetMax + * PUBLIC: __P((Tcl_Interp *, DB_ENV *,Tcl_Obj *,u_int32_t *,u_int32_t *)); + */ +int +tcl_LogSetMax(interp, dbenv, objv, logbufset, logmaxset) + Tcl_Interp *interp; + DB_ENV *dbenv; + Tcl_Obj *objv; + u_int32_t *logbufset; + u_int32_t *logmaxset; +{ + int result, ret; + u_int32_t uintarg; + + result = _GetUInt32(interp, objv, &uintarg); + /* + * If logbufset is NULL it means we're setting it after + * the env is opened. If logbufset is not NULL, we're called + * from opening the environment and only set if logbufset + * has already been set to a value. + */ + if (result == TCL_OK && (logbufset == NULL || (*logbufset) == 0)) { + _debug_check(); + ret = dbenv->set_lg_max(dbenv, uintarg); + result = _ReturnSetup(interp, ret, + DB_RETOK_STD(ret), "log_max"); + if (logbufset != NULL) + *logbufset = 0; + } else + if (logmaxset != NULL) + *logmaxset = uintarg; + + return (result); +} #endif diff --git a/lang/tcl/tcl_mp.c b/lang/tcl/tcl_mp.c index ba4318da..7e0619dc 100644 --- a/lang/tcl/tcl_mp.c +++ b/lang/tcl/tcl_mp.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -19,6 +19,8 @@ */ #ifdef CONFIG_TEST static int mp_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*)); +static int mp_size_getinput __P((Tcl_Interp *, Tcl_Obj * CONST*, int, + u_int32_t *, u_int32_t *)); static int pg_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*)); static int tcl_MpGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_MPOOLFILE *, DBTCL_INFO *)); @@ -152,35 +154,52 @@ tcl_Mp(interp, objc, objv, dbenv, envip) DBTCL_INFO *envip; /* Info pointer */ { static const char *mpopts[] = { + "-clear_len", "-create", + "-lsn_offset", + "-maxsize", "-mode", "-multiversion", "-nommap", "-pagesize", + "-pgcookie", "-rdonly", NULL }; enum mpopts { + MPCLEARLEN, MPCREATE, + MPLSNOFFSET, + MPMAXSIZE, MPMODE, MPMULTIVERSION, MPNOMMAP, MPPAGE, + MPPGCOOKIE, MPRDONLY }; + DBT cookie; DBTCL_INFO *ip; DB_MPOOLFILE *mpf; Tcl_Obj *res; - u_int32_t flag; - int i, pgsize, mode, optindex, result, ret; + u_int32_t bytes, flag, gbytes, len; + int32_t offset; + int cookiesz, i, mode, optindex, pgsize; + int result, ret, setlen, setofs, setsize, value; char *file, newname[MSG_SIZE]; + ip = NULL; + mpf = NULL; result = TCL_OK; i = 2; flag = 0; + bytes = gbytes = len = 0; + offset = 0; mode = 0; pgsize = 0; + ret = setlen = setofs = setsize = value = 0; memset(newname, 0, MSG_SIZE); + memset(&cookie, 0, sizeof(DBT)); while (i < objc) { if (Tcl_GetIndexFromObj(interp, objv[i], mpopts, "option", TCL_EXACT, &optindex) != TCL_OK) { @@ -196,9 +215,41 @@ tcl_Mp(interp, objc, objv, dbenv, envip) } i++; switch ((enum mpopts)optindex) { + case MPCLEARLEN: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-clearlen len?"); + result = TCL_ERROR; + break; + } + result = _GetUInt32(interp, objv[i++], &len); + setlen = 1; + break; + case MPLSNOFFSET: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-lsnoffset offset?"); + result = TCL_ERROR; + break; + } + result = Tcl_GetIntFromObj(interp, objv[i++], &value); + offset = (int32_t)value; + setofs = 1; + break; case MPCREATE: flag |= DB_CREATE; break; + case MPMAXSIZE: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-maxsize {gbytes bytes}?"); + result = TCL_ERROR; + break; + } + result = mp_size_getinput(interp, + objv, i++, &gbytes, &bytes); + setsize = 1; + break; case MPMODE: if (i >= objc) { Tcl_WrongNumArgs(interp, 2, objv, @@ -235,6 +286,16 @@ tcl_Mp(interp, objc, objv, dbenv, envip) */ result = Tcl_GetIntFromObj(interp, objv[i++], &pgsize); break; + case MPPGCOOKIE: + if (i >= objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-pgcookie cookie?"); + result = TCL_ERROR; + break; + } + cookie.data = Tcl_GetStringFromObj(objv[i++], &cookiesz); + cookie.size = (u_int32_t)cookiesz; + break; case MPRDONLY: flag |= DB_RDONLY; break; @@ -265,23 +326,27 @@ tcl_Mp(interp, objc, objv, dbenv, envip) } _debug_check(); - if ((ret = dbenv->memp_fcreate(dbenv, &mpf, 0)) != 0) { - result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "mpool"); - _DeleteInfo(ip); + if ((ret = dbenv->memp_fcreate(dbenv, &mpf, 0)) != 0) + goto error; + + if (setlen != 0 && (ret = mpf->set_clear_len(mpf, len)) != 0) + goto error; + + if (setsize != 0 && (ret = mpf->set_maxsize(mpf, gbytes, bytes)) != 0) + goto error; + + if (setofs != 0 && (ret = mpf->set_lsn_offset(mpf, offset)) != 0) + goto error; + + if (cookie.data != NULL && (ret = mpf->set_pgcookie(mpf, &cookie)) != 0) goto error; - } /* * XXX * Interface doesn't currently support DB_MPOOLFILE configuration. */ - if ((ret = mpf->open(mpf, file, flag, mode, (size_t)pgsize)) != 0) { - result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "mpool"); - _DeleteInfo(ip); - - (void)mpf->close(mpf, 0); + if ((ret = mpf->open(mpf, file, flag, mode, (size_t)pgsize)) != 0) goto error; - } /* * Success. Set up return. Set up new info and command widget for @@ -297,6 +362,12 @@ tcl_Mp(interp, objc, objv, dbenv, envip) Tcl_SetObjResult(interp, res); error: + if (ret != 0) { + result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "mpool"); + _DeleteInfo(ip); + if (mpf != NULL) + (void)mpf->close(mpf, 0); + } return (result); } @@ -324,11 +395,9 @@ tcl_MpStat(interp, objc, objv, dbenv) flag = 0; result = TCL_OK; savefsp = NULL; - /* - * No args for this. Error if there are some. - */ + if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); + Tcl_WrongNumArgs(interp, 2, objv, "?-clear?"); return (TCL_ERROR); } @@ -354,7 +423,6 @@ tcl_MpStat(interp, objc, objv, dbenv) * list pairs and free up the memory. */ res = Tcl_NewObj(); -#ifdef HAVE_STATISTICS /* * MAKE_STAT_LIST assumes 'res' and 'error' label. */ @@ -378,6 +446,10 @@ tcl_MpStat(interp, objc, objv, dbenv) MAKE_WSTAT_LIST("Clean page evictions", sp->st_ro_evict); MAKE_WSTAT_LIST("Dirty page evictions", sp->st_rw_evict); MAKE_WSTAT_LIST("Dirty pages trickled", sp->st_page_trickle); + /* Undocumented field used by tests only. */ + MAKE_STAT_LIST("Odd file size detected", sp->st_oddfsize_detect); + /* Undocumented field used by tests only. */ + MAKE_STAT_LIST("Odd file size resolved", sp->st_oddfsize_resolve); MAKE_STAT_LIST("Cached pages", sp->st_pages); MAKE_WSTAT_LIST("Cached clean pages", sp->st_page_clean); MAKE_WSTAT_LIST("Cached dirty pages", sp->st_page_dirty); @@ -398,6 +470,8 @@ tcl_MpStat(interp, objc, objv, dbenv) MAKE_WSTAT_LIST("Buffers frozen", sp->st_mvcc_frozen); MAKE_WSTAT_LIST("Buffers thawed", sp->st_mvcc_thawed); MAKE_WSTAT_LIST("Frozen buffers freed", sp->st_mvcc_freed); + MAKE_WSTAT_LIST("The number of outdated intermediate versions reused", + sp->st_mvcc_reused); MAKE_WSTAT_LIST("Page allocations", sp->st_alloc); MAKE_STAT_LIST("Buckets examined during allocation", sp->st_alloc_buckets); @@ -415,6 +489,7 @@ tcl_MpStat(interp, objc, objv, dbenv) * our per-file sublist. */ res1 = res; +#ifdef HAVE_STATISTICS for (savefsp = fsp; fsp != NULL && *fsp != NULL; fsp++) { res = Tcl_NewObj(); MAKE_STAT_STRLIST("File Name", (*fsp)->file_name); @@ -459,12 +534,14 @@ tcl_MpStatPrint(interp, objc, objv, dbenv) { static const char *mpstatprtopts[] = { "-all", + "-alloc", "-clear", "-hash", NULL }; enum mpstatprtopts { MPSTATPRTALL, + MPSTATPRTALLOC, MPSTATPRTCLEAR, MPSTATPRTHASH }; @@ -486,6 +563,9 @@ tcl_MpStatPrint(interp, objc, objv, dbenv) case MPSTATPRTALL: flag |= DB_STAT_ALL; break; + case MPSTATPRTALLOC: + flag |= DB_STAT_ALLOC; + break; case MPSTATPRTCLEAR: flag |= DB_STAT_CLEAR; break; @@ -526,8 +606,11 @@ mp_Cmd(clientData, interp, objc, objv) "get_clear_len", "get_fileid", "get_ftype", + "get_last_pgno", "get_lsn_offset", + "get_maxsize", "get_pgcookie", + "set_maxsize", NULL }; enum mpcmds { @@ -537,16 +620,20 @@ mp_Cmd(clientData, interp, objc, objv) MPGETCLEARLEN, MPGETFILEID, MPGETFTYPE, + MPGETLASTPGNO, MPGETLSNOFFSET, - MPGETPGCOOKIE + MPGETMAXSIZE, + MPGETPGCOOKIE, + MPSETMAXSIZE }; DB_MPOOLFILE *mp; int cmdindex, ftype, length, result, ret; DBTCL_INFO *mpip; - Tcl_Obj *res; + Tcl_Obj *res, *myobjv[2]; char *obj_name; - u_int32_t value; + u_int32_t bytes, gbytes, value; int32_t intval; + db_pgno_t pgno; u_int8_t fileid[DB_FILE_ID_LEN]; DBT cookie; @@ -608,7 +695,7 @@ mp_Cmd(clientData, interp, objc, objv) ret = mp->get_clear_len(mp, &value); if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "mp get_clear_len")) == TCL_OK) - res = Tcl_NewIntObj((int)value); + res = Tcl_NewLongObj((long)value); break; case MPGETFILEID: if (objc != 2) { @@ -630,6 +717,16 @@ mp_Cmd(clientData, interp, objc, objv) "mp get_ftype")) == TCL_OK) res = Tcl_NewIntObj(ftype); break; + case MPGETLASTPGNO: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = mp->get_last_pgno(mp, &pgno); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "mp get_last_pgno")) == TCL_OK) + res = Tcl_NewLongObj((long)pgno); + break; case MPGETLSNOFFSET: if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, NULL); @@ -640,6 +737,19 @@ mp_Cmd(clientData, interp, objc, objv) "mp get_lsn_offset")) == TCL_OK) res = Tcl_NewIntObj(intval); break; + case MPGETMAXSIZE: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, NULL); + return (TCL_ERROR); + } + ret = mp->get_maxsize(mp, &gbytes, &bytes); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "mp get_maxsize")) == TCL_OK) { + myobjv[0] = Tcl_NewLongObj((long)gbytes); + myobjv[1] = Tcl_NewLongObj((long)bytes); + res = Tcl_NewListObj(2, myobjv); + } + break; case MPGETPGCOOKIE: if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, NULL); @@ -652,6 +762,21 @@ mp_Cmd(clientData, interp, objc, objv) res = Tcl_NewByteArrayObj((u_char *)cookie.data, (int)cookie.size); break; + case MPSETMAXSIZE: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, + "?set_maxsize {gbytes bytes}?"); + return (TCL_ERROR); + } + _debug_check(); + if ((result = mp_size_getinput(interp, + objv, 2, &gbytes, &bytes)) != TCL_OK) + break; + ret = mp->set_maxsize(mp, gbytes, bytes); + if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "set_maxsize")) == TCL_OK) + res = Tcl_NewIntObj(ret); + break; } /* * Only set result if we have a res. Otherwise, lower @@ -1018,4 +1143,34 @@ tcl_PgIsset(interp, objc, objv, page, pgip) Tcl_SetObjResult(interp, res); return (result); } + +static int +mp_size_getinput(interp, objv, indx, gbytes, bytes) + Tcl_Interp *interp; + Tcl_Obj *CONST objv[]; + int indx; + u_int32_t *gbytes, *bytes; +{ + Tcl_Obj **myobjv; + int myobjc, result; + + if ((result = Tcl_ListObjGetElements(interp, objv[indx], + &myobjc, &myobjv)) != TCL_OK) + goto error; + + if (myobjc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, + "?set_maxsize {gbytes bytes}?"); + result = TCL_ERROR; + goto error; + } + + if ((result = _GetUInt32(interp, myobjv[0], gbytes)) != TCL_OK) + goto error; + + result = _GetUInt32(interp, myobjv[1], bytes); + +error: + return (result); +} #endif diff --git a/lang/tcl/tcl_mutex.c b/lang/tcl/tcl_mutex.c index 384f91ad..d5e9bc3c 100644 --- a/lang/tcl/tcl_mutex.c +++ b/lang/tcl/tcl_mutex.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2004, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -84,6 +84,40 @@ tcl_Mutex(interp, objc, objv, dbenv) } /* + * tcl_MutexFailchkTimeout -- + * + * PUBLIC: int tcl_MutexFailchkTimeout __P((Tcl_Interp *, int, + * PUBLIC: Tcl_Obj * CONST*, DB_ENV *)); + */ +int +tcl_MutexFailchkTimeout(interp, objc, objv, dbenv) + Tcl_Interp *interp; /* Interpreter */ + int objc; /* How many arguments? */ + Tcl_Obj *CONST objv[]; /* The argument objects */ + DB_ENV *dbenv; /* Environment pointer */ +{ + long timeout; + int result, ret; + + /* + * One arg, the timeout. + */ + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?timeout?"); + return (TCL_ERROR); + } + result = Tcl_GetLongFromObj(interp, objv[2], &timeout); + if (result != TCL_OK) + return (result); + _debug_check(); + ret = dbenv->set_timeout(dbenv, (u_int32_t)timeout, + DB_SET_MUTEX_FAILCHK_TIMEOUT); + result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "mutex failchk timeout"); + return (result); +} + +/* * PUBLIC: int tcl_MutFree __P((Tcl_Interp *, int, Tcl_Obj * CONST*, * PUBLIC: DB_ENV *)); * @@ -314,11 +348,13 @@ tcl_MutStatPrint(interp, objc, objv, dbenv) { static const char *mutstatprtopts[] = { "-all", + "-alloc", "-clear", NULL }; enum mutstatprtopts { MUTSTATPRTALL, + MUTSTATPRTALLOC, MUTSTATPRTCLEAR }; u_int32_t flag; @@ -339,6 +375,9 @@ tcl_MutStatPrint(interp, objc, objv, dbenv) case MUTSTATPRTALL: flag |= DB_STAT_ALL; break; + case MUTSTATPRTALLOC: + flag |= DB_STAT_ALLOC; + break; case MUTSTATPRTCLEAR: flag |= DB_STAT_CLEAR; break; diff --git a/lang/tcl/tcl_rep.c b/lang/tcl/tcl_rep.c index a616cc7c..01710597 100644 --- a/lang/tcl/tcl_rep.c +++ b/lang/tcl/tcl_rep.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -36,10 +36,13 @@ static const NAMEMAP rep_config_types[] = { {"autorollback", DB_REP_CONF_AUTOROLLBACK}, {"bulk", DB_REP_CONF_BULK}, {"delayclient", DB_REP_CONF_DELAYCLIENT}, + {"electloglength", DB_REP_CONF_ELECT_LOGLENGTH}, {"inmem", DB_REP_CONF_INMEM}, {"lease", DB_REP_CONF_LEASE}, {"mgr2sitestrict", DB_REPMGR_CONF_2SITE_STRICT}, {"mgrelections", DB_REPMGR_CONF_ELECTIONS}, + {"mgrprefmasclient", DB_REPMGR_CONF_PREFMAS_CLIENT}, + {"mgrprefmasmaster", DB_REPMGR_CONF_PREFMAS_MASTER}, {"nowait", DB_REP_CONF_NOWAIT}, {NULL, 0} }; @@ -137,6 +140,14 @@ tcl_RepGetTwo(interp, dbenv, op) case DBTCL_GETCLOCK: ret = dbenv->rep_get_clockskew(dbenv, &val1, &val2); break; + case DBTCL_GETINQUEUE_MAX: + ret = dbenv->repmgr_get_incoming_queue_max(dbenv, + &val1, &val2); + break; + case DBTCL_GETINQUEUE_REDZONE: + ret = __repmgr_get_incoming_queue_redzone(dbenv, + &val1, &val2); + break; case DBTCL_GETLIMIT: ret = dbenv->rep_get_limit(dbenv, &val1, &val2); break; @@ -456,7 +467,7 @@ tcl_RepLease(interp, objc, objv, dbenv) if ((result = _GetUInt32(interp, objv[0], &timeout)) != TCL_OK) return (result); - if (objc == 4) { + if (objc == 3) { if ((result = _GetUInt32(interp, objv[1], &clock_fast)) != TCL_OK) return (result); @@ -519,14 +530,14 @@ tcl_RepLimit(interp, objc, objv, dbenv) int result, ret; u_int32_t bytes, gbytes; - if (objc != 4) { + if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, "gbytes bytes"); return (TCL_ERROR); } - if ((result = _GetUInt32(interp, objv[2], &gbytes)) != TCL_OK) + if ((result = _GetUInt32(interp, objv[0], &gbytes)) != TCL_OK) return (result); - if ((result = _GetUInt32(interp, objv[3], &bytes)) != TCL_OK) + if ((result = _GetUInt32(interp, objv[1], &bytes)) != TCL_OK) return (result); _debug_check(); @@ -589,14 +600,14 @@ tcl_RepRequest(interp, objc, objv, dbenv) int result, ret; long min, max; - if (objc != 4) { + if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, "min max"); return (TCL_ERROR); } - if ((result = Tcl_GetLongFromObj(interp, objv[2], &min)) != TCL_OK) + if ((result = Tcl_GetLongFromObj(interp, objv[0], &min)) != TCL_OK) return (result); - if ((result = Tcl_GetLongFromObj(interp, objv[3], &max)) != TCL_OK) + if ((result = Tcl_GetLongFromObj(interp, objv[1], &max)) != TCL_OK) return (result); _debug_check(); @@ -944,7 +955,7 @@ tcl_RepStat(interp, objc, objv, dbenv) result = TCL_OK; if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); + Tcl_WrongNumArgs(interp, 2, objv, "?-clear?"); return (TCL_ERROR); } if (objc == 3) { @@ -970,7 +981,6 @@ tcl_RepStat(interp, objc, objv, dbenv) * list pairs and free up the memory. */ res = Tcl_NewObj(); -#ifdef HAVE_STATISTICS /* * MAKE_STAT_* assumes 'res' and 'error' label. */ @@ -998,6 +1008,7 @@ tcl_RepStat(interp, objc, objv, dbenv) MAKE_STAT_LIST("Generation number", sp->st_gen); MAKE_STAT_LIST("Election generation number", sp->st_egen); MAKE_STAT_LIST("Startup complete", sp->st_startup_complete); + MAKE_STAT_LIST("Is view", sp->st_view); MAKE_WSTAT_LIST("Lease messages sent", sp->st_lease_sends); MAKE_WSTAT_LIST("Lease checks", sp->st_lease_chk); MAKE_WSTAT_LIST("Lease check invalid", sp->st_lease_chk_misses); @@ -1046,8 +1057,10 @@ tcl_RepStat(interp, objc, objv, dbenv) sp->st_startsync_delayed); MAKE_STAT_LIST("Maximum lease seconds", sp->st_max_lease_sec); MAKE_STAT_LIST("Maximum lease usecs", sp->st_max_lease_usec); + /* Undocumented field used by tests only. */ MAKE_STAT_LIST("File fail cleanups done", sp->st_filefail_cleanups); -#endif + /* Undocumented field used by tests only. */ + MAKE_WSTAT_LIST("Future duplicated log records", sp->st_log_futuredup); Tcl_SetObjResult(interp, res); error: @@ -1130,6 +1143,7 @@ tcl_RepMgr(interp, objc, objv, dbenv) { static const char *rmgr[] = { "-ack", + "-inqueue", "-local", "-msgth", "-pri", @@ -1141,6 +1155,7 @@ tcl_RepMgr(interp, objc, objv, dbenv) }; enum rmgr { RMGR_ACK, + RMGR_INQUEUE, RMGR_LOCAL, RMGR_MSGTH, RMGR_PRI, @@ -1154,13 +1169,13 @@ tcl_RepMgr(interp, objc, objv, dbenv) long to; int ack, creator, i, j, legacy, myobjc, optindex; int peer, result, ret, totype, t_ret; - u_int32_t msgth, start_flag, uintarg; + u_int32_t call_start, msgth, start_flag, uintarg, uintarg2; char *arg; result = TCL_OK; ack = ret = totype = 0; msgth = 1; - start_flag = 0; + call_start = start_flag = 0; if (objc <= 2) { Tcl_WrongNumArgs(interp, 2, objv, "?args?"); @@ -1202,6 +1217,32 @@ tcl_RepMgr(interp, objc, objv, dbenv) result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "ack"); break; + case RMGR_INQUEUE: + result = Tcl_ListObjGetElements(interp, objv[i], + &myobjc, &myobjv); + if (result == TCL_OK) + i++; + else + break; + if (myobjc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-inqueue {gbytes bytes}?"); + result = TCL_ERROR; + break; + } + arg = Tcl_GetStringFromObj(myobjv[0], NULL); + if ((result = _GetUInt32(interp, myobjv[0], &uintarg)) + != TCL_OK) + break; + if ((result = _GetUInt32(interp, myobjv[1], &uintarg2)) + != TCL_OK) + break; + _debug_check(); + ret = dbenv->repmgr_set_incoming_queue_max(dbenv, + uintarg, uintarg2); + result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), + "repmgr_set_incoming_queue_max"); + break; case RMGR_LOCAL: result = Tcl_ListObjGetElements(interp, objv[i], &myobjc, &myobjv); @@ -1370,12 +1411,18 @@ tcl_RepMgr(interp, objc, objv, dbenv) start_flag = DB_REP_CLIENT; else if (strcmp(arg, "elect") == 0) start_flag = DB_REP_ELECTION; + else if (strcmp(arg, "none") == 0) { + start_flag = 0; + call_start = 1; + } else { Tcl_AddErrorInfo( interp, "start: illegal state"); result = TCL_ERROR; break; } + if (start_flag) + call_start = 1; /* * Some config functions need to be called * before repmgr_start. So finish parsing all @@ -1423,7 +1470,7 @@ tcl_RepMgr(interp, objc, objv, dbenv) * Only call repmgr_start if needed. The user may use this * call just to reconfigure, change policy, etc. */ - if (start_flag != 0 && result == TCL_OK) { + if (call_start && result == TCL_OK) { _debug_check(); ret = dbenv->repmgr_start(dbenv, (int)msgth, start_flag); result = _ReturnSetup( @@ -1448,9 +1495,9 @@ tcl_RepMgrSiteList(interp, objc, objv, dbenv) DB_ENV *dbenv; { DB_REPMGR_SITE *sp; - Tcl_Obj *myobjv[5], *res, *thislist; + Tcl_Obj *myobjv[6], *res, *thislist; u_int count, i; - char *pr, *st; + char *pr, *st, *vw; int myobjc, result, ret; result = TCL_OK; @@ -1483,11 +1530,9 @@ tcl_RepMgrSiteList(interp, objc, objv, dbenv) st = "disconnected"; else st = "unknown"; - if (F_ISSET(&sp[i], DB_REPMGR_ISPEER)) - pr = "peer"; - else - pr = "non-peer"; - MAKE_SITE_LIST(sp[i].eid, sp[i].host, sp[i].port, st, pr); + pr = F_ISSET(&sp[i], DB_REPMGR_ISPEER) ? "peer" : "non-peer"; + vw = F_ISSET(&sp[i], DB_REPMGR_ISVIEW) ? "view" : "participant"; + MAKE_SITE_LIST(sp[i].eid, sp[i].host, sp[i].port, st, pr, vw); } Tcl_SetObjResult(interp, res); @@ -1520,7 +1565,7 @@ tcl_RepMgrStat(interp, objc, objv, dbenv) result = TCL_OK; if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); + Tcl_WrongNumArgs(interp, 2, objv, "?-clear?"); return (TCL_ERROR); } if (objc == 3) { @@ -1546,18 +1591,27 @@ tcl_RepMgrStat(interp, objc, objv, dbenv) * list pairs and free up the memory. */ res = Tcl_NewObj(); -#ifdef HAVE_STATISTICS /* * MAKE_STAT_* assumes 'res' and 'error' label. */ MAKE_WSTAT_LIST("Acknowledgement failures", sp->st_perm_failed); MAKE_WSTAT_LIST("Messages delayed", sp->st_msgs_queued); MAKE_WSTAT_LIST("Messages discarded", sp->st_msgs_dropped); + MAKE_WSTAT_LIST("Incoming messages size (gbytes)", + sp->st_incoming_queue_gbytes); + MAKE_WSTAT_LIST("Incoming messages size (bytes)", + sp->st_incoming_queue_bytes); + MAKE_WSTAT_LIST("Incoming messages discarded", + sp->st_incoming_msgs_dropped); MAKE_WSTAT_LIST("Connections dropped", sp->st_connection_drop); MAKE_WSTAT_LIST("Failed re-connects", sp->st_connect_fail); - MAKE_WSTAT_LIST("Election threads", sp->st_elect_threads); - MAKE_WSTAT_LIST("Max elect threads", sp->st_max_elect_threads); -#endif + MAKE_STAT_LIST("Election threads", sp->st_elect_threads); + MAKE_STAT_LIST("Max elect threads", sp->st_max_elect_threads); + MAKE_STAT_LIST("Total sites", sp->st_site_total); + MAKE_STAT_LIST("View sites", sp->st_site_views); + MAKE_STAT_LIST("Participant sites", sp->st_site_participants); + MAKE_WSTAT_LIST("Automatic replication process takeovers", + sp->st_takeovers); Tcl_SetObjResult(interp, res); error: diff --git a/lang/tcl/tcl_seq.c b/lang/tcl/tcl_seq.c index 75f59fee..c84123ce 100644 --- a/lang/tcl/tcl_seq.c +++ b/lang/tcl/tcl_seq.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2004, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -77,7 +77,8 @@ seq_Cmd(clientData, interp, objc, objv) DB_SEQUENCE *seq; Tcl_Obj *myobjv[2], *res; db_seq_t min, max; - int cmdindex, ncache, result, ret; + int cmdindex, result, ret; + u_int32_t ncache; Tcl_ResetResult(interp); seq = (DB_SEQUENCE *)clientData; @@ -140,7 +141,7 @@ seq_Cmd(clientData, interp, objc, objv) ret = seq->get_cachesize(seq, &ncache); if ((result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "sequence get_cachesize")) == TCL_OK) - res = Tcl_NewIntObj(ncache); + res = Tcl_NewIntObj((int)ncache); break; case SEQGETDB: if (objc != 2) { @@ -203,14 +204,18 @@ tcl_SeqStat(interp, objc, objv, seq) flag = 0; if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?-clear?"); + Tcl_WrongNumArgs(interp, 2, objv, "?-all? ?-clear?"); return (TCL_ERROR); } if (objc == 3) { arg = Tcl_GetStringFromObj(objv[2], NULL); - if (strcmp(arg, "-clear") == 0) + if (strcmp(arg, "-all") == 0) { + flag = DB_STAT_ALL; + } + else if (strcmp(arg, "-clear") == 0) { flag = DB_STAT_CLEAR; + } else { Tcl_SetResult(interp, "db stat: unknown arg", TCL_STATIC); @@ -266,10 +271,12 @@ tcl_SeqStatPrint(interp, objc, objv, seq) DB_SEQUENCE *seq; /* Environment pointer */ { static const char *seqstatprtopts[] = { + "-all", "-clear", NULL }; enum seqstatprtopts { + SEQSTATPRTALL, SEQSTATPRTCLEAR }; u_int32_t flag; @@ -287,6 +294,9 @@ tcl_SeqStatPrint(interp, objc, objv, seq) } i++; switch ((enum seqstatprtopts)optindex) { + case SEQSTATPRTALL: + flag |= DB_STAT_ALL; + break; case SEQSTATPRTCLEAR: flag |= DB_STAT_CLEAR; break; @@ -422,7 +432,7 @@ tcl_SeqGet(interp, objc, objv, seq) if ((result = _GetUInt32(interp, objv[objc - 1], &delta)) != TCL_OK) goto out; - ret = seq->get(seq, txn, (int32_t)delta, &value, aflag); + ret = seq->get(seq, txn, delta, &value, aflag); result = _ReturnSetup(interp, ret, DB_RETOK_DBGET(ret), "sequence get"); if (ret == 0) { res = Tcl_NewWideIntObj((Tcl_WideInt)value); @@ -459,8 +469,6 @@ tcl_SeqRemove(interp, objc, objv, seq, ip) txn = NULL; aflag = 0; - _DeleteInfo(ip); - if (objc < 2) { Tcl_WrongNumArgs(interp, 2, objv, "?-args?"); return (TCL_ERROR); @@ -510,6 +518,7 @@ tcl_SeqRemove(interp, objc, objv, seq, ip) if (result != TCL_OK) goto out; + _DeleteInfo(ip); ret = seq->remove(seq, txn, aflag); result = _ReturnSetup(interp, ret, DB_RETOK_DBGET(ret), "sequence remove"); @@ -557,7 +566,7 @@ tcl_SeqGetFlags(interp, objc, objv, seq) if (strlen(buf) > 0) (void)strncat(buf, " ", sizeof(buf)); (void)strncat( - buf, seq_flags[i].arg, sizeof(buf)); + buf, seq_flags[i].arg, sizeof(buf) - 1); } res = NewStringObj(buf, strlen(buf)); diff --git a/lang/tcl/tcl_txn.c b/lang/tcl/tcl_txn.c index e8c69c08..55676da5 100644 --- a/lang/tcl/tcl_txn.c +++ b/lang/tcl/tcl_txn.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -399,19 +399,31 @@ tcl_TxnStat(interp, objc, objv, dbenv) DB_TXN_ACTIVE *p; DB_TXN_STAT *sp; Tcl_Obj *myobjv[2], *res, *thislist, *lsnlist; - u_int32_t i; + u_int32_t i, flag; + char *arg; int myobjc, result, ret; + flag = 0; result = TCL_OK; - /* - * No args for this. Error if there are some. - */ - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); + + if (objc > 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?-clear?"); return (TCL_ERROR); } + + if (objc == 3) { + arg = Tcl_GetStringFromObj(objv[2], NULL); + if (strcmp(arg, "-clear") == 0) + flag = DB_STAT_CLEAR; + else { + Tcl_SetResult(interp, + "db stat: unknown arg", TCL_STATIC); + return (TCL_ERROR); + } + } + _debug_check(); - ret = dbenv->txn_stat(dbenv, &sp, 0); + ret = dbenv->txn_stat(dbenv, &sp, flag); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "txn stat"); if (result == TCL_ERROR) @@ -425,7 +437,6 @@ tcl_TxnStat(interp, objc, objv, dbenv) /* * MAKE_STAT_LIST assumes 'res' and 'error' label. */ -#ifdef HAVE_STATISTICS MAKE_STAT_LIST("Region size", sp->st_regsize); MAKE_STAT_LSN("LSN of last checkpoint", &sp->st_last_ckp); MAKE_STAT_LIST("Time of last checkpoint", sp->st_time_ckp); @@ -457,7 +468,7 @@ tcl_TxnStat(interp, objc, objv, dbenv) break; } } -#endif + Tcl_SetObjResult(interp, res); error: __os_ufree(dbenv->env, sp); @@ -479,11 +490,13 @@ tcl_TxnStatPrint(interp, objc, objv, dbenv) { static const char *txnprtopts[] = { "-all", + "-alloc", "-clear", NULL }; enum txnprtopts { TXNPRTALL, + TXNPRTALLOC, TXNPRTCLEAR }; u_int32_t flag; @@ -504,6 +517,9 @@ tcl_TxnStatPrint(interp, objc, objv, dbenv) case TXNPRTALL: flag |= DB_STAT_ALL; break; + case TXNPRTALLOC: + flag |= DB_STAT_ALLOC; + break; case TXNPRTCLEAR: flag |= DB_STAT_CLEAR; break; diff --git a/lang/tcl/tcl_util.c b/lang/tcl/tcl_util.c index 0e83826f..81f3b7da 100644 --- a/lang/tcl/tcl_util.c +++ b/lang/tcl/tcl_util.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ |