private void checkDrainCondition() { // Don't ever go backwards once the drain decision is made. if (m_mustDrain) { return; } // if we've got things to sequence, check to if we're blocked if (!m_replayEntries.isEmpty()) { ReplayEntry head = m_replayEntries.firstEntry().getValue(); if (!head.isReady()) { // if we're blocked, see if we have a sentinel or a fragment. // we know we have one or the other but not both. Neither // means we wouldn't exist, and both would make us ready. // if it's the sentinel, see if the MPI's command log is done if (head.hasSentinel() && m_mpiEOLReached) { m_mustDrain = true; } } } }
// Offer a new message. Return false if the offered message can be run immediately. public boolean offer(long inTxnId, TransactionInfoBaseMessage in) { ReplayEntry found = m_replayEntries.get(inTxnId); if (in instanceof Iv2EndOfLogMessage) { m_mpiEOLReached = true; return true; } if (in instanceof MultiPartitionParticipantMessage) { /* * DR sends multiple @LoadMultipartitionTable proc calls with the * same txnId, which is the snapshot txnId. For each partition, * there is a sentinel paired with the @LoadMultipartitionTable * call. Dedupe the sentinels the same way as we dedupe fragments, * so that there won't be sentinels end up in the sequencer where * matching fragments are deduped. */ if (inTxnId <= m_lastPolledFragmentTxnId) { return true; } if (found == null) { ReplayEntry newEntry = new ReplayEntry(); newEntry.m_sentinalTxnId = inTxnId; m_replayEntries.put(inTxnId, newEntry); } else { found.m_sentinalTxnId = inTxnId; assert (found.isReady()); } } else if (in instanceof FragmentTaskMessage) { // already sequenced if (inTxnId <= m_lastPolledFragmentTxnId) { return false; } FragmentTaskMessage ftm = (FragmentTaskMessage) in; if (found == null) { ReplayEntry newEntry = new ReplayEntry(); newEntry.m_firstFragment = ftm; m_replayEntries.put(inTxnId, newEntry); } else if (found.m_firstFragment == null) { found.m_firstFragment = ftm; assert (found.isReady()); } else { found.addFragmentMessage(ftm); } } else if (in instanceof CompleteTransactionMessage) { CompleteTransactionMessage ctm = (CompleteTransactionMessage) in; // already sequenced if (inTxnId <= m_lastPolledFragmentTxnId) { if (found != null && found.m_firstFragment != null) { found.markLastFragment(ctm); } return false; } if (found != null && found.m_firstFragment != null) { found.addCompletedMessage(ctm); } else { // Always expect to see the fragment first, but there are places in the protocol // where CompleteTransactionMessages may arrive for transactions that this site hasn't // done/won't do, e.g. txn restart, so just tell the caller that we can't do // anything with it and hope the right thing happens. return false; } } else { if (dedupe(inTxnId, in) != null) { // Ignore an already seen txn return true; } updateLastSeenTxnId(inTxnId, in); if (m_replayEntries.isEmpty() || !m_replayEntries.lastEntry().getValue().hasSentinel()) { // not-blocked work; rejected and not queued. return false; } else { // blocked work queues with the newest replayEntry m_replayEntries.lastEntry().getValue().addBlockedMessage(in); } } return true; }