Esempio n. 1
0
void Row_mvcc::update_buffer(TxnManager * txn) {
	MVReqEntry * ready_read = debuffer_req(R_REQ, NULL);
	MVReqEntry * req = ready_read;
	MVReqEntry * tofree = NULL;

	while (req != NULL) {
		// find the version for the request
		MVHisEntry * whis = writehis;
		while (whis != NULL && whis->ts > req->ts) 
			whis = whis->next;
		row_t * row = (whis == NULL)? 
			_row : whis->row;
		req->txn->cur_row = row;
		insert_history(req->ts, NULL);
		assert(row->get_data() != NULL);
		assert(row->get_table() != NULL);
		assert(row->get_schema() == _row->get_schema());

		req->txn->ts_ready = true;
		uint64_t timespan = get_sys_clock() - req->starttime;
		req->txn->txn_stats.cc_block_time += timespan;
		req->txn->txn_stats.cc_block_time_short += timespan;
    txn_table.restart_txn(txn->get_thd_id(),req->txn->get_txn_id(),0);
		tofree = req;
		req = req->next;
		// free ready_read
		return_req_entry(tofree);
	}
}
Esempio n. 2
0
RC Row_ts::access(txn_man * txn, TsType type, row_t * row) {
	RC rc;
	ts_t ts = txn->get_ts();
	if (g_central_man)
		glob_manager.lock_row(_row);
	else
		pthread_mutex_lock( latch );
	if (type == R_REQ) {
		if (ts < wts) {
			rc = Abort;
		} else if (ts > min_pts) {
			// insert the req into the read request queue
			buffer_req(R_REQ, txn, NULL);
			txn->ts_ready = false;
			rc = WAIT;
		} else {
			// return the value.
			txn->cur_row->copy(_row);
			if (rts < ts)
				rts = ts;
			rc = RCOK;
		}
	} else if (type == P_REQ) {
		if (ts < rts) {
			rc = Abort;
		} else {
#if TS_TWR
			buffer_req(P_REQ, txn, NULL);
			rc = RCOK;
#else 
			if (ts < wts) {
				rc = Abort;
			} else {
				buffer_req(P_REQ, txn, NULL);
				rc = RCOK;
			}
#endif
		}
	} else if (type == W_REQ) {
		// write requests are always accepted.
		rc = RCOK;
#if TS_TWR
		// according to TWR, this write is already stale, ignore. 
		if (ts < wts) {
			TsReqEntry * req = debuffer_req(P_REQ, txn);
			assert(req != NULL);
			update_buffer();
			return_req_entry(req);
			row->free_row();
			mem_allocator.free(row, sizeof(row_t));
			goto final;
		}
Esempio n. 3
0
TsReqEntry * Row_ts::debuffer_req(TsType type, ts_t ts) {
	return debuffer_req(type, NULL, ts);
}
Esempio n. 4
0
TsReqEntry * Row_ts::debuffer_req(TsType type, txn_man * txn) {
	return debuffer_req(type, txn, UINT64_MAX);
}
Esempio n. 5
0
RC Row_mvcc::access(TxnManager * txn, TsType type, row_t * row) {
	RC rc = RCOK;
	ts_t ts = txn->get_timestamp();
	uint64_t starttime = get_sys_clock();

	if (g_central_man)
		glob_manager.lock_row(_row);
	else
		pthread_mutex_lock( latch );
  if (type == R_REQ) {
		// figure out if ts is in interval(prewrite(x))
		bool conf = conflict(type, ts);
		if ( conf && rreq_len < g_max_read_req) {
			rc = WAIT;
      //txn->wait_starttime = get_sys_clock();
        DEBUG("buf R_REQ %ld %ld\n",txn->get_txn_id(),_row->get_primary_key());
			buffer_req(R_REQ, txn);
			txn->ts_ready = false;
		} else if (conf) { 
			rc = Abort;
			printf("\nshould never happen. rreq_len=%ld", rreq_len);
		} else {
			// return results immediately.
			rc = RCOK;
			MVHisEntry * whis = writehis;
			while (whis != NULL && whis->ts > ts) 
				whis = whis->next;
			row_t * ret = (whis == NULL)? 
				_row : whis->row;
			txn->cur_row = ret;
			insert_history(ts, NULL);
			assert(strstr(_row->get_table_name(), ret->get_table_name()));
		}
	} else if (type == P_REQ) {
		if ( conflict(type, ts) ) {
			rc = Abort;
		} else if (preq_len < g_max_pre_req){
        DEBUG("buf P_REQ %ld %ld\n",txn->get_txn_id(),_row->get_primary_key());
			buffer_req(P_REQ, txn);
			rc = RCOK;
		} else  {
			rc = Abort;
		}
	} else if (type == W_REQ) {
		rc = RCOK;
		// the corresponding prewrite request is debuffered.
		insert_history(ts, row);
        DEBUG("debuf %ld %ld\n",txn->get_txn_id(),_row->get_primary_key());
		MVReqEntry * req = debuffer_req(P_REQ, txn);
		assert(req != NULL);
		return_req_entry(req);
		update_buffer(txn);
	} else if (type == XP_REQ) {
        DEBUG("debuf %ld %ld\n",txn->get_txn_id(),_row->get_primary_key());
		MVReqEntry * req = debuffer_req(P_REQ, txn);
		assert (req != NULL);
		return_req_entry(req);
		update_buffer(txn);
	} else 
		assert(false);
	
	if (rc == RCOK) {
		if (whis_len > g_his_recycle_len || rhis_len > g_his_recycle_len) {
			ts_t t_th = glob_manager.get_min_ts(txn->get_thd_id());
			if (readhistail && readhistail->ts < t_th)
				clear_history(R_REQ, t_th);
			// Here is a tricky bug. The oldest transaction might be 
			// reading an even older version whose timestamp < t_th.
			// But we cannot recycle that version because it is still being used.
			// So the HACK here is to make sure that the first version older than
			// t_th not be recycled.
			if (whis_len > 1 && 
				writehistail->prev->ts < t_th) {
				row_t * latest_row = clear_history(W_REQ, t_th);
				if (latest_row != NULL) {
					assert(_row != latest_row);
					_row->copy(latest_row);
				}
			}
		}
	}
	
	uint64_t timespan = get_sys_clock() - starttime;
	txn->txn_stats.cc_time += timespan;
	txn->txn_stats.cc_time_short += timespan;

	if (g_central_man)
		glob_manager.release_row(_row);
	else
		pthread_mutex_unlock( latch );	
		
	return rc;
}