diff options
Diffstat (limited to 'src/third_party/wiredtiger/src/txn/txn.c')
-rw-r--r-- | src/third_party/wiredtiger/src/txn/txn.c | 135 |
1 files changed, 105 insertions, 30 deletions
diff --git a/src/third_party/wiredtiger/src/txn/txn.c b/src/third_party/wiredtiger/src/txn/txn.c index 191f7e0ba0f..09efb2924bf 100644 --- a/src/third_party/wiredtiger/src/txn/txn.c +++ b/src/third_party/wiredtiger/src/txn/txn.c @@ -445,12 +445,11 @@ __wt_txn_config(WT_SESSION_IMPL *session, const char *cfg[]) WT_RET(__wt_txn_parse_timestamp( session, "read", &txn->read_timestamp, &cval)); - __wt_readlock(session, &txn_global->rwlock); - __wt_timestamp_set( - &oldest_timestamp, &txn_global->oldest_timestamp); - __wt_timestamp_set( - &stable_timestamp, &txn_global->stable_timestamp); - __wt_readunlock(session, &txn_global->rwlock); + WT_WITH_TIMESTAMP_READLOCK(session, &txn_global->rwlock, + __wt_timestamp_set( + &oldest_timestamp, &txn_global->oldest_timestamp); + __wt_timestamp_set( + &stable_timestamp, &txn_global->stable_timestamp)); if (__wt_timestamp_cmp( &txn->read_timestamp, &oldest_timestamp) < 0) WT_RET_MSG(session, EINVAL, @@ -568,18 +567,20 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[]) WT_CONNECTION_IMPL *conn; WT_DECL_RET; WT_TXN *txn; + WT_TXN_GLOBAL *txn_global; WT_TXN_OP *op; + u_int i; + bool did_update, locked; #ifdef HAVE_TIMESTAMPS - WT_TXN_GLOBAL *txn_global = &S2C(session)->txn_global; wt_timestamp_t prev_commit_timestamp; bool update_timestamp; #endif - u_int i; - bool did_update; txn = &session->txn; conn = S2C(session); + txn_global = &conn->txn_global; did_update = txn->mod_count != 0; + locked = false; WT_ASSERT(session, F_ISSET(txn, WT_TXN_RUNNING)); WT_ASSERT(session, !F_ISSET(txn, WT_TXN_ERROR) || !did_update); @@ -665,6 +666,14 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[]) * This is particularly important for checkpoints. */ __wt_txn_release_snapshot(session); + /* + * We hold the visibility lock for reading from the time + * we write our log record until the time we release our + * transaction so that the LSN any checkpoint gets will + * always reflect visible data. + */ + __wt_readlock(session, &txn_global->visibility_rwlock); + locked = true; WT_ERR(__wt_txn_log_commit(session, cfg)); } @@ -687,9 +696,12 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[]) #ifdef HAVE_TIMESTAMPS if (F_ISSET(txn, WT_TXN_HAS_TS_COMMIT) && - op->type != WT_TXN_OP_BASIC_TS) + op->type != WT_TXN_OP_BASIC_TS) { + WT_ASSERT(session, + op->fileid != WT_METAFILE_ID); __wt_timestamp_set(&op->u.upd->timestamp, &txn->commit_timestamp); + } #endif break; @@ -724,14 +736,15 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[]) #endif __wt_txn_release(session); + if (locked) + __wt_readunlock(session, &txn_global->visibility_rwlock); #ifdef HAVE_TIMESTAMPS /* First check if we've already committed something in the future. */ if (update_timestamp) { - __wt_readlock(session, &txn_global->rwlock); - __wt_timestamp_set( - &prev_commit_timestamp, &txn_global->commit_timestamp); - __wt_readunlock(session, &txn_global->rwlock); + WT_WITH_TIMESTAMP_READLOCK(session, &txn_global->rwlock, + __wt_timestamp_set( + &prev_commit_timestamp, &txn_global->commit_timestamp)); update_timestamp = __wt_timestamp_cmp( &txn->commit_timestamp, &prev_commit_timestamp) > 0; } @@ -760,6 +773,8 @@ err: /* * !!! * Nothing can fail after this point. */ + if (locked) + __wt_readunlock(session, &txn_global->visibility_rwlock); WT_TRET(__wt_txn_rollback(session, cfg)); return (ret); } @@ -930,6 +945,7 @@ __wt_txn_global_init(WT_SESSION_IMPL *session, const char *cfg[]) WT_RET(__wt_spin_init( session, &txn_global->id_lock, "transaction id lock")); WT_RET(__wt_rwlock_init(session, &txn_global->rwlock)); + WT_RET(__wt_rwlock_init(session, &txn_global->visibility_rwlock)); WT_RET(__wt_rwlock_init(session, &txn_global->commit_timestamp_rwlock)); TAILQ_INIT(&txn_global->commit_timestamph); @@ -971,6 +987,7 @@ __wt_txn_global_destroy(WT_SESSION_IMPL *session) __wt_rwlock_destroy(session, &txn_global->commit_timestamp_rwlock); __wt_rwlock_destroy(session, &txn_global->read_timestamp_rwlock); __wt_rwlock_destroy(session, &txn_global->nsnap_rwlock); + __wt_rwlock_destroy(session, &txn_global->visibility_rwlock); __wt_free(session, txn_global->states); } @@ -981,10 +998,7 @@ __wt_txn_global_destroy(WT_SESSION_IMPL *session) int __wt_txn_global_shutdown(WT_SESSION_IMPL *session) { - WT_DECL_RET; - WT_TXN_GLOBAL *txn_global; - - txn_global = &S2C(session)->txn_global; + bool txn_active; /* * We're shutting down. Make sure everything gets freed. @@ -995,10 +1009,8 @@ __wt_txn_global_shutdown(WT_SESSION_IMPL *session) * transaction ID will catch up with the current ID. */ for (;;) { - WT_TRET(__wt_txn_update_oldest(session, - WT_TXN_OLDEST_STRICT | WT_TXN_OLDEST_WAIT)); - if (txn_global->oldest_id == txn_global->current && - txn_global->metadata_pinned == txn_global->current) + WT_RET(__wt_txn_activity_check(session, &txn_active)); + if (!txn_active) break; WT_STAT_CONN_INCR(session, txn_release_blocked); @@ -1010,10 +1022,10 @@ __wt_txn_global_shutdown(WT_SESSION_IMPL *session) * Now that all transactions have completed, no timestamps should be * pinned. */ - __wt_timestamp_set_inf(&txn_global->pinned_timestamp); + __wt_timestamp_set_inf(&S2C(session)->txn_global.pinned_timestamp); #endif - return (ret); + return (0); } #if defined(HAVE_DIAGNOSTIC) || defined(HAVE_VERBOSE) @@ -1031,7 +1043,9 @@ __wt_verbose_dump_txn(WT_SESSION_IMPL *session) const char *iso_tag; uint64_t id; uint32_t i, session_cnt; - +#ifdef HAVE_TIMESTAMPS + char hex_timestamp[3][2 * WT_TIMESTAMP_SIZE + 1]; +#endif conn = S2C(session); txn_global = &conn->txn_global; @@ -1042,10 +1056,35 @@ __wt_verbose_dump_txn(WT_SESSION_IMPL *session) WT_RET(__wt_msg(session, "last running ID: %" PRIu64, txn_global->last_running)); WT_RET(__wt_msg(session, "oldest ID: %" PRIu64, txn_global->oldest_id)); - WT_RET(__wt_msg(session, - "oldest named snapshot ID: %" PRIu64, txn_global->nsnap_oldest_id)); - WT_RET(__wt_msg(session, "checkpoint running? %s", +#ifdef HAVE_TIMESTAMPS + WT_RET(__wt_timestamp_to_hex_string( + session, hex_timestamp[0], &txn_global->commit_timestamp)); + WT_RET(__wt_msg(session, "commit timestamp: %s", hex_timestamp[0])); + WT_RET(__wt_timestamp_to_hex_string( + session, hex_timestamp[0], &txn_global->oldest_timestamp)); + WT_RET(__wt_msg(session, "oldest timestamp: %s", hex_timestamp[0])); + WT_RET(__wt_timestamp_to_hex_string( + session, hex_timestamp[0], &txn_global->pinned_timestamp)); + WT_RET(__wt_msg(session, "pinned timestamp: %s", hex_timestamp[0])); + WT_RET(__wt_timestamp_to_hex_string( + session, hex_timestamp[0], &txn_global->stable_timestamp)); + WT_RET(__wt_msg(session, "stable timestamp: %s", hex_timestamp[0])); + WT_RET(__wt_msg(session, "has_commit_timestamp: %s", + txn_global->has_commit_timestamp ? "yes" : "no")); + WT_RET(__wt_msg(session, "has_oldest_timestamp: %s", + txn_global->has_oldest_timestamp ? "yes" : "no")); + WT_RET(__wt_msg(session, "has_pinned_timestamp: %s", + txn_global->has_pinned_timestamp ? "yes" : "no")); + WT_RET(__wt_msg(session, "has_stable_timestamp: %s", + txn_global->has_stable_timestamp ? "yes" : "no")); + WT_RET(__wt_msg(session, "oldest_is_pinned: %s", + txn_global->oldest_is_pinned ? "yes" : "no")); + WT_RET(__wt_msg(session, "stable_is_pinned: %s", + txn_global->stable_is_pinned ? "yes" : "no")); +#endif + + WT_RET(__wt_msg(session, "checkpoint running: %s", txn_global->checkpoint_running ? "yes" : "no")); WT_RET(__wt_msg(session, "checkpoint generation: %" PRIu64, __wt_gen(session, WT_GEN_CHECKPOINT))); @@ -1054,9 +1093,11 @@ __wt_verbose_dump_txn(WT_SESSION_IMPL *session) WT_RET(__wt_msg(session, "checkpoint txn ID: %" PRIu64, txn_global->checkpoint_state.id)); + WT_RET(__wt_msg(session, + "oldest named snapshot ID: %" PRIu64, txn_global->nsnap_oldest_id)); + WT_ORDERED_READ(session_cnt, conn->session_cnt); WT_RET(__wt_msg(session, "session count: %" PRIu32, session_cnt)); - WT_RET(__wt_msg(session, "Transaction state of active sessions:")); /* @@ -1083,7 +1124,40 @@ __wt_verbose_dump_txn(WT_SESSION_IMPL *session) iso_tag = "WT_ISO_SNAPSHOT"; break; } - +#ifdef HAVE_TIMESTAMPS + WT_RET(__wt_timestamp_to_hex_string( + session, hex_timestamp[0], &txn->commit_timestamp)); + WT_RET(__wt_timestamp_to_hex_string( + session, hex_timestamp[1], &txn->first_commit_timestamp)); + WT_RET(__wt_timestamp_to_hex_string( + session, hex_timestamp[2], &txn->read_timestamp)); + WT_RET(__wt_msg(session, + "ID: %8" PRIu64 + ", mod count: %u" + ", pinned ID: %8" PRIu64 + ", snap min: %" PRIu64 + ", snap max: %" PRIu64 + ", commit_timestamp: %s" + ", first_commit_timestamp: %s" + ", read_timestamp: %s" + ", metadata pinned ID: %" PRIu64 + ", flags: 0x%08" PRIx32 + ", name: %s" + ", isolation: %s", + id, + txn->mod_count, + s->pinned_id, + txn->snap_min, + txn->snap_max, + hex_timestamp[0], + hex_timestamp[1], + hex_timestamp[2], + s->metadata_pinned, + txn->flags, + conn->sessions[i].name == NULL ? + "EMPTY" : conn->sessions[i].name, + iso_tag)); +#else WT_RET(__wt_msg(session, "ID: %6" PRIu64 ", mod count: %u" @@ -1104,6 +1178,7 @@ __wt_verbose_dump_txn(WT_SESSION_IMPL *session) conn->sessions[i].name == NULL ? "EMPTY" : conn->sessions[i].name, iso_tag)); +#endif } WT_RET(__wt_msg(session, "%s", WT_DIVIDER)); |