Commit f586dc95 authored by Zardosht Kasheff's avatar Zardosht Kasheff Committed by Yoni Fogel

refs #5891, merge to main

git-svn-id: file:///svn/toku/tokudb@54377 c7de825b-a66e-492c-adef-691d508d4ae1
parent 1164029f
...@@ -169,6 +169,9 @@ struct tokutxn { ...@@ -169,6 +169,9 @@ struct tokutxn {
XIDS xids; // Represents the xid list XIDS xids; // Represents the xid list
TXNID oldest_referenced_xid; TXNID oldest_referenced_xid;
TOKUTXN snapshot_next;
TOKUTXN snapshot_prev;
bool begin_was_logged; bool begin_was_logged;
bool declared_read_only; // true if the txn was declared read only when began bool declared_read_only; // true if the txn was declared read only when began
// These are not read until a commit, prepare, or abort starts, and // These are not read until a commit, prepare, or abort starts, and
......
...@@ -253,6 +253,8 @@ static txn_child_manager tcm; ...@@ -253,6 +253,8 @@ static txn_child_manager tcm;
.live_root_txn_list = nullptr, .live_root_txn_list = nullptr,
.xids = NULL, .xids = NULL,
.oldest_referenced_xid = TXNID_NONE, .oldest_referenced_xid = TXNID_NONE,
.snapshot_next = NULL,
.snapshot_prev = NULL,
.begin_was_logged = false, .begin_was_logged = false,
.declared_read_only = read_only, .declared_read_only = read_only,
.do_fsync = false, .do_fsync = false,
......
...@@ -181,7 +181,9 @@ void toku_txn_manager_init(TXN_MANAGER* txn_managerp) { ...@@ -181,7 +181,9 @@ void toku_txn_manager_init(TXN_MANAGER* txn_managerp) {
toku_mutex_init(&txn_manager->txn_manager_lock, NULL); toku_mutex_init(&txn_manager->txn_manager_lock, NULL);
txn_manager->live_root_txns.create(); txn_manager->live_root_txns.create();
txn_manager->live_root_ids.create(); txn_manager->live_root_ids.create();
txn_manager->snapshot_txnids.create(); txn_manager->snapshot_head = NULL;
txn_manager->snapshot_tail = NULL;
txn_manager->num_snapshots = 0;
txn_manager->referenced_xids.create(); txn_manager->referenced_xids.create();
txn_manager->last_xid = 0; txn_manager->last_xid = 0;
...@@ -196,8 +198,7 @@ void toku_txn_manager_destroy(TXN_MANAGER txn_manager) { ...@@ -196,8 +198,7 @@ void toku_txn_manager_destroy(TXN_MANAGER txn_manager) {
txn_manager->live_root_txns.destroy(); txn_manager->live_root_txns.destroy();
invariant(txn_manager->live_root_ids.size() == 0); invariant(txn_manager->live_root_ids.size() == 0);
txn_manager->live_root_ids.destroy(); txn_manager->live_root_ids.destroy();
invariant(txn_manager->snapshot_txnids.size() == 0); invariant(txn_manager->snapshot_head == NULL);
txn_manager->snapshot_txnids.destroy();
invariant(txn_manager->referenced_xids.size() == 0); invariant(txn_manager->referenced_xids.size() == 0);
txn_manager->referenced_xids.destroy(); txn_manager->referenced_xids.destroy();
toku_free(txn_manager); toku_free(txn_manager);
...@@ -284,10 +285,9 @@ static TXNID get_oldest_referenced_xid_unlocked(TXN_MANAGER txn_manager) { ...@@ -284,10 +285,9 @@ static TXNID get_oldest_referenced_xid_unlocked(TXN_MANAGER txn_manager) {
oldest_referenced_xid = tuple->begin_id; oldest_referenced_xid = tuple->begin_id;
} }
} }
if (txn_manager->snapshot_txnids.size() > 0) { if (txn_manager->snapshot_head != NULL) {
TXNID id; TXNID id = txn_manager->snapshot_head->snapshot_txnid64;
r = txn_manager->snapshot_txnids.fetch(0, &id); if (id < oldest_referenced_xid) {
if (r == 0 && id < oldest_referenced_xid) {
oldest_referenced_xid = id; oldest_referenced_xid = id;
} }
} }
...@@ -319,9 +319,17 @@ static inline void txn_manager_create_snapshot_unlocked( ...@@ -319,9 +319,17 @@ static inline void txn_manager_create_snapshot_unlocked(
// Add this txn to the global list of txns that have their own snapshots. // Add this txn to the global list of txns that have their own snapshots.
// (Note, if a txn is a child that creates its own snapshot, then that child xid // (Note, if a txn is a child that creates its own snapshot, then that child xid
// is the xid stored in the global list.) // is the xid stored in the global list.)
uint32_t idx = txn_manager->snapshot_txnids.size(); if (txn_manager->snapshot_head == NULL) {
int r = txn_manager->snapshot_txnids.insert_at(txn->snapshot_txnid64, idx); invariant(txn_manager->snapshot_tail == NULL);
lazy_assert_zero(r); txn_manager->snapshot_head = txn;
txn_manager->snapshot_tail = txn;
}
else {
txn_manager->snapshot_tail->snapshot_next = txn;
txn->snapshot_prev = txn_manager->snapshot_tail;
txn_manager->snapshot_tail = txn;
}
txn_manager->num_snapshots++;
} }
// template-only function, but must be extern // template-only function, but must be extern
...@@ -414,17 +422,23 @@ note_snapshot_txn_end_by_txn_live_list(TXN_MANAGER mgr, xid_omt_t* live_root_txn ...@@ -414,17 +422,23 @@ note_snapshot_txn_end_by_txn_live_list(TXN_MANAGER mgr, xid_omt_t* live_root_txn
static inline void txn_manager_remove_snapshot_unlocked( static inline void txn_manager_remove_snapshot_unlocked(
TOKUTXN txn, TOKUTXN txn,
TXN_MANAGER txn_manager, TXN_MANAGER txn_manager
uint32_t* index_in_snapshot_txnids
) )
{ {
TXNID xid; // Remove from linked list of snapshot txns
//Free memory used for snapshot_txnids if (txn_manager->snapshot_head == txn) {
int r = txn_manager->snapshot_txnids.find_zero<TXNID, toku_find_xid_by_xid>(txn->snapshot_txnid64, &xid, index_in_snapshot_txnids); txn_manager->snapshot_head = txn->snapshot_next;
invariant_zero(r); }
invariant(xid == txn->snapshot_txnid64); if (txn_manager->snapshot_tail == txn) {
r = txn_manager->snapshot_txnids.delete_at(*index_in_snapshot_txnids); txn_manager->snapshot_tail = txn->snapshot_prev;
invariant_zero(r); }
if (txn->snapshot_next) {
txn->snapshot_next->snapshot_prev = txn->snapshot_prev;
}
if (txn->snapshot_prev) {
txn->snapshot_prev->snapshot_next = txn->snapshot_next;
}
txn_manager->num_snapshots--;
uint32_t ref_xids_size = txn_manager->referenced_xids.size(); uint32_t ref_xids_size = txn_manager->referenced_xids.size();
uint32_t live_list_size = txn->live_root_txn_list->size(); uint32_t live_list_size = txn->live_root_txn_list->size();
if (ref_xids_size > 0 && live_list_size > 0) { if (ref_xids_size > 0 && live_list_size > 0) {
...@@ -474,9 +488,8 @@ void toku_txn_manager_handle_snapshot_destroy_for_child_txn( ...@@ -474,9 +488,8 @@ void toku_txn_manager_handle_snapshot_destroy_for_child_txn(
invariant(txn->parent != NULL); invariant(txn->parent != NULL);
bool is_snapshot = txn_needs_snapshot(snapshot_type, txn->parent); bool is_snapshot = txn_needs_snapshot(snapshot_type, txn->parent);
if (is_snapshot) { if (is_snapshot) {
uint32_t index;
txn_manager_lock(txn_manager); txn_manager_lock(txn_manager);
txn_manager_remove_snapshot_unlocked(txn, txn_manager, &index); txn_manager_remove_snapshot_unlocked(txn, txn_manager);
txn_manager_unlock(txn_manager); txn_manager_unlock(txn_manager);
invariant(txn->live_root_txn_list != nullptr); invariant(txn->live_root_txn_list != nullptr);
txn->live_root_txn_list->destroy(); txn->live_root_txn_list->destroy();
...@@ -606,12 +619,10 @@ void toku_txn_manager_finish_txn(TXN_MANAGER txn_manager, TOKUTXN txn) { ...@@ -606,12 +619,10 @@ void toku_txn_manager_finish_txn(TXN_MANAGER txn_manager, TOKUTXN txn) {
verify_snapshot_system(txn_manager); verify_snapshot_system(txn_manager);
} }
uint32_t index_in_snapshot_txnids;
if (is_snapshot) { if (is_snapshot) {
txn_manager_remove_snapshot_unlocked( txn_manager_remove_snapshot_unlocked(
txn, txn,
txn_manager, txn_manager
&index_in_snapshot_txnids
); );
} }
...@@ -629,15 +640,18 @@ void toku_txn_manager_finish_txn(TXN_MANAGER txn_manager, TOKUTXN txn) { ...@@ -629,15 +640,18 @@ void toku_txn_manager_finish_txn(TXN_MANAGER txn_manager, TOKUTXN txn) {
invariant_zero(r); invariant_zero(r);
if (!toku_txn_is_read_only(txn) || garbage_collection_debug) { if (!toku_txn_is_read_only(txn) || garbage_collection_debug) {
if (!is_snapshot) { uint32_t num_references = 0;
// TOKUTXN curr_txn = txn_manager->snapshot_tail;
// If it's a snapshot, we already calculated index_in_snapshot_txnids. while(curr_txn != NULL) {
// Otherwise, calculate it now. if (curr_txn->snapshot_txnid64 > txn->txnid.parent_id64) {
// num_references++;
r = txn_manager->snapshot_txnids.find_zero<TXNID, toku_find_xid_by_xid>(txn->txnid.parent_id64, nullptr, &index_in_snapshot_txnids); }
invariant(r == DB_NOTFOUND); else {
break;
}
curr_txn = curr_txn->snapshot_prev;
} }
uint32_t num_references = txn_manager->snapshot_txnids.size() - index_in_snapshot_txnids;
if (num_references > 0) { if (num_references > 0) {
// This transaction exists in a live list of another transaction. // This transaction exists in a live list of another transaction.
struct referenced_xid_tuple tuple = { struct referenced_xid_tuple tuple = {
...@@ -673,7 +687,21 @@ void toku_txn_manager_clone_state_for_gc( ...@@ -673,7 +687,21 @@ void toku_txn_manager_clone_state_for_gc(
) )
{ {
txn_manager_lock(txn_manager); txn_manager_lock(txn_manager);
snapshot_xids->clone(txn_manager->snapshot_txnids); TXNID* snapshot_xids_array = NULL;
XMALLOC_N(txn_manager->num_snapshots, snapshot_xids_array);
TOKUTXN curr_txn = txn_manager->snapshot_head;
uint32_t curr_index = 0;
while (curr_txn != NULL) {
snapshot_xids_array[curr_index] = curr_txn->snapshot_txnid64;
curr_txn = curr_txn->snapshot_next;
curr_index++;
}
snapshot_xids->create_steal_sorted_array(
&snapshot_xids_array,
txn_manager->num_snapshots,
txn_manager->num_snapshots
);
referenced_xids->clone(txn_manager->referenced_xids); referenced_xids->clone(txn_manager->referenced_xids);
setup_live_root_txn_list(&txn_manager->live_root_ids, live_root_txns); setup_live_root_txn_list(&txn_manager->live_root_ids, live_root_txns);
txn_manager_unlock(txn_manager); txn_manager_unlock(txn_manager);
......
...@@ -27,7 +27,9 @@ struct txn_manager { ...@@ -27,7 +27,9 @@ struct txn_manager {
toku_mutex_t txn_manager_lock; // a lock protecting this object toku_mutex_t txn_manager_lock; // a lock protecting this object
txn_omt_t live_root_txns; // a sorted tree. txn_omt_t live_root_txns; // a sorted tree.
xid_omt_t live_root_ids; //contains TXNID x | x is snapshot txn xid_omt_t live_root_ids; //contains TXNID x | x is snapshot txn
xid_omt_t snapshot_txnids; //contains TXNID x | x is snapshot txn TOKUTXN snapshot_head;
TOKUTXN snapshot_tail;
uint32_t num_snapshots;
// Contains 3-tuples: (TXNID begin_id, TXNID end_id, uint64_t num_live_list_references) // Contains 3-tuples: (TXNID begin_id, TXNID end_id, uint64_t num_live_list_references)
// for committed root transaction ids that are still referenced by a live list. // for committed root transaction ids that are still referenced by a live list.
rx_omt_t referenced_xids; rx_omt_t referenced_xids;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment