diff options
author | Clarisse Cheah <clarisse.cheah@mongodb.com> | 2022-10-16 23:44:08 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-10-17 00:18:57 +0000 |
commit | d38979363d12493873ea26cfe847d528dacee70e (patch) | |
tree | 3f4f0c5aa389b6685df696b2b4129cbdafd8c116 | |
parent | db634af010edf9566d596aa8418c15c7e3f9b2da (diff) | |
download | mongo-d38979363d12493873ea26cfe847d528dacee70e.tar.gz |
Import wiredtiger: d69ee179611d881d06d0469480985992a7f186a2 from branch mongodb-master
ref: 994ff9d67a..d69ee17961
for: 6.2.0-rc0
WT-9936 Reduce overhead of configuration parsing for the bounded cursor. (#8342)
10 files changed, 83 insertions, 96 deletions
diff --git a/src/third_party/wiredtiger/dist/api_data.py b/src/third_party/wiredtiger/dist/api_data.py index 84b3719692c..448506a4473 100644 --- a/src/third_party/wiredtiger/dist/api_data.py +++ b/src/third_party/wiredtiger/dist/api_data.py @@ -1207,18 +1207,15 @@ cursor_bound_config = [ Config('action', 'set', r''' configures whether this call into the API will set or clear range bounds on the given cursor. It takes one of two values, "set" or "clear". If "set" is specified then "bound" - must also be specified. If "clear" is specified without any bounds then both bounds will - be cleared. The keys relevant to the given bound must have been set prior to the call using - WT_CURSOR::set_key. This configuration is currently a work in progress and should not be - used.''', + must also be specified. The keys relevant to the given bound must have been set prior to the + call using WT_CURSOR::set_key.''', choices=['clear','set']), Config('inclusive', 'true', r''' - configures whether the given bound is inclusive or not. This configuration is currently a - work in progress and should not be used.''', + configures whether the given bound is inclusive or not.''', type='boolean'), Config('bound', '', r''' configures which bound is being operated on. It takes one of two values, "lower" or "upper". - This configuration is currently a work in progress and should not be used.''', + ''', choices=['lower','upper']), ] diff --git a/src/third_party/wiredtiger/dist/s_funcs.list b/src/third_party/wiredtiger/dist/s_funcs.list index a5f61123e88..7501ce0ce85 100644 --- a/src/third_party/wiredtiger/dist/s_funcs.list +++ b/src/third_party/wiredtiger/dist/s_funcs.list @@ -3,6 +3,7 @@ WT_CRC32_ENTRY WT_CURDUMP_PASS __bit_ffs __bit_nclr +__curstd_config_value_for __ovfl_discard_dump __ovfl_reuse_dump __wt_bloom_drop diff --git a/src/third_party/wiredtiger/dist/s_string.ok b/src/third_party/wiredtiger/dist/s_string.ok index c65436830d8..8f2951fad48 100644 --- a/src/third_party/wiredtiger/dist/s_string.ok +++ b/src/third_party/wiredtiger/dist/s_string.ok @@ -612,6 +612,7 @@ bm bnd bool boolean +booleans boption br breakpoint @@ -750,6 +751,7 @@ cursoring cursorp curstartrecno curstat +curstd curtable curtiered curversion diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index 034278f67f7..d37c28d4312 100644 --- a/src/third_party/wiredtiger/import.data +++ b/src/third_party/wiredtiger/import.data @@ -2,5 +2,5 @@ "vendor": "wiredtiger", "github": "wiredtiger/wiredtiger.git", "branch": "mongodb-master", - "commit": "994ff9d67aec692c6add208035d7d8691b271e6f" + "commit": "d69ee179611d881d06d0469480985992a7f186a2" } diff --git a/src/third_party/wiredtiger/src/cursor/cur_std.c b/src/third_party/wiredtiger/src/cursor/cur_std.c index f6ca142c2f6..ae5f6c242e4 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_std.c +++ b/src/third_party/wiredtiger/src/cursor/cur_std.c @@ -9,6 +9,23 @@ #include "wt_internal.h" /* + * __curstd_config_value_for -- + * Returns NULL if the string being searched for isn't found, or the string after the "=" sign + * in the config string. + */ +static inline char * +__curstd_config_value_for(const char *config, const char *var, size_t len) +{ + char *cfg; + if ((cfg = strstr(config, var)) == NULL) + return (NULL); + return (cfg + len); +} + +#define CONFIG_VALUE_FOR(config, var, cfg) \ + ((cfg) = __curstd_config_value_for((config), var "=", strlen(var "="))) + +/* * __wt_cursor_noop -- * Cursor noop. */ @@ -1177,19 +1194,33 @@ err: int __wt_cursor_bound(WT_CURSOR *cursor, const char *config) { - WT_CONFIG_ITEM cval; WT_CURSOR_BTREE *cbt; WT_DECL_RET; WT_ITEM key; WT_SESSION_IMPL *session; int exact; - bool inclusive; + char *cfg; + bool inclusive, have_action; + cfg = NULL; cbt = (WT_CURSOR_BTREE *)cursor; exact = 0; - inclusive = false; - CURSOR_API_CALL_CONF(cursor, session, bound, config, cfg, NULL); + /* + * Our API defines "inclusive" as true by default, it also defines "set" as the default action. + * This means we can't expect the user to have provided those configurations via the config + * string. Normally WiredTiger merges the user provided configuration with the default + * configuration, for performance reasons we are skipping this step. As such we need to handle + * the cases where the user did and didn't provide the config making up the difference for the + * defaults. + * + * These two booleans provide a mechanism to handle the user not providing the configuration and + * still being able to parse it. + */ + inclusive = true; + have_action = false; + + CURSOR_API_CALL(cursor, session, bound, NULL); if (CUR2BT(cursor)->type == BTREE_COL_FIX) WT_ERR_MSG(session, EINVAL, "setting bounds is not compatible with fixed column store."); @@ -1197,22 +1228,28 @@ __wt_cursor_bound(WT_CURSOR *cursor, const char *config) if (F_ISSET(cursor, WT_CURSTD_PREFIX_SEARCH)) WT_ERR_MSG(session, EINVAL, "setting bounds is not compatible with prefix search."); - WT_ERR(__wt_config_gets(session, cfg, "action", &cval)); - if (WT_STRING_MATCH("set", cval.str, cval.len)) { - WT_ERR(__wt_config_gets(session, cfg, "inclusive", &cval)); - inclusive = cval.val != 0; + if (config == NULL || config[0] == '\0') + WT_ERR_MSG(session, EINVAL, "an empty config is not valid when setting or clearing bounds"); - /* Check that bound is set with action set configuration. */ - WT_ERR(__wt_config_gets(session, cfg, "bound", &cval)); - if (cval.len == 0) - WT_ERR_MSG(session, EINVAL, "setting bounds must require the bound configuration set"); + /* Action is default to "set". */ + if (CONFIG_VALUE_FOR(config, "action", cfg) != NULL) + have_action = true; + if (!have_action || WT_PREFIX_MATCH(cfg, "set")) { if (WT_CURSOR_IS_POSITIONED(cbt)) WT_ERR_MSG(session, EINVAL, "setting bounds on a positioned cursor is not allowed"); /* The cursor must have a key set to place the lower or upper bound. */ WT_ERR(__cursor_checkkey(cursor)); - if (WT_STRING_MATCH("upper", cval.str, cval.len)) { + + /* Inclusive is true by default. */ + if (CONFIG_VALUE_FOR(config, "inclusive", cfg) != NULL && !WT_PREFIX_MATCH(cfg, "true")) + inclusive = false; + + if (CONFIG_VALUE_FOR(config, "bound", cfg) == NULL) + WT_ERR_MSG(session, EINVAL, + "a bound must be specified when setting bounds, either \"lower\" or \"upper\""); + else if (WT_PREFIX_MATCH(cfg, "upper")) { /* * If the lower bounds are set, make sure that the upper bound is greater than the lower * bound. @@ -1238,7 +1275,7 @@ __wt_cursor_bound(WT_CURSOR *cursor, const char *config) else F_CLR(cursor, WT_CURSTD_BOUND_UPPER_INCLUSIVE); WT_ERR(__wt_buf_set(session, &cursor->upper_bound, key.data, key.size)); - } else if (WT_STRING_MATCH("lower", cval.str, cval.len)) { + } else if (WT_PREFIX_MATCH(cfg, "lower")) { /* * If the upper bounds are set, make sure that the lower bound is less than the upper * bound. @@ -1266,30 +1303,16 @@ __wt_cursor_bound(WT_CURSOR *cursor, const char *config) WT_ERR(__wt_buf_set(session, &cursor->lower_bound, key.data, key.size)); } else WT_ERR_MSG(session, EINVAL, - "setting bounds only accepts \"upper\" or \"lower\" as the configuration"); - - } else if (WT_STRING_MATCH("clear", cval.str, cval.len)) { - /* Inclusive should not be supplied from the application with action clear configuration. */ - if (__wt_config_getones(session, config, "inclusive", &cval) != WT_NOTFOUND) - WT_ERR_MSG(session, EINVAL, - "clearing bounds is not compatible with the inclusive configuration"); - - /* - * Check if there is a lower or upper specified bound config. If there are no specified - * bounds, both the upper and lower bound will be cleared. - */ - WT_ERR(__wt_config_gets(session, cfg, "bound", &cval)); - if (cval.len == 0 || WT_STRING_MATCH("upper", cval.str, cval.len)) { - F_CLR(cursor, WT_CURSTD_BOUND_UPPER | WT_CURSTD_BOUND_UPPER_INCLUSIVE); - __wt_buf_free(session, &cursor->upper_bound); - WT_CLEAR(cursor->upper_bound); - } - if (cval.len == 0 || WT_STRING_MATCH("lower", cval.str, cval.len)) { - F_CLR(cursor, WT_CURSTD_BOUND_LOWER | WT_CURSTD_BOUND_LOWER_INCLUSIVE); - __wt_buf_free(session, &cursor->lower_bound); - WT_CLEAR(cursor->lower_bound); - } - } + "a bound must be specified when setting bounds, either \"lower\" or \"upper\""); + } else if (have_action && WT_PREFIX_MATCH(cfg, "clear")) { + F_CLR(cursor, WT_CURSTD_BOUND_ALL); + __wt_buf_free(session, &cursor->upper_bound); + __wt_buf_free(session, &cursor->lower_bound); + WT_CLEAR(cursor->upper_bound); + WT_CLEAR(cursor->lower_bound); + } else + WT_ERR_MSG(session, EINVAL, + "an action of either \"clear\" or \"set\" should be specified when setting bounds"); err: API_END_RET_STAT(session, ret, cursor_bound); } diff --git a/src/third_party/wiredtiger/src/include/wiredtiger.in b/src/third_party/wiredtiger/src/include/wiredtiger.in index e103766eed4..f1e66e10ad7 100644 --- a/src/third_party/wiredtiger/src/include/wiredtiger.in +++ b/src/third_party/wiredtiger/src/include/wiredtiger.in @@ -684,18 +684,14 @@ struct __wt_cursor { * @configstart{WT_CURSOR.bound, see dist/api_data.py} * @config{action, configures whether this call into the API will set or clear range bounds * on the given cursor. It takes one of two values\, "set" or "clear". If "set" is - * specified then "bound" must also be specified. If "clear" is specified without any - * bounds then both bounds will be cleared. The keys relevant to the given bound must have - * been set prior to the call using WT_CURSOR::set_key. This configuration is currently a - * work in progress and should not be used., a string\, chosen from the following options: - * \c "clear"\, \c "set"; default \c set.} + * specified then "bound" must also be specified. The keys relevant to the given bound must + * have been set prior to the call using WT_CURSOR::set_key., a string\, chosen from the + * following options: \c "clear"\, \c "set"; default \c set.} * @config{bound, configures which bound is being operated on. It takes one of two values\, - * "lower" or "upper". This configuration is currently a work in progress and should not be - * used., a string\, chosen from the following options: \c "lower"\, \c "upper"; default - * empty.} - * @config{inclusive, configures whether the given bound is inclusive or not. This - * configuration is currently a work in progress and should not be used., a boolean flag; - * default \c true.} + * "lower" or "upper"., a string\, chosen from the following options: \c "lower"\, \c + * "upper"; default empty.} + * @config{inclusive, configures whether the given bound is inclusive or not., a boolean + * flag; default \c true.} * @configend * @errors */ diff --git a/src/third_party/wiredtiger/test/suite/test_cursor_bound01.py b/src/third_party/wiredtiger/test/suite/test_cursor_bound01.py index cf24f1e14e1..ca18364ea04 100644 --- a/src/third_party/wiredtiger/test/suite/test_cursor_bound01.py +++ b/src/third_party/wiredtiger/test/suite/test_cursor_bound01.py @@ -81,11 +81,11 @@ class test_cursor_bound01(bound_base): # LSM format is not supported with range cursors. if self.uri == 'lsm:': - self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: cursor.bound("bound=lower"), + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: cursor.bound("action=set,bound=lower"), '/Operation not supported/') return if self.value_format == '8t': - self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: cursor.bound("bound=lower"), + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: cursor.bound("action=set,bound=lower"), '/Invalid argument/') return @@ -95,15 +95,9 @@ class test_cursor_bound01(bound_base): # Check that bound configuration works properly. cursor.set_key(self.gen_key(1)) - cursor.bound("bound=lower") + cursor.bound("action=set,bound=lower") cursor.set_key(self.gen_key(10)) - cursor.bound("bound=upper") - - # Clear and inclusive configuration are not compatible with each other. - self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: cursor.bound("action=clear,inclusive=true"), - '/Invalid argument/') - self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: cursor.bound("action=clear,inclusive=false"), - '/Invalid argument/') + cursor.bound("action=set,bound=upper") # Check that clear with bound configuration works properly. cursor.bound("action=clear") @@ -112,7 +106,7 @@ class test_cursor_bound01(bound_base): # Check that largest key doesn't work with bounded cursors. cursor.set_key(self.gen_key(1)) - cursor.bound("bound=lower") + cursor.bound("action=set,bound=lower") self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: cursor.largest_key(), '/Invalid argument/') diff --git a/src/third_party/wiredtiger/test/suite/test_cursor_bound02.py b/src/third_party/wiredtiger/test/suite/test_cursor_bound02.py index 459c9aabd85..ce308dbe473 100644 --- a/src/third_party/wiredtiger/test/suite/test_cursor_bound02.py +++ b/src/third_party/wiredtiger/test/suite/test_cursor_bound02.py @@ -208,16 +208,6 @@ class test_cursor_bound02(bound_base): cursor.set_key(self.gen_key(90)) self.assertEqual(self.set_bounds(cursor, 90, "upper"), 0) - # Test bound API: Test that clearing the lower bound works. - self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: self.set_bounds(cursor, 10, "upper"), '/Invalid argument/') - self.assertEqual(cursor.bound("action=clear,bound=lower"), 0) - self.assertEqual(self.set_bounds(cursor, 10, "upper"), 0) - - # Test bound API: Test that clearing the upper bound works. - self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: self.set_bounds(cursor, 99, "lower"), '/Invalid argument/') - self.assertEqual(cursor.bound("action=clear,bound=upper"), 0) - self.assertEqual(self.set_bounds(cursor, 99, "lower"), 0) - # Test bound API: Test that clearing both of the bounds works. cursor.reset() self.assertEqual(self.set_bounds(cursor, 50, "upper"), 0) diff --git a/src/third_party/wiredtiger/test/suite/test_cursor_bound03.py b/src/third_party/wiredtiger/test/suite/test_cursor_bound03.py index 76f074d4b7e..ac9c6b1c877 100644 --- a/src/third_party/wiredtiger/test/suite/test_cursor_bound03.py +++ b/src/third_party/wiredtiger/test/suite/test_cursor_bound03.py @@ -123,14 +123,6 @@ class test_cursor_bound03(bound_base): self.assertEqual(cursor.bound("action=clear"), 0) self.cursor_traversal_bound(cursor, None, None, True) self.assertEqual(cursor.reset(), 0) - - # Test bound api: Test upper bound clearing with only lower bounds. - self.set_bounds(cursor, 50, "lower") - cursor.bound("action=clear,bound=upper") - self.cursor_traversal_bound(cursor, None, None, self.direction, self.end_key - 49) - - cursor.bound("action=clear,bound=lower") - self.cursor_traversal_bound(cursor, None, None) # Test bound api: Test that changing upper bounds works. self.set_bounds(cursor, 50, "upper", self.upper_inclusive) diff --git a/src/third_party/wiredtiger/test/suite/test_cursor_bound04.py b/src/third_party/wiredtiger/test/suite/test_cursor_bound04.py index 0dd1849d39c..f1ec5c5ae8c 100644 --- a/src/third_party/wiredtiger/test/suite/test_cursor_bound04.py +++ b/src/third_party/wiredtiger/test/suite/test_cursor_bound04.py @@ -68,17 +68,9 @@ class test_cursor_bound04(bound_base): def test_bound_special_scenario(self): cursor = self.create_session_and_cursor() - # Test bound api: Test upper bound clearing with only lower bounds. + # Test bound api: Test lower bound clearing works. self.set_bounds(cursor, 45, "lower") - cursor.bound("action=clear,bound=upper") - self.assertEqual(cursor.next(), 0) - key = cursor.get_key() - self.assertEqual(key, self.check_key(45)) - cursor.reset() - - # Test bound api: Test lower bound clearing with lower bounds works. - self.set_bounds(cursor, 45, "lower") - cursor.bound("action=clear,bound=lower") + cursor.bound("action=clear") self.assertEqual(cursor.next(), 0) key = cursor.get_key() self.assertEqual(key, self.check_key(self.start_key)) |