// This is going to run in the BabySitter's thread. This and deliver are synchronized by // virtue of both being called on InitiatorMailbox and not directly called. // (That is, InitiatorMailbox's API, used by BabySitter, is synchronized on the same // lock deliver() is synchronized on.) @Override public void updateReplicas(List<Long> replicas) { // First - correct the official replica set. m_replicaHSIds = replicas; // Update the list of remote replicas that we'll need to send to List<Long> sendToHSIds = new ArrayList<Long>(m_replicaHSIds); sendToHSIds.remove(m_mailbox.getHSId()); m_sendToHSIds = Longs.toArray(sendToHSIds); // Cleanup duplicate counters and collect DONE counters // in this list for further processing. List<DuplicateCounterKey> doneCounters = new LinkedList<DuplicateCounterKey>(); for (Entry<DuplicateCounterKey, DuplicateCounter> entry : m_duplicateCounters.entrySet()) { DuplicateCounter counter = entry.getValue(); int result = counter.updateReplicas(m_replicaHSIds); if (result == DuplicateCounter.DONE) { doneCounters.add(entry.getKey()); } } // Maintain the CI invariant that responses arrive in txnid order. Collections.sort(doneCounters); for (DuplicateCounterKey key : doneCounters) { DuplicateCounter counter = m_duplicateCounters.remove(key); VoltMessage resp = counter.getLastResponse(); if (resp != null) { // MPI is tracking deps per partition HSID. We need to make // sure we write ours into the message getting sent to the MPI if (resp instanceof FragmentResponseMessage) { FragmentResponseMessage fresp = (FragmentResponseMessage) resp; fresp.setExecutorSiteId(m_mailbox.getHSId()); } m_mailbox.send(counter.m_destinationId, resp); } else { hostLog.warn( "TXN " + counter.getTxnId() + " lost all replicas and " + "had no responses. This should be impossible?"); } } writeIv2ViableReplayEntry(); }
// Eventually, the master for a partition set will need to be able to dedupe // FragmentResponses from its replicas. public void handleFragmentResponseMessage(FragmentResponseMessage message) { // Send the message to the duplicate counter, if any DuplicateCounter counter = m_duplicateCounters.get(new DuplicateCounterKey(message.getTxnId(), message.getSpHandle())); if (counter != null) { int result = counter.offer(message); if (result == DuplicateCounter.DONE) { m_duplicateCounters.remove( new DuplicateCounterKey(message.getTxnId(), message.getSpHandle())); m_repairLogTruncationHandle = message.getSpHandle(); FragmentResponseMessage resp = (FragmentResponseMessage) counter.getLastResponse(); // MPI is tracking deps per partition HSID. We need to make // sure we write ours into the message getting sent to the MPI resp.setExecutorSiteId(m_mailbox.getHSId()); m_mailbox.send(counter.m_destinationId, resp); } else if (result == DuplicateCounter.MISMATCH) { VoltDB.crashLocalVoltDB("HASH MISMATCH running multi-part procedure.", true, null); } // doing duplicate suppresion: all done. return; } m_mailbox.send(message.getDestinationSiteId(), message); }