summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/test/format/ops.c
diff options
context:
space:
mode:
authorAlex Gorrod <alexander.gorrod@mongodb.com>2017-06-19 20:58:06 +0000
committerAlex Gorrod <alexander.gorrod@mongodb.com>2017-06-19 20:58:06 +0000
commit0513806e66fca4715c20ae5ea64e172a2bf1ee74 (patch)
tree4337ea4650af08f0343ad5a73e9cda6d88f6e535 /src/third_party/wiredtiger/test/format/ops.c
parenta4bee00dcaf814493818c1a55f8d060e9195ea9e (diff)
downloadmongo-0513806e66fca4715c20ae5ea64e172a2bf1ee74.tar.gz
Import wiredtiger: d687cc19830b5b479d7474724ed609c416bfb1d2 from branch mongodb-3.0
ref: b1aab8db7d..d687cc1983 for: 3.0.16 WT-2321 Fix a race between eviction and worker threads on the eviction queue WT-3000 Missing log records in recovery when crashing after a log file switch WT-3008 Run wtperf stress testing against all maintained branches WT-3010 shared-cache-stress can hang on mongodb-3.0 branch WT-3038 WiredTigers mongodb-3.0 branch crashes and hangs when run against test format WT-3049 Backport test/format to mongodb-3.0 branch WT-3158 Fix structure layout on Windows. WT-3277 [v3.0] Eviction of pages belonging to tables that have been force dropped WT-3286 [v3.0] Improve search if an index hint is wrong
Diffstat (limited to 'src/third_party/wiredtiger/test/format/ops.c')
-rw-r--r--src/third_party/wiredtiger/test/format/ops.c990
1 files changed, 636 insertions, 354 deletions
diff --git a/src/third_party/wiredtiger/test/format/ops.c b/src/third_party/wiredtiger/test/format/ops.c
index 2a2ff91fbf0..9b2aacaecff 100644
--- a/src/third_party/wiredtiger/test/format/ops.c
+++ b/src/third_party/wiredtiger/test/format/ops.c
@@ -1,5 +1,5 @@
/*-
- * Public Domain 2014-2015 MongoDB, Inc.
+ * Public Domain 2014-2016 MongoDB, Inc.
* Public Domain 2008-2014 WiredTiger, Inc.
*
* This is free and unencumbered software released into the public domain.
@@ -28,19 +28,21 @@
#include "format.h"
-static int col_insert(TINFO *, WT_CURSOR *, WT_ITEM *, WT_ITEM *, uint64_t *);
-static int col_remove(WT_CURSOR *, WT_ITEM *, uint64_t, int *);
-static int col_update(TINFO *, WT_CURSOR *, WT_ITEM *, WT_ITEM *, uint64_t);
-static int nextprev(WT_CURSOR *, int, int *);
-static int notfound_chk(const char *, int, int, uint64_t);
+static int col_insert(WT_CURSOR *, WT_ITEM *, WT_ITEM *, uint64_t *);
+static int col_remove(WT_CURSOR *, WT_ITEM *, uint64_t);
+static int col_update(WT_CURSOR *, WT_ITEM *, WT_ITEM *, uint64_t);
+static int nextprev(WT_CURSOR *, int);
static void *ops(void *);
-static void print_item(const char *, WT_ITEM *);
-static int read_row(WT_CURSOR *, WT_ITEM *, uint64_t);
-static int row_insert(TINFO *, WT_CURSOR *, WT_ITEM *, WT_ITEM *, uint64_t);
-static int row_remove(WT_CURSOR *, WT_ITEM *, uint64_t, int *);
-static int row_update(TINFO *, WT_CURSOR *, WT_ITEM *, WT_ITEM *, uint64_t);
+static int row_insert(WT_CURSOR *, WT_ITEM *, WT_ITEM *, uint64_t);
+static int row_remove(WT_CURSOR *, WT_ITEM *, uint64_t);
+static int row_update(WT_CURSOR *, WT_ITEM *, WT_ITEM *, uint64_t);
static void table_append_init(void);
+#ifdef HAVE_BERKELEY_DB
+static int notfound_chk(const char *, int, int, uint64_t);
+static void print_item(const char *, WT_ITEM *);
+#endif
+
/*
* wts_ops --
* Perform a number of operations in a set of threads.
@@ -51,23 +53,17 @@ wts_ops(int lastrun)
TINFO *tinfo, total;
WT_CONNECTION *conn;
WT_SESSION *session;
- pthread_t backup_tid, compact_tid;
+ pthread_t backup_tid, compact_tid, lrt_tid;
int64_t fourths, thread_ops;
uint32_t i;
- int ret, running;
+ int running;
conn = g.wts_conn;
session = NULL; /* -Wconditional-uninitialized */
memset(&backup_tid, 0, sizeof(backup_tid));
memset(&compact_tid, 0, sizeof(compact_tid));
-
- /*
- * We support replay of threaded runs, but don't log random numbers
- * after threaded operations start, there's no point.
- */
- if (!SINGLETHREADED)
- g.rand_log_stop = 1;
+ memset(&lrt_tid, 0, sizeof(lrt_tid));
/*
* There are two mechanisms to specify the length of the run, a number
@@ -87,37 +83,45 @@ wts_ops(int lastrun)
if (g.c_timer == 0)
fourths = -1;
else
- fourths = (g.c_timer * 4 * 60) / FORMAT_OPERATION_REPS;
+ fourths = ((int64_t)g.c_timer * 4 * 60) / FORMAT_OPERATION_REPS;
/* Initialize the table extension code. */
table_append_init();
+ /*
+ * We support replay of threaded runs, but don't log random numbers
+ * after threaded operations start, there's no point.
+ */
+ if (!SINGLETHREADED)
+ g.rand_log_stop = 1;
+
/* Open a session. */
if (g.logging != 0) {
- if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
- die(ret, "connection.open_session");
+ testutil_check(conn->open_session(conn, NULL, NULL, &session));
(void)g.wt_api->msg_printf(g.wt_api, session,
"=============== thread ops start ===============");
}
/* Create thread structure; start the worker threads. */
- if ((tinfo = calloc((size_t)g.c_threads, sizeof(*tinfo))) == NULL)
- die(errno, "calloc");
+ tinfo = dcalloc((size_t)g.c_threads, sizeof(*tinfo));
for (i = 0; i < g.c_threads; ++i) {
tinfo[i].id = (int)i + 1;
tinfo[i].state = TINFO_RUNNING;
- if ((ret =
- pthread_create(&tinfo[i].tid, NULL, ops, &tinfo[i])) != 0)
- die(ret, "pthread_create");
+ testutil_check(
+ pthread_create(&tinfo[i].tid, NULL, ops, &tinfo[i]));
}
- /* If a multi-threaded run, start backup and compaction threads. */
- if (g.c_backups &&
- (ret = pthread_create(&backup_tid, NULL, backup, NULL)) != 0)
- die(ret, "pthread_create: backup");
- if (g.c_compact &&
- (ret = pthread_create(&compact_tid, NULL, compact, NULL)) != 0)
- die(ret, "pthread_create: compaction");
+ /*
+ * If a multi-threaded run, start optional backup, compaction and
+ * long-running reader threads.
+ */
+ if (g.c_backups)
+ testutil_check(pthread_create(&backup_tid, NULL, backup, NULL));
+ if (g.c_compact)
+ testutil_check(
+ pthread_create(&compact_tid, NULL, compact, NULL));
+ if (!SINGLETHREADED && g.c_long_running_txn)
+ testutil_check(pthread_create(&lrt_tid, NULL, lrt, NULL));
/* Spin on the threads, calculating the totals. */
for (;;) {
@@ -171,70 +175,247 @@ wts_ops(int lastrun)
}
free(tinfo);
- /* Wait for the backup, compaction thread. */
+ /* Wait for the backup, compaction, long-running reader threads. */
g.workers_finished = 1;
if (g.c_backups)
(void)pthread_join(backup_tid, NULL);
if (g.c_compact)
(void)pthread_join(compact_tid, NULL);
+ if (!SINGLETHREADED && g.c_long_running_txn)
+ (void)pthread_join(lrt_tid, NULL);
+ g.workers_finished = 0;
if (g.logging != 0) {
(void)g.wt_api->msg_printf(g.wt_api, session,
"=============== thread ops stop ===============");
- if ((ret = session->close(session, NULL)) != 0)
- die(ret, "session.close");
+ testutil_check(session->close(session, NULL));
}
}
/*
- * ops_session_config --
- * Return the current session configuration.
+ * isolation_config --
+ * Return an isolation configuration.
*/
-static const char *
-ops_session_config(WT_RAND_STATE *rnd)
+static inline const char *
+isolation_config(WT_RAND_STATE *rnd, bool *iso_snapshotp)
{
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:
+ *iso_snapshotp = false;
return ("isolation=read-uncommitted");
case ISOLATION_READ_COMMITTED:
+ *iso_snapshotp = false;
return ("isolation=read-committed");
case ISOLATION_SNAPSHOT:
default:
+ *iso_snapshotp = true;
return ("isolation=snapshot");
}
}
+typedef struct {
+ uint64_t keyno; /* Row number */
+
+ void *kdata; /* If an insert, the generated key */
+ size_t ksize;
+ size_t kmemsize;
+
+ void *vdata; /* If not a delete, the value */
+ size_t vsize;
+ size_t vmemsize;
+
+ bool deleted; /* Delete operation */
+ bool insert; /* Insert operation */
+} SNAP_OPS;
+
+/*
+ * snap_track --
+ * Add a single snapshot isolation returned value to the list.
+ */
+static void
+snap_track(SNAP_OPS *snap, uint64_t keyno, WT_ITEM *key, WT_ITEM *value)
+{
+ snap->keyno = keyno;
+ if (key == NULL)
+ snap->insert = false;
+ else {
+ snap->insert = true;
+
+ if (snap->kmemsize < key->size) {
+ snap->kdata = drealloc(snap->kdata, key->size);
+ snap->kmemsize = key->size;
+ }
+ memcpy(snap->kdata, key->data, snap->ksize = key->size);
+ }
+ if (value == NULL)
+ snap->deleted = true;
+ else {
+ snap->deleted = false;
+ if (snap->vmemsize < value->size) {
+ snap->vdata = drealloc(snap->vdata, value->size);
+ snap->vmemsize = value->size;
+ }
+ memcpy(snap->vdata, value->data, snap->vsize = value->size);
+ }
+}
+
+/*
+ * snap_check --
+ * Check snapshot isolation operations are repeatable.
+ */
+static int
+snap_check(WT_CURSOR *cursor,
+ SNAP_OPS *start, SNAP_OPS *stop, WT_ITEM *key, WT_ITEM *value)
+{
+ WT_DECL_RET;
+ SNAP_OPS *p;
+ uint8_t bitfield;
+
+ for (; start < stop; ++start) {
+ /* Check for subsequent changes to this record. */
+ for (p = start + 1; p < stop && p->keyno != start->keyno; ++p)
+ ;
+ if (p != stop)
+ continue;
+
+ /*
+ * Retrieve the key/value pair by key. Row-store inserts have a
+ * unique generated key we saved, else generate the key from the
+ * key number.
+ */
+ if (start->insert == 0) {
+ switch (g.type) {
+ case FIX:
+ case VAR:
+ cursor->set_key(cursor, start->keyno);
+ break;
+ case ROW:
+ key_gen(key, start->keyno);
+ cursor->set_key(cursor, key);
+ break;
+ }
+ } else {
+ key->data = start->kdata;
+ key->size = start->ksize;
+ cursor->set_key(cursor, key);
+ }
+ if ((ret = cursor->search(cursor)) == 0) {
+ if (g.type == FIX) {
+ testutil_check(
+ cursor->get_value(cursor, &bitfield));
+ *(uint8_t *)(value->data) = bitfield;
+ value->size = 1;
+ } else
+ testutil_check(
+ cursor->get_value(cursor, value));
+ } else
+ if (ret != WT_NOTFOUND)
+ return (ret);
+
+ /* Check for simple matches. */
+ if (ret == 0 && !start->deleted &&
+ value->size == start->vsize &&
+ memcmp(value->data, start->vdata, value->size) == 0)
+ continue;
+ if (ret == WT_NOTFOUND && start->deleted)
+ continue;
+
+ /*
+ * In fixed length stores, zero values at the end of the key
+ * space are returned as not-found, and not-found row reads
+ * are saved as zero values. Map back-and-forth for simplicity.
+ */
+ if (g.type == FIX) {
+ if (ret == WT_NOTFOUND &&
+ start->vsize == 1 && *(uint8_t *)start->vdata == 0)
+ continue;
+ if (start->deleted &&
+ value->size == 1 && *(uint8_t *)value->data == 0)
+ continue;
+ }
+
+ /* Things went pear-shaped. */
+ switch (g.type) {
+ case FIX:
+ testutil_die(ret,
+ "snapshot-isolation: %" PRIu64 " search: "
+ "expected {0x%02x}, found {0x%02x}",
+ start->keyno,
+ start->deleted ? 0 : *(uint8_t *)start->vdata,
+ ret == WT_NOTFOUND ? 0 : *(uint8_t *)value->data);
+ /* NOTREACHED */
+ case ROW:
+ testutil_die(ret,
+ "snapshot-isolation: %.*s search: "
+ "expected {%.*s}, found {%.*s}",
+ (int)key->size, key->data,
+ start->deleted ?
+ (int)strlen("deleted") : (int)start->vsize,
+ start->deleted ? "deleted" : start->vdata,
+ ret == WT_NOTFOUND ?
+ (int)strlen("deleted") : (int)value->size,
+ ret == WT_NOTFOUND ? "deleted" : value->data);
+ /* NOTREACHED */
+ case VAR:
+ testutil_die(ret,
+ "snapshot-isolation: %" PRIu64 " search: "
+ "expected {%.*s}, found {%.*s}",
+ start->keyno,
+ start->deleted ?
+ (int)strlen("deleted") : (int)start->vsize,
+ start->deleted ? "deleted" : start->vdata,
+ ret == WT_NOTFOUND ?
+ (int)strlen("deleted") : (int)value->size,
+ ret == WT_NOTFOUND ? "deleted" : value->data);
+ /* NOTREACHED */
+ }
+ }
+ return (0);
+}
+
+/*
+ * ops --
+ * Per-thread operations.
+ */
static void *
ops(void *arg)
{
+ SNAP_OPS *snap, snap_list[64];
TINFO *tinfo;
WT_CONNECTION *conn;
WT_CURSOR *cursor, *cursor_insert;
+ WT_DECL_RET;
+ WT_ITEM *key, _key, *value, _value;
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;
+ uint32_t op, rnd;
+ u_int i;
+ int dir;
char *ckpt_config, ckpt_name[64];
+ bool ckpt_available, intxn, iso_snapshot, positioned, readonly;
tinfo = arg;
conn = g.wts_conn;
- keybuf = valbuf = NULL;
- readonly = 0; /* -Wconditional-uninitialized */
+ readonly = false; /* -Wconditional-uninitialized */
+
+ /* Initialize tracking of snapshot isolation transaction returns. */
+ snap = NULL;
+ iso_snapshot = false;
+ memset(snap_list, 0, sizeof(snap_list));
+
+ /* Initialize the per-thread random number generator. */
+ __wt_random_init(&tinfo->rnd);
/* Set up the default key and value buffers. */
- key_gen_setup(&keybuf);
- val_gen_setup(&tinfo->rnd, &valbuf);
+ key = &_key;
+ key_gen_setup(key);
+ value = &_value;
+ val_gen_setup(&tinfo->rnd, value);
/* Set the first operation where we'll create sessions and cursors. */
session_op = 0;
@@ -243,32 +424,29 @@ ops(void *arg)
/* Set the first operation where we'll perform checkpoint operations. */
ckpt_op = g.c_checkpoints ? mmrand(&tinfo->rnd, 100, 10000) : 0;
- ckpt_available = 0;
+ ckpt_available = false;
- for (intxn = 0; !tinfo->quit; ++tinfo->ops) {
+ for (intxn = false; !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");
+ testutil_check(
+ session->commit_transaction(session, NULL));
++tinfo->commit;
- intxn = 0;
+ intxn = false;
}
/* 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 (session != NULL)
+ testutil_check(session->close(session, NULL));
- if ((ret = conn->open_session(conn, NULL,
- ops_session_config(&tinfo->rnd), &session)) != 0)
- die(ret, "connection.open_session");
+ testutil_check(
+ conn->open_session(conn, NULL, NULL, &session));
/*
* 10% of the time, perform some read-only operations
@@ -283,15 +461,14 @@ ops(void *arg)
*/
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");
+ testutil_check(session->open_cursor(session,
+ g.uri, NULL, ckpt_name, &cursor));
/* Pick the next session/cursor close/open. */
session_op += 250;
/* Checkpoints are read-only. */
- readonly = 1;
+ readonly = true;
} else {
/*
* Open two cursors: one for overwriting and one
@@ -306,33 +483,43 @@ ops(void *arg)
* 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");
+ testutil_check(session->open_cursor(session,
+ g.uri, NULL, "overwrite", &cursor));
+ if (g.type == FIX || g.type == VAR)
+ testutil_check(session->open_cursor(
+ session, g.uri,
+ NULL, "append", &cursor_insert));
/* Pick the next session/cursor close/open. */
- session_op += 100 * mmrand(&tinfo->rnd, 1, 50);
+ session_op += mmrand(&tinfo->rnd, 100, 5000);
/* Updates supported. */
- readonly = 0;
+ readonly = false;
}
}
/* Checkpoint the database. */
if (tinfo->ops == ckpt_op && g.c_checkpoints) {
/*
- * LSM and data-sources don't support named checkpoints,
+ * Checkpoints are single-threaded inside WiredTiger,
+ * skip our checkpoint if another thread is already
+ * doing one.
+ */
+ ret = pthread_rwlock_trywrlock(&g.checkpoint_lock);
+ if (ret == EBUSY)
+ goto skip_checkpoint;
+ testutil_check(ret);
+
+ /*
+ * 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.
+ * backup in progress, otherwise name the checkpoint 5%
+ * of the time.
*/
- if (DATASOURCE("helium") || DATASOURCE("kvsbdb") ||
- DATASOURCE("lsm") || readonly ||
- mmrand(&tinfo->rnd, 1, 5) == 1)
+ if (mmrand(&tinfo->rnd, 1, 20) != 1 ||
+ DATASOURCE("helium") ||
+ DATASOURCE("kvsbdb") || DATASOURCE("lsm") ||
+ pthread_rwlock_trywrlock(&g.backup_lock) == EBUSY)
ckpt_config = NULL;
else {
(void)snprintf(ckpt_name, sizeof(ckpt_name),
@@ -340,22 +527,22 @@ ops(void *arg)
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 ? "" : ": ",
+ ret = session->checkpoint(session, ckpt_config);
+ /*
+ * We may be trying to create a named checkpoint while
+ * we hold a cursor open to the previous checkpoint.
+ * Tolerate EBUSY.
+ */
+ if (ret != 0 && ret != EBUSY)
+ testutil_die(ret, "%s",
ckpt_config == NULL ? "" : ckpt_config);
+ ret = 0;
- if (ckpt_config != NULL &&
- (ret = pthread_rwlock_unlock(&g.backup_lock)) != 0)
- die(ret,
- "pthread_rwlock_wrlock: backup lock");
+ if (ckpt_config != NULL)
+ testutil_check(
+ pthread_rwlock_unlock(&g.backup_lock));
+ testutil_check(
+ pthread_rwlock_unlock(&g.checkpoint_lock));
/* Rephrase the checkpoint name for cursor open. */
if (ckpt_config == NULL)
@@ -364,29 +551,31 @@ ops(void *arg)
else
(void)snprintf(ckpt_name, sizeof(ckpt_name),
"checkpoint=thread-%d", tinfo->id);
- ckpt_available = 1;
+ ckpt_available = true;
- /* Pick the next checkpoint operation. */
- ckpt_op += 1000 * mmrand(&tinfo->rnd, 5, 20);
+skip_checkpoint: /* 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 we're not single-threaded and not in a transaction, choose
+ * an isolation level and start a transaction some percentage 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;
+ if (!SINGLETHREADED &&
+ !intxn && mmrand(&tinfo->rnd, 1, 100) >= g.c_txn_freq) {
+ testutil_check(
+ session->reconfigure(session,
+ isolation_config(&tinfo->rnd, &iso_snapshot)));
+ testutil_check(
+ session->begin_transaction(session, NULL));
+
+ snap = iso_snapshot ? snap_list : NULL;
+ intxn = true;
}
- insert = notfound = 0;
-
- keyno = mmrand(&tinfo->rnd, 1, g.rows);
- key.data = keybuf;
- value.data = valbuf;
+ keyno = mmrand(&tinfo->rnd, 1, (u_int)g.rows);
+ positioned = false;
/*
* Perform some number of operations: the percentage of deletes,
@@ -395,32 +584,35 @@ ops(void *arg)
* of deletes will mean fewer inserts and writes. Modifications
* are always followed by a read to confirm it worked.
*/
- op = readonly ? UINT32_MAX : (uint32_t)(rng(&tinfo->rnd) % 100);
+ 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;
+ ret = row_remove(cursor, key, keyno);
break;
case FIX:
case VAR:
- if (col_remove(cursor, &key, keyno, &notfound))
- goto deadlock;
+ ret = col_remove(cursor, key, keyno);
break;
}
+ if (ret == 0) {
+ positioned = true;
+ if (snap != NULL && (size_t)
+ (snap - snap_list) < WT_ELEMENTS(snap_list))
+ snap_track(snap++, keyno, NULL, NULL);
+ } else {
+ positioned = false;
+ if (ret == WT_ROLLBACK && intxn)
+ goto deadlock;
+ }
} 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;
+ key_gen_insert(&tinfo->rnd, key, keyno);
+ val_gen(&tinfo->rnd, value, keyno);
+ ret = row_insert(cursor, key, value, keyno);
break;
case FIX:
case VAR:
@@ -433,38 +625,60 @@ ops(void *arg)
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;
+ val_gen(&tinfo->rnd, value, g.rows + 1);
+ ret = col_insert(
+ cursor_insert, key, value, &keyno);
+ testutil_check(
+ cursor_insert->reset(cursor_insert));
break;
}
+ positioned = false;
+ if (ret == 0) {
+ if (snap != NULL && (size_t)
+ (snap - snap_list) < WT_ELEMENTS(snap_list))
+ snap_track(snap++, keyno,
+ g.type == ROW ? key : NULL, value);
+ } else
+ if (ret == WT_ROLLBACK && intxn)
+ goto deadlock;
} 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;
+ key_gen(key, keyno);
+ val_gen(&tinfo->rnd, value, keyno);
+ ret = row_update(cursor, key, value, keyno);
break;
case FIX:
case VAR:
-skip_insert: if (col_update(
- tinfo, cursor, &key, &value, keyno))
- goto deadlock;
+skip_insert: val_gen(&tinfo->rnd, value, keyno);
+ ret = col_update(cursor, key, value, keyno);
break;
}
+ if (ret == 0) {
+ positioned = true;
+ if (snap != NULL && (size_t)
+ (snap - snap_list) < WT_ELEMENTS(snap_list))
+ snap_track(snap++, keyno, NULL, value);
+ } else {
+ positioned = false;
+ if (ret == WT_ROLLBACK && intxn)
+ goto deadlock;
+ }
} else {
++tinfo->search;
- if (read_row(cursor, &key, keyno))
- if (intxn)
+ ret = read_row(cursor, key, value, keyno);
+ if (ret == 0) {
+ positioned = true;
+ if (snap != NULL && (size_t)
+ (snap - snap_list) < WT_ELEMENTS(snap_list))
+ snap_track(snap++, keyno, NULL, value);
+ } else {
+ positioned = false;
+ if (ret == WT_ROLLBACK && intxn)
goto deadlock;
- continue;
+ }
}
/*
@@ -472,59 +686,64 @@ skip_insert: if (col_update(
* insert, do a small number of next/prev cursor operations in
* a random direction.
*/
- if (!insert) {
+ if (positioned) {
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))
+ for (i = 0; i < mmrand(&tinfo->rnd, 1, 100); ++i) {
+ if ((ret = nextprev(cursor, dir)) == 0)
+ continue;
+ if (ret == WT_ROLLBACK && intxn)
goto deadlock;
+ break;
}
}
- /* 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 (cursor != NULL && (ret = cursor->reset(cursor)) != 0)
- die(ret, "cursor.reset");
+ testutil_check(cursor->reset(cursor));
/*
- * If we're in the transaction, commit 40% of the time and
+ * If we're in a 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 (!intxn || (rnd = mmrand(&tinfo->rnd, 1, 10)) > 5)
+ continue;
+
+ /*
+ * Ending the transaction. If in snapshot isolation, repeat the
+ * operations and confirm they're unchanged.
+ */
+ if (snap != NULL && (ret = snap_check(
+ cursor, snap_list, snap, key, value)) == WT_ROLLBACK)
+ goto deadlock;
+
+ switch (rnd) {
+ case 1: case 2: case 3: case 4: /* 40% */
+ testutil_check(
+ session->commit_transaction(session, NULL));
+ ++tinfo->commit;
+ break;
+ case 5: /* 10% */
+ if (0) {
+deadlock: ++tinfo->deadlock;
}
+ testutil_check(
+ session->rollback_transaction(session, NULL));
+ ++tinfo->rollback;
+ break;
+ }
+
+ intxn = false;
+ snap = NULL;
}
- if (session != NULL && (ret = session->close(session, NULL)) != 0)
- die(ret, "session.close");
+ if (session != NULL)
+ testutil_check(session->close(session, NULL));
- free(keybuf);
- free(valbuf);
+ for (i = 0; i < WT_ELEMENTS(snap_list); ++i) {
+ free(snap_list[i].kdata);
+ free(snap_list[i].vdata);
+ }
+ free(key->mem);
+ free(value->mem);
tinfo->state = TINFO_COMPLETE;
return (NULL);
@@ -539,56 +758,59 @@ wts_read_scan(void)
{
WT_CONNECTION *conn;
WT_CURSOR *cursor;
- WT_ITEM key;
+ WT_DECL_RET;
+ WT_ITEM key, value;
WT_SESSION *session;
- uint64_t cnt, last_cnt;
- uint8_t *keybuf;
- int ret;
+ uint64_t keyno, last_keyno;
conn = g.wts_conn;
- /* Set up the default key buffer. */
- key_gen_setup(&keybuf);
+ /* Set up the default key/value buffers. */
+ key_gen_setup(&key);
+ val_gen_setup(NULL, &value);
/* 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");
+ testutil_check(conn->open_session(conn, NULL, NULL, &session));
+ testutil_check(
+ session->open_cursor(session, g.uri, NULL, NULL, &cursor));
/* Check a random subset of the records using the key. */
- for (last_cnt = cnt = 0; cnt < g.key_cnt;) {
- cnt += rng(NULL) % 17 + 1;
- if (cnt > g.rows)
- cnt = g.rows;
- if (cnt - last_cnt > 1000) {
- track("read row scan", cnt, NULL);
- last_cnt = cnt;
+ for (last_keyno = keyno = 0; keyno < g.key_cnt;) {
+ keyno += mmrand(NULL, 1, 17);
+ if (keyno > g.rows)
+ keyno = g.rows;
+ if (keyno - last_keyno > 1000) {
+ track("read row scan", keyno, NULL);
+ last_keyno = keyno;
}
- key.data = keybuf;
- if ((ret = read_row(cursor, &key, cnt)) != 0)
- die(ret, "read_scan");
+ switch (ret = read_row(cursor, &key, &value, keyno)) {
+ case 0:
+ case WT_NOTFOUND:
+ case WT_ROLLBACK:
+ break;
+ default:
+ testutil_die(
+ ret, "wts_read_scan: read row %" PRIu64, keyno);
+ }
}
- if ((ret = session->close(session, NULL)) != 0)
- die(ret, "session.close");
+ testutil_check(session->close(session, NULL));
- free(keybuf);
+ free(key.mem);
+ free(value.mem);
}
/*
* read_row --
* Read and verify a single element in a row- or column-store file.
*/
-static int
-read_row(WT_CURSOR *cursor, WT_ITEM *key, uint64_t keyno)
+int
+read_row(WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value, uint64_t keyno)
{
- WT_ITEM bdb_value, value;
+ static int sn = 0;
WT_SESSION *session;
- int notfound, ret;
+ int exact, ret;
uint8_t bitfield;
session = cursor->session;
@@ -605,56 +827,74 @@ read_row(WT_CURSOR *cursor, WT_ITEM *key, uint64_t keyno)
cursor->set_key(cursor, keyno);
break;
case ROW:
- key_gen((uint8_t *)key->data, &key->size, keyno);
+ key_gen(key, keyno);
cursor->set_key(cursor, key);
break;
}
- if ((ret = cursor->search(cursor)) == 0) {
+ if (sn) {
+ ret = cursor->search_near(cursor, &exact);
+ if (ret == 0 && exact != 0)
+ ret = WT_NOTFOUND;
+ sn = 0;
+ } else {
+ ret = cursor->search(cursor);
+ sn = 1;
+ }
+ switch (ret) {
+ case 0:
if (g.type == FIX) {
- ret = cursor->get_value(cursor, &bitfield);
- value.data = &bitfield;
- value.size = 1;
- } else {
- ret = cursor->get_value(cursor, &value);
+ testutil_check(cursor->get_value(cursor, &bitfield));
+ *(uint8_t *)(value->data) = bitfield;
+ value->size = 1;
+ } else
+ testutil_check(cursor->get_value(cursor, value));
+ break;
+ case WT_NOTFOUND:
+ /*
+ * In fixed length stores, zero values at the end of the key
+ * space are returned as not found. Treat this the same as
+ * a zero value in the key space, to match BDB's behavior.
+ */
+ if (g.type == FIX) {
+ *(uint8_t *)(value->data) = 0;
+ value->size = 1;
+ ret = 0;
}
- }
- if (ret == WT_ROLLBACK)
+ break;
+ case WT_ROLLBACK:
return (WT_ROLLBACK);
- if (ret != 0 && ret != WT_NOTFOUND)
- die(ret, "read_row: read row %" PRIu64, keyno);
- /*
- * In fixed length stores, zero values at the end of the key space are
- * returned as not found. Treat this the same as a zero value in the
- * key space, to match BDB's behavior.
- */
- if (ret == WT_NOTFOUND && g.type == FIX) {
- bitfield = 0;
- value.data = &bitfield;
- value.size = 1;
- ret = 0;
+ default:
+ testutil_die(ret, "read_row: read row %" PRIu64, keyno);
}
+#ifdef HAVE_BERKELEY_DB
if (!SINGLETHREADED)
- return (0);
+ return (ret);
/* Retrieve the BDB value. */
+ {
+ WT_ITEM bdb_value;
+ int notfound;
+
bdb_read(keyno, &bdb_value.data, &bdb_value.size, &notfound);
/* Check for not-found status. */
if (notfound_chk("read_row", ret, notfound, keyno))
- return (0);
+ return (ret);
/* Compare the two. */
- if (value.size != bdb_value.size ||
- memcmp(value.data, bdb_value.data, value.size) != 0) {
+ if (value->size != bdb_value.size ||
+ memcmp(value->data, bdb_value.data, value->size) != 0) {
fprintf(stderr,
- "read_row: read row value mismatch %" PRIu64 ":\n", keyno);
+ "read_row: value mismatch %" PRIu64 ":\n", keyno);
print_item("bdb", &bdb_value);
- print_item(" wt", &value);
- die(0, NULL);
+ print_item(" wt", value);
+ testutil_die(0, NULL);
}
- return (0);
+ }
+#endif
+ return (ret);
}
/*
@@ -662,24 +902,19 @@ read_row(WT_CURSOR *cursor, WT_ITEM *key, uint64_t keyno)
* Read and verify the next/prev element in a row- or column-store file.
*/
static int
-nextprev(WT_CURSOR *cursor, int next, int *notfoundp)
+nextprev(WT_CURSOR *cursor, int next)
{
- WT_ITEM key, value, bdb_key, bdb_value;
- WT_SESSION *session;
+ WT_DECL_RET;
+ WT_ITEM key, value;
uint64_t keyno;
- int notfound, ret;
uint8_t bitfield;
const char *which;
- char *p;
- session = cursor->session;
+ keyno = 0;
which = next ? "next" : "prev";
- keyno = 0;
- ret = next ? cursor->next(cursor) : cursor->prev(cursor);
- if (ret == WT_ROLLBACK)
- return (WT_ROLLBACK);
- if (ret == 0)
+ switch (ret = (next ? cursor->next(cursor) : cursor->prev(cursor))) {
+ case 0:
switch (g.type) {
case FIX:
if ((ret = cursor->get_key(cursor, &keyno)) == 0 &&
@@ -697,19 +932,35 @@ nextprev(WT_CURSOR *cursor, int next, int *notfoundp)
ret = cursor->get_value(cursor, &value);
break;
}
- if (ret != 0 && ret != WT_NOTFOUND)
- die(ret, "%s", which);
- *notfoundp = (ret == WT_NOTFOUND);
+ if (ret != 0)
+ testutil_die(ret, "nextprev: get_key/get_value");
+ break;
+ case WT_NOTFOUND:
+ break;
+ case WT_ROLLBACK:
+ return (WT_ROLLBACK);
+ default:
+ testutil_die(ret, "%s", which);
+ }
+#ifdef HAVE_BERKELEY_DB
if (!SINGLETHREADED)
- return (0);
+ return (ret);
+
+ {
+ WT_ITEM bdb_key, bdb_value;
+ WT_SESSION *session;
+ int notfound;
+ char *p;
+
+ session = cursor->session;
/* Retrieve the BDB value. */
bdb_np(next, &bdb_key.data, &bdb_key.size,
&bdb_value.data, &bdb_value.size, &notfound);
if (notfound_chk(
next ? "nextprev(next)" : "nextprev(prev)", ret, notfound, keyno))
- return (0);
+ return (ret);
/* Compare the two. */
if (g.type == ROW) {
@@ -718,7 +969,7 @@ nextprev(WT_CURSOR *cursor, int next, int *notfoundp)
fprintf(stderr, "nextprev: %s key mismatch:\n", which);
print_item("bdb-key", &bdb_key);
print_item(" wt-key", &key);
- die(0, NULL);
+ testutil_die(0, NULL);
}
} else {
if (keyno != (uint64_t)atoll(bdb_key.data)) {
@@ -728,7 +979,7 @@ nextprev(WT_CURSOR *cursor, int next, int *notfoundp)
"nextprev: %s key mismatch: %.*s != %" PRIu64 "\n",
which,
(int)bdb_key.size, (char *)bdb_key.data, keyno);
- die(0, NULL);
+ testutil_die(0, NULL);
}
}
if (value.size != bdb_value.size ||
@@ -736,7 +987,7 @@ nextprev(WT_CURSOR *cursor, int next, int *notfoundp)
fprintf(stderr, "nextprev: %s value mismatch:\n", which);
print_item("bdb-value", &bdb_value);
print_item(" wt-value", &value);
- die(0, NULL);
+ testutil_die(0, NULL);
}
if (g.logging == LOG_OPS)
@@ -758,7 +1009,9 @@ nextprev(WT_CURSOR *cursor, int next, int *notfoundp)
keyno, (int)value.size, (char *)value.data);
break;
}
- return (0);
+ }
+#endif
+ return (ret);
}
/*
@@ -766,37 +1019,38 @@ nextprev(WT_CURSOR *cursor, int next, int *notfoundp)
* Update a row in a row-store file.
*/
static int
-row_update(TINFO *tinfo,
- WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value, uint64_t keyno)
+row_update(WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value, uint64_t keyno)
{
+ WT_DECL_RET;
WT_SESSION *session;
- int notfound, ret;
session = cursor->session;
- key_gen((uint8_t *)key->data, &key->size, keyno);
- val_gen(&tinfo->rnd, (uint8_t *)value->data, &value->size, keyno);
-
/* Log the operation */
if (g.logging == LOG_OPS)
(void)g.wt_api->msg_printf(g.wt_api, session,
- "%-10s{%.*s}\n%-10s{%.*s}",
- "putK", (int)key->size, (char *)key->data,
- "putV", (int)value->size, (char *)value->data);
+ "%-10s{%.*s}, {%.*s}",
+ "put",
+ (int)key->size, key->data, (int)value->size, value->data);
cursor->set_key(cursor, key);
cursor->set_value(cursor, value);
- ret = cursor->update(cursor);
- if (ret == WT_ROLLBACK)
+ switch (ret = cursor->update(cursor)) {
+ case 0:
+ break;
+ case WT_ROLLBACK:
return (WT_ROLLBACK);
- if (ret != 0 && ret != WT_NOTFOUND)
- die(ret, "row_update: update row %" PRIu64 " by key", keyno);
+ default:
+ testutil_die(ret,
+ "row_update: update row %" PRIu64 " by key", keyno);
+ }
+#ifdef HAVE_BERKELEY_DB
if (!SINGLETHREADED)
return (0);
- bdb_update(key->data, key->size, value->data, value->size, &notfound);
- (void)notfound_chk("row_update", ret, notfound, keyno);
+ bdb_update(key->data, key->size, value->data, value->size);
+#endif
return (0);
}
@@ -805,16 +1059,13 @@ row_update(TINFO *tinfo,
* Update a row in a column-store file.
*/
static int
-col_update(TINFO *tinfo,
- WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value, uint64_t keyno)
+col_update(WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value, uint64_t keyno)
{
+ WT_DECL_RET;
WT_SESSION *session;
- int notfound, ret;
session = cursor->session;
- val_gen(&tinfo->rnd, (uint8_t *)value->data, &value->size, keyno);
-
/* Log the operation */
if (g.logging == LOG_OPS) {
if (g.type == FIX)
@@ -834,18 +1085,24 @@ col_update(TINFO *tinfo,
cursor->set_value(cursor, *(uint8_t *)value->data);
else
cursor->set_value(cursor, value);
- ret = cursor->update(cursor);
- if (ret == WT_ROLLBACK)
+ switch (ret = cursor->update(cursor)) {
+ case 0:
+ break;
+ case WT_ROLLBACK:
return (WT_ROLLBACK);
- if (ret != 0 && ret != WT_NOTFOUND)
- die(ret, "col_update: %" PRIu64, keyno);
+ default:
+ testutil_die(ret, "col_update: %" PRIu64, keyno);
+ }
+#ifdef HAVE_BERKELEY_DB
if (!SINGLETHREADED)
return (0);
- key_gen((uint8_t *)key->data, &key->size, keyno);
- bdb_update(key->data, key->size, value->data, value->size, &notfound);
- (void)notfound_chk("col_update", ret, notfound, keyno);
+ key_gen(key, keyno);
+ bdb_update(key->data, key->size, value->data, value->size);
+#else
+ (void)key; /* [-Wunused-variable] */
+#endif
return (0);
}
@@ -860,12 +1117,8 @@ table_append_init(void)
g.append_max = (size_t)g.c_threads * 10;
g.append_cnt = 0;
- if (g.append != NULL) {
- free(g.append);
- g.append = NULL;
- }
- if ((g.append = calloc(g.append_max, sizeof(uint64_t))) == NULL)
- die(errno, "calloc");
+ free(g.append);
+ g.append = dcalloc(g.append_max, sizeof(uint64_t));
}
/*
@@ -876,13 +1129,13 @@ static void
table_append(uint64_t keyno)
{
uint64_t *p, *ep;
- int done, ret;
+ int done;
ep = g.append + g.append_max;
/*
* We don't want to ignore records we append, which requires we update
- * the "last row" as we insert new records. Threads allocating record
+ * the "last row" as we insert new records. Threads allocating record
* numbers can race with other threads, so the thread allocating record
* N may return after the thread allocating N + 1. We can't update a
* record before it's been inserted, and so we can't leave gaps when the
@@ -900,15 +1153,14 @@ table_append(uint64_t keyno)
* to sleep (so the append table fills up), then N threads of control
* used the same g.append_cnt value to decide there was an available
* slot in the append table and both allocated new records, we could run
- * out of space in the table. It's unfortunately not even unlikely in
+ * out of space in the table. It's unfortunately not even unlikely in
* the case of a large number of threads all inserting as fast as they
* can and a single thread going to sleep for an unexpectedly long time.
* If it happens, sleep and retry until earlier records are resolved
* and we find a slot.
*/
for (done = 0;;) {
- if ((ret = pthread_rwlock_wrlock(&g.append_lock)) != 0)
- die(ret, "pthread_rwlock_wrlock: append_lock");
+ testutil_check(pthread_rwlock_wrlock(&g.append_lock));
/*
* If this is the thread we've been waiting for, and its record
@@ -945,8 +1197,7 @@ table_append(uint64_t keyno)
break;
}
- if ((ret = pthread_rwlock_unlock(&g.append_lock)) != 0)
- die(ret, "pthread_rwlock_unlock: append_lock");
+ testutil_check(pthread_rwlock_unlock(&g.append_lock));
if (done)
break;
@@ -959,37 +1210,38 @@ table_append(uint64_t keyno)
* Insert a row in a row-store file.
*/
static int
-row_insert(TINFO *tinfo,
- WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value, uint64_t keyno)
+row_insert(WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value, uint64_t keyno)
{
+ WT_DECL_RET;
WT_SESSION *session;
- int notfound, ret;
session = cursor->session;
- key_gen_insert(&tinfo->rnd, (uint8_t *)key->data, &key->size, keyno);
- val_gen(&tinfo->rnd, (uint8_t *)value->data, &value->size, keyno);
-
/* Log the operation */
if (g.logging == LOG_OPS)
(void)g.wt_api->msg_printf(g.wt_api, session,
- "%-10s{%.*s}\n%-10s{%.*s}",
- "insertK", (int)key->size, (char *)key->data,
- "insertV", (int)value->size, (char *)value->data);
+ "%-10s{%.*s}, {%.*s}",
+ "insert",
+ (int)key->size, key->data, (int)value->size, value->data);
cursor->set_key(cursor, key);
cursor->set_value(cursor, value);
- ret = cursor->insert(cursor);
- if (ret == WT_ROLLBACK)
+ switch (ret = cursor->insert(cursor)) {
+ case 0:
+ break;
+ case WT_ROLLBACK:
return (WT_ROLLBACK);
- if (ret != 0 && ret != WT_NOTFOUND)
- die(ret, "row_insert: insert row %" PRIu64 " by key", keyno);
+ default:
+ testutil_die(ret,
+ "row_insert: insert row %" PRIu64 " by key", keyno);
+ }
+#ifdef HAVE_BERKELEY_DB
if (!SINGLETHREADED)
return (0);
- bdb_update(key->data, key->size, value->data, value->size, &notfound);
- (void)notfound_chk("row_insert", ret, notfound, keyno);
+ bdb_update(key->data, key->size, value->data, value->size);
+#endif
return (0);
}
@@ -998,28 +1250,27 @@ row_insert(TINFO *tinfo,
* Insert an element in a column-store file.
*/
static int
-col_insert(TINFO *tinfo,
- WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value, uint64_t *keynop)
+col_insert(WT_CURSOR *cursor, WT_ITEM *key, WT_ITEM *value, uint64_t *keynop)
{
+ WT_DECL_RET;
WT_SESSION *session;
uint64_t keyno;
- int notfound, ret;
session = cursor->session;
- val_gen(&tinfo->rnd, (uint8_t *)value->data, &value->size, g.rows + 1);
-
if (g.type == FIX)
cursor->set_value(cursor, *(uint8_t *)value->data);
else
cursor->set_value(cursor, value);
- if ((ret = cursor->insert(cursor)) != 0) {
- if (ret == WT_ROLLBACK)
- return (WT_ROLLBACK);
- die(ret, "cursor.insert");
+ switch (ret = cursor->insert(cursor)) {
+ case 0:
+ break;
+ case WT_ROLLBACK:
+ return (WT_ROLLBACK);
+ default:
+ testutil_die(ret, "cursor.insert");
}
- if ((ret = cursor->get_key(cursor, &keyno)) != 0)
- die(ret, "cursor.get_key");
+ testutil_check(cursor->get_key(cursor, &keyno));
*keynop = (uint32_t)keyno;
table_append(keyno); /* Extend the object. */
@@ -1037,11 +1288,15 @@ col_insert(TINFO *tinfo,
(int)value->size, (char *)value->data);
}
+#ifdef HAVE_BERKELEY_DB
if (!SINGLETHREADED)
return (0);
- key_gen((uint8_t *)key->data, &key->size, keyno);
- bdb_update(key->data, key->size, value->data, value->size, &notfound);
+ key_gen(key, keyno);
+ bdb_update(key->data, key->size, value->data, value->size);
+#else
+ (void)key; /* [-Wunused-variable] */
+#endif
return (0);
}
@@ -1050,14 +1305,14 @@ col_insert(TINFO *tinfo,
* Remove an row from a row-store file.
*/
static int
-row_remove(WT_CURSOR *cursor, WT_ITEM *key, uint64_t keyno, int *notfoundp)
+row_remove(WT_CURSOR *cursor, WT_ITEM *key, uint64_t keyno)
{
+ WT_DECL_RET;
WT_SESSION *session;
- int notfound, ret;
session = cursor->session;
- key_gen((uint8_t *)key->data, &key->size, keyno);
+ key_gen(key, keyno);
/* Log the operation */
if (g.logging == LOG_OPS)
@@ -1068,18 +1323,31 @@ row_remove(WT_CURSOR *cursor, WT_ITEM *key, uint64_t keyno, int *notfoundp)
/* We use the cursor in overwrite mode, check for existence. */
if ((ret = cursor->search(cursor)) == 0)
ret = cursor->remove(cursor);
- if (ret == WT_ROLLBACK)
+ switch (ret) {
+ case 0:
+ case WT_NOTFOUND:
+ break;
+ case WT_ROLLBACK:
return (WT_ROLLBACK);
- if (ret != 0 && ret != WT_NOTFOUND)
- die(ret, "row_remove: remove %" PRIu64 " by key", keyno);
- *notfoundp = (ret == WT_NOTFOUND);
+ default:
+ testutil_die(ret,
+ "row_remove: remove %" PRIu64 " by key", keyno);
+ }
+#ifdef HAVE_BERKELEY_DB
if (!SINGLETHREADED)
- return (0);
+ return (ret);
+
+ {
+ int notfound;
bdb_remove(keyno, &notfound);
(void)notfound_chk("row_remove", ret, notfound, keyno);
- return (0);
+ }
+#else
+ (void)key; /* [-Wunused-variable] */
+#endif
+ return (ret);
}
/*
@@ -1087,10 +1355,10 @@ row_remove(WT_CURSOR *cursor, WT_ITEM *key, uint64_t keyno, int *notfoundp)
* Remove a row from a column-store file.
*/
static int
-col_remove(WT_CURSOR *cursor, WT_ITEM *key, uint64_t keyno, int *notfoundp)
+col_remove(WT_CURSOR *cursor, WT_ITEM *key, uint64_t keyno)
{
+ WT_DECL_RET;
WT_SESSION *session;
- int notfound, ret;
session = cursor->session;
@@ -1103,28 +1371,41 @@ col_remove(WT_CURSOR *cursor, WT_ITEM *key, uint64_t keyno, int *notfoundp)
/* We use the cursor in overwrite mode, check for existence. */
if ((ret = cursor->search(cursor)) == 0)
ret = cursor->remove(cursor);
- if (ret == WT_ROLLBACK)
+ switch (ret) {
+ case 0:
+ case WT_NOTFOUND:
+ break;
+ case WT_ROLLBACK:
return (WT_ROLLBACK);
- if (ret != 0 && ret != WT_NOTFOUND)
- die(ret, "col_remove: remove %" PRIu64 " by key", keyno);
- *notfoundp = (ret == WT_NOTFOUND);
+ default:
+ testutil_die(ret,
+ "col_remove: remove %" PRIu64 " by key", keyno);
+ }
+#ifdef HAVE_BERKELEY_DB
if (!SINGLETHREADED)
- return (0);
+ return (ret);
/*
* Deleting a fixed-length item is the same as setting the bits to 0;
* do the same thing for the BDB store.
*/
if (g.type == FIX) {
- key_gen((uint8_t *)key->data, &key->size, keyno);
- bdb_update(key->data, key->size, "\0", 1, &notfound);
- } else
+ key_gen(key, keyno);
+ bdb_update(key->data, key->size, "\0", 1);
+ } else {
+ int notfound;
+
bdb_remove(keyno, &notfound);
- (void)notfound_chk("col_remove", ret, notfound, keyno);
- return (0);
+ (void)notfound_chk("col_remove", ret, notfound, keyno);
+ }
+#else
+ (void)key; /* [-Wunused-variable] */
+#endif
+ return (ret);
}
+#ifdef HAVE_BERKELEY_DB
/*
* notfound_chk --
* Compare notfound returns for consistency.
@@ -1142,7 +1423,7 @@ notfound_chk(const char *f, int wt_ret, int bdb_notfound, uint64_t keyno)
fprintf(stderr, " row %" PRIu64 ":", keyno);
fprintf(stderr,
" not found in Berkeley DB, found in WiredTiger\n");
- die(0, NULL);
+ testutil_die(0, NULL);
}
if (wt_ret == WT_NOTFOUND) {
fprintf(stderr, "%s: %s:", g.progname, f);
@@ -1150,7 +1431,7 @@ notfound_chk(const char *f, int wt_ret, int bdb_notfound, uint64_t keyno)
fprintf(stderr, " row %" PRIu64 ":", keyno);
fprintf(stderr,
" found in Berkeley DB, not found in WiredTiger\n");
- die(0, NULL);
+ testutil_die(0, NULL);
}
return (0);
}
@@ -1165,7 +1446,7 @@ print_item(const char *tag, WT_ITEM *item)
static const char hex[] = "0123456789abcdef";
const uint8_t *data;
size_t size;
- int ch;
+ u_char ch;
data = item->data;
size = item->size;
@@ -1185,3 +1466,4 @@ print_item(const char *tag, WT_ITEM *item)
}
fprintf(stderr, "}\n");
}
+#endif