Exemple #1
0
void ResourceNode::wakeAndDetach()
{
	TransactionNode *txn;
	set<RGNode *>::iterator sit;
	set<RGNode *>::iterator dummy_sit;

	for (sit = in.begin(); sit != in.end(); ) {
		txn = dynamic_cast<TransactionNode *>(*sit);
		txn->wake();
		dummy_sit = ++sit;
		removeInEdge(txn);
		sit = dummy_sit;
	}
	in.clear();
}
LBIDResourceGraph::~LBIDResourceGraph()
{
	std::map<VER_t, TransactionNode *>::iterator tnit;
	RNodes_t::iterator rit;
	TransactionNode *txnNode;

	for (tnit = txns.begin(); tnit != txns.end(); ) {
		txnNode = (*tnit).second;
		if (txnNode->sleeping()) {
			txnNode->die();
			txnNode->wake();
			++tnit;
		}
		else {
			txns.erase(tnit++);
			delete txnNode;
		}	
	}
	
	for (rit = resources.begin(); rit != resources.end(); ) {
		delete *rit;
		resources.erase(rit++);
	}
}
void LBIDResourceGraph::releaseResources(VER_t txn)
{
	/*
		get transaction node
		get all inbound nodes
			detach them and wake all txns on the in-edges
			delete the resource nodes
		get all outbound nodes (this can happen if a rollback comes in while blocked)
			detach them
		if txnNode isn't sleeping,
			delete the transaction node
		else 
			mark it dead and wake it
	*/

	TransactionNode *txnNode;
	ResourceNode *rNode;
	map<VER_t, TransactionNode *>::iterator it;
	set<RGNode *>::iterator sit;
	set<RGNode *>::iterator dummy_sit;

	it = txns.find(txn);
	if (it == txns.end())
		return;

	txnNode = (*it).second;
	for (sit = txnNode->in.begin(); sit != txnNode->in.end(); ) {
		rNode = dynamic_cast<ResourceNode *>(*sit);
                dummy_sit = ++sit;
		rNode->wakeAndDetach();
		txnNode->removeInEdge(rNode);
		resources.erase(rNode);
		delete rNode;
                sit = dummy_sit;
	}
	for (sit = txnNode->out.begin(); sit != txnNode->out.end(); )
        {
		rNode = dynamic_cast<ResourceNode *>(*sit);
                dummy_sit = ++sit;
		txnNode->removeOutEdge(rNode);
                sit = dummy_sit;
        }

	if (txnNode->sleeping()) {
		txnNode->die();
		txnNode->wake();
	}
	else {
		txns.erase(txn);
		delete txnNode;
	}
}
/* 
	0 = OK
   	1 = transaction node was not found on wake
	-1 = deadlock detected, transaction node destroyed and resources released

	mutex should be slavelock
*/
int LBIDResourceGraph::reserveRange(LBID_t start, LBID_t end, VER_t txn,
	boost::mutex &mutex)
{
	TransactionNode *txnNode;
	map<VER_t, TransactionNode *>::iterator it;

	/* 	
		look for existing transaction node T
			- make one if necessary
		connectResources();
		checkDeadlock();
		while (txnNode.out.size() > 0)
			block on T's condvar
			connectResources();
			checkDeadlock();
		}
	*/

	it = txns.find(txn);
	if (it == txns.end()) {
		txnNode = new TransactionNode(txn);
		txns[txn] = txnNode;
	}
	else
		txnNode = (*it).second;

	connectResources(start, end, txnNode);

	// "If txnNode is waiting on at least one LBID range..."
	while (txnNode->out.size() > 0) {
		// make sure there's no deadlock before blocking
		if (checkDeadlock(*txnNode)) {
// 			releaseResources(txn);
			return ERR_DEADLOCK;
		}
#ifdef BRM_VERBOSE
		cerr << " RG: sleeping transaction " << txn << endl;

		set<RGNode *>::iterator sit;
		cerr << " waiting on: " << endl;
		for (sit = txnNode->out.begin(); sit != txnNode->out.end(); sit++) {
			ResourceNode *rn = dynamic_cast<ResourceNode *>(*sit);
			cerr << hex << rn << dec << " " << rn->lbid() << endl;
		}
#endif

		txnNode->sleep(mutex);
#ifdef BRM_VERBOSE
		cerr << " RG: txn " << txn << " is awake" << endl;
#endif
		if (txnNode->dead()) {
			txns.erase(txn);
			delete txnNode;
			return ERR_KILLED;
		}	

		// attempt to grab remaining resources
		connectResources(start, end, txnNode);
	}

	// txn has all requested LBID ranges
	return ERR_OK;
}