static void
initiateSnowFlake (SnowScreen *ss,
		   SnowFlake  *sf)
{
    /* TODO: possibly place snowflakes based on FOV, instead of a cube. */
    //int boxing = starGetScreenBoxing (ss->s->display);
    float init;

	// speed of star
	sf->xs = mmrand(-50000, 50000, 5000);
	sf->ys = mmrand(-50000, 50000, 5000);
	sf->zs = mmrand(000, 200, 2000);

	//TODO: possibly place stars based on FOV, instead of a cube.
	sf->x = ss->s->width * .5 + starGetStarOffsetX (ss->s->display); // X Offset
	sf->y = ss->s->height * .5 + starGetStarOffsetY (ss->s->display); // Y Offset
	sf->z = mmrand(000, 0.1, 5000);
	init = mmrand(0,100, 1); //init = distance to center of the screen

	sf->x += init * sf->xs;
	sf->y += init * sf->ys;

   /* switch (snowGetSnowDirection (ss->s->display))
    {
    case SnowDirectionTopToBottom:
	sf->x  = mmRand (-boxing, ss->s->width + boxing, 1);
	sf->xs = mmRand (-1, 1, 500);
	sf->y  = mmRand (-300, 0, 1);
	sf->ys = mmRand (1, 3, 1);
	break;
    case SnowDirectionBottomToTop:
	sf->x  = mmRand (-boxing, ss->s->width + boxing, 1);
	sf->xs = mmRand (-1, 1, 500);
	sf->y  = mmRand (ss->s->height, ss->s->height + 300, 1);
	sf->ys = -mmRand (1, 3, 1);
	break;
    case SnowDirectionRightToLeft:
	sf->x  = mmRand (ss->s->width, ss->s->width + 300, 1);
	sf->xs = -mmRand (1, 3, 1);
	sf->y  = mmRand (-boxing, ss->s->height + boxing, 1);
	sf->ys = mmRand (-1, 1, 500);
	break;
    case SnowDirectionLeftToRight:
	sf->x  = mmRand (-300, 0, 1);
	sf->xs = mmRand (1, 3, 1);
	sf->y  = mmRand (-boxing, ss->s->height + boxing, 1);
	sf->ys = mmRand (-1, 1, 500);
	break;
    default:
	break;
    }

    sf->z  = mmRand (-snowGetScreenDepth (ss->s->display), 0.1, 5000);
    sf->zs = mmRand (-1000, 1000, 500000);
    sf->ra = mmRand (-1000, 1000, 50);
    sf->rs = mmRand (-1000, 1000, 1000);*/
}
示例#2
0
void
val_gen(WT_RAND_STATE *rnd, WT_ITEM *value, uint64_t keyno)
{
	char *p;

	p = value->mem;
	value->data = value->mem;

	/*
	 * Fixed-length records: take the low N bits from the last digit of
	 * the record number.
	 */
	if (g.type == FIX) {
		switch (g.c_bitcnt) {
		case 8: p[0] = (char)mmrand(rnd, 1, 0xff); break;
		case 7: p[0] = (char)mmrand(rnd, 1, 0x7f); break;
		case 6: p[0] = (char)mmrand(rnd, 1, 0x3f); break;
		case 5: p[0] = (char)mmrand(rnd, 1, 0x1f); break;
		case 4: p[0] = (char)mmrand(rnd, 1, 0x0f); break;
		case 3: p[0] = (char)mmrand(rnd, 1, 0x07); break;
		case 2: p[0] = (char)mmrand(rnd, 1, 0x03); break;
		case 1: p[0] = 1; break;
		}
		value->size = 1;
		return;
	}

	/*
	 * WiredTiger doesn't store zero-length data items in row-store files,
	 * test that by inserting a zero-length data item every so often.
	 */
	if (keyno % 63 == 0) {
		p[0] = '\0';
		value->size = 0;
		return;
	}

	/*
	 * Start the data with a 10-digit number.
	 *
	 * For row and non-repeated variable-length column-stores, change the
	 * leading number to ensure every data item is unique.  For repeated
	 * variable-length column-stores (that is, to test run-length encoding),
	 * use the same data value all the time.
	 */
	if ((g.type == ROW || g.type == VAR) &&
	    g.c_repeat_data_pct != 0 &&
	    mmrand(rnd, 1, 100) < g.c_repeat_data_pct) {
		(void)strcpy(p, "DUPLICATEV");
		p[10] = '/';
		value->size = val_dup_data_len;
	} else {
		(void)sprintf(p, "%010" PRIu64, keyno);
		p[10] = '/';
		value->size =
		    value_len(rnd, keyno, g.c_value_min, g.c_value_max);
	}
}
示例#3
0
文件: util.c 项目: Machyne/mongo
void
val_gen_setup(WT_RAND_STATE *rnd, WT_ITEM *value)
{
	size_t i, len;
	char *p;

	memset(value, 0, sizeof(WT_ITEM));

	/*
	 * Set initial buffer contents to recognizable text.
	 *
	 * Add a few extra bytes in order to guarantee we can always offset
	 * into the buffer by a few extra bytes, used to generate different
	 * data for column-store run-length encoded files.
	 */
	len = MAX(KILOBYTE(100), g.c_value_max) + 20;
	p = dmalloc(len);
	for (i = 0; i < len; ++i)
		p[i] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i % 26];

	value->mem = p;
	value->memsize = len;
	value->data = value->mem;
	value->size = 0;

	val_dup_data_len = value_len(rnd,
	    (uint64_t)mmrand(rnd, 1, 20), g.c_value_min, g.c_value_max);
}
示例#4
0
文件: util.c 项目: Machyne/mongo
void
key_len_setup(void)
{
	size_t i;
	uint32_t max;

	/*
	 * The key is a variable length item with a leading 10-digit value.
	 * Since we have to be able re-construct it from the record number
	 * (when doing row lookups), we pre-load a set of random lengths in
	 * a lookup table, and then use the record number to choose one of
	 * the pre-loaded lengths.
	 *
	 * Fill in the random key lengths.
	 *
	 * Focus on relatively small items, admitting the possibility of larger
	 * items. Pick a size close to the minimum most of the time, only create
	 * a larger item 1 in 20 times.
	 */
	for (i = 0;
	    i < sizeof(g.key_rand_len) / sizeof(g.key_rand_len[0]); ++i) {
		max = g.c_key_max;
		if (i % 20 != 0 && max > g.c_key_min + 20)
			max = g.c_key_min + 20;
		g.key_rand_len[i] = mmrand(NULL, g.c_key_min, max);
	}
}
示例#5
0
文件: util.c 项目: Machyne/mongo
void
val_gen(WT_RAND_STATE *rnd, WT_ITEM *value, uint64_t keyno)
{
	char *p;

	p = value->mem;
	value->data = value->mem;

	/*
	 * Fixed-length records: take the low N bits from the last digit of
	 * the record number.
	 */
	if (g.type == FIX) {
		switch (g.c_bitcnt) {
		case 8: p[0] = (char)mmrand(rnd, 1, 0xff); break;
		case 7: p[0] = (char)mmrand(rnd, 1, 0x7f); break;
		case 6: p[0] = (char)mmrand(rnd, 1, 0x3f); break;
		case 5: p[0] = (char)mmrand(rnd, 1, 0x1f); break;
		case 4: p[0] = (char)mmrand(rnd, 1, 0x0f); break;
		case 3: p[0] = (char)mmrand(rnd, 1, 0x07); break;
		case 2: p[0] = (char)mmrand(rnd, 1, 0x03); break;
		case 1: p[0] = 1; break;
		}
		value->size = 1;
		return;
	}

	/*
	 * WiredTiger doesn't store zero-length data items in row-store files,
	 * test that by inserting a zero-length data item every so often.
	 */
	if (keyno % 63 == 0) {
		p[0] = '\0';
		value->size = 0;
		return;
	}

	/*
	 * Data items have unique leading numbers by default and random lengths;
	 * variable-length column-stores use a duplicate data value to test RLE.
	 */
	if (g.type == VAR && mmrand(rnd, 1, 100) < g.c_repeat_data_pct) {
		(void)strcpy(p, "DUPLICATEV");
		p[10] = '/';
		value->size = val_dup_data_len;
	} else {
		u64_to_string_zf(keyno, p, 11);
		p[10] = '/';
		value->size =
		    value_len(rnd, keyno, g.c_value_min, g.c_value_max);
	}
}
示例#6
0
文件: util.c 项目: Machyne/mongo
void
key_gen_insert(WT_RAND_STATE *rnd, WT_ITEM *key, uint64_t keyno)
{
	static const char * const suffix[15] = {
	    "01", "02", "03", "04", "05",
	    "06", "07", "08", "09", "10",
	    "11", "12", "13", "14", "15"
	};

	key_gen_common(key, keyno, suffix[mmrand(rnd, 1, 15) - 1]);
}
示例#7
0
/*
 * compaction --
 *	Periodically do a compaction operation.
 */
WT_THREAD_RET
compact(void *arg)
{
	WT_CONNECTION *conn;
	WT_DECL_RET;
	WT_SESSION *session;
	u_int period;

	(void)(arg);

	/* Compaction isn't supported for all data sources. */
	if (DATASOURCE("helium") || DATASOURCE("kvsbdb"))
		return (WT_THREAD_RET_VALUE);

	/* Open a session. */
	conn = g.wts_conn;
	testutil_check(conn->open_session(conn, NULL, NULL, &session));

	/*
	 * Perform compaction at somewhere under 15 seconds (so we get at
	 * least one done), and then at 23 second intervals.
	 */
	for (period = mmrand(NULL, 1, 15);; period = 23) {
		/* Sleep for short periods so we don't make the run wait. */
		while (period > 0 && !g.workers_finished) {
			--period;
			__wt_sleep(1, 0);
		}
		if (g.workers_finished)
			break;

		/*
		 * Compact can return EBUSY if concurrent with alter or if there
		 * is eviction pressure, or we collide with checkpoints.
		 *
		 * Compact returns ETIMEDOUT if the compaction doesn't finish in
		 * in some number of seconds. We don't configure a timeout and
		 * occasionally exceed the default of 1200 seconds.
		 */
		ret = session->compact(session, g.uri, NULL);
		if (ret != 0 &&
		    ret != EBUSY && ret != ETIMEDOUT && ret != WT_ROLLBACK)
			testutil_die(ret, "session.compact");
	}

	testutil_check(session->close(session, NULL));

	return (WT_THREAD_RET_VALUE);
}
示例#8
0
文件: util.c 项目: Machyne/mongo
static inline uint32_t
value_len(WT_RAND_STATE *rnd, uint64_t keyno, uint32_t min, uint32_t max)
{
	/*
	 * Focus on relatively small items, admitting the possibility of larger
	 * items. Pick a size close to the minimum most of the time, only create
	 * a larger item 1 in 20 times, and a really big item 1 in somewhere
	 * around 2500 items.
	 */
	if (keyno % 2500 == 0 && max < KILOBYTE(80)) {
		min = KILOBYTE(80);
		max = KILOBYTE(100);
	} else if (keyno % 20 != 0 && max > min + 20)
		max = min + 20;
	return (mmrand(rnd, min, max));
}
示例#9
0
/*
 * wts_read_scan --
 *	Read and verify all elements in a file.
 */
void
wts_read_scan(void)
{
	WT_CONNECTION *conn;
	WT_CURSOR *cursor;
	WT_ITEM key;
	WT_SESSION *session;
	uint64_t cnt, last_cnt;
	uint8_t *keybuf;
	int ret;

	conn = g.wts_conn;

	/* Set up the default key buffer. */
	key_gen_setup(&keybuf);

	/* Open a session and cursor pair. */
	if ((ret = conn->open_session(
	    conn, NULL, ops_session_config(NULL), &session)) != 0)
		die(ret, "connection.open_session");
	if ((ret = session->open_cursor(
	    session, g.uri, NULL, NULL, &cursor)) != 0)
		die(ret, "session.open_cursor");

	/* Check a random subset of the records using the key. */
	for (last_cnt = cnt = 0; cnt < g.key_cnt;) {
		cnt += mmrand(NULL, 1, 17);
		if (cnt > g.rows)
			cnt = g.rows;
		if (cnt - last_cnt > 1000) {
			track("read row scan", cnt, NULL);
			last_cnt = cnt;
		}

		key.data = keybuf;
		if ((ret = read_row(cursor, &key, cnt)) != 0)
			die(ret, "read_scan");
	}

	if ((ret = session->close(session, NULL)) != 0)
		die(ret, "session.close");

	free(keybuf);
}
示例#10
0
/*
 * ops_session_config --
 *	Return the current session configuration.
 */
static const char *
ops_session_config(uint64_t *rnd)
{
	u_int v;

	/*
	 * The only current session configuration is the isolation level.
	 */
	if ((v = g.c_isolation_flag) == ISOLATION_RANDOM)
		v = mmrand(rnd, 2, 4);
	switch (v) {
	case ISOLATION_READ_UNCOMMITTED:
		return ("isolation=read-uncommitted");
	case ISOLATION_READ_COMMITTED:
		return ("isolation=read-committed");
	case ISOLATION_SNAPSHOT:
	default:
		return ("isolation=snapshot");
	}
}
示例#11
0
文件: compact.c 项目: Asamaha/mongo
/*
 * compaction --
 *	Periodically do a compaction operation.
 */
void *
compact(void *arg)
{
	WT_CONNECTION *conn;
	WT_SESSION *session;
	u_int period;
	int ret;

	(void)(arg);

	/* Compaction isn't supported for all data sources. */
	if (DATASOURCE("helium") || DATASOURCE("kvsbdb"))
		return (NULL);

	/* Open a session. */
	conn = g.wts_conn;
	testutil_check(conn->open_session(conn, NULL, NULL, &session));

	/*
	 * Perform compaction at somewhere under 15 seconds (so we get at
	 * least one done), and then at 23 second intervals.
	 */
	for (period = mmrand(NULL, 1, 15);; period = 23) {
		/* Sleep for short periods so we don't make the run wait. */
		while (period > 0 && !g.workers_finished) {
			--period;
			sleep(1);
		}
		if (g.workers_finished)
			break;

		if ((ret = session->compact(
		    session, g.uri, NULL)) != 0 && ret != WT_ROLLBACK)
			testutil_die(ret, "session.compact");
	}

	testutil_check(session->close(session, NULL));

	return (NULL);
}
示例#12
0
文件: util.c 项目: ksuarz/mongo
/*
 * alter --
 *	Periodically alter a table's metadata.
 */
void *
alter(void *arg)
{
	WT_CONNECTION *conn;
	WT_SESSION *session;
	u_int period;
	bool access_value;
	char buf[32];

	(void)(arg);
	conn = g.wts_conn;

	/*
	 * Only alter the access pattern hint.  If we alter the cache resident
	 * setting we may end up with a setting that fills cache and doesn't
	 * allow it to be evicted.
	 */
	access_value = false;

	/* Open a session */
	testutil_check(conn->open_session(conn, NULL, NULL, &session));

	while (!g.workers_finished) {
		period = mmrand(NULL, 1, 10);

		snprintf(buf, sizeof(buf),
		    "access_pattern_hint=%s", access_value ? "random" : "none");
		access_value = !access_value;
		if (session->alter(session, g.uri, buf) != 0)
			break;
		while (period > 0 && !g.workers_finished) {
			--period;
			sleep(1);
		}
	}

	testutil_check(session->close(session, NULL));
	return (NULL);
}
static void
initiateSnowFlake (SnowScreen *ss,
		   SnowFlake  *sf)
{
    /* TODO: possibly place snowflakes based on FOV, instead of a cube. */
    int boxing = firefliesGetScreenBoxing (ss->s->display);

    sf->x = mmrand(-boxing, ss->s->width + boxing, 1);
	sf->y = mmrand(-boxing, ss->s->height + boxing, 1);
	sf->z = mmrand(-firefliesGetScreenDepth (ss->s->display), 0.1, 5000);

	sf->lifespan = mmrand(50,1000, 100);
	sf->age = 0.0;

	// speed of firefly
	int i = 0;
	for (i = 0; i < 4; i++)
	{
		sf->xs[i] = mmrand(-3000, 3000, 1000);
		sf->ys[i] = mmrand(-3000, 3000, 1000);
		sf->zs[i] = mmrand(-1000, 1000, 500000);
	}
}
示例#14
0
/*
 * backup --
 *	Periodically do a backup and verify it.
 */
void *
backup(void *arg)
{
	WT_CONNECTION *conn;
	WT_CURSOR *backup_cursor;
	WT_DECL_RET;
	WT_SESSION *session;
	u_int incremental, period;
	bool full;
	const char *config, *key;

	(void)(arg);

	conn = g.wts_conn;

	/* Backups aren't supported for non-standard data sources. */
	if (DATASOURCE("helium") || DATASOURCE("kvsbdb"))
		return (NULL);

	/* Open a session. */
	testutil_check(conn->open_session(conn, NULL, NULL, &session));

	/*
	 * Perform a full backup at somewhere under 10 seconds (that way there's
	 * at least one), then at larger intervals, optionally do incremental
	 * backups between full backups.
	 */
	incremental = 0;
	for (period = mmrand(NULL, 1, 10);; period = mmrand(NULL, 20, 45)) {
		/* Sleep for short periods so we don't make the run wait. */
		while (period > 0 && !g.workers_finished) {
			--period;
			sleep(1);
		}

		/*
		 * We can't drop named checkpoints while there's a backup in
		 * progress, serialize backups with named checkpoints. Wait
		 * for the checkpoint to complete, otherwise backups might be
		 * starved out.
		 */
		testutil_check(pthread_rwlock_wrlock(&g.backup_lock));
		if (g.workers_finished) {
			testutil_check(pthread_rwlock_unlock(&g.backup_lock));
			break;
		}

		if (incremental) {
			config = "target=(\"log:\")";
			full = false;
		} else {
			/* Re-create the backup directory. */
			testutil_checkfmt(
			    system(g.home_backup_init),
			    "%s", "backup directory creation failed");

			config = NULL;
			full = true;
		}

		/*
		 * open_cursor can return EBUSY if concurrent with a metadata
		 * operation, retry in that case.
		 */
		while ((ret = session->open_cursor(
		    session, "backup:", NULL, config, &backup_cursor)) == EBUSY)
			__wt_yield();
		if (ret != 0)
			testutil_die(ret, "session.open_cursor: backup");

		while ((ret = backup_cursor->next(backup_cursor)) == 0) {
			testutil_check(
			    backup_cursor->get_key(backup_cursor, &key));
			copy_file(session, key);
		}
		if (ret != WT_NOTFOUND)
			testutil_die(ret, "backup-cursor");

		/* After an incremental backup, truncate the log files. */
		if (incremental)
			testutil_check(session->truncate(
			    session, "log:", backup_cursor, NULL, NULL));

		testutil_check(backup_cursor->close(backup_cursor));
		testutil_check(pthread_rwlock_unlock(&g.backup_lock));

		/*
		 * If automatic log archival isn't configured, optionally do
		 * incremental backups after each full backup. If we're not
		 * doing any more incrementals, verify the backup (we can't
		 * verify intermediate states, once we perform recovery on the
		 * backup database, we can't do any more incremental backups).
		 */
		if (full)
			incremental =
			    g.c_logging_archive ? 1 : mmrand(NULL, 1, 5);
		if (--incremental == 0)
			check_copy();
	}

	if (incremental != 0)
		check_copy();

	testutil_check(session->close(session, NULL));

	return (NULL);
}
示例#15
0
static void *
ops(void *arg)
{
	TINFO *tinfo;
	WT_CONNECTION *conn;
	WT_CURSOR *cursor, *cursor_insert;
	WT_SESSION *session;
	WT_ITEM key, value;
	uint64_t keyno, ckpt_op, session_op;
	uint32_t op;
	uint8_t *keybuf, *valbuf;
	u_int np;
	int ckpt_available, dir, insert, intxn, notfound, readonly, ret;
	char *ckpt_config, ckpt_name[64];

	tinfo = arg;

	/* Initialize the per-thread random number generator. */
	__wt_random_init(&tinfo->rnd);

	conn = g.wts_conn;
	keybuf = valbuf = NULL;
	readonly = 0;			/* -Wconditional-uninitialized */

	/* Set up the default key and value buffers. */
	key_gen_setup(&keybuf);
	val_gen_setup(&tinfo->rnd, &valbuf);

	/* Set the first operation where we'll create sessions and cursors. */
	session_op = 0;
	session = NULL;
	cursor = cursor_insert = NULL;

	/* Set the first operation where we'll perform checkpoint operations. */
	ckpt_op = g.c_checkpoints ? mmrand(&tinfo->rnd, 100, 10000) : 0;
	ckpt_available = 0;

	for (intxn = 0; !tinfo->quit; ++tinfo->ops) {
		/*
		 * We can't checkpoint or swap sessions/cursors while in a
		 * transaction, resolve any running transaction.
		 */
		if (intxn &&
		    (tinfo->ops == ckpt_op || tinfo->ops == session_op)) {
			if ((ret = session->commit_transaction(
			    session, NULL)) != 0)
				die(ret, "session.commit_transaction");
			++tinfo->commit;
			intxn = 0;
		}

		/* Open up a new session and cursors. */
		if (tinfo->ops == session_op ||
		    session == NULL || cursor == NULL) {
			if (session != NULL &&
			    (ret = session->close(session, NULL)) != 0)
				die(ret, "session.close");

			if ((ret = conn->open_session(conn, NULL,
			    ops_session_config(&tinfo->rnd), &session)) != 0)
				die(ret, "connection.open_session");

			/*
			 * 10% of the time, perform some read-only operations
			 * from a checkpoint.
			 *
			 * Skip that if we single-threaded and doing checks
			 * against a Berkeley DB database, because that won't
			 * work because the Berkeley DB database records won't
			 * match the checkpoint.  Also skip if we are using
			 * LSM, because it doesn't support reads from
			 * checkpoints.
			 */
			if (!SINGLETHREADED && !DATASOURCE("lsm") &&
			    ckpt_available && mmrand(&tinfo->rnd, 1, 10) == 1) {
				if ((ret = session->open_cursor(session,
				    g.uri, NULL, ckpt_name, &cursor)) != 0)
					die(ret, "session.open_cursor");

				/* Pick the next session/cursor close/open. */
				session_op += 250;

				/* Checkpoints are read-only. */
				readonly = 1;
			} else {
				/*
				 * Open two cursors: one for overwriting and one
				 * for append (if it's a column-store).
				 *
				 * The reason is when testing with existing
				 * records, we don't track if a record was
				 * deleted or not, which means we must use
				 * cursor->insert with overwriting configured.
				 * But, in column-store files where we're
				 * testing with new, appended records, we don't
				 * want to have to specify the record number,
				 * which requires an append configuration.
				 */
				if ((ret = session->open_cursor(session, g.uri,
				    NULL, "overwrite", &cursor)) != 0)
					die(ret, "session.open_cursor");
				if ((g.type == FIX || g.type == VAR) &&
				    (ret = session->open_cursor(session, g.uri,
				    NULL, "append", &cursor_insert)) != 0)
					die(ret, "session.open_cursor");

				/* Pick the next session/cursor close/open. */
				session_op += mmrand(&tinfo->rnd, 100, 5000);

				/* Updates supported. */
				readonly = 0;
			}
		}

		/* Checkpoint the database. */
		if (tinfo->ops == ckpt_op && g.c_checkpoints) {
			/*
			 * LSM and data-sources don't support named checkpoints,
			 * and we can't drop a named checkpoint while there's a
			 * cursor open on it, otherwise 20% of the time name the
			 * checkpoint.
			 */
			if (DATASOURCE("helium") || DATASOURCE("kvsbdb") ||
			    DATASOURCE("lsm") ||
			    readonly || mmrand(&tinfo->rnd, 1, 5) == 1)
				ckpt_config = NULL;
			else {
				(void)snprintf(ckpt_name, sizeof(ckpt_name),
				    "name=thread-%d", tinfo->id);
				ckpt_config = ckpt_name;
			}

			/* Named checkpoints lock out backups */
			if (ckpt_config != NULL &&
			    (ret = pthread_rwlock_wrlock(&g.backup_lock)) != 0)
				die(ret,
				    "pthread_rwlock_wrlock: backup lock");

			if ((ret =
			    session->checkpoint(session, ckpt_config)) != 0)
				die(ret, "session.checkpoint%s%s",
				    ckpt_config == NULL ? "" : ": ",
				    ckpt_config == NULL ? "" : ckpt_config);

			if (ckpt_config != NULL &&
			    (ret = pthread_rwlock_unlock(&g.backup_lock)) != 0)
				die(ret,
				    "pthread_rwlock_wrlock: backup lock");

			/* Rephrase the checkpoint name for cursor open. */
			if (ckpt_config == NULL)
				strcpy(ckpt_name,
				    "checkpoint=WiredTigerCheckpoint");
			else
				(void)snprintf(ckpt_name, sizeof(ckpt_name),
				    "checkpoint=thread-%d", tinfo->id);
			ckpt_available = 1;

			/* Pick the next checkpoint operation. */
			ckpt_op += mmrand(&tinfo->rnd, 5000, 20000);
		}

		/*
		 * If we're not single-threaded and we're not in a transaction,
		 * start a transaction 20% of the time.
		 */
		if (!SINGLETHREADED &&
		    !intxn && mmrand(&tinfo->rnd, 1, 10) >= 8) {
			if ((ret =
			    session->begin_transaction(session, NULL)) != 0)
				die(ret, "session.begin_transaction");
			intxn = 1;
		}

		insert = notfound = 0;

		keyno = mmrand(&tinfo->rnd, 1, (u_int)g.rows);
		key.data = keybuf;
		value.data = valbuf;

		/*
		 * Perform some number of operations: the percentage of deletes,
		 * inserts and writes are specified, reads are the rest.  The
		 * percentages don't have to add up to 100, a high percentage
		 * of deletes will mean fewer inserts and writes.  Modifications
		 * are always followed by a read to confirm it worked.
		 */
		op = readonly ? UINT32_MAX : mmrand(&tinfo->rnd, 1, 100);
		if (op < g.c_delete_pct) {
			++tinfo->remove;
			switch (g.type) {
			case ROW:
				/*
				 * If deleting a non-existent record, the cursor
				 * won't be positioned, and so can't do a next.
				 */
				if (row_remove(cursor, &key, keyno, &notfound))
					goto deadlock;
				break;
			case FIX:
			case VAR:
				if (col_remove(cursor, &key, keyno, &notfound))
					goto deadlock;
				break;
			}
		} else if (op < g.c_delete_pct + g.c_insert_pct) {
			++tinfo->insert;
			switch (g.type) {
			case ROW:
				if (row_insert(
				    tinfo, cursor, &key, &value, keyno))
					goto deadlock;
				insert = 1;
				break;
			case FIX:
			case VAR:
				/*
				 * We can only append so many new records, if
				 * we've reached that limit, update a record
				 * instead of doing an insert.
				 */
				if (g.append_cnt >= g.append_max)
					goto skip_insert;

				/* Insert, then reset the insert cursor. */
				if (col_insert(tinfo,
				    cursor_insert, &key, &value, &keyno))
					goto deadlock;
				if ((ret =
				    cursor_insert->reset(cursor_insert)) != 0)
					die(ret, "cursor.reset");

				insert = 1;
				break;
			}
		} else if (
		    op < g.c_delete_pct + g.c_insert_pct + g.c_write_pct) {
			++tinfo->update;
			switch (g.type) {
			case ROW:
				if (row_update(
				    tinfo, cursor, &key, &value, keyno))
					goto deadlock;
				break;
			case FIX:
			case VAR:
skip_insert:			if (col_update(tinfo,
				    cursor, &key, &value, keyno))
					goto deadlock;
				break;
			}
		} else {
			++tinfo->search;
			if (read_row(cursor, &key, keyno))
				if (intxn)
					goto deadlock;
			continue;
		}

		/*
		 * The cursor is positioned if we did any operation other than
		 * insert, do a small number of next/prev cursor operations in
		 * a random direction.
		 */
		if (!insert) {
			dir = (int)mmrand(&tinfo->rnd, 0, 1);
			for (np = 0; np < mmrand(&tinfo->rnd, 1, 8); ++np) {
				if (notfound)
					break;
				if (nextprev(cursor, dir, &notfound))
					goto deadlock;
			}
		}

		/* Read to confirm the operation. */
		++tinfo->search;
		if (read_row(cursor, &key, keyno))
			goto deadlock;

		/* Reset the cursor: there is no reason to keep pages pinned. */
		if ((ret = cursor->reset(cursor)) != 0)
			die(ret, "cursor.reset");

		/*
		 * If we're in the transaction, commit 40% of the time and
		 * rollback 10% of the time.
		 */
		if (intxn)
			switch (mmrand(&tinfo->rnd, 1, 10)) {
			case 1: case 2: case 3: case 4:		/* 40% */
				if ((ret = session->commit_transaction(
				    session, NULL)) != 0)
					die(ret, "session.commit_transaction");
				++tinfo->commit;
				intxn = 0;
				break;
			case 5:					/* 10% */
				if (0) {
deadlock:				++tinfo->deadlock;
				}
				if ((ret = session->rollback_transaction(
				    session, NULL)) != 0)
					die(ret,
					    "session.rollback_transaction");
				++tinfo->rollback;
				intxn = 0;
				break;
			default:
				break;
			}
	}

	if (session != NULL && (ret = session->close(session, NULL)) != 0)
		die(ret, "session.close");

	free(keybuf);
	free(valbuf);

	tinfo->state = TINFO_COMPLETE;
	return (NULL);
}
示例#16
0
/*
 * backup --
 *	Periodically do a backup and verify it.
 */
void *
backup(void *arg)
{
	WT_CONNECTION *conn;
	WT_CURSOR *backup_cursor;
	WT_SESSION *session;
	u_int period;
	int ret;
	const char *key;

	(void)(arg);

	conn = g.wts_conn;

	/* Backups aren't supported for non-standard data sources. */
	if (DATASOURCE("helium") || DATASOURCE("kvsbdb"))
		return (NULL);

	/* Open a session. */
	if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
		die(ret, "connection.open_session");

	/*
	 * Perform a backup at somewhere under 10 seconds (so we get at
	 * least one done), and then at 45 second intervals.
	 */
	for (period = mmrand(NULL, 1, 10);; period = 45) {
		/* Sleep for short periods so we don't make the run wait. */
		while (period > 0 && !g.workers_finished) {
			--period;
			sleep(1);
		}
		if (g.workers_finished)
			break;

		/* Lock out named checkpoints */
		if ((ret = pthread_rwlock_wrlock(&g.backup_lock)) != 0)
			die(ret, "pthread_rwlock_wrlock: backup lock");

		/* Re-create the backup directory. */
		if ((ret = system(g.home_backup_init)) != 0)
			die(ret, "backup directory creation failed");

		/*
		 * open_cursor can return EBUSY if a metadata operation is
		 * currently happening - retry in that case.
		 */
		while ((ret = session->open_cursor(session,
		    "backup:", NULL, NULL, &backup_cursor)) == EBUSY)
			sleep(1);
		if (ret != 0)
			die(ret, "session.open_cursor: backup");

		while ((ret = backup_cursor->next(backup_cursor)) == 0) {
			if ((ret =
			    backup_cursor->get_key(backup_cursor, &key)) != 0)
				die(ret, "cursor.get_key");
			copy_file(key);
		}

		if ((ret = backup_cursor->close(backup_cursor)) != 0)
			die(ret, "cursor.close");

		if ((ret = pthread_rwlock_unlock(&g.backup_lock)) != 0)
			die(ret, "pthread_rwlock_unlock: backup lock");

		check_copy();
	}

	if ((ret = session->close(session, NULL)) != 0)
		die(ret, "session.close");

	return (NULL);
}
示例#17
0
文件: salvage.c 项目: Arikes/mongo
/*
 * corrupt --
 *	Corrupt the file in a random way.
 */
static int
corrupt(void)
{
	FILE *fp;
	struct stat sb;
	size_t len, nw;
	wt_off_t offset;
	int fd, ret;
	char buf[8 * 1024], copycmd[2 * 1024];

	/*
	 * If it's a single Btree file (not LSM), open the file, and corrupt
	 * roughly 2% of the file at a random spot, including the beginning
	 * of the file and overlapping the end.
	 *
	 * It's a little tricky: if the data source is a file, we're looking
	 * for "wt", if the data source is a table, we're looking for "wt.wt".
	 */
	(void)snprintf(buf, sizeof(buf), "%s/%s", g.home, WT_NAME);
	if ((fd = open(buf, O_RDWR)) != -1) {
#ifdef _WIN32
		(void)snprintf(copycmd, sizeof(copycmd),
		    "copy %s\\%s %s\\slvg.copy\\%s.corrupted",
		    g.home, WT_NAME, g.home, WT_NAME);
#else
		(void)snprintf(copycmd, sizeof(copycmd),
		    "cp %s/%s %s/slvg.copy/%s.corrupted",
		    g.home, WT_NAME, g.home, WT_NAME);
#endif
		goto found;
	}
	(void)snprintf(buf, sizeof(buf), "%s/%s.wt", g.home, WT_NAME);
	if ((fd = open(buf, O_RDWR)) != -1) {
#ifdef _WIN32
		(void)snprintf(copycmd, sizeof(copycmd),
		    "copy %s\\%s.wt %s\\slvg.copy\\%s.wt.corrupted",
		    g.home, WT_NAME, g.home, WT_NAME);
#else
		(void)snprintf(copycmd, sizeof(copycmd),
		    "cp %s/%s.wt %s/slvg.copy/%s.wt.corrupted",
		    g.home, WT_NAME, g.home, WT_NAME);
#endif
		goto found;
	}
	return (0);

found:	if (fstat(fd, &sb) == -1)
		die(errno, "salvage-corrupt: fstat");

	offset = mmrand(NULL, 0, (u_int)sb.st_size);
	len = (size_t)(20 + (sb.st_size / 100) * 2);
	(void)snprintf(buf, sizeof(buf), "%s/slvg.corrupt", g.home);
	if ((fp = fopen(buf, "w")) == NULL)
		die(errno, "salvage-corrupt: open: %s", buf);
	(void)fprintf(fp,
	    "salvage-corrupt: offset %" PRIuMAX ", length " SIZET_FMT "\n",
	    (uintmax_t)offset, len);
	fclose_and_clear(&fp);

	if (lseek(fd, offset, SEEK_SET) == -1)
		die(errno, "salvage-corrupt: lseek");

	memset(buf, 'z', sizeof(buf));
	for (; len > 0; len -= nw) {
		nw = (size_t)(len > sizeof(buf) ? sizeof(buf) : len);
		if (write(fd, buf, nw) == -1)
			die(errno, "salvage-corrupt: write");
	}

	if (close(fd) == -1)
		die(errno, "salvage-corrupt: close");

	/*
	 * Save a copy of the corrupted file so we can replay the salvage step
	 * as necessary.
	 */
	if ((ret = system(copycmd)) != 0)
		die(ret, "salvage corrupt copy step failed");

	return (1);
}
示例#18
0
void
key_gen_insert(WT_RAND_STATE *rnd, WT_ITEM *key, uint64_t keyno)
{
	key_gen_common(key, keyno, (int)mmrand(rnd, 1, 15));
}