/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */

package com.sleepycat.je.rep.impl.networkRestore;

import static com.sleepycat.je.rep.impl.networkRestore.NetworkBackupStatDefinition.BACKUP_FILE_COUNT;
import static com.sleepycat.je.rep.impl.networkRestore.NetworkBackupStatDefinition.DISPOSED_COUNT;
import static com.sleepycat.je.rep.impl.networkRestore.NetworkBackupStatDefinition.EXPECTED_BYTES;
import static com.sleepycat.je.rep.impl.networkRestore.NetworkBackupStatDefinition.FETCH_COUNT;
import static com.sleepycat.je.rep.impl.networkRestore.NetworkBackupStatDefinition.SKIP_COUNT;
import static com.sleepycat.je.rep.impl.networkRestore.NetworkBackupStatDefinition.TRANSFERRED_BYTES;
import static com.sleepycat.je.rep.impl.networkRestore.NetworkBackupStatDefinition.TRANSFER_RATE;
import static java.util.concurrent.TimeUnit.MINUTES;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.EnvironmentFailureException;
import com.sleepycat.je.log.FileManager;
import com.sleepycat.je.log.LogManager;
import com.sleepycat.je.log.RestoreMarker;
import com.sleepycat.je.log.entry.RestoreRequired;
import com.sleepycat.je.rep.impl.RepImpl;
import com.sleepycat.je.rep.impl.networkRestore.Protocol.FeederInfoResp;
import com.sleepycat.je.rep.impl.networkRestore.Protocol.FileEnd;
import com.sleepycat.je.rep.impl.networkRestore.Protocol.FileInfoResp;
import com.sleepycat.je.rep.impl.networkRestore.Protocol.FileListResp;
import com.sleepycat.je.rep.impl.networkRestore.Protocol.FileStart;
import com.sleepycat.je.rep.impl.node.NameIdPair;
import com.sleepycat.je.rep.net.DataChannel;
import com.sleepycat.je.rep.net.DataChannelFactory;
import com.sleepycat.je.rep.net.DataChannelFactory.ConnectOptions;
import com.sleepycat.je.rep.utilint.BinaryProtocol.ProtocolException;
import com.sleepycat.je.rep.utilint.BinaryProtocol.ServerVersion;
import com.sleepycat.je.rep.utilint.ServiceDispatcher;
import com.sleepycat.je.rep.utilint.ServiceDispatcher.ServiceConnectFailedException;
import com.sleepycat.je.utilint.AtomicIntStat;
import com.sleepycat.je.utilint.AtomicLongStat;
import com.sleepycat.je.utilint.LoggerUtils;
import com.sleepycat.je.utilint.LongAvgRateStat;
import com.sleepycat.je.utilint.StatGroup;
import com.sleepycat.je.utilint.TestHook;
import com.sleepycat.je.utilint.TestHookExecute;
import com.sleepycat.je.utilint.VLSN;

/**
 * This class implements a hot network backup that permits it to obtain a
 * consistent set of log files from any running environment that provides a
 * LogFileFeeder service. This class thus plays the role of a client, and the
 * running environment that of a server.
 * <p>
 * The log files that are retrieved over the network are placed in a directory
 * that can serve as an environment directory for a JE stand alone or HA
 * environment. If log files are already present in the target directory, it
 * will try reuse them, if they are really consistent with those on the server.
 * Extant log files that are no longer part of the current backup file set are
 * deleted or are renamed, depending on how the backup operation was
 * configured.
 * <p>
 * Renamed backup files have the following syntax:
 *
 * NNNNNNNN.bup.<i>backup number</i>
 *
 * where the backup number is the number associated with the backup attempt,
 * rather than with an individual file. That is, the backup number is increased
 * by one each time a backup is repeated in the same directory and log files
 * actually needed to be renamed.
 * <p>
 * The implementation tries to be resilient in the face of network failures and
 * minimizes the amount of work that might need to be done if the client or
 * server were to fail and had to be restarted. Users of this API must be
 * careful to ensure that the execute() completes successfully before accessing
 * the environment. The user fails to do this, the InsufficientLogException
 * will be thrown again when the user attempts to open the environment. This
 * safeguard is implemented using the {@link RestoreMarker} mechanism.
 */
public class NetworkBackup {
    /* The server that was chosen to supply the log files. */
    private final InetSocketAddress serverAddress;

    /* The environment directory into which the log files will be backed up */
    private final File envDir;

    /* The id used during logging to identify a node. */
    private final NameIdPair clientNameId;

    /*
     * Determines whether any existing log files in the envDir should be
     * retained under a different name (with a BUP_SUFFIX), or whether it
     * should be deleted.
     */
    private final boolean retainLogfiles;

    /*
     * The minimal VLSN that the backup must cover. Used to ensure that the
     * backup is sufficient to permit replay of a replication stream from a
     * feeder. It's NULL_VLSN if the VLSN does not matter, that is, it's a
     * backup for a standalone environment.
     */
    private final VLSN minVLSN;

    /*
     * The client abandons a backup attempt if the server is loaded beyond this
     * threshold
     */
    private final int serverLoadThreshold;

    /* The RepImpl instance used in Protocol; it may be null during tests */
    private final RepImpl repImpl;

    private final FileManager fileManager;

    /* The factory for creating new channels */
    private final DataChannelFactory channelFactory;

    /* The protocol used to communicate with the server. */
    private Protocol protocol;

    /* The channel connecting this client to the server. */
    private DataChannel channel;

    /*
     * The message digest used to compute the digest as each log file is pulled
     * over the network.
     */
    private final MessageDigest messageDigest;

    /* Statistics on number of files actually fetched and skipped */
    private final StatGroup statistics;
    private final AtomicIntStat backupFileCount;
    private final AtomicIntStat disposedCount;
    private final AtomicIntStat fetchCount;
    private final AtomicIntStat skipCount;
    private final AtomicLongStat expectedBytes;
    private final AtomicLongStat transferredBytes;
    private final LongAvgRateStat transferRate;

    private final Logger logger;

    private CyclicBarrier testBarrier = null;

    /**
     * The receive buffer size associated with the socket used for the log file
     * transfers
     */
    private final int receiveBufferSize;

    /**
     * Time to wait for a request from the client.
     */
    private static final int SOCKET_TIMEOUT_MS = 10000;

    /**
     * The number of times to retry on a digest exception. That is, when the
     * SHA1 hash as computed by the server for the file does not match the hash
     * as computed by the client for the same file.
     */
    private static final int DIGEST_RETRIES = 5;

    /*
     * Save the properties from the instigating InsufficientLogException in
     * order to persist the exception into a RestoreRequired entry.
     */
    private final Properties exceptionProperties;

    /*
     * Be prepared to create a marker file saying that the log can't be
     * recovered.
     */
    private final RestoreMarker restoreMarker;

    /* For testing */
    private TestHook<File> interruptHook;

    /**
     * Creates a configured backup instance which when executed will backup the
     * files to the environment directory.
     *
     * @param serverSocket the socket on which to contact the server
     * @param receiveBufferSize the receive buffer size to be associated with
     * the socket used for the log file transfers.
     * @param envDir the directory in which to place the log files
     * @param clientNameId the id used to identify this client
     * @param retainLogfiles determines whether obsolete log files should be
     * retained by renaming them, instead of deleting them.
     * @param serverLoadThreshold only backup from this server if it has fewer
     * than this number of feeders active.
     * @param repImpl is passed in as a distinct field from the log manager and
     * file manager because it is used only for logging and environment
     * invalidation. A network backup may be invoked by unit tests without
     * an enclosing environment.
     * @param minVLSN the VLSN that should be covered by the server. It ensures
     * that the log files are sufficiently current for this client's needs.
     * @throws IllegalArgumentException if the environment directory is not
     * valid. When used internally, this should be caught appropriately.
     */
    public NetworkBackup(InetSocketAddress serverSocket,
                         int receiveBufferSize,
                         File envDir,
                         NameIdPair clientNameId,
                         boolean retainLogfiles,
                         int serverLoadThreshold,
                         VLSN minVLSN,
                         RepImpl repImpl,
                         FileManager fileManager,
                         LogManager logManager,
                         DataChannelFactory channelFactory,
                         Properties exceptionProperties)
        throws IllegalArgumentException {

        super();
        this.serverAddress = serverSocket;
        this.receiveBufferSize = receiveBufferSize;

        if (!envDir.exists()) {
            throw new IllegalArgumentException("Environment directory: " +
                                               envDir + " not found");
        }
        this.envDir = envDir;
        this.clientNameId = clientNameId;
        this.retainLogfiles = retainLogfiles;
        this.serverLoadThreshold = serverLoadThreshold;
        this.minVLSN = minVLSN;
        this.repImpl = repImpl;
        this.fileManager = fileManager;
        this.channelFactory = channelFactory;

        try {
            messageDigest = MessageDigest.getInstance("SHA1");
        } catch (NoSuchAlgorithmException e) {
            // Should not happen -- if it does it's a JDK config issue
            throw EnvironmentFailureException.unexpectedException(e);
        }

        logger = LoggerUtils.getLoggerFixedPrefix(getClass(),
                                                  clientNameId.toString(),
                                                  repImpl);
        statistics = new StatGroup(NetworkBackupStatDefinition.GROUP_NAME,
                                   NetworkBackupStatDefinition.GROUP_DESC);
        backupFileCount = new AtomicIntStat(statistics, BACKUP_FILE_COUNT);
        disposedCount = new AtomicIntStat(statistics, DISPOSED_COUNT);
        fetchCount = new AtomicIntStat(statistics, FETCH_COUNT);
        skipCount = new AtomicIntStat(statistics, SKIP_COUNT);
        expectedBytes = new AtomicLongStat(statistics, EXPECTED_BYTES);
        transferredBytes = new AtomicLongStat(
            statistics, TRANSFERRED_BYTES);
        transferRate = new LongAvgRateStat(
            statistics, TRANSFER_RATE, 10000, MINUTES);

        this.exceptionProperties = exceptionProperties;
        restoreMarker = new RestoreMarker(fileManager, logManager);
    }

    /**
     * Convenience overloading.
     *
     * @see NetworkBackup(InetSocketAddress, int, File, NameIdPair, boolean,
     * int, VLSN, RepImpl, FileManager, LogManager, DataChannelFactory,
     * Properties)
     */
    public NetworkBackup(InetSocketAddress serverSocket,
                         File envDir,
                         NameIdPair clientNameId,
                         boolean retainLogfiles,
                         FileManager fileManager,
                         LogManager logManager,
                         DataChannelFactory channelFactory)
        throws DatabaseException {

        this(serverSocket,
             0,
             envDir,
             clientNameId,
             retainLogfiles,
             Integer.MAX_VALUE,
             VLSN.NULL_VLSN,
             null,
             fileManager,
             logManager,
             channelFactory,
             new Properties());
    }

    /**
     * Returns statistics associated with the NetworkBackup execution.
     */
    public NetworkBackupStats getStats() {
        return new NetworkBackupStats(statistics.cloneGroup(false));
    }

    /**
     * Execute the backup.
     *
     * @throws ServiceConnectFailedException
     * @throws LoadThresholdExceededException
     * @throws InsufficientVLSNRangeException
     */
    public String[] execute()
        throws IOException,
               DatabaseException,
               ServiceConnectFailedException,
               LoadThresholdExceededException,
               InsufficientVLSNRangeException,
               RestoreMarker.FileCreationException {

         try {
            channel = channelFactory.
                connect(serverAddress,
                        (repImpl != null) ? repImpl.getHostAddress() : null,
                        new ConnectOptions().
                        setTcpNoDelay(true).
                        setReceiveBufferSize(receiveBufferSize).
                        setOpenTimeout(SOCKET_TIMEOUT_MS).
                        setReadTimeout(SOCKET_TIMEOUT_MS));
            ServiceDispatcher.doServiceHandshake
                (channel, FeederManager.FEEDER_SERVICE);

            protocol = checkProtocol(new Protocol(clientNameId,
                                                  Protocol.VERSION,
                                                  repImpl));
            checkServer();
            final String[] fileNames = getFileList();

            LoggerUtils.info(logger, repImpl,
                "Restoring from:" + serverAddress +
                " Allocated network receive buffer size:" +
                channel.socket().getReceiveBufferSize() +
                "(" + receiveBufferSize + ")" +
                " candidate log file count:" + fileNames.length);

            getFiles(fileNames);
            cleanup(fileNames);
            assert fileManager.listJDBFiles().length == fileNames.length :
                "envDir=" + envDir + " list=" +
                Arrays.asList(fileManager.listJDBFiles()) +
                " fileNames=" + Arrays.asList(fileNames);

            /*
             * The fileNames array is sorted in getFileList method, so we can
             * use the first and last array elements to get the range of the
             * files to be restored.
             */
            final long fileBegin = fileManager.getNumFromName(fileNames[0]);
            final long fileEnd =
                fileManager.getNumFromName(fileNames[fileNames.length - 1]);
            /* Return file names with sub directories' names if exists. */
            return fileManager.listFileNames(fileBegin, fileEnd);
        } finally {
            if (channel != null) {
                /*
                 * Closing the socket directly is not correct.  Let the channel
                 * do the work (necessary for correct TLS operation).
                */
                channel.close();
            }
            LoggerUtils.info(logger, repImpl,
                "Backup file total: " +
                backupFileCount.get() +
                ".  Files actually fetched: " +
                fetchCount.get() +
                ".  Files skipped(available locally): " +
                skipCount.get() +
                ".  Local files renamed/deleted: " +
                disposedCount.get());
        }
    }

    /**
     * Ensures that the log file feeder is a suitable choice for this backup:
     * The feeder's VLSN range end must be GTE the minVSLN and its load must
     * be LTE the serverLoadThreshold.
     */
    private void checkServer()
        throws IOException,
               ProtocolException,
               LoadThresholdExceededException,
               InsufficientVLSNRangeException {

        protocol.write(protocol.new FeederInfoReq(), channel);
        FeederInfoResp resp = protocol.read(channel, FeederInfoResp.class);
        if (resp.getRangeLast().compareTo(minVLSN) < 0) {
            throw new InsufficientVLSNRangeException(
                minVLSN,
                resp.getRangeFirst(), resp.getRangeLast(),
                resp.getActiveFeeders());
        }
        if (resp.getActiveFeeders() > serverLoadThreshold) {
            throw new LoadThresholdExceededException(
                serverLoadThreshold,
                resp.getRangeFirst(), resp.getRangeLast(),
                resp.getActiveFeeders());
        }
    }

    /**
     * Delete or rename residual jdb files that are not part of the log file
     * set. This method is only invoked after all required files have been
     * copied over from the server.
     *
     * @throws IOException
     */
    private void cleanup(String[] fileNames)
        throws IOException {

        LoggerUtils.fine(logger, repImpl, "Cleaning up");

        Set<String> logFileSet = new HashSet<>(Arrays.asList(fileNames));
        for (File file : fileManager.listJDBFiles()) {
            if (!logFileSet.contains(file.getName())) {
                disposeFile(file);
            }
        }

        StringBuilder logFiles = new StringBuilder();
        for (String string : logFileSet) {

            /*
             * Use the full path of this file in case the environment uses
             * multiple data directories.
             */
            File file = new File(fileManager.getFullFileName(string));
            if (!file.exists()) {
                throw EnvironmentFailureException.unexpectedState
                    ("Missing file: " + file);
            }
            logFiles.append(file.getCanonicalPath()).append(", ");
        }

        String names = logFiles.toString();
        if (names.length() > 0) {
            names = names.substring(0, names.length()-2);
        }
        LoggerUtils.fine(logger, repImpl, "Log file set: " + names);
    }

    /**
     * Retrieves all the files in the list, that are not already in the envDir.
     * @throws DatabaseException
     */
    private void getFiles(String[] fileNames)
        throws IOException, DatabaseException,
                RestoreMarker.FileCreationException {

        LoggerUtils.info(logger, repImpl,
            fileNames.length + " files in backup set");

        /* Get all file transfer lengths first, so we can track progress */
        final List<FileAndLength> fileTransferLengths =
            getFileTransferLengths(fileNames);

        for (final FileAndLength entry : fileTransferLengths) {
            if (testBarrier != null) {
                try {
                    testBarrier.await();
                } catch (InterruptedException e) {
                    // Ignore just a test mechanism
                } catch (BrokenBarrierException e) {
                    throw EnvironmentFailureException.unexpectedException(e);
                }
            }

            for (int i = 0; i < DIGEST_RETRIES; i++) {
                try {
                    getFile(entry.file);
                    fetchCount.increment();
                    break;
                } catch (DigestException e) {
                    if ((i + 1) == DIGEST_RETRIES) {
                        throw new IOException("Digest mismatch despite "
                            + DIGEST_RETRIES + " attempts");
                    }

                    /* Account for the additional transfer */
                    expectedBytes.add(entry.length);
                    continue;
                }
            }
        }
        /* We've finished transferring all files, remove the marker file. */
        restoreMarker.removeMarkerFile(fileManager);

        /* All done, shutdown conversation with the server. */
        protocol.write(protocol.new Done(), channel);
    }

    /** Store File and file length pair. */
    private static class FileAndLength {
        FileAndLength(File file, long length) {
            this.file = file;
            this.length = length;
        }
        final File file;
        final long length;
    }

    /**
     * Returns information about files that need to be transferred, and updates
     * expectedBytes and skipCount accordingly.  This method tries to avoid
     * requesting the SHA1 if the file lengths are not equal, since computing
     * the SHA1 if it's not already cached requires a pass over the log
     * file. Note that the server will always send back the SHA1 value if it
     * has it cached.
     */
    private List<FileAndLength> getFileTransferLengths(String[] fileNames)
        throws IOException, DatabaseException {

        final List<FileAndLength> fileTransferLengths = new ArrayList<>();
        for (final String fileName : fileNames) {

            /*
             * Use the full path of this file in case the environment uses
             * multiple data directories.
             */
            final File file = new File(fileManager.getFullFileName(fileName));
            protocol.write(protocol.new FileInfoReq(fileName, false), channel);
            FileInfoResp statResp =
                protocol.read(channel, Protocol.FileInfoResp.class);
            final long fileLength = statResp.getFileLength();

            /*
             * See if we can skip the file if it is present with correct length
             */
            if (file.exists() && (fileLength == file.length())) {

                /* Make sure we have the message digest */
                if (statResp.getDigestSHA1().length == 0) {
                    protocol.write(
                        protocol.new FileInfoReq(fileName, true), channel);
                    statResp =
                        protocol.read(channel, Protocol.FileInfoResp.class);
                }
                final byte digest[] =
                    LogFileFeeder.getSHA1Digest(file, fileLength).digest();
                if (Arrays.equals(digest, statResp.getDigestSHA1())) {
                    LoggerUtils.info(logger, repImpl,
                        "File: " + file.getCanonicalPath() +
                        " length: " + fileLength +
                        " available with matching SHA1, copy skipped");
                    skipCount.increment();
                    continue;
                }
            }
            fileTransferLengths.add(new FileAndLength(file, fileLength));
            expectedBytes.add(fileLength);
        }
        return fileTransferLengths;
    }

    /**
     * Requests and obtains the specific log file from the server. The file is
     * first created under a name with the .tmp suffix and is renamed to its
     * true name only after its digest has been verified.
     *
     * This method is protected to facilitate error testing.
     */
    protected void getFile(File file)
        throws IOException, ProtocolException, DigestException,
                RestoreMarker.FileCreationException {

        LoggerUtils.fine(logger, repImpl, "Requesting file: " + file);
        protocol.write(protocol.new FileReq(file.getName()), channel);
        FileStart fileResp = protocol.read(channel, Protocol.FileStart.class);

        /*
         * Delete the tmp file if it already exists.
         *
         * Use the full path of this file in case the environment uses multiple
         * data directories.
         */
        File tmpFile = new File(fileManager.getFullFileName(file.getName()) +
                                FileManager.TMP_SUFFIX);
        if (tmpFile.exists()) {
            boolean deleted = tmpFile.delete();
            if (!deleted) {
                throw EnvironmentFailureException.unexpectedState
                    ("Could not delete file: " + tmpFile);
            }
        }

        /*
         * Use a direct buffer to avoid an unnecessary copies into and out of
         * native buffers.
         */
        final ByteBuffer buffer =
                ByteBuffer.allocateDirect(LogFileFeeder.TRANSFER_BYTES);
        messageDigest.reset();

        /* Write the tmp file. */
        final FileOutputStream fileStream = new FileOutputStream(tmpFile);
        final FileChannel fileChannel = fileStream.getChannel();

        try {
            /* Compute the transfer rate roughly once each MB */
            final int rateInterval = 0x100000 / LogFileFeeder.TRANSFER_BYTES;
            int count = 0;

            /* Copy over the file contents. */
            for (long bytes = fileResp.getFileLength(); bytes > 0;) {
                int readSize =
                    (int) Math.min(LogFileFeeder.TRANSFER_BYTES, bytes);
                buffer.clear();
                buffer.limit(readSize);
                int actualBytes = channel.read(buffer);
                if (actualBytes == -1) {
                    throw new IOException("Premature EOF. Was expecting:"
                                          + readSize);
                }
                bytes -= actualBytes;

                buffer.flip();
                fileChannel.write(buffer);

                buffer.rewind();
                messageDigest.update(buffer);
                transferredBytes.add(actualBytes);

                /* Update the transfer rate at interval and last time */
                if (((++count % rateInterval) == 0) || (bytes <= 0)) {
                    transferRate.add(
                        transferredBytes.get(), System.currentTimeMillis());
                }
            }

            if (logger.isLoggable(Level.INFO)) {
                LoggerUtils.info(logger, repImpl,
                    String.format(
                        "Fetched log file: %s, size: %,d bytes," +
                        " %s bytes," +
                        " %s bytes," +
                        " %s bytes/second",
                        file.getName(),
                        fileResp.getFileLength(),
                        transferredBytes,
                        expectedBytes,
                        transferRate));
            }
        } finally {
            fileStream.close();
        }

        final FileEnd fileEnd = protocol.read(channel, Protocol.FileEnd.class);

        /* Check that the read is successful. */
        if (!Arrays.equals(messageDigest.digest(), fileEnd.getDigestSHA1())) {
            LoggerUtils.warning(logger, repImpl,
                "digest mismatch on file: " + file);
            throw new DigestException();
        }

        /*
         * We're about to alter the files that exist in the log, either by
         * deleting file N.jdb, or by renaming N.jdb.tmp -> N, and thereby
         * adding a file to the set in the directory. Create the marker that
         * says this log is no longer coherent and can't be recovered. Marker
         * file creation can safely be called multiple times; the file will
         * only be created the first time.
         */
        restoreMarker.createMarkerFile
            (RestoreRequired.FailureType.NETWORK_RESTORE,
             exceptionProperties);

        assert TestHookExecute.doHookIfSet(interruptHook, file);

        /* Now that we know it's good, move the file into place. */
        if (file.exists()) {
            /*
             * Delete or back up this and all subsequent obsolete files,
             * excluding the marker file. The marker file will be explicitly
             * cleaned up when the entire backup finishes.
             */
            disposeObsoleteFiles(file);
        }

        /* Rename the tmp file. */
        LoggerUtils.fine(logger, repImpl, "Renamed " + tmpFile + " to " + file);
        boolean renamed = tmpFile.renameTo(file);
        if (!renamed) {
            throw EnvironmentFailureException.unexpectedState
                ("Rename from: " + tmpFile + " to " + file + " failed");
        }

        /*
         * Note that we no longer update the modified time to match the
         * original, which was done to aid debugging, because the BackupManager
         * needs to be able to detect when a network restore modifies a log
         * file.
         */
    }

    /**
     * Renames (or deletes) this log file, and all other files following it in
     * the log sequence. The operation is done from the highest file down to
     * this one, to ensure the integrity of the log files in the directory is
     * always preserved. Exclude the marker file because that is meant to serve
     * as an indicator that the backup is in progress. It will be explicitly
     * removed only when the entire backup is finished.
     *
     * @param startFile the lowest numbered log file that must be renamed or
     * deleted
     * @throws IOException
     */
    private void disposeObsoleteFiles(File startFile) throws IOException {
        File[] dirFiles = fileManager.listJDBFiles();
        Arrays.sort(dirFiles); // sorts in ascending order

        /* Start with highest numbered file to be robust in case of failure. */
        for (int i = dirFiles.length - 1; i >= 0; i--) {
            File file = dirFiles[i];

            /* Skip the marker file, wait until the whole backup is done */
            if (file.getName().equals(RestoreMarker.getMarkerFileName())) {
                continue;
            }
            disposeFile(file);
            if (startFile.equals(file)) {
                break;
            }
        }
    }

    /**
     * Remove the file from the current set of log files in the directory.
     * @param file
     */
    private void disposeFile(File file) {
        disposedCount.increment();
        final long fileNumber = fileManager.getNumFromName(file.getName());
        if (retainLogfiles) {
            boolean renamed = false;
            try {
                renamed =
                    fileManager.renameFile(fileNumber, FileManager.BUP_SUFFIX);
            } catch (IOException e) {
                throw EnvironmentFailureException.unexpectedState
                    ("Could not rename log file " + file.getPath() +
                     " because of exception: " + e.getMessage());
            }

            if (!renamed) {
                throw EnvironmentFailureException.unexpectedState
                    ("Could not rename log file " +  file.getPath());
            }
            LoggerUtils.fine(logger, repImpl,
                "Renamed log file: " + file.getPath());
        } else {
            boolean deleted = false;
            try {
                deleted = fileManager.deleteFile(fileNumber);
            } catch (IOException e) {
                throw EnvironmentFailureException.unexpectedException
                    ("Could not delete log file " + file.getPath() +
                     " during network restore.", e);
            }
            if (!deleted) {
                throw EnvironmentFailureException.unexpectedState
                    ("Could not delete log file " +  file.getPath());
            }
            LoggerUtils.fine(logger, repImpl,
                "deleted log file: " + file.getPath());
        }
    }

    /**
     * Carries out the message exchange to obtain the list of backup files.
     * @return
     * @throws IOException
     * @throws ProtocolException
     */
    private String[] getFileList()
        throws IOException, ProtocolException {

        protocol.write(protocol.new FileListReq(), channel);
        FileListResp fileListResp = protocol.read(channel,
                                                  Protocol.FileListResp.class);
        String[] fileList = fileListResp.getFileNames();
        Arrays.sort(fileList); //sort the file names in ascending order
        backupFileCount.set(fileList.length);
        return fileList;
    }

    /**
     * Verify that the protocols are compatible, switch to a different protocol
     * version, if we need to.
     *
     * @throws DatabaseException
     */
    private Protocol checkProtocol(Protocol candidateProtocol)
        throws IOException, ProtocolException {

        candidateProtocol.write
            (candidateProtocol.new ClientVersion(), channel);
        ServerVersion serverVersion =
            candidateProtocol.read(channel, Protocol.ServerVersion.class);

        if (serverVersion.getVersion() != candidateProtocol.getVersion()) {
            String message = "Server requested protocol version:"
                    + serverVersion.getVersion()
                    + " but the client version is " +
                    candidateProtocol.getVersion();
            LoggerUtils.info(logger, repImpl, message);
            throw new ProtocolException(message);
        }

        /*
         * In future we may switch protocol versions to accommodate the server.
         * For now, simply return the one and only version.
         */
        return candidateProtocol;
    }

    /*
     * @hidden
     *
     * A test entry point used to simulate a slow network restore.
     */
    public void setTestBarrier(CyclicBarrier  testBarrier) {
        this.testBarrier = testBarrier;
    }

    /* For unit testing only */
    public void setInterruptHook(TestHook<File> hook) {
        interruptHook = hook;
    }

    /**
     * Exception indicating that the digest sent by the server did not match
     * the digest computed by the client, that is, the log file was corrupted
     * during transit.
     */
    @SuppressWarnings("serial")
    protected static class DigestException extends Exception {
    }

    /**
     * Exception indicating that the server could not be used for the restore.
     */
    @SuppressWarnings("serial")
    public static class RejectedServerException extends Exception {

        /* The actual range covered by the server. */
        final VLSN rangeFirst;
        final VLSN rangeLast;

        /* The actual load of the server. */
        final int activeServers;

        RejectedServerException(VLSN rangeFirst,
                                VLSN rangeLast,
                                int activeServers) {
            this.rangeFirst = rangeFirst;
            this.rangeLast = rangeLast;
            this.activeServers = activeServers;
        }

        public VLSN getRangeLast() {
            return rangeLast;
        }

        public int getActiveServers() {
            return activeServers;
        }
    }

    /**
     * Exception indicating that the server vlsn range did not cover the VLSN
     * of interest.
     */
    @SuppressWarnings("serial")
    public static class InsufficientVLSNRangeException
        extends RejectedServerException {

        /* The VLSN that must be covered by the server. */
        private final VLSN minVLSN;

        InsufficientVLSNRangeException(VLSN minVLSN,
                                       VLSN rangeFirst,
                                       VLSN rangeLast,
                                       int activeServers) {
            super(rangeFirst, rangeLast, activeServers);
            this.minVLSN = minVLSN;
        }

        @Override
        public String getMessage() {
            return "Insufficient VLSN range. Needed VLSN: " + minVLSN +
                   " Available range: " +
                   "[" + rangeFirst + ", " + rangeLast + "]";
        }
    }

    @SuppressWarnings("serial")
    public static class LoadThresholdExceededException
        extends RejectedServerException {

        private final int threshold;

        LoadThresholdExceededException(int threshold,
                                       VLSN rangeFirst,
                                       VLSN rangeLast,
                                       int activeServers) {
            super(rangeFirst, rangeLast, activeServers);
            assert(activeServers > threshold);
            this.threshold = threshold;
        }

        @Override
        public String getMessage() {
            return "Active server threshold: " + threshold + " exceeded. " +
            "Active servers: " + activeServers;
        }
    }
}
