/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.internal.cache.backup;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

import org.apache.logging.log4j.Logger;

import org.apache.geode.InternalGemFireError;
import org.apache.geode.cache.DiskStore;
import org.apache.geode.cache.persistence.PersistentID;
import org.apache.geode.internal.cache.DiskStoreImpl;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.Oplog;
import org.apache.geode.internal.logging.LogService;

/**
 * This class manages the state an logic to backup a single cache.
 */
class BackupTask {
  private static final Logger logger = LogService.getLogger();

  private final Map<DiskStoreImpl, DiskStoreBackup> backupByDiskStore = new HashMap<>();
  private final RestoreScript restoreScript = new RestoreScript();
  private final InternalCache cache;
  private final CountDownLatch allowDestroys = new CountDownLatch(1);
  private final CountDownLatch locksAcquired = new CountDownLatch(1);
  private final CountDownLatch otherMembersReady = new CountDownLatch(1);
  private final HashSet<PersistentID> diskStoresWithData = new HashSet<>();
  private final BackupWriter backupWriter;

  private volatile boolean isCancelled;

  private TemporaryBackupFiles temporaryFiles;
  private BackupFileCopier fileCopier;

  BackupTask(InternalCache cache, BackupWriter backupWriter) {
    this.cache = cache;
    this.backupWriter = backupWriter;
  }

  HashSet<PersistentID> getPreparedDiskStores() throws InterruptedException {
    locksAcquired.await();
    return diskStoresWithData;
  }

  void notifyOtherMembersReady() {
    otherMembersReady.countDown();
  }

  HashSet<PersistentID> backup() throws InterruptedException, IOException {
    prepareForBackup();
    locksAcquired.countDown();
    try {
      otherMembersReady.await();
    } catch (InterruptedException e) {
      cleanup();
      throw e;
    }
    if (isCancelled) {
      cleanup();
      return new HashSet<>();
    }

    return doBackup();
  }

  private void prepareForBackup() {
    for (DiskStore store : cache.listDiskStoresIncludingRegionOwned()) {
      DiskStoreImpl storeImpl = (DiskStoreImpl) store;

      storeImpl.lockStoreBeforeBackup();
      if (logger.isDebugEnabled()) {
        logger.debug("Acquired lock for backup on disk store {}", store.getName());
      }
      if (storeImpl.hasPersistedData()) {
        diskStoresWithData.add(storeImpl.getPersistentID());
        storeImpl.getStats().startBackup();
      }
    }
  }

  private HashSet<PersistentID> doBackup() throws IOException {
    if (isCancelled) {
      cleanup();
      return new HashSet<>();
    }

    try {
      Collection<DiskStore> diskStores = cache.listDiskStoresIncludingRegionOwned();
      temporaryFiles = TemporaryBackupFiles.create();
      fileCopier = new BackupFileCopier(cache, temporaryFiles);

      Map<DiskStoreImpl, DiskStoreBackup> backupByDiskStores = startDiskStoreBackups(diskStores);

      allowDestroys.countDown();

      HashSet<PersistentID> persistentIds = finishDiskStoreBackups(backupByDiskStores);

      if (!backupByDiskStores.isEmpty()) {
        backupAdditionalFiles();
        BackupDefinition backupDefinition = fileCopier.getBackupDefinition();
        backupDefinition.setRestoreScript(restoreScript);
        backupWriter.backupFiles(backupDefinition);
      }
      return persistentIds;
    } finally {
      cleanup();
    }
  }

  private HashSet<PersistentID> finishDiskStoreBackups(
      Map<DiskStoreImpl, DiskStoreBackup> backupByDiskStores) throws IOException {
    HashSet<PersistentID> persistentIds = new HashSet<>();
    for (Map.Entry<DiskStoreImpl, DiskStoreBackup> entry : backupByDiskStores.entrySet()) {
      DiskStoreImpl diskStore = entry.getKey();
      completeBackup(diskStore, entry.getValue());
      diskStore.getStats().endBackup();
      persistentIds.add(diskStore.getPersistentID());
    }
    return persistentIds;
  }

  private Map<DiskStoreImpl, DiskStoreBackup> startDiskStoreBackups(
      Collection<DiskStore> diskStores) throws IOException {
    Map<DiskStoreImpl, DiskStoreBackup> backupByDiskStore = new HashMap<>();

    for (DiskStore store : diskStores) {
      DiskStoreImpl diskStore = (DiskStoreImpl) store;
      try {
        if (diskStore.hasPersistedData()) {
          DiskStoreBackup backup = startDiskStoreBackup(diskStore);
          backupByDiskStore.put(diskStore, backup);
        }
      } finally {
        diskStore.releaseBackupLock();
        if (logger.isDebugEnabled()) {
          logger.debug("Released lock for backup on disk store {}", store.getName());
        }
      }
    }
    return backupByDiskStore;
  }

  void abort() {
    isCancelled = true;
    otherMembersReady.countDown();
  }

  boolean isCancelled() {
    return isCancelled;
  }

  void waitTillBackupFilesAreCopiedToTemporaryLocation() {
    try {
      allowDestroys.await();
    } catch (InterruptedException e) {
      throw new InternalGemFireError(e);
    }
  }

  private void cleanup() {
    isCancelled = true;
    allowDestroys.countDown();
    if (temporaryFiles != null) {
      temporaryFiles.cleanupFiles();
    }
    releaseBackupLocks();
  }

  private void releaseBackupLocks() {
    for (DiskStore store : cache.listDiskStoresIncludingRegionOwned()) {
      ((DiskStoreImpl) store).releaseBackupLock();
    }
  }

  private void backupAdditionalFiles() throws IOException {
    fileCopier.copyConfigFiles();
    fileCopier.copyUserFiles();
    fileCopier.copyDeployedJars();
  }

  /**
   * Copy the oplogs to the backup directory. This is the final step of the backup process. The
   * oplogs we copy are defined in the startDiskStoreBackup method.
   */
  private void completeBackup(DiskStoreImpl diskStore, DiskStoreBackup backup) throws IOException {
    if (backup == null) {
      return;
    }
    try {
      // Wait for oplogs to be unpreblown before backing them up.
      diskStore.waitForDelayedWrites();

      // Backup all of the oplogs
      for (Oplog oplog : backup.getPendingBackup()) {
        if (isCancelled()) {
          break;
        }
        oplog.finishKrf();
        fileCopier.copyOplog(diskStore, oplog);

        // Allow the oplog to be deleted, and process any pending delete
        backup.backupFinished(oplog);
      }
    } finally {
      backup.cleanup();
    }
  }

  /**
   * Start the backup process. This is the second step of the backup process. In this method, we
   * define the data we're backing up by copying the init file and rolling to the next file. After
   * this method returns operations can proceed as normal, except that we don't remove oplogs.
   */
  private DiskStoreBackup startDiskStoreBackup(DiskStoreImpl diskStore) throws IOException {
    DiskStoreBackup backup = null;
    boolean done = false;
    try {
      for (;;) {
        Oplog childOplog = diskStore.getPersistentOplogSet().getChild();
        if (childOplog == null) {
          backup = new DiskStoreBackup(new Oplog[0]);
          backupByDiskStore.put(diskStore, backup);
          break;
        }

        // Get an appropriate lock object for each set of oplogs.
        Object childLock = childOplog.getLock();

        // TODO: We really should move this lock into the disk store, but until then we need to do
        // this magic to make sure we're actually locking the latest child for both types of oplogs

        // This ensures that all writing to disk is blocked while we are creating the snapshot
        synchronized (childLock) {
          if (logger.isDebugEnabled()) {
            logger.debug("Synchronized on lock for oplog {} on disk store {}",
                childOplog.getOplogId(), diskStore.getName());
          }

          if (diskStore.getPersistentOplogSet().getChild() != childOplog) {
            continue;
          }

          if (logger.isDebugEnabled()) {
            logger.debug("Creating snapshot of oplogs for disk store {}", diskStore.getName());
          }

          restoreScript.addExistenceTest(diskStore.getDiskInitFile().getIFFile());

          // Contains all oplogs that will backed up
          Oplog[] allOplogs = diskStore.getAllOplogsForBackup();
          backup = new DiskStoreBackup(allOplogs);
          backupByDiskStore.put(diskStore, backup);

          fileCopier.copyDiskInitFile(diskStore);
          diskStore.getPersistentOplogSet().forceRoll(null);

          if (logger.isDebugEnabled()) {
            logger.debug("Finished backup of disk store {}", diskStore.getName());
          }
          break;
        }
      }
      done = true;
    } finally {
      if (!done && backup != null) {
        backupByDiskStore.remove(diskStore);
        backup.cleanup();
      }
    }
    return backup;
  }

  DiskStoreBackup getBackupForDiskStore(DiskStoreImpl diskStore) {
    return backupByDiskStore.get(diskStore);
  }
}
