void TxnManager::cleanup(RC rc) { #if CC_ALG == OCC && MODE == NORMAL_MODE occ_man.finish(rc,this); #endif ts_t starttime = get_sys_clock(); uint64_t row_cnt = txn->accesses.get_count(); assert(txn->accesses.get_count() == txn->row_cnt); //assert((WORKLOAD == YCSB && row_cnt <= g_req_per_query) || (WORKLOAD == TPCC && row_cnt <= g_max_items_per_txn*2 + 3)); DEBUG("Cleanup %ld %ld\n",get_txn_id(),row_cnt); for (int rid = row_cnt - 1; rid >= 0; rid --) { cleanup_row(rc,rid); } #if CC_ALG == CALVIN // cleanup locked rows for (uint64_t i = 0; i < calvin_locked_rows.size(); i++) { row_t * row = calvin_locked_rows[i]; row->return_row(rc,RD,this,row); } #endif if (rc == Abort) { txn->release_inserts(get_thd_id()); txn->insert_rows.clear(); INC_STATS(get_thd_id(), abort_time, get_sys_clock() - starttime); } }
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; }
itemid_t * TxnManager::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()); uint64_t t = get_sys_clock() - starttime; INC_STATS(get_thd_id(), txn_index_time, t); //txn_time_idx += t; return item; }
RC InputThread::server_recv_loop() { myrand rdm; rdm.init(get_thd_id()); RC rc = RCOK; assert (rc == RCOK); uint64_t starttime; std::vector<Message*> * msgs; while (!simulation->is_done()) { heartbeat(); starttime = get_sys_clock(); msgs = tport_man.recv_msg(get_thd_id()); INC_STATS(_thd_id,mtx[28], get_sys_clock() - starttime); starttime = get_sys_clock(); if(msgs == NULL) continue; while(!msgs->empty()) { Message * msg = msgs->front(); if(msg->rtype == INIT_DONE) { msgs->erase(msgs->begin()); continue; } #if CC_ALG == CALVIN if(msg->rtype == CALVIN_ACK ||(msg->rtype == CL_QRY && ISCLIENTN(msg->get_return_id()))) { work_queue.sequencer_enqueue(get_thd_id(),msg); msgs->erase(msgs->begin()); continue; } if( msg->rtype == RDONE || msg->rtype == CL_QRY) { assert(ISSERVERN(msg->get_return_id())); work_queue.sched_enqueue(get_thd_id(),msg); msgs->erase(msgs->begin()); continue; } #endif work_queue.enqueue(get_thd_id(),msg,false); msgs->erase(msgs->begin()); } delete msgs; INC_STATS(_thd_id,mtx[29], get_sys_clock() - starttime); } printf("FINISH %ld:%ld\n",_node_id,_thd_id); fflush(stdout); return FINISH; }
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 InputThread::client_recv_loop() { int rsp_cnts[g_servers_per_client]; memset(rsp_cnts, 0, g_servers_per_client * sizeof(int)); run_starttime = get_sys_clock(); uint64_t return_node_offset; uint64_t inf; std::vector<Message*> * msgs; while (!simulation->is_done()) { heartbeat(); uint64_t starttime = get_sys_clock(); msgs = tport_man.recv_msg(get_thd_id()); INC_STATS(_thd_id,mtx[28], get_sys_clock() - starttime); starttime = get_sys_clock(); //while((m_query = work_queue.get_next_query(get_thd_id())) != NULL) { //Message * msg = work_queue.dequeue(); if(msgs == NULL) continue; while(!msgs->empty()) { Message * msg = msgs->front(); assert(msg->rtype == CL_RSP); return_node_offset = msg->return_node_id - g_server_start_node; assert(return_node_offset < g_servers_per_client); rsp_cnts[return_node_offset]++; INC_STATS(get_thd_id(),txn_cnt,1); uint64_t timespan = get_sys_clock() - ((ClientResponseMessage*)msg)->client_startts; INC_STATS(get_thd_id(),txn_run_time, timespan); if (warmup_done) { INC_STATS_ARR(get_thd_id(),client_client_latency, timespan); } //INC_STATS_ARR(get_thd_id(),all_lat,timespan); inf = client_man.dec_inflight(return_node_offset); DEBUG("Recv %ld from %ld, %ld -- %f\n",((ClientResponseMessage*)msg)->txn_id,msg->return_node_id,inf,float(timespan)/BILLION); assert(inf >=0); // TODO: delete message msgs->erase(msgs->begin()); } delete msgs; INC_STATS(_thd_id,mtx[29], get_sys_clock() - starttime); } printf("FINISH %ld:%ld\n",_node_id,_thd_id); fflush(stdout); return FINISH; }
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; }
RC YCSBTxnManager::send_remote_request() { YCSBQuery* ycsb_query = (YCSBQuery*) query; uint64_t dest_node_id = GET_NODE_ID(ycsb_query->requests[next_record_id]->key); ycsb_query->partitions_touched.add_unique(GET_PART_ID(0,dest_node_id)); msg_queue.enqueue(get_thd_id(),Message::create_message(this,RQRY),dest_node_id); return WAIT_REM; }
RC TxnManager::commit() { DEBUG("Commit %ld\n",get_txn_id()); release_locks(RCOK); #if CC_ALG == MAAT time_table.release(get_thd_id(),get_txn_id()); #endif commit_stats(); #if LOGGING LogRecord * record = logger.createRecord(get_txn_id(),L_NOTIFY,0,0); if(g_repl_cnt > 0) { msg_queue.enqueue(get_thd_id(),Message::create_message(record,LOG_MSG),g_node_id + g_node_cnt + g_client_node_cnt); } logger.enqueueRecord(record); return WAIT; #endif return Commit; }
void TxnManager::cleanup_row(RC rc, uint64_t rid) { access_t type = txn->accesses[rid]->type; if (type == WR && rc == Abort && CC_ALG != MAAT) { type = XP; } // Handle calvin elsewhere #if CC_ALG != CALVIN #if ISOLATION_LEVEL != READ_UNCOMMITTED row_t * orig_r = txn->accesses[rid]->orig_row; if (ROLL_BACK && type == XP && (CC_ALG == DL_DETECT || CC_ALG == NO_WAIT || CC_ALG == WAIT_DIE || CC_ALG == HSTORE || CC_ALG == HSTORE_SPEC )) { orig_r->return_row(rc,type, this, txn->accesses[rid]->orig_data); } else { #if ISOLATION_LEVEL == READ_COMMITTED if(type == WR) { orig_r->return_row(rc,type, this, txn->accesses[rid]->data); } #else orig_r->return_row(rc,type, this, txn->accesses[rid]->data); #endif } #endif #if ROLL_BACK && (CC_ALG == NO_WAIT || CC_ALG == WAIT_DIE || CC_ALG == HSTORE || CC_ALG == HSTORE_SPEC) if (type == WR) { //printf("free 10 %ld\n",get_txn_id()); txn->accesses[rid]->orig_data->free_row(); DEBUG_M("TxnManager::cleanup row_t free\n"); row_pool.put(get_thd_id(),txn->accesses[rid]->orig_data); if(rc == RCOK) { INC_STATS(get_thd_id(),record_write_cnt,1); ++txn_stats.write_cnt; } } #endif #endif txn->accesses[rid]->data = NULL; }
void TxnManager::release_locks(RC rc) { uint64_t starttime = get_sys_clock(); cleanup(rc); uint64_t timespan = (get_sys_clock() - starttime); INC_STATS(get_thd_id(), txn_cleanup_time, timespan); }
void TxnManager::send_prepare_messages() { rsp_cnt = query->partitions_touched.size() - 1; DEBUG("%ld Send PREPARE messages to %d\n",get_txn_id(),rsp_cnt); for(uint64_t i = 0; i < query->partitions_touched.size(); i++) { if(GET_NODE_ID(query->partitions_touched[i]) == g_node_id) { continue; } msg_queue.enqueue(get_thd_id(),Message::create_message(this,RPREPARE),GET_NODE_ID(query->partitions_touched[i])); } }
void TxnManager::send_finish_messages() { rsp_cnt = query->partitions_touched.size() - 1; assert(IS_LOCAL(get_txn_id())); DEBUG("%ld Send FINISH messages to %d\n",get_txn_id(),rsp_cnt); for(uint64_t i = 0; i < query->partitions_touched.size(); i++) { if(GET_NODE_ID(query->partitions_touched[i]) == g_node_id) { continue; } msg_queue.enqueue(get_thd_id(),Message::create_message(this,RFIN),GET_NODE_ID(query->partitions_touched[i])); } }
RC TxnManager::get_lock(row_t * row, access_t type) { if (calvin_locked_rows.contains(row)) { return RCOK; } calvin_locked_rows.add(row); RC rc = row->get_lock(type, this); if(rc == WAIT) { INC_STATS(get_thd_id(), txn_wait_cnt, 1); } return rc; }
void TxnManager::release() { uint64_t prof_starttime = get_sys_clock(); qry_pool.put(get_thd_id(),query); INC_STATS(get_thd_id(),mtx[0],get_sys_clock()-prof_starttime); query = NULL; prof_starttime = get_sys_clock(); txn_pool.put(get_thd_id(),txn); INC_STATS(get_thd_id(),mtx[1],get_sys_clock()-prof_starttime); txn = NULL; #if CC_ALG == MAAT delete uncommitted_writes; delete uncommitted_writes_y; delete uncommitted_reads; #endif #if CC_ALG == CALVIN calvin_locked_rows.release(); #endif txn_ready = true; }
RC TxnManager::get_row_post_wait(row_t *& row_rtn) { assert(CC_ALG != HSTORE && CC_ALG != HSTORE_SPEC); uint64_t starttime = get_sys_clock(); row_t * row = this->last_row; access_t type = this->last_type; assert(row != NULL); DEBUG_M("TxnManager::get_row_post_wait access alloc\n") Access * access; access_pool.get(get_thd_id(),access); row->get_row_post_wait(type,this,access->data); access->type = type; access->orig_row = row; #if ROLL_BACK && (CC_ALG == DL_DETECT || CC_ALG == NO_WAIT || CC_ALG == WAIT_DIE) if (type == WR) { uint64_t part_id = row->get_part_id(); //printf("alloc 10 %ld\n",get_txn_id()); DEBUG_M("TxnManager::get_row_post_wait row_t alloc\n") row_pool.get(get_thd_id(),access->orig_data); access->orig_data->init(row->get_table(), part_id, 0); access->orig_data->copy(row); } #endif ++txn->row_cnt; if (type == WR) ++txn->write_cnt; txn->accesses.add(access); uint64_t timespan = get_sys_clock() - starttime; INC_STATS(get_thd_id(), txn_manager_time, timespan); this->last_row_rtn = access->data; row_rtn = access->data; return RCOK; }
void TxnManager::init(uint64_t thd_id, Workload * h_wl) { uint64_t prof_starttime = get_sys_clock(); if(!txn) { DEBUG_M("Transaction alloc\n"); txn_pool.get(thd_id,txn); } INC_STATS(get_thd_id(),mtx[15],get_sys_clock()-prof_starttime); prof_starttime = get_sys_clock(); //txn->init(); if(!query) { DEBUG_M("TxnManager::init Query alloc\n"); qry_pool.get(thd_id,query); } INC_STATS(get_thd_id(),mtx[16],get_sys_clock()-prof_starttime); //query->init(); //reset(); sem_init(&rsp_mutex, 0, 1); return_id = UINT64_MAX; this->h_wl = h_wl; #if CC_ALG == MAAT uncommitted_writes = new std::set<uint64_t>(); uncommitted_writes_y = new std::set<uint64_t>(); uncommitted_reads = new std::set<uint64_t>(); #endif #if CC_ALG == CALVIN phase = CALVIN_RW_ANALYSIS; locking_done = false; calvin_locked_rows.init(MAX_ROW_PER_TXN); #endif txn_ready = true; twopl_wait_start = 0; txn_stats.init(); }
void InputThread::setup() { std::vector<Message*> * msgs; while(!simulation->is_setup_done()) { msgs = tport_man.recv_msg(get_thd_id()); if(msgs == NULL) continue; while(!msgs->empty()) { Message * msg = msgs->front(); if(msg->rtype == INIT_DONE) { printf("Received INIT_DONE from node %ld\n",msg->return_node_id); fflush(stdout); simulation->process_setup_msg(); } else { assert(ISSERVER || ISREPLICA); //printf("Received Msg %d from node %ld\n",msg->rtype,msg->return_node_id); #if CC_ALG == CALVIN if(msg->rtype == CALVIN_ACK ||(msg->rtype == CL_QRY && ISCLIENTN(msg->get_return_id()))) { work_queue.sequencer_enqueue(get_thd_id(),msg); msgs->erase(msgs->begin()); continue; } if( msg->rtype == RDONE || msg->rtype == CL_QRY) { assert(ISSERVERN(msg->get_return_id())); work_queue.sched_enqueue(get_thd_id(),msg); msgs->erase(msgs->begin()); continue; } #endif work_queue.enqueue(get_thd_id(),msg,false); } msgs->erase(msgs->begin()); } delete msgs; } }
RC TxnManager::send_remote_reads() { assert(CC_ALG == CALVIN); #if !YCSB_ABORT_MODE && WORKLOAD == YCSB return RCOK; #endif assert(query->active_nodes.size() == g_node_cnt); for(uint64_t i = 0; i < query->active_nodes.size(); i++) { if(i == g_node_id) continue; if(query->active_nodes[i] == 1) { DEBUG("(%ld,%ld) send_remote_read to %ld\n",get_txn_id(),get_batch_id(),i); msg_queue.enqueue(get_thd_id(),Message::create_message(this,RFWD),i); } } return RCOK; }
RC TxnManager::validate() { #if MODE != NORMAL_MODE return RCOK; #endif if (CC_ALG != OCC && CC_ALG != MAAT) { return RCOK; } RC rc = RCOK; uint64_t starttime = get_sys_clock(); if(CC_ALG == OCC && rc == RCOK) rc = occ_man.validate(this); if(CC_ALG == MAAT && rc == RCOK) { rc = maat_man.validate(this); // Note: home node must be last to validate if(IS_LOCAL(get_txn_id()) && rc == RCOK) { rc = maat_man.find_bound(this); } } INC_STATS(get_thd_id(),txn_validate_time,get_sys_clock() - starttime); return rc; }
RC YCSBTxnManager::acquire_locks() { uint64_t starttime = get_sys_clock(); assert(CC_ALG == CALVIN); YCSBQuery* ycsb_query = (YCSBQuery*) query; locking_done = false; RC rc = RCOK; incr_lr(); assert(ycsb_query->requests.size() == g_req_per_query); assert(phase == CALVIN_RW_ANALYSIS); for (uint32_t rid = 0; rid < ycsb_query->requests.size(); rid ++) { ycsb_request * req = ycsb_query->requests[rid]; uint64_t part_id = _wl->key_to_part( req->key ); DEBUG("LK Acquire (%ld,%ld) %d,%ld -> %ld\n",get_txn_id(),get_batch_id(),req->acctype,req->key,GET_NODE_ID(part_id)); if(GET_NODE_ID(part_id) != g_node_id) continue; INDEX * index = _wl->the_index; itemid_t * item; item = index_read(index, req->key, part_id); row_t * row = ((row_t *)item->location); RC rc2 = get_lock(row,req->acctype); if(rc2 != RCOK) { rc = rc2; } } if(decr_lr() == 0) { if(ATOM_CAS(lock_ready,false,true)) rc = RCOK; } txn_stats.wait_starttime = get_sys_clock(); /* if(rc == WAIT && lock_ready_cnt == 0) { if(ATOM_CAS(lock_ready,false,true)) //lock_ready = true; rc = RCOK; } */ INC_STATS(get_thd_id(),calvin_sched_time,get_sys_clock() - starttime); locking_done = true; return rc; }
RC TPCCTxnManager::send_remote_request() { assert(IS_LOCAL(get_txn_id())); TPCCQuery* tpcc_query = (TPCCQuery*) query; TPCCRemTxnType next_state = TPCC_FIN; uint64_t w_id = tpcc_query->w_id; uint64_t c_w_id = tpcc_query->c_w_id; uint64_t dest_node_id = UINT64_MAX; if(state == TPCC_PAYMENT0) { dest_node_id = GET_NODE_ID(wh_to_part(w_id)); next_state = TPCC_PAYMENT2; } else if(state == TPCC_PAYMENT4) { dest_node_id = GET_NODE_ID(wh_to_part(c_w_id)); next_state = TPCC_FIN; } else if(state == TPCC_NEWORDER0) { dest_node_id = GET_NODE_ID(wh_to_part(w_id)); next_state = TPCC_NEWORDER6; } else if(state == TPCC_NEWORDER8) { dest_node_id = GET_NODE_ID(wh_to_part(tpcc_query->items[next_item_id]->ol_supply_w_id)); /* while(GET_NODE_ID(wh_to_part(tpcc_query->items[next_item_id]->ol_supply_w_id)) != dest_node_id) { msg->items.add(tpcc_query->items[next_item_id++]); } */ if(is_done()) next_state = TPCC_FIN; else next_state = TPCC_NEWORDER6; } else { assert(false); } TPCCQueryMessage * msg = (TPCCQueryMessage*)Message::create_message(this,RQRY); msg->state = state; query->partitions_touched.add_unique(GET_PART_ID(0,dest_node_id)); msg_queue.enqueue(get_thd_id(),msg,dest_node_id); state = next_state; return WAIT_REM; }
// reset after abort void TxnManager::reset() { lock_ready = false; lock_ready_cnt = 0; locking_done = true; ready_part = 0; rsp_cnt = 0; aborted = false; return_id = UINT64_MAX; twopl_wait_start = 0; //ready = true; // MaaT greatest_write_timestamp = 0; greatest_read_timestamp = 0; commit_timestamp = 0; #if CC_ALG == MAAT uncommitted_writes->clear(); uncommitted_writes_y->clear(); uncommitted_reads->clear(); #endif #if CC_ALG == CALVIN phase = CALVIN_RW_ANALYSIS; locking_done = false; calvin_locked_rows.clear(); #endif assert(txn); assert(query); txn->reset(get_thd_id()); // Stats txn_stats.reset(); }
RC TxnManager::abort() { if(aborted) return Abort; DEBUG("Abort %ld\n",get_txn_id()); txn->rc = Abort; INC_STATS(get_thd_id(),total_txn_abort_cnt,1); txn_stats.abort_cnt++; if(IS_LOCAL(get_txn_id())) { INC_STATS(get_thd_id(), local_txn_abort_cnt, 1); } else { INC_STATS(get_thd_id(), remote_txn_abort_cnt, 1); txn_stats.abort_stats(get_thd_id()); } aborted = true; release_locks(Abort); #if CC_ALG == MAAT //assert(time_table.get_state(get_txn_id()) == MAAT_ABORTED); time_table.release(get_thd_id(),get_txn_id()); #endif uint64_t timespan = get_sys_clock() - txn_stats.restart_starttime; if (IS_LOCAL(get_txn_id()) && warmup_done) { INC_STATS_ARR(get_thd_id(),start_abort_commit_latency, timespan); } /* // latency from most recent start or restart of transaction PRINT_LATENCY("lat_s %ld %ld 0 %f %f %f %f %f %f 0.0\n" , get_txn_id() , txn_stats.work_queue_cnt , (double) timespan / BILLION , (double) txn_stats.work_queue_time / BILLION , (double) txn_stats.msg_queue_time / BILLION , (double) txn_stats.cc_block_time / BILLION , (double) txn_stats.cc_time / BILLION , (double) txn_stats.process_time / BILLION ); */ //commit_stats(); return Abort; }
RC ClientThread::run() { tsetup(); printf("Running ClientThread %ld\n",_thd_id); BaseQuery * m_query; uint64_t iters = 0; uint32_t num_txns_sent = 0; int txns_sent[g_servers_per_client]; for (uint32_t i = 0; i < g_servers_per_client; ++i) txns_sent[i] = 0; run_starttime = get_sys_clock(); while(!simulation->is_done()) { heartbeat(); #if SERVER_GENERATE_QUERIES break; #endif //uint32_t next_node = iters++ % g_node_cnt; progress_stats(); int32_t inf_cnt; uint32_t next_node = (((iters++) * g_client_thread_cnt) + _thd_id )% g_servers_per_client; uint32_t next_node_id = next_node + g_server_start_node; // Just in case... if (iters == UINT64_MAX) iters = 0; #if LOAD_METHOD == LOAD_MAX if ((inf_cnt = client_man.inc_inflight(next_node)) < 0) continue; m_query = client_query_queue.get_next_query(next_node,_thd_id); if(last_send_time > 0) { INC_STATS(get_thd_id(),cl_send_intv,get_sys_clock() - last_send_time); } last_send_time = get_sys_clock(); #elif LOAD_METHOD == LOAD_RATE if ((inf_cnt = client_man.inc_inflight(next_node)) < 0) continue; uint64_t gate_time; while((gate_time = get_sys_clock()) - last_send_time < send_interval) { } if(last_send_time > 0) { INC_STATS(get_thd_id(),cl_send_intv,gate_time - last_send_time); } last_send_time = gate_time; m_query = client_query_queue.get_next_query(next_node,_thd_id); #else assert(false); #endif assert(m_query); DEBUG("Client: thread %lu sending query to node: %u, %d, %f\n", _thd_id, next_node_id,inf_cnt,simulation->seconds_from_start(get_sys_clock())); Message * msg = Message::create_message((BaseQuery*)m_query,CL_QRY); ((ClientQueryMessage*)msg)->client_startts = get_sys_clock(); msg_queue.enqueue(get_thd_id(),msg,next_node_id); num_txns_sent++; txns_sent[next_node]++; INC_STATS(get_thd_id(),txn_sent_cnt,1); } for (uint64_t l = 0; l < g_servers_per_client; ++l) printf("Txns sent to node %lu: %d\n", l+g_server_start_node, txns_sent[l]); //SET_STATS(get_thd_id(), total_runtime, get_sys_clock() - simulation->run_starttime); printf("FINISH %ld:%ld\n",_node_id,_thd_id); fflush(stdout); return FINISH; }
RC TPCCTxnManager::acquire_locks() { uint64_t starttime = get_sys_clock(); assert(CC_ALG == CALVIN); locking_done = false; RC rc = RCOK; RC rc2; INDEX * index; itemid_t * item; row_t* row; uint64_t key; incr_lr(); TPCCQuery* tpcc_query = (TPCCQuery*) query; uint64_t w_id = tpcc_query->w_id; uint64_t d_id = tpcc_query->d_id; uint64_t c_id = tpcc_query->c_id; uint64_t d_w_id = tpcc_query->d_w_id; uint64_t c_w_id = tpcc_query->c_w_id; uint64_t c_d_id = tpcc_query->c_d_id; char * c_last = tpcc_query->c_last; uint64_t part_id_w = wh_to_part(w_id); uint64_t part_id_c_w = wh_to_part(c_w_id); switch(tpcc_query->txn_type) { case TPCC_PAYMENT: if(GET_NODE_ID(part_id_w) == g_node_id) { // WH index = _wl->i_warehouse; item = index_read(index, w_id, part_id_w); row_t * row = ((row_t *)item->location); rc2 = get_lock(row,g_wh_update? WR:RD); if(rc2 != RCOK) rc = rc2; // Dist key = distKey(d_id, d_w_id); item = index_read(_wl->i_district, key, part_id_w); row = ((row_t *)item->location); rc2 = get_lock(row, WR); if(rc2 != RCOK) rc = rc2; } if(GET_NODE_ID(part_id_c_w) == g_node_id) { // Cust if (tpcc_query->by_last_name) { key = custNPKey(c_last, c_d_id, c_w_id); index = _wl->i_customer_last; item = index_read(index, key, part_id_c_w); int cnt = 0; itemid_t * it = item; itemid_t * mid = item; while (it != NULL) { cnt ++; it = it->next; if (cnt % 2 == 0) mid = mid->next; } row = ((row_t *)mid->location); } else { key = custKey(c_id, c_d_id, c_w_id); index = _wl->i_customer_id; item = index_read(index, key, part_id_c_w); row = (row_t *) item->location; } rc2 = get_lock(row, WR); if(rc2 != RCOK) rc = rc2; } break; case TPCC_NEW_ORDER: if(GET_NODE_ID(part_id_w) == g_node_id) { // WH index = _wl->i_warehouse; item = index_read(index, w_id, part_id_w); row_t * row = ((row_t *)item->location); rc2 = get_lock(row,RD); if(rc2 != RCOK) rc = rc2; // Cust index = _wl->i_customer_id; key = custKey(c_id, d_id, w_id); item = index_read(index, key, wh_to_part(w_id)); row = (row_t *) item->location; rc2 = get_lock(row, RD); if(rc2 != RCOK) rc = rc2; // Dist key = distKey(d_id, w_id); item = index_read(_wl->i_district, key, wh_to_part(w_id)); row = ((row_t *)item->location); rc2 = get_lock(row, WR); if(rc2 != RCOK) rc = rc2; } // Items for(uint64_t i = 0; i < tpcc_query->ol_cnt; i++) { if(GET_NODE_ID(wh_to_part(tpcc_query->items[i]->ol_supply_w_id)) != g_node_id) continue; key = tpcc_query->items[i]->ol_i_id; item = index_read(_wl->i_item, key, 0); row = ((row_t *)item->location); rc2 = get_lock(row, RD); if(rc2 != RCOK) rc = rc2; key = stockKey(tpcc_query->items[i]->ol_i_id, tpcc_query->items[i]->ol_supply_w_id); index = _wl->i_stock; item = index_read(index, key, wh_to_part(tpcc_query->items[i]->ol_supply_w_id)); row = ((row_t *)item->location); rc2 = get_lock(row, WR); if(rc2 != RCOK) rc = rc2; } break; default: assert(false); } if(decr_lr() == 0) { if(ATOM_CAS(lock_ready,false,true)) rc = RCOK; } txn_stats.wait_starttime = get_sys_clock(); locking_done = true; INC_STATS(get_thd_id(),calvin_sched_time,get_sys_clock() - starttime); return rc; }
void TxnManager::commit_stats() { uint64_t commit_time = get_sys_clock(); uint64_t timespan_short = commit_time - txn_stats.restart_starttime; uint64_t timespan_long = commit_time - txn_stats.starttime; INC_STATS(get_thd_id(),total_txn_commit_cnt,1); if(!IS_LOCAL(get_txn_id()) && CC_ALG != CALVIN) { INC_STATS(get_thd_id(),remote_txn_commit_cnt,1); txn_stats.commit_stats(get_thd_id(),get_txn_id(),get_batch_id(), timespan_long, timespan_short); return; } INC_STATS(get_thd_id(),txn_cnt,1); INC_STATS(get_thd_id(),local_txn_commit_cnt,1); INC_STATS(get_thd_id(), txn_run_time, timespan_long); if(query->partitions_touched.size() > 1) { INC_STATS(get_thd_id(),multi_part_txn_cnt,1); INC_STATS(get_thd_id(),multi_part_txn_run_time,timespan_long); } else { INC_STATS(get_thd_id(),single_part_txn_cnt,1); INC_STATS(get_thd_id(),single_part_txn_run_time,timespan_long); } /*if(cflt) { INC_STATS(get_thd_id(),cflt_cnt_txn,1); }*/ txn_stats.commit_stats(get_thd_id(),get_txn_id(),get_batch_id(),timespan_long, timespan_short); #if CC_ALG == CALVIN return; #endif INC_STATS_ARR(get_thd_id(),start_abort_commit_latency, timespan_short); INC_STATS_ARR(get_thd_id(),last_start_commit_latency, timespan_short); INC_STATS_ARR(get_thd_id(),first_start_commit_latency, timespan_long); assert(query->partitions_touched.size() > 0); INC_STATS(get_thd_id(),parts_touched,query->partitions_touched.size()); INC_STATS(get_thd_id(),part_cnt[query->partitions_touched.size()-1],1); for(uint64_t i = 0 ; i < query->partitions_touched.size(); i++) { INC_STATS(get_thd_id(),part_acc[query->partitions_touched[i]],1); } }
void TxnManager::register_thread(Thread * h_thd) { this->h_thd = h_thd; #if CC_ALG == HSTORE || CC_ALG == HSTORE_SPEC this->active_part = GET_PART_ID_FROM_IDX(get_thd_id()); #endif }
RC tpcc_txn_man::run_payment(tpcc_query * query) { RC rc = RCOK; uint64_t key; itemid_t * item; uint64_t w_id = query->w_id; uint64_t d_id = query->d_id; uint64_t c_w_id = query->c_w_id; uint64_t c_d_id = query->c_d_id; uint64_t c_id = query->c_id; double h_amount = query->h_amount; row_t * r_cust; if (query->by_last_name) { /*==========================================================+ EXEC SQL SELECT count(c_id) INTO :namecnt FROM customer WHERE c_last=:c_last AND c_d_id=:c_d_id AND c_w_id=:c_w_id; +==========================================================*/ /*==========================================================================+ EXEC SQL DECLARE c_byname CURSOR FOR SELECT c_first, c_middle, c_id, c_street_1, c_street_2, c_city, c_state, c_zip, c_phone, c_credit, c_credit_lim, c_discount, c_balance, c_since FROM customer WHERE c_w_id=:c_w_id AND c_d_id=:c_d_id AND c_last=:c_last ORDER BY c_first; EXEC SQL OPEN c_byname; +===========================================================================*/ uint64_t key = custNPKey(query->c_last, query->c_d_id, query->c_w_id); // XXX: the list is not sorted. But let's assume it's sorted... // The performance won't be much different. INDEX * index = _wl->i_customer_last; item = index_read(index, key, wh_to_part(c_w_id)); assert(item != NULL); int cnt = 0; itemid_t * it = item; itemid_t * mid = item; while (it != NULL) { cnt ++; it = it->next; if (cnt % 2 == 0) mid = mid->next; } r_cust = ((row_t *)mid->location); /*============================================================================+ for (n=0; n<namecnt/2; n++) { EXEC SQL FETCH c_byname INTO :c_first, :c_middle, :c_id, :c_street_1, :c_street_2, :c_city, :c_state, :c_zip, :c_phone, :c_credit, :c_credit_lim, :c_discount, :c_balance, :c_since; } EXEC SQL CLOSE c_byname; +=============================================================================*/ // XXX: we don't retrieve all the info, just the tuple we are interested in } else { // search customers by cust_id /*=====================================================================+ EXEC SQL SELECT c_first, c_middle, c_last, c_street_1, c_street_2, c_city, c_state, c_zip, c_phone, c_credit, c_credit_lim, c_discount, c_balance, c_since INTO :c_first, :c_middle, :c_last, :c_street_1, :c_street_2, :c_city, :c_state, :c_zip, :c_phone, :c_credit, :c_credit_lim, :c_discount, :c_balance, :c_since FROM customer WHERE c_w_id=:c_w_id AND c_d_id=:c_d_id AND c_id=:c_id; +======================================================================*/ key = custKey(query->c_id, query->c_d_id, query->c_w_id); INDEX * index = _wl->i_customer_id; item = index_read(index, key, wh_to_part(c_w_id)); assert(item != NULL); // rc = index->index_read(key, item, wh_to_part(c_w_id)); // assert(rc == RCOK); r_cust = (row_t *) item->location; } /*======================================================================+ EXEC SQL UPDATE customer SET c_balance = :c_balance, c_data = :c_new_data WHERE c_w_id = :c_w_id AND c_d_id = :c_d_id AND c_id = :c_id; +======================================================================*/ row_t * r_cust_local = get_row(r_cust, WR); if (r_cust_local == NULL) { return finish(Abort); } double c_balance; double c_ytd_payment; double c_payment_cnt; r_cust_local->get_value(C_BALANCE, c_balance); r_cust_local->set_value(C_BALANCE, c_balance - query->h_amount); r_cust_local->get_value(C_YTD_PAYMENT, c_ytd_payment); r_cust_local->set_value(C_YTD_PAYMENT, c_ytd_payment + query->h_amount); r_cust_local->get_value(C_PAYMENT_CNT, c_payment_cnt); r_cust_local->set_value(C_PAYMENT_CNT, c_payment_cnt + 1); char * c_credit = r_cust_local->get_value(C_CREDIT); if ( strstr(c_credit, "BC") ) { /*=====================================================+ EXEC SQL SELECT c_data INTO :c_data FROM customer WHERE c_w_id=:c_w_id AND c_d_id=:c_d_id AND c_id=:c_id; +=====================================================*/ // char c_new_data[501]; // sprintf(c_new_data,"| %4d %2d %4d %2d %4d $%7.2f", // c_id, c_d_id, c_w_id, d_id, w_id, query->h_amount); // char * c_data = r_cust->get_value("C_DATA"); // strncat(c_new_data, c_data, 500 - strlen(c_new_data)); // r_cust->set_value("C_DATA", c_new_data); } /*=====================================================+ EXEC SQL UPDATE district SET d_ytd = d_ytd + :h_amount WHERE d_w_id=:w_id AND d_id=:d_id; +=====================================================*/ uint64_t t3 = get_sys_clock(); key = distKey(query->d_id, query->d_w_id); item = index_read(_wl->i_district, key, wh_to_part(w_id)); assert(item != NULL); // rc = _wl->i_district->index_read(key, item, wh_to_part(w_id)); // assert(rc == RCOK); row_t * r_dist = ((row_t *)item->location); row_t * r_dist_local = get_row(r_dist, WR); if (r_dist_local == NULL) { return finish(Abort); } uint64_t tt3 = get_sys_clock() - t3; INC_STATS(get_thd_id(), debug3, tt3); double d_ytd; r_dist_local->get_value(D_YTD, d_ytd); r_dist_local->set_value(D_YTD, d_ytd + query->h_amount); /*====================================================+ EXEC SQL UPDATE warehouse SET w_ytd = w_ytd + :h_amount WHERE w_id=:w_id; +====================================================*/ /*===================================================================+ EXEC SQL SELECT w_street_1, w_street_2, w_city, w_state, w_zip, w_name INTO :w_street_1, :w_street_2, :w_city, :w_state, :w_zip, :w_name FROM warehouse WHERE w_id=:w_id; +===================================================================*/ key = query->w_id; INDEX * index = _wl->i_warehouse; item = index_read(index, key, wh_to_part(w_id)); assert(item != NULL); // rc = index->index_read(key, item, wh_to_part(w_id)); // assert(rc == RCOK); row_t * r_wh = ((row_t *)item->location); row_t * r_wh_local; uint64_t t5 = get_sys_clock(); if (g_wh_update) r_wh_local = get_row(r_wh, WR); else r_wh_local = get_row(r_wh, RD); uint64_t tt5 = get_sys_clock() - t5; INC_STATS(get_thd_id(), debug5, tt5); if (r_wh_local == NULL) { return finish(Abort); } double w_ytd; uint64_t t1 = get_sys_clock(); r_wh_local->get_value(W_YTD, w_ytd); /*=============================================================================+ EXEC SQL INSERT INTO history (h_c_d_id, h_c_w_id, h_c_id, h_d_id, h_w_id, h_date, h_amount, h_data) VALUES (:c_d_id, :c_w_id, :c_id, :d_id, :w_id, :datetime, :h_amount, :h_data); +=============================================================================*/ row_t * r_hist; uint64_t row_id; _wl->t_history->get_new_row(r_hist, 0, row_id); r_hist->set_value(H_C_ID, c_id); r_hist->set_value(H_C_D_ID, c_d_id); r_hist->set_value(H_C_W_ID, c_w_id); r_hist->set_value(H_D_ID, d_id); r_hist->set_value(H_W_ID, w_id); int64_t date = 2013; r_hist->set_value(H_DATE, date); r_hist->set_value(H_AMOUNT, h_amount); insert_row(r_hist, _wl->t_history); if (g_wh_update) { r_wh_local->set_value(W_YTD, w_ytd + query->h_amount); } uint64_t tt1 = get_sys_clock() - t1; INC_STATS(get_thd_id(), debug1, tt1); assert( rc == RCOK ); return finish(rc); }
RC TxnManager::get_row(row_t * row, access_t type, row_t *& row_rtn) { uint64_t starttime = get_sys_clock(); uint64_t timespan; RC rc = RCOK; DEBUG_M("TxnManager::get_row access alloc\n"); Access * access; access_pool.get(get_thd_id(),access); //uint64_t row_cnt = txn->row_cnt; //assert(txn->accesses.get_count() - 1 == row_cnt); this->last_row = row; this->last_type = type; rc = row->get_row(type, this, access->data); if (rc == Abort || rc == WAIT) { row_rtn = NULL; DEBUG_M("TxnManager::get_row(abort) access free\n"); access_pool.put(get_thd_id(),access); timespan = get_sys_clock() - starttime; INC_STATS(get_thd_id(), txn_manager_time, timespan); INC_STATS(get_thd_id(), txn_conflict_cnt, 1); //cflt = true; #if DEBUG_TIMELINE printf("CONFLICT %ld %ld\n",get_txn_id(),get_sys_clock()); #endif return rc; } access->type = type; access->orig_row = row; #if ROLL_BACK && (CC_ALG == DL_DETECT || CC_ALG == NO_WAIT || CC_ALG == WAIT_DIE || CC_ALG == HSTORE || CC_ALG == HSTORE_SPEC) if (type == WR) { //printf("alloc 10 %ld\n",get_txn_id()); uint64_t part_id = row->get_part_id(); DEBUG_M("TxnManager::get_row row_t alloc\n") row_pool.get(get_thd_id(),access->orig_data); access->orig_data->init(row->get_table(), part_id, 0); access->orig_data->copy(row); assert(access->orig_data->get_schema() == row->get_schema()); // ARIES-style physiological logging #if LOGGING //LogRecord * record = logger.createRecord(LRT_UPDATE,L_UPDATE,get_txn_id(),part_id,row->get_table()->get_table_id(),row->get_primary_key()); LogRecord * record = logger.createRecord(get_txn_id(),L_UPDATE,row->get_table()->get_table_id(),row->get_primary_key()); if(g_repl_cnt > 0) { msg_queue.enqueue(get_thd_id(),Message::create_message(record,LOG_MSG),g_node_id + g_node_cnt + g_client_node_cnt); } logger.enqueueRecord(record); #endif } #endif ++txn->row_cnt; if (type == WR) ++txn->write_cnt; txn->accesses.add(access); timespan = get_sys_clock() - starttime; INC_STATS(get_thd_id(), txn_manager_time, timespan); row_rtn = access->data; if(CC_ALG == HSTORE || CC_ALG == HSTORE_SPEC || CC_ALG == CALVIN) assert(rc == RCOK); return rc; }