/// <summary>
        /// Add a full backup folder to the chain.
        /// </summary>
        /// <param name="backupFolder">Path of the input full backup folder.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>Task that represents the asynchronous work.</returns>
        /// <exception cref="ArgumentException">The relevant folder is not a valid full backup folder.</exception>
        /// <exception cref="InvalidDataException">There is a corruption in the file.</exception>
        private async Task AddFullBackupFolderAsync(string backupFolder, CancellationToken cancellationToken)
        {
            Utility.Assert(this.StateManagerBackupFolderPath == null, "There can only be one full backup.");
            Utility.Assert(FabricDirectory.Exists(backupFolder), "Directory must exist.");

            var stateManagerBackupFolderPath = Path.Combine(backupFolder, Replicator.Constants.StateManagerBackupFolderName);

            if (false == FabricDirectory.Exists(stateManagerBackupFolderPath))
            {
                throw new ArgumentException(SR.Error_BackupFolderInfo_NullFolder, "backupFolder");
            }

            this.fullBackupFolderPath         = backupFolder;
            this.stateManagerBackupFolderPath = stateManagerBackupFolderPath;

            var metadataPath = Path.Combine(backupFolder, Replicator.Constants.ReplicatorBackupMetadataFileName);

            // Can throw InvalidDataException
            BackupMetadataFile backupMetadataFile;

            try
            {
                backupMetadataFile = await BackupMetadataFile.OpenAsync(metadataPath, cancellationToken).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                FabricEvents.Events.RestoreException(
                    this.traceType,
                    Guid.Empty,
                    e.GetType().ToString(),
                    e.Message,
                    e.StackTrace);
                throw;
            }

            var version = new BackupInfo.BackupVersion(
                backupMetadataFile.BackupEpoch,
                backupMetadataFile.BackupLsn);

            this.backupVersionList.Add(version);
            this.backupMetadataFileList.Add(backupMetadataFile);

            var logFolderPath = Path.Combine(
                backupFolder,
                Replicator.Constants.ReplicatorBackupFolderName,
                Replicator.Constants.ReplicatorBackupLogName);

            this.logFileList.Add(logFolderPath);
        }
        /// <summary>
        /// Add an incremental backup folder to the chain.
        /// </summary>
        /// <param name="backupFolder">Path of the input full backup folder.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>Task that represents the asynchronous work.</returns>
        /// <exception cref="InvalidDataException">There is a corruption in the file.</exception>
        private async Task AddIncrementalBackupFolderAsync(string backupFolder, CancellationToken cancellationToken)
        {
            Utility.Assert(
                this.StateManagerBackupFolderPath != null,
                "There must at least be one full backup. Full backup must be added first.");

            var metadataPath = Path.Combine(backupFolder, Replicator.Constants.ReplicatorIncrementalBackupMetadataFileName);

            // Can throw InvalidDataException
            BackupMetadataFile backupMetadataFile;

            try
            {
                backupMetadataFile = await BackupMetadataFile.OpenAsync(metadataPath, cancellationToken).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                FabricEvents.Events.RestoreException(
                    this.traceType,
                    Guid.Empty,
                    e.GetType().ToString(),
                    e.Message,
                    e.StackTrace);
                throw;
            }

            var version = new BackupInfo.BackupVersion(
                backupMetadataFile.BackupEpoch,
                backupMetadataFile.BackupLsn);

            // If item is found, the right position will be returned, otherwise, a negative number that
            // is the bitwise complement of the index of the next element which is larger than the item or, if there is no
            // larger element, the bitwise complement of list count.
            int pos       = backupVersionList.BinarySearch(version);
            int insertPos = pos < 0 ? ~pos : pos;

            this.backupVersionList.Insert(insertPos, version);

            this.backupMetadataFileList.Insert(insertPos, backupMetadataFile);

            var backupLogFilePath = Path.Combine(
                backupFolder,
                Replicator.Constants.ReplicatorBackupFolderName,
                Replicator.Constants.ReplicatorBackupLogName);

            this.logFileList.Insert(insertPos, backupLogFilePath);
        }