int run_truncate(CONFIG *cfg, CONFIG_THREAD *thread, WT_CURSOR *cursor, WT_SESSION *session, int *truncatedp) { TRUNCATE_CONFIG *trunc_cfg; TRUNCATE_QUEUE_ENTRY *truncate_item; char *truncate_key; int ret, t_ret; ret = 0; trunc_cfg = &thread->trunc_cfg; *truncatedp = 0; /* 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) return (0); while (trunc_cfg->num_stones < trunc_cfg->needed_stones) { trunc_cfg->last_key += trunc_cfg->stone_gap; truncate_key = calloc(cfg->key_sz, 1); if (truncate_key == NULL) { lprintf(cfg, ENOMEM, 0, "truncate: couldn't allocate key array"); return (ENOMEM); } truncate_item = calloc(sizeof(TRUNCATE_QUEUE_ENTRY), 1); if (truncate_item == NULL) { free(truncate_key); lprintf(cfg, ENOMEM, 0, "truncate: couldn't allocate item"); return (ENOMEM); } generate_key(cfg, truncate_key, trunc_cfg->last_key); truncate_item->key = truncate_key; truncate_item->diff = trunc_cfg->stone_gap; TAILQ_INSERT_TAIL(&cfg->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) return (0); truncate_item = TAILQ_FIRST(&cfg->stone_head); trunc_cfg->num_stones--; TAILQ_REMOVE(&cfg->stone_head, truncate_item, q); cursor->set_key(cursor,truncate_item->key); if ((ret = cursor->search(cursor)) != 0) { lprintf(cfg, ret, 0, "Truncate search: failed"); goto err; } if ((ret = session->truncate(session, NULL, NULL, cursor, NULL)) != 0) { lprintf(cfg, ret, 0, "Truncate: failed"); goto err; } *truncatedp = 1; trunc_cfg->expected_total -= truncate_item->diff; err: free(truncate_item->key); free(truncate_item); t_ret = cursor->reset(cursor); if (t_ret != 0) lprintf(cfg, t_ret, 0, "Cursor reset failed"); if (ret == 0 && t_ret != 0) ret = t_ret; return (ret); }
int run_truncate(CONFIG *cfg, CONFIG_THREAD *thread, WT_CURSOR *cursor, WT_SESSION *session, int *truncatedp) { TRUNCATE_CONFIG *trunc_cfg; TRUNCATE_QUEUE_ENTRY *truncate_item; char *truncate_key; int ret, t_ret; uint64_t used_stone_gap; ret = 0; trunc_cfg = &thread->trunc_cfg; *truncatedp = 0; /* 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 <= thread->workload->truncate_count) return (0); /* * If we are falling behind and using more than one stone per lap we * should widen the stone gap for this lap to try and catch up quicker. */ if (trunc_cfg->expected_total > thread->workload->truncate_count + trunc_cfg->stone_gap) { /* * Increase the multiplier until we create stones that are * almost large enough to truncate the whole expected table size * in one operation. */ trunc_cfg->catchup_multiplier = WT_MIN(trunc_cfg->catchup_multiplier + 1, trunc_cfg->needed_stones - 1); } else { /* Back off if we start seeing an improvement */ trunc_cfg->catchup_multiplier = WT_MAX(trunc_cfg->catchup_multiplier - 1, 1); } used_stone_gap = trunc_cfg->stone_gap * trunc_cfg->catchup_multiplier; while (trunc_cfg->num_stones < trunc_cfg->needed_stones) { trunc_cfg->last_key += used_stone_gap; truncate_key = calloc(cfg->key_sz, 1); if (truncate_key == NULL) { lprintf(cfg, ENOMEM, 0, "truncate: couldn't allocate key array"); return (ENOMEM); } truncate_item = calloc(sizeof(TRUNCATE_QUEUE_ENTRY), 1); if (truncate_item == NULL) { free(truncate_key); lprintf(cfg, ENOMEM, 0, "truncate: couldn't allocate item"); return (ENOMEM); } generate_key(cfg, truncate_key, trunc_cfg->last_key); truncate_item->key = truncate_key; truncate_item->diff = used_stone_gap; TAILQ_INSERT_TAIL(&cfg->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) return (0); truncate_item = TAILQ_FIRST(&cfg->stone_head); trunc_cfg->num_stones--; TAILQ_REMOVE(&cfg->stone_head, truncate_item, q); cursor->set_key(cursor,truncate_item->key); if ((ret = cursor->search(cursor)) != 0) { lprintf(cfg, ret, 0, "Truncate search: failed"); goto err; } if ((ret = session->truncate(session, NULL, NULL, cursor, NULL)) != 0) { lprintf(cfg, ret, 0, "Truncate: failed"); goto err; } *truncatedp = 1; trunc_cfg->expected_total -= truncate_item->diff; err: free(truncate_item->key); free(truncate_item); t_ret = cursor->reset(cursor); if (t_ret != 0) lprintf(cfg, t_ret, 0, "Cursor reset failed"); if (ret == 0 && t_ret != 0) ret = t_ret; return (ret); }