docs: synchronized void repair(SiteTasker task, List<Long> masters, Map<Integer, Long> partitionMasters, boolean balanceSPI)
      {
          // We know that every Site assigned to the MPI (either the main writer or
          // any of the MP read pool) will only have one active transaction at a time,
          // and that we either have active reads or active writes, but never both.
          // Figure out which we're doing, and then poison all of the appropriate sites.
          Map<Long, TransactionTask> currentSet;
          boolean readonly = true;
          if (!m_currentReads.isEmpty()) {
              assert(m_currentWrites.isEmpty());
              if (tmLog.isDebugEnabled()) {
                  tmLog.debug("MpTTQ: repairing reads. MigratePartitionLeader:" + balanceSPI);
              }
              for (Long txnId : m_currentReads.keySet()) {
                  m_sitePool.repair(txnId, task);
              }
              currentSet = m_currentReads;
          }
          else {
              if (tmLog.isDebugEnabled()) {
                  tmLog.debug("MpTTQ: repairing writes. MigratePartitionLeader:" + balanceSPI);
              }
              m_taskQueue.offer(task);
              currentSet = m_currentWrites;
              readonly = false;
          }
          for (Entry<Long, TransactionTask> e : currentSet.entrySet()) {
              if (e.getValue() instanceof MpProcedureTask) {
                  MpProcedureTask next = (MpProcedureTask)e.getValue();
                  if (tmLog.isDebugEnabled()) {
                      tmLog.debug("MpTTQ: poisoning task: " + next.toShortString());
                  }
                  next.doRestart(masters, partitionMasters);
  
                  if (!balanceSPI) {
                      MpTransactionState txn = (MpTransactionState)next.getTransactionState();
                      // inject poison pill
                      FragmentTaskMessage dummy = new FragmentTaskMessage(0L, 0L, txn.txnId, txn.uniqueId,
                              false, false, false, txn.isNPartTxn(), txn.getTimetamp());
                      FragmentResponseMessage poison =
                              new FragmentResponseMessage(dummy, 0L); // Don't care about source HSID here
                      // Provide a TransactionRestartException which will be converted
                      // into a ClientResponse.RESTART, so that the MpProcedureTask can
                      // detect the restart and take the appropriate actions.
                      TransactionRestartException restart = new TransactionRestartException(
                              "Transaction being restarted due to fault recovery or shutdown.", next.getTxnId());
                      restart.setMisrouted(false);
                      poison.setStatus(FragmentResponseMessage.UNEXPECTED_ERROR, restart);
                      txn.offerReceivedFragmentResponse(poison);
                      if (tmLog.isDebugEnabled()) {
                          tmLog.debug("MpTTQ: restarting:" + next.toShortString());
                      }
                  }
              }
          }
          // Now, iterate through the backlog and update the partition masters
          // for all ProcedureTasks
          Iterator<TransactionTask> iter = m_backlog.iterator();
          while (iter.hasNext()) {
              TransactionTask tt = iter.next();
              if (tt instanceof MpProcedureTask) {
                  MpProcedureTask next = (MpProcedureTask)tt;
  
                  if (tmLog.isDebugEnabled()) {
                      tmLog.debug("Repair updating task: " + next.toShortString() + " with masters: " + CoreUtils.hsIdCollectionToString(masters));
                  }
                  next.updateMasters(masters, partitionMasters);
              }
              else if (tt instanceof EveryPartitionTask) {
                  EveryPartitionTask next = (EveryPartitionTask)tt;
                  if (tmLog.isDebugEnabled())  {
                      tmLog.debug("Repair updating EPT task: " + next + " with masters: " + CoreUtils.hsIdCollectionToString(masters));
                  }
                  next.updateMasters(masters);
              }
          }
      }