// 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; }