diff options
author | Alex Gorrod <alexg@wiredtiger.com> | 2015-07-24 17:21:00 +1000 |
---|---|---|
committer | Alex Gorrod <alexg@wiredtiger.com> | 2015-07-24 17:21:00 +1000 |
commit | 10c5a4c4eec49666d79e4069a72f6a7ab19757b3 (patch) | |
tree | a38e571eb94d7c5fed62bfcbdbf0c4c03ffb9343 /bench/wtperf/wtperf_truncate.c | |
parent | 6cdd3625de3678b6f48ea0ba182430b0ae3e756e (diff) | |
download | mongo-10c5a4c4eec49666d79e4069a72f6a7ab19757b3.tar.gz |
Review feedback for wtperf truncate.
Diffstat (limited to 'bench/wtperf/wtperf_truncate.c')
-rw-r--r-- | bench/wtperf/wtperf_truncate.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/bench/wtperf/wtperf_truncate.c b/bench/wtperf/wtperf_truncate.c new file mode 100644 index 00000000000..9c4e0387a90 --- /dev/null +++ b/bench/wtperf/wtperf_truncate.c @@ -0,0 +1,201 @@ +/*- + * Public Domain 2014-2015 MongoDB, Inc. + * Public Domain 2008-2014 WiredTiger, Inc. + * + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "wtperf.h" + +int +setup_truncate(CONFIG *cfg, CONFIG_THREAD *thread, WT_SESSION *session) { + + TRUNCATE_CONFIG *trunc_cfg; + TRUNCATE_QUEUE_ENTRY *truncate_item; + WORKLOAD *workload; + WT_CURSOR *cursor; + char *key, *truncate_key; + int ret; + size_t i; + uint64_t end_point, final_stone_gap, start_point; + + end_point = final_stone_gap = start_point = 0; + trunc_cfg = &thread->trunc_cfg; + workload = thread->workload; + + /* We are limited to only one table when running truncate. */ + if ((ret = session->open_cursor( + session, cfg->uris[0], NULL, NULL, &cursor)) != 0) + goto err; + + /* Truncation percentage value. eg 10% is 0.1. */ + trunc_cfg->truncation_percentage = (double)workload->truncate_pct / 100; + /* How many entries between each stone. */ + trunc_cfg->truncate_stone_gap = + workload->truncate_count * trunc_cfg->truncation_percentage; + /* How many stones we need. */ + trunc_cfg->needed_stones = + workload->truncate_count / trunc_cfg->truncate_stone_gap; + + final_stone_gap = trunc_cfg->truncate_stone_gap; + + /* Reset this value for use again. */ + trunc_cfg->truncate_stone_gap = 0; + + /* + * Here we check if there is data in the collection. If there is + * data available, then we need to setup some initial truncation + * stones. + */ + if ((ret = cursor->next(cursor)) != 0 || + (ret = cursor->get_key(cursor, &key)) != 0) { + lprintf(cfg, ret, 0, "truncate setup start: failed"); + goto err; + } + + start_point = decode_key(key); + if ((cursor->reset(cursor)) != 0 || (ret = cursor->prev(cursor)) != 0 || + (ret = cursor->get_key(cursor, &key)) != 0) { + lprintf(cfg, ret, 0, "truncate setup end: failed"); + goto err; + } + end_point = decode_key(key); + + /* Assign stones if there are enough documents. */ + if (start_point + trunc_cfg->needed_stones > end_point) + trunc_cfg->truncate_stone_gap = 0; + else + trunc_cfg->truncate_stone_gap = + (end_point - start_point) / trunc_cfg->needed_stones; + + /* If we have enough data allocate some stones. */ + if (trunc_cfg->truncate_stone_gap != 0) { + trunc_cfg->expected_total = (end_point - start_point); + for (i = 0; i < trunc_cfg->needed_stones; i++) { + truncate_key = calloc(cfg->key_sz, 1); + truncate_item = calloc(sizeof(TRUNCATE_QUEUE_ENTRY), 1); + if (truncate_item == NULL) { + ret = enomem(cfg); + goto err; + } + generate_key(cfg, truncate_key, + trunc_cfg->truncate_stone_gap * (i+1)); + truncate_item->key = truncate_key; + truncate_item->diff = + (trunc_cfg->truncate_stone_gap * (i+1)) - + trunc_cfg->last_key; + STAILQ_INSERT_TAIL( &cfg->truncate_stone_head, + truncate_item, q); + trunc_cfg->last_key = + trunc_cfg->truncate_stone_gap * (i+1); + trunc_cfg->num_stones++; + } + } + trunc_cfg->truncate_stone_gap = final_stone_gap; + +err: cursor->close(cursor); + return (ret); +} + +int +run_truncate(CONFIG *cfg, CONFIG_THREAD *thread, + TRACK **trk, WT_CURSOR *cursor, WT_SESSION *session) { + + TRUNCATE_CONFIG *trunc_cfg; + TRUNCATE_QUEUE_ENTRY *truncate_item; + char *truncate_key; + int ret; + + ret = 0; + trunc_cfg = &thread->trunc_cfg; + + /* Update the total inserts */ + trunc_cfg->total_inserts = sum_insert_ops(cfg); + trunc_cfg->expected_total += + (trunc_cfg->total_inserts - trunc_cfg->last_total_inserts); + trunc_cfg->last_total_inserts = trunc_cfg->total_inserts; + + /* We are done if there isn't enough data to trigger a new milestone. */ + if (trunc_cfg->expected_total <= trunc_cfg->needed_stones) { + (void)usleep(1000); + *trk = &thread->truncate_sleep; + return (0); + } + + while (trunc_cfg->num_stones < trunc_cfg->needed_stones) { + trunc_cfg->last_key += trunc_cfg->truncate_stone_gap; + truncate_key = calloc(cfg->key_sz, 1); + truncate_item = calloc(sizeof(TRUNCATE_QUEUE_ENTRY), 1); + if (truncate_item == NULL) { + lprintf(cfg, ENOMEM, 0, + "worker: couldn't allocate cursor array"); + return (ENOMEM); + } + generate_key(cfg, truncate_key, trunc_cfg->last_key); + truncate_item->key = truncate_key; + truncate_item->diff = trunc_cfg->truncate_stone_gap; + STAILQ_INSERT_TAIL(&cfg->truncate_stone_head, truncate_item, q); + trunc_cfg->num_stones++; + } + + /* We are done if there isn't enough data to trigger a truncate. */ + if (trunc_cfg->num_stones == 0 || + trunc_cfg->expected_total <= thread->workload->truncate_count) { + (void)usleep(1000); + *trk = &thread->truncate_sleep; + return (0); + } + + truncate_item = STAILQ_FIRST(&cfg->truncate_stone_head); + trunc_cfg->num_stones--; + STAILQ_REMOVE_HEAD(&cfg->truncate_stone_head, q); + cursor->set_key(cursor,truncate_item->key); + if ((ret = cursor->search(cursor)) != 0) { + lprintf(cfg, ret, 0, "Truncate search: failed"); + return (ret); + } + + if ((ret = session->truncate(session, NULL, NULL, cursor, NULL)) != 0) { + lprintf(cfg, ret, 0, "Truncate: failed"); + return (ret); + } + trunc_cfg->expected_total -= truncate_item->diff; + free(truncate_item->key); + free(truncate_item); + truncate_item = NULL; + + return (ret); +} + +void +cleanup_truncate_config(CONFIG *cfg) { + TRUNCATE_QUEUE_ENTRY *truncate_item; + + while (!STAILQ_EMPTY(&cfg->truncate_stone_head)) { + truncate_item = STAILQ_FIRST(&cfg->truncate_stone_head); + STAILQ_REMOVE_HEAD(&cfg->truncate_stone_head, q); + free(truncate_item->key); + free(truncate_item); + } +} |