} else if (message instanceof LocalObjectMessage) {
LocalObjectMessage lom = (LocalObjectMessage)message;
if (lom.payload instanceof Runnable) {
((Runnable)lom.payload).run();
} else if (lom.payload instanceof Request) {
Request r = (Request)lom.payload;
long txnId = 0;
boolean isRead = false;
switch(r.type) {
case OpCode.createSession:
txnId = r.sessionId;
break;
//For reads see if we can skip global agreement and just do the read
case OpCode.exists:
case OpCode.getChildren:
case OpCode.getChildren2:
case OpCode.getData:
//If there are writes they can go in the queue (and some reads), don't short circuit
//in this case because ordering of reads and writes matters
if (m_txnQueue.isEmpty()) {
r.setOwner(m_hsId);
m_server.prepRequest(new Request(r), m_lastUsedTxnId);
return;
}
isRead = true;
//Fall through is intentional, going with the default of putting
//it in the global order
default:
txnId = m_idManager.getNextUniqueTransactionId();
break;
}
/*
* Don't send the whole request if this is a read blocked on a write
* We may send a heartbeat instead of propagating a useless read transaction
* at the end of this block
*/
if (!isRead) {
for (long initiatorHSId : m_hsIds) {
if (initiatorHSId == m_hsId) continue;
AgreementTaskMessage atm =
new AgreementTaskMessage(
r,
txnId,
m_hsId,
m_safetyState.getNewestGloballySafeTxnId());
m_mailbox.send( initiatorHSId, atm);
}
}
//Process the ATM eagerly locally to aid
//in having a complete set of stuff to ship
//to a recovering agreement site
AgreementTaskMessage atm =
new AgreementTaskMessage(
new Request(r),
txnId,
m_hsId,
m_safetyState.getNewestGloballySafeTxnId());
atm.m_sourceHSId = m_hsId;
processMessage(atm);