use of org.apache.geode.internal.cache.locks.TXLockId in project geode by apache.
the class TXCommitMessage method memberDeparted.
public void memberDeparted(final InternalDistributedMember id, boolean crashed) {
if (!getSender().equals(id)) {
return;
}
this.dm.removeMembershipListener(this);
ThreadGroup group = LoggingThreadGroup.createThreadGroup("TXCommitMessage Threads", logger);
synchronized (this) {
if (isProcessing() || this.departureNoticed) {
if (logger.isDebugEnabled()) {
logger.debug("Member departed: Commit data is already being processed for lockid: {}", lockId);
}
return;
}
this.departureNoticed = true;
}
// determine if any one of them have received a CommitProcessMessage
if (this.farSiders != null && !this.farSiders.isEmpty()) {
if (logger.isDebugEnabled()) {
logger.debug("Member departed: {} sending query for CommitProcess message to other recipients.", id);
}
// Create a new thread, send the CommitProcessQuery, wait for a response and potentially
// process
Thread fellowFarSidersQuery = new Thread(group, "CommitProcessQuery Thread") {
// Should I use a thread pool?, Darrel suggests look in DM somewhere or introduce a zero
// sized thread pool
@Override
public void run() {
final TXCommitMessage mess = TXCommitMessage.this;
Object trackerKey = mess.getTrackerKey();
DistributedMember member = getMemberFromTrackerKey(trackerKey);
if (!mess.getSender().equals(member)) {
/*
* Do not send a CommitProcessQueryMessage when the sender of CommitMessage is not the
* member in the tracker key. (If this happens we are the redundant node for PR, and the
* primary just crashed).
*/
txTracker.removeMessage(mess);
return;
}
CommitProcessQueryReplyProcessor replProc = new CommitProcessQueryReplyProcessor(mess.dm, mess.farSiders);
CommitProcessQueryMessage query = new CommitProcessQueryMessage(mess.getTrackerKey(), replProc.getProcessorId());
query.setRecipients(mess.farSiders);
mess.dm.putOutgoing(query);
// Wait for any one positive response or all negative responses.
// (while() loop removed for bug 36983 - you can't loop on waitForReplies()
TXCommitMessage.this.dm.getCancelCriterion().checkCancelInProgress(null);
try {
replProc.waitForRepliesUninterruptibly();
} catch (ReplyException e) {
e.handleAsUnexpected();
}
if (replProc.receivedACommitProcessMessage()) {
if (logger.isDebugEnabled()) {
logger.debug("Transaction associated with lockID: {} from orign {} is processing due to a received \"commit process\" message", mess.lockId, id);
}
try {
// Set processor to zero to avoid the ack to the now departed origin
mess.processorId = 0;
mess.basicProcess();
} finally {
txTracker.processed(mess);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Transaction associated with lockID: {} from origin {} ignored. No other recipients received \"commit process\" message", mess.lockId, id);
}
txTracker.removeMessage(mess);
}
}
private DistributedMember getMemberFromTrackerKey(Object trackerKey) {
if (trackerKey instanceof TXId) {
TXId id1 = (TXId) trackerKey;
return id1.getMemberId();
} else if (trackerKey instanceof TXLockId) {
TXLockId id2 = (TXLockId) trackerKey;
return id2.getMemberId();
}
return null;
}
};
fellowFarSidersQuery.setDaemon(true);
fellowFarSidersQuery.start();
} else {
if (logger.isDebugEnabled()) {
logger.debug("Member departed: {}. Processing commit data.", getSender());
}
// Optimimal case where we are the only FarSider, assume we
// will never get the CommitProcess message, but it
// doesn't matter since we can commit anyway.
// Start a new thread to process the commit
Thread originDepartedCommit = new Thread(group, "Origin Departed Commit") {
@Override
public void run() {
final TXCommitMessage mess = TXCommitMessage.this;
try {
// Set processor to zero to avoid the ack to the now departed origin
mess.processorId = 0;
mess.basicProcess();
} finally {
txTracker.processed(mess);
}
}
};
originDepartedCommit.setDaemon(true);
originDepartedCommit.start();
}
}
use of org.apache.geode.internal.cache.locks.TXLockId in project geode by apache.
the class TXFarSideCMTracker method commitProcessReceived.
/**
* Answers fellow "Far Siders" question about an DACK transaction when the transaction originator
* died before it sent the CommitProcess message.
*/
public boolean commitProcessReceived(Object key, DM dm) {
// transaction messages
if (key instanceof TXLockId) {
TXLockId lk = (TXLockId) key;
waitForMemberToDepart(lk.getMemberId(), dm);
} else if (key instanceof TXId) {
TXId id = (TXId) key;
waitForMemberToDepart(id.getMemberId(), dm);
} else {
Assert.assertTrue(false, "TXTracker received an unknown key class: " + key.getClass());
}
final TXCommitMessage mess;
synchronized (this.txInProgress) {
mess = (TXCommitMessage) this.txInProgress.get(key);
if (null != mess && mess.isProcessing()) {
return true;
}
for (int i = this.txHistory.length - 1; i >= 0; --i) {
if (key.equals(this.txHistory[i])) {
return true;
}
}
}
if (mess != null) {
synchronized (mess) {
if (!mess.isProcessing()) {
// Prevent any potential future processing
// of this message
mess.setDontProcess();
return false;
} else {
return true;
}
}
}
return false;
}
Aggregations