private void finishSynchronization(String liveID) throws Exception {
    for (JournalContent jc : EnumSet.allOf(JournalContent.class)) {
      Journal journal = journalsHolder.remove(jc);
      journal.synchronizationLock();
      try {
        // files should be already in place.
        filesReservedForSync.remove(jc);
        registerJournal(jc.typeByte, journal);
        journal.stop();
        journal.start();
        journal.loadSyncOnly(JournalState.SYNCING_UP_TO_DATE);
      } finally {
        journal.synchronizationUnlock();
      }
    }
    ByteBuffer buffer = ByteBuffer.allocate(4 * 1024);
    for (Entry<Long, ReplicatedLargeMessage> entry : largeMessages.entrySet()) {
      ReplicatedLargeMessage lm = entry.getValue();
      if (lm instanceof LargeServerMessageInSync) {
        LargeServerMessageInSync lmSync = (LargeServerMessageInSync) lm;
        lmSync.joinSyncedData(buffer);
      }
    }

    journalsHolder = null;
    backupQuorum.liveIDSet(liveID);
    activation.setRemoteBackupUpToDate();
    ActiveMQServerLogger.LOGGER.backupServerSynched(server);
    return;
  }
  /**
   * Reserves files (with the given fileID) in the specified journal, and places a {@link
   * FileWrapperJournal} in place to store messages while synchronization is going on.
   *
   * @param packet
   * @throws Exception
   * @return if the incoming packet indicates the synchronization is finished then return an
   *     acknowledgement otherwise return an empty response
   */
  private ReplicationResponseMessageV2 handleStartReplicationSynchronization(
      final ReplicationStartSyncMessage packet) throws Exception {
    ReplicationResponseMessageV2 replicationResponseMessage = new ReplicationResponseMessageV2();
    if (activation.isRemoteBackupUpToDate()) {
      throw ActiveMQMessageBundle.BUNDLE.replicationBackupUpToDate();
    }

    synchronized (this) {
      if (!started) return replicationResponseMessage;

      if (packet.isSynchronizationFinished()) {
        finishSynchronization(packet.getNodeID());
        replicationResponseMessage.setSynchronizationIsFinishedAcknowledgement(true);
        return replicationResponseMessage;
      }

      switch (packet.getDataType()) {
        case LargeMessages:
          for (long msgID : packet.getFileIds()) {
            createLargeMessage(msgID, true);
          }
          break;
        case JournalBindings:
        case JournalMessages:
          if (wantedFailBack && !packet.isServerToFailBack()) {
            ActiveMQServerLogger.LOGGER.autoFailBackDenied();
          }

          final JournalContent journalContent =
              SyncDataType.getJournalContentType(packet.getDataType());
          final Journal journal = journalsHolder.get(journalContent);

          if (packet.getNodeID() != null) {
            // At the start of replication, we still do not know which is the nodeID that the live
            // uses.
            // This is the point where the backup gets this information.
            backupQuorum.liveIDSet(packet.getNodeID());
          }
          Map<Long, JournalSyncFile> mapToFill = filesReservedForSync.get(journalContent);

          for (Entry<Long, JournalFile> entry :
              journal.createFilesForBackupSync(packet.getFileIds()).entrySet()) {
            mapToFill.put(entry.getKey(), new JournalSyncFile(entry.getValue()));
          }
          FileWrapperJournal syncJournal = new FileWrapperJournal(journal);
          registerJournal(journalContent.typeByte, syncJournal);
          break;
        default:
          throw ActiveMQMessageBundle.BUNDLE.replicationUnhandledDataType();
      }
    }

    return replicationResponseMessage;
  }