From 213c7685f575bf08971cfc9f9d35e253b8080aae Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 13 Sep 2017 16:33:22 +0000 Subject: [PATCH 1/7] Track search structures. --- ctables/command-body.c-subst | 2 +- ctables/ctable.h | 3 ++- ctables/ctable_search.c | 17 +++++++++-------- ctables/template.c-subst | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ctables/command-body.c-subst b/ctables/command-body.c-subst index 337b6ef8..80137f57 100644 --- a/ctables/command-body.c-subst +++ b/ctables/command-body.c-subst @@ -648,7 +648,7 @@ int ${table}ObjCmd (ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CON return TCL_ERROR; } - if(ctable->searching) { + if(ctable->searches) { Tcl_AppendResult(interp, "Can not delete from inside search.", NULL); Tcl_SetErrorCode (interp, "speedtables", "no_delete_inside_search", NULL); return TCL_ERROR; diff --git a/ctables/ctable.h b/ctables/ctable.h index 255bf905..a50da9fd 100644 --- a/ctables/ctable.h +++ b/ctables/ctable.h @@ -367,6 +367,7 @@ struct CTableSearchFilter { // ctable search struct - this controls everything about a search struct CTableSearch { struct CTable *ctable; + struct CTableSearch *previousSearch; CTableSearchComponent *components; CTableSearchFilter *filters; char *pattern; @@ -512,7 +513,7 @@ struct CTable { int autoRowNumber; int destroying; - int searching; + CTableSearch *searches; char *nullKeyValue; #ifdef WITH_SHARED_TABLES int was_locked; diff --git a/ctables/ctable_search.c b/ctables/ctable_search.c index b35ef207..da526c5d 100644 --- a/ctables/ctable_search.c +++ b/ctables/ctable_search.c @@ -147,7 +147,7 @@ ctable_ParseFieldList (Tcl_Interp *interp, Tcl_Obj *fieldListObj, CONST char **f // and store the field number in the corresponding field number array. // // If the dash was present set the corresponding direction in the direction -// array to 0 else set it to 1. +// array to -1 else set it to 1. // // It is up to the caller to free the memory pointed to through the // fieldList argument. @@ -1992,7 +1992,7 @@ if(num_restarts) fprintf(stderr, "%d: Restarted search %d times\n", getpid(), nu // // static int -ctable_SetupSearch (Tcl_Interp *interp, CTable *ctable, Tcl_Obj *CONST objv[], int objc, CTableSearch *search, int indexField, int nested_search) { +ctable_SetupSearch (Tcl_Interp *interp, CTable *ctable, Tcl_Obj *CONST objv[], int objc, CTableSearch *search, int indexField, CTableSearch *previous_search) { int i; int searchTerm = 0; CONST char **fieldNames = ctable->creator->fieldNames; @@ -2035,6 +2035,7 @@ ctable_SetupSearch (Tcl_Interp *interp, CTable *ctable, Tcl_Obj *CONST objv[], i // initialize search control structure search->ctable = ctable; + search->previousSearch = previous_search; search->action = CTABLE_SEARCH_ACTION_NONE; search->nComponents = 0; search->components = NULL; @@ -2277,7 +2278,7 @@ ctable_SetupSearch (Tcl_Interp *interp, CTable *ctable, Tcl_Obj *CONST objv[], i Tcl_SetErrorCode (interp, "speedtables", "no_delete_with_cursors", NULL); return TCL_ERROR; } - if(nested_search) { + if(previous_search) { Tcl_AppendResult(interp, "Can not delete in nested search.", NULL); Tcl_SetErrorCode (interp, "speedtables", "no_delete_inside_search", NULL); return TCL_ERROR; @@ -2637,12 +2638,12 @@ ctable_SetupAndPerformSearch (Tcl_Interp *interp, Tcl_Obj *CONST objv[], int obj #endif // flag this search in progress - int nested_search = ctable->searching; - ctable->searching = 1; + CTableSearch *previous_search = ctable->searches; + ctable->searches = &search; - result = ctable_SetupSearch (interp, ctable, objv, objc, &search, indexField, nested_search); + result = ctable_SetupSearch (interp, ctable, objv, objc, &search, indexField, previous_search); if (result == TCL_ERROR) { - ctable->searching = nested_search; + ctable->searches = previous_search; return TCL_ERROR; } @@ -2661,7 +2662,7 @@ ctable_SetupAndPerformSearch (Tcl_Interp *interp, Tcl_Obj *CONST objv[], int obj ctable_TeardownSearch (&search); - ctable->searching = nested_search; + ctable->searches = previous_search; #ifdef CTABLES_CLOCK if (ctable->performanceCallbackEnable) { diff --git a/ctables/template.c-subst b/ctables/template.c-subst index 89f668d9..066951a9 100644 --- a/ctables/template.c-subst +++ b/ctables/template.c-subst @@ -249,7 +249,7 @@ ${table}MetaObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj ctable->count = 0; ctable->autoRowNumber = 0; ctable->destroying = 0; - ctable->searching = 0; + ctable->searches = NULL; ctable->nullKeyValue = NULL; ctable->cursors = NULL; #ifdef WITH_SHARED_TABLES From 37d04a15fa4a0da134abfbb1d4b66799bf94bb84 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Thu, 14 Sep 2017 14:02:59 +0000 Subject: [PATCH 2/7] Use the hash table if walking a nested search. --- ctables/ctable_search.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ctables/ctable_search.c b/ctables/ctable_search.c index da526c5d..473d4ae4 100644 --- a/ctables/ctable_search.c +++ b/ctables/ctable_search.c @@ -1337,6 +1337,13 @@ ctable_PerformSearch (Tcl_Interp *interp, CTable *ctable, CTableSearch *search) int num_restarts = 0; jsw_skip_t *skipListCopy = NULL; + + // Nested searches need to walk the hash table and there's no hash table in shared reader tables. + if(ctable->share_type == CTABLE_SHARED_READER && search->previousSearch) { + Tcl_AppendResult (interp, "can't perform nested search with shared tables", (char *) NULL); + finalResult = TCL_ERROR; + goto clean_and_return; + } #endif if (search->writingTabsepIncludeFieldNames) { @@ -1450,6 +1457,11 @@ ctable_PerformSearch (Tcl_Interp *interp, CTable *ctable, CTableSearch *search) search->reqIndexField = CTABLE_SEARCH_INDEX_NONE; } + // If it's a nested search, you have to use the hash table + if(search->previousSearch) { + search->reqIndexField = CTABLE_SEARCH_INDEX_NONE; + } + // Check if we can use the hash table. #ifdef WITH_SHARED_TABLES // fprintf(stderr, "ctable->share_type=%d\n", ctable->share_type); From 1987ead0cf18f3c5bffd23ab3b46477d4819fd05 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Fri, 15 Sep 2017 16:30:50 +0000 Subject: [PATCH 3/7] Don't search fields in outer searches. --- ctables/ctable.h | 3 +++ ctables/ctable_search.c | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/ctables/ctable.h b/ctables/ctable.h index a50da9fd..868a2836 100644 --- a/ctables/ctable.h +++ b/ctables/ctable.h @@ -431,6 +431,9 @@ struct CTableSearch { // cursor ID and structure char *cursorName; struct cursor *cursor; + + // what index is this searching? + int searchField; }; struct ctable_FieldInfo { diff --git a/ctables/ctable_search.c b/ctables/ctable_search.c index 473d4ae4..d4550a03 100644 --- a/ctables/ctable_search.c +++ b/ctables/ctable_search.c @@ -1544,6 +1544,17 @@ ctable_PerformSearch (Tcl_Interp *interp, CTable *ctable, CTableSearch *search) } } + // If we have previous searches, walk back through the previous searches to see if we're already using + // this field + for(s = search->previousSearch; s; s = s->previousSearch) { + if(s->searchField == field) { + break; + } + } + if(s) { + continue; + } + score = skipTypes[comparisonType].score; // Prefer to avoid sort @@ -1555,6 +1566,7 @@ ctable_PerformSearch (Tcl_Interp *interp, CTable *ctable, CTableSearch *search) // Got a new best candidate, save the world. skipField = field; + search->searchField = field; skipNext = skipTypes[comparisonType].skipNext; skipStart = skipTypes[comparisonType].skipStart; @@ -1606,6 +1618,7 @@ ctable_PerformSearch (Tcl_Interp *interp, CTable *ctable, CTableSearch *search) } } + // if we're sorting on the field we're searching, AND we can eliminate // the sort because we know we're walking in order, then eliminate the // sort step @@ -2083,6 +2096,7 @@ ctable_SetupSearch (Tcl_Interp *interp, CTable *ctable, Tcl_Obj *CONST objv[], i search->offsetLimit = search->offset + search->limit; search->cursorName = NULL; search->cursor = NULL; + search->searchField = -1; // Give each search a unique non-zero sequence number if(++staticSequence == 0) ++staticSequence; From 1aefe15d431b3e3afa70ca39721862be7fa93759 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Fri, 15 Sep 2017 16:34:04 +0000 Subject: [PATCH 4/7] Don't reserve search keys once we're in post-search transaction processing. --- ctables/ctable_search.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ctables/ctable_search.c b/ctables/ctable_search.c index d4550a03..0aa4ad88 100644 --- a/ctables/ctable_search.c +++ b/ctables/ctable_search.c @@ -1961,6 +1961,10 @@ if(num_restarts == 0) fprintf(stderr, "%d: loop restart: loop_cycle=%ld; row->_r // We only jump to this on success, so we got to the end of the loop // or we broke out of it early search_complete: + + // We're no longer walking a skiplist, so make a note of that so it can be re-used. + search->searchField = -1; + switch (ctable_PostSearchCommonActions (interp, ctable, search)) { case TCL_ERROR: { finalResult = TCL_ERROR; From 0b9c2ff0d5ab1c9cbc8543aa8957bab70f2dfb06 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Fri, 15 Sep 2017 16:35:02 +0000 Subject: [PATCH 5/7] Don't unilaterally block nested searches from using skiplists. --- ctables/ctable_search.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/ctables/ctable_search.c b/ctables/ctable_search.c index 0aa4ad88..7548485d 100644 --- a/ctables/ctable_search.c +++ b/ctables/ctable_search.c @@ -1337,13 +1337,6 @@ ctable_PerformSearch (Tcl_Interp *interp, CTable *ctable, CTableSearch *search) int num_restarts = 0; jsw_skip_t *skipListCopy = NULL; - - // Nested searches need to walk the hash table and there's no hash table in shared reader tables. - if(ctable->share_type == CTABLE_SHARED_READER && search->previousSearch) { - Tcl_AppendResult (interp, "can't perform nested search with shared tables", (char *) NULL); - finalResult = TCL_ERROR; - goto clean_and_return; - } #endif if (search->writingTabsepIncludeFieldNames) { @@ -1457,11 +1450,6 @@ ctable_PerformSearch (Tcl_Interp *interp, CTable *ctable, CTableSearch *search) search->reqIndexField = CTABLE_SEARCH_INDEX_NONE; } - // If it's a nested search, you have to use the hash table - if(search->previousSearch) { - search->reqIndexField = CTABLE_SEARCH_INDEX_NONE; - } - // Check if we can use the hash table. #ifdef WITH_SHARED_TABLES // fprintf(stderr, "ctable->share_type=%d\n", ctable->share_type); From cbb06b942348875ad55a45dd5e59778648a89472 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Fri, 15 Sep 2017 21:08:49 +0000 Subject: [PATCH 6/7] Declare search table pointer. --- ctables/ctable_search.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ctables/ctable_search.c b/ctables/ctable_search.c index 7548485d..3e79ef66 100644 --- a/ctables/ctable_search.c +++ b/ctables/ctable_search.c @@ -1331,6 +1331,8 @@ ctable_PerformSearch (Tcl_Interp *interp, CTable *ctable, CTableSearch *search) int canUseHash = 1; + CTableSearch *s; + #ifdef WITH_SHARED_TABLES int firstTime = 1; int locked_cycle = LOST_HORIZON; From 1dcc92d7066cc94af8ce8188365ace68b5db5886 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Thu, 21 Sep 2017 17:43:15 +0000 Subject: [PATCH 7/7] Prepare for version upgrade and release. --- configure.in | 2 +- ctable_server/configure.in | 2 +- ctable_server/ctable_client.tcl | 2 +- ctable_server/ctable_client_server.tcl | 2 +- ctable_server/ctable_server.tcl | 2 +- ctable_server/sttp_buffer.tcl | 2 +- ctables/configure.in | 2 +- stapi/client/cass.tcl | 2 +- stapi/client/client.tcl | 2 +- stapi/client/extend.tcl | 2 +- stapi/client/pgsql.tcl | 2 +- stapi/client/shared.tcl | 2 +- stapi/client/uri.tcl | 2 +- stapi/configure.in | 2 +- stapi/copy.tcl | 2 +- stapi/debug.tcl | 2 +- stapi/display/display.tcl | 2 +- stapi/display/test.tcl | 2 +- stapi/pgsql.tcl | 2 +- stapi/server/lock.tcl | 2 +- stapi/server/server.tcl | 2 +- stapi/stapi.tcl | 2 +- update_ver.sh | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) diff --git a/configure.in b/configure.in index 41f1b188..2b565536 100755 --- a/configure.in +++ b/configure.in @@ -18,7 +18,7 @@ dnl to configure the system for the local environment. # so you can encode the package version directly into the source files. #----------------------------------------------------------------------- -AC_INIT([speedtables], [1.13.5]) +AC_INIT([speedtables], [1.13.6]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. diff --git a/ctable_server/configure.in b/ctable_server/configure.in index 1bf96b13..d2495f19 100755 --- a/ctable_server/configure.in +++ b/ctable_server/configure.in @@ -18,7 +18,7 @@ dnl to configure the system for the local environment. # so you can encode the package version directly into the source files. #----------------------------------------------------------------------- -AC_INIT([ctable_server], [1.13.5]) +AC_INIT([ctable_server], [1.13.6]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. diff --git a/ctable_server/ctable_client.tcl b/ctable_server/ctable_client.tcl index 8e1efefa..04f6343c 100644 --- a/ctable_server/ctable_client.tcl +++ b/ctable_server/ctable_client.tcl @@ -621,6 +621,6 @@ proc maketable {cttpUrl sock} { return [::sttp_buffer::table $cttpUrl] } -package provide ctable_client 1.13.5 +package provide ctable_client 1.13.6 # vim: set ts=8 sw=4 sts=4 noet : diff --git a/ctable_server/ctable_client_server.tcl b/ctable_server/ctable_client_server.tcl index 8a501b00..044b6b0b 100644 --- a/ctable_server/ctable_client_server.tcl +++ b/ctable_server/ctable_client_server.tcl @@ -98,6 +98,6 @@ namespace export split_ctable_url join_ctable_url } -package provide ctable_net 1.13.5 +package provide ctable_net 1.13.6 # vim: set ts=8 sw=4 sts=4 noet : diff --git a/ctable_server/ctable_server.tcl b/ctable_server/ctable_server.tcl index eb50888a..6c1ffae9 100644 --- a/ctable_server/ctable_server.tcl +++ b/ctable_server/ctable_server.tcl @@ -678,7 +678,7 @@ proc serverdie {{message ""}} { } -package provide ctable_server 1.13.5 +package provide ctable_server 1.13.6 #get, set, array_get, array_get_with_nulls, exists, delete, count, foreach, sort, type, import, import_postgres_result, export, fields, fieldtype, needs_quoting, names, reset, destroy, statistics, write_tabsep, or read_tabsep diff --git a/ctable_server/sttp_buffer.tcl b/ctable_server/sttp_buffer.tcl index 1b5352e0..6546fb69 100644 --- a/ctable_server/sttp_buffer.tcl +++ b/ctable_server/sttp_buffer.tcl @@ -177,6 +177,6 @@ proc table {cttpUrl} { } -package provide sttp_buffer 1.13.5 +package provide sttp_buffer 1.13.6 # vim: set ts=8 sw=4 sts=4 noet : diff --git a/ctables/configure.in b/ctables/configure.in index ec1915df..a10792d9 100755 --- a/ctables/configure.in +++ b/ctables/configure.in @@ -18,7 +18,7 @@ dnl to configure the system for the local environment. # so you can encode the package version directly into the source files. #----------------------------------------------------------------------- -AC_INIT([ctable], [1.13.5]) +AC_INIT([ctable], [1.13.6]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. diff --git a/stapi/client/cass.tcl b/stapi/client/cass.tcl index fbb38bac..8b800c7f 100644 --- a/stapi/client/cass.tcl +++ b/stapi/client/cass.tcl @@ -1236,6 +1236,6 @@ namespace eval ::stapi { } } -package provide st_client_cassandra 1.13.5 +package provide st_client_cassandra 1.13.6 # vim: set ts=8 sw=4 sts=4 noet : diff --git a/stapi/client/client.tcl b/stapi/client/client.tcl index 40f36556..26491ae3 100644 --- a/stapi/client/client.tcl +++ b/stapi/client/client.tcl @@ -100,6 +100,6 @@ namespace eval ::stapi { register package connect_package } -package provide st_client 1.13.5 +package provide st_client 1.13.6 # vim: set ts=8 sw=4 sts=4 noet : diff --git a/stapi/client/extend.tcl b/stapi/client/extend.tcl index cd62d400..8cda6e53 100644 --- a/stapi/client/extend.tcl +++ b/stapi/client/extend.tcl @@ -395,7 +395,7 @@ namespace eval ::stapi { namespace import ::stapi::extend::* } -package provide stapi_extend 1.13.5 +package provide stapi_extend 1.13.6 # vim: set ts=8 sw=4 sts=4 noet : diff --git a/stapi/client/pgsql.tcl b/stapi/client/pgsql.tcl index 192a41c5..4b57e1ea 100644 --- a/stapi/client/pgsql.tcl +++ b/stapi/client/pgsql.tcl @@ -952,6 +952,6 @@ namespace eval ::stapi { } } -package provide st_client_postgres 1.13.5 +package provide st_client_postgres 1.13.6 # vim: set ts=8 sw=4 sts=4 noet : diff --git a/stapi/client/shared.tcl b/stapi/client/shared.tcl index 1c3a0c2a..2c284c8a 100644 --- a/stapi/client/shared.tcl +++ b/stapi/client/shared.tcl @@ -115,6 +115,6 @@ namespace eval ::stapi { } } -package provide st_shared 1.13.5 +package provide st_shared 1.13.6 # vim: set ts=8 sw=4 sts=4 noet : diff --git a/stapi/client/uri.tcl b/stapi/client/uri.tcl index 847e4283..0da84294 100644 --- a/stapi/client/uri.tcl +++ b/stapi/client/uri.tcl @@ -40,6 +40,6 @@ namespace eval stapi { } -package provide st_client_uri 1.13.5 +package provide st_client_uri 1.13.6 # vim: set ts=8 sw=4 sts=4 noet : diff --git a/stapi/configure.in b/stapi/configure.in index 4613a3f4..6a74265c 100755 --- a/stapi/configure.in +++ b/stapi/configure.in @@ -18,7 +18,7 @@ dnl to configure the system for the local environment. # so you can encode the package version directly into the source files. #----------------------------------------------------------------------- -AC_INIT([stapi], [1.13.5]) +AC_INIT([stapi], [1.13.6]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. diff --git a/stapi/copy.tcl b/stapi/copy.tcl index e0aa87ba..bf9706d8 100644 --- a/stapi/copy.tcl +++ b/stapi/copy.tcl @@ -167,5 +167,5 @@ namespace eval ::stapi { } } -package provide st_postgres 1.13.5 +package provide st_postgres 1.13.6 diff --git a/stapi/debug.tcl b/stapi/debug.tcl index 6b370b11..e0af9cc6 100644 --- a/stapi/debug.tcl +++ b/stapi/debug.tcl @@ -54,4 +54,4 @@ namespace eval ::stapi { } } -package provide st_debug 1.13.5 +package provide st_debug 1.13.6 diff --git a/stapi/display/display.tcl b/stapi/display/display.tcl index ce364f78..4fcae5ef 100644 --- a/stapi/display/display.tcl +++ b/stapi/display/display.tcl @@ -2576,5 +2576,5 @@ catch { ::itcl::delete class ::STDisplayField_boolean } } ; ## ::itcl::class ::STDisplayField_boolean -package provide st_display 1.13.5 +package provide st_display 1.13.6 diff --git a/stapi/display/test.tcl b/stapi/display/test.tcl index 12cfc2a1..a9ff020d 100644 --- a/stapi/display/test.tcl +++ b/stapi/display/test.tcl @@ -29,4 +29,4 @@ proc stapi_display_test {} { } } -package provide st_display_test 1.13.5 +package provide st_display_test 1.13.6 diff --git a/stapi/pgsql.tcl b/stapi/pgsql.tcl index 8084febf..81c60efa 100644 --- a/stapi/pgsql.tcl +++ b/stapi/pgsql.tcl @@ -379,4 +379,4 @@ namespace eval ::stapi { } } -package provide st_postgres 1.13.5 +package provide st_postgres 1.13.6 diff --git a/stapi/server/lock.tcl b/stapi/server/lock.tcl index 08fad0db..4d8429dd 100644 --- a/stapi/server/lock.tcl +++ b/stapi/server/lock.tcl @@ -185,4 +185,4 @@ namespace eval ::stapi { } } -package provide st_locks 1.13.5 +package provide st_locks 1.13.6 diff --git a/stapi/server/server.tcl b/stapi/server/server.tcl index 94244717..fede3b69 100644 --- a/stapi/server/server.tcl +++ b/stapi/server/server.tcl @@ -1279,4 +1279,4 @@ namespace eval ::stapi { } } -package provide st_server 1.13.5 +package provide st_server 1.13.6 diff --git a/stapi/stapi.tcl b/stapi/stapi.tcl index ac9cb250..02d7a50f 100644 --- a/stapi/stapi.tcl +++ b/stapi/stapi.tcl @@ -2,5 +2,5 @@ package require st_client -package provide stapi 1.13.5 +package provide stapi 1.13.6 diff --git a/update_ver.sh b/update_ver.sh index dddc9333..96321998 100755 --- a/update_ver.sh +++ b/update_ver.sh @@ -2,7 +2,7 @@ # This script simplifies the process of incrementing all version numbers for a new release. -NEWVER="1.13.5" +NEWVER="1.13.6" perl -p -i -e "s/^(AC_INIT\\(\\[[a-z_]+\\],) \\[[0-9.]+\\]/\\1 \\[$NEWVER\\]/" configure.in ctables/configure.in stapi/configure.in ctable_server/configure.in