Beispiel #1
0
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);
}