row_t * txn_man::get_row(row_t * row, access_t type) { if (CC_ALG == HSTORE) return row; uint64_t starttime = get_sys_clock(); RC rc = RCOK; // assert(row_cnt < MAX_ROW_PER_TXN); uint64_t part_id = row->get_part_id(); if (accesses[row_cnt] == NULL) { accesses[row_cnt] = (Access *) mem_allocator.alloc(sizeof(Access), part_id); num_accesses_alloc ++; } rc = row->get_row(type, this, accesses[ row_cnt ]->data); if (rc == Abort) { return NULL; } accesses[row_cnt]->type = type; accesses[row_cnt]->orig_row = row; #if ROLL_BACK && (CC_ALG == DL_DETECT || CC_ALG == NO_WAIT || CC_ALG == WAIT_DIE) if (type == WR) { accesses[row_cnt]->orig_data = (row_t *) mem_allocator.alloc(sizeof(row_t), part_id); accesses[row_cnt]->orig_data->init(row->get_table(), part_id, 0); accesses[row_cnt]->orig_data->copy(row); } #endif row_cnt ++; if (type == WR) wr_cnt ++; uint64_t timespan = get_sys_clock() - starttime; INC_TMP_STATS(get_thd_id(), time_man, timespan); return accesses[row_cnt - 1]->data; }
itemid_t * txn_man::index_read(INDEX * index, idx_key_t key, int part_id) { uint64_t starttime = get_sys_clock(); itemid_t * item; index->index_read(key, item, part_id, get_thd_id()); INC_TMP_STATS(get_thd_id(), time_index, get_sys_clock() - starttime); return item; }
RC txn_man::finish(RC rc) { if (CC_ALG == HSTORE) return RCOK; uint64_t starttime = get_sys_clock(); if (CC_ALG == OCC && rc == RCOK) { // validation phase. rc = occ_man.validate(this); } else cleanup(rc); uint64_t timespan = get_sys_clock() - starttime; INC_TMP_STATS(get_thd_id(), time_man, timespan); INC_STATS(get_thd_id(), time_cleanup, timespan); return rc; }
RC row_t::get_row(access_t type, txn_man * txn, row_t *& row) { RC rc = RCOK; #if CC_ALG == WAIT_DIE || CC_ALG == NO_WAIT || CC_ALG == DL_DETECT uint64_t thd_id = txn->get_thd_id(); lock_t lt = (type == RD || type == SCAN)? LOCK_SH : LOCK_EX; #if CC_ALG == DL_DETECT uint64_t * txnids; int txncnt; rc = this->manager->lock_get(lt, txn, txnids, txncnt); #else rc = this->manager->lock_get(lt, txn); #endif if (rc == RCOK) { row = this; } else if (rc == Abort) {} else if (rc == WAIT) { ASSERT(CC_ALG == WAIT_DIE || CC_ALG == DL_DETECT); uint64_t starttime = get_sys_clock(); #if CC_ALG == DL_DETECT bool dep_added = false; #endif uint64_t endtime; txn->lock_abort = false; INC_STATS(txn->get_thd_id(), wait_cnt, 1); while (!txn->lock_ready && !txn->lock_abort) { #if CC_ALG == WAIT_DIE continue; #elif CC_ALG == DL_DETECT uint64_t last_detect = starttime; uint64_t last_try = starttime; uint64_t now = get_sys_clock(); if (now - starttime > g_timeout ) { txn->lock_abort = true; break; } if (g_no_dl) continue; int ok = 0; if ((now - last_detect > g_dl_loop_detect) && (now - last_try > DL_LOOP_TRIAL)) { if (!dep_added) { ok = dl_detector.add_dep(txn->get_txn_id(), txnids, txncnt, txn->row_cnt); if (ok == 0) dep_added = true; else if (ok == 16) last_try = now; } if (dep_added) { ok = dl_detector.detect_cycle(txn->get_txn_id()); if (ok == 16) // failed to lock the deadlock detector last_try = now; else if (ok == 0) last_detect = now; else if (ok == 1) { last_detect = now; } } } #endif } if (txn->lock_ready) rc = RCOK; else if (txn->lock_abort) { rc = Abort; return_row(type, txn, NULL); } endtime = get_sys_clock(); INC_TMP_STATS(thd_id, time_wait, endtime - starttime); row = this; } return rc; #elif CC_ALG == TIMESTAMP || CC_ALG == MVCC uint64_t thd_id = txn->get_thd_id(); // For TIMESTAMP RD, a new copy of the row will be returned. // for MVCC RD, the version will be returned instead of a copy // So for MVCC RD-WR, the version should be explicitly copied. row_t * newr = NULL; #if CC_ALG == TIMESTAMP // TIMESTAMP makes a whole copy of the row before reading txn->cur_row = (row_t *) mem_allocator.alloc(sizeof(row_t), this->get_part_id()); txn->cur_row->init(get_table(), this->get_part_id()); #elif CC_ALG == MVCC if (type == WR) { newr = (row_t *) mem_allocator.alloc(sizeof(row_t), get_part_id()); newr->init(this->get_table(), get_part_id()); } #endif if (type == WR) { rc = this->manager->access(txn, P_REQ, NULL); if (rc != RCOK) return rc; } if ((type == WR && rc == RCOK) || type == RD || type == SCAN) { rc = this->manager->access(txn, R_REQ, NULL); if (rc == RCOK ) { row = txn->cur_row; } else if (rc == WAIT) { uint64_t t1 = get_sys_clock(); while (!txn->ts_ready) {} uint64_t t2 = get_sys_clock(); INC_TMP_STATS(thd_id, time_wait, t2 - t1); row = txn->cur_row; } else if (rc == Abort) { } if (rc != Abort) { assert(row->get_data() != NULL); assert(row->get_table() != NULL); assert(row->get_schema() == this->get_schema()); assert(row->get_table_name() != NULL); } } if (rc != Abort && CC_ALG == MVCC && type == WR) { newr->copy(row); row = newr; } return rc; #elif CC_ALG == OCC // OCC always make a local copy regardless of read or write txn->cur_row = (row_t *) mem_allocator.alloc(sizeof(row_t), get_part_id()); txn->cur_row->init(get_table(), get_part_id()); rc = this->manager->access(txn, R_REQ); row = txn->cur_row; return rc; #elif CC_ALG == HSTORE || CC_ALG == VLL row = this; return rc; #else assert(false); #endif }
RC row_t::get_row(access_t type, txn_man * txn, row_t *& row) { RC rc = RCOK; #if CC_ALG == WAIT_DIE || CC_ALG == NO_WAIT || CC_ALG == DL_DETECT uint64_t thd_id = txn->get_thd_id(); lock_t lt = (type == RD || type == SCAN)? LOCK_SH : LOCK_EX; #if CC_ALG == DL_DETECT uint64_t * txnids; int txncnt; rc = this->manager->lock_get(lt, txn, txnids, txncnt); #else rc = this->manager->lock_get(lt, txn); #endif if (rc == RCOK) { row = this; } else if (rc == Abort) {} else if (rc == WAIT) { ASSERT(CC_ALG == WAIT_DIE || CC_ALG == DL_DETECT); uint64_t starttime = get_sys_clock(); #if CC_ALG == DL_DETECT bool dep_added = false; #endif uint64_t endtime; txn->lock_abort = false; INC_STATS(txn->get_thd_id(), wait_cnt, 1); while (!txn->lock_ready && !txn->lock_abort) { #if CC_ALG == WAIT_DIE continue; #elif CC_ALG == DL_DETECT uint64_t last_detect = starttime; uint64_t last_try = starttime; uint64_t now = get_sys_clock(); if (now - starttime > g_timeout ) { txn->lock_abort = true; break; } if (g_no_dl) { PAUSE continue; } int ok = 0; if ((now - last_detect > g_dl_loop_detect) && (now - last_try > DL_LOOP_TRIAL)) { if (!dep_added) { ok = dl_detector.add_dep(txn->get_txn_id(), txnids, txncnt, txn->row_cnt); if (ok == 0) dep_added = true; else if (ok == 16) last_try = now; } if (dep_added) { ok = dl_detector.detect_cycle(txn->get_txn_id()); if (ok == 16) // failed to lock the deadlock detector last_try = now; else if (ok == 0) last_detect = now; else if (ok == 1) { last_detect = now; } } } else PAUSE #endif } if (txn->lock_ready) rc = RCOK; else if (txn->lock_abort) { rc = Abort; return_row(type, txn, NULL); } endtime = get_sys_clock(); INC_TMP_STATS(thd_id, time_wait, endtime - starttime); row = this; }