/*
 * 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;

import static org.apache.geode.internal.cache.DiskStoreAttributes.checkMinAndMaxOplogSize;
import static org.apache.geode.internal.cache.DiskStoreAttributes.checkMinOplogSize;
import static org.apache.geode.internal.cache.DiskStoreAttributes.checkQueueSize;
import static org.apache.geode.internal.cache.DiskStoreAttributes.checkTimeInterval;
import static org.apache.geode.internal.cache.DiskStoreAttributes.checkWriteBufferSize;
import static org.apache.geode.internal.cache.DiskStoreAttributes.verifyNonNegativeDirSize;

import java.io.File;
import java.util.Arrays;

import org.apache.geode.GemFireIOException;
import org.apache.geode.annotations.VisibleForTesting;
import org.apache.geode.cache.DiskStore;
import org.apache.geode.cache.DiskStoreFactory;
import org.apache.geode.distributed.internal.ResourceEvent;
import org.apache.geode.internal.cache.backup.BackupService;
import org.apache.geode.internal.cache.xmlcache.CacheCreation;
import org.apache.geode.internal.cache.xmlcache.CacheXml;
import org.apache.geode.internal.cache.xmlcache.DiskStoreAttributesCreation;
import org.apache.geode.pdx.internal.TypeRegistry;

/**
 * Implementation of DiskStoreFactory
 *
 * @since GemFire prPersistSprint2
 */
public class DiskStoreFactoryImpl implements DiskStoreFactory {

  private final InternalCache cache;
  private final DiskStoreAttributes attrs = new DiskStoreAttributes();

  public DiskStoreFactoryImpl(InternalCache cache) {
    this.cache = cache;
  }

  public DiskStoreFactoryImpl(InternalCache cache, DiskStoreAttributes attrs) {
    this.attrs.name = attrs.name;
    setAutoCompact(attrs.getAutoCompact());
    setAllowForceCompaction(attrs.getAllowForceCompaction());
    setCompactionThreshold(attrs.getCompactionThreshold());
    setMaxOplogSizeInBytes(attrs.getMaxOplogSizeInBytes());
    setTimeInterval(attrs.getTimeInterval());
    setWriteBufferSize(attrs.getWriteBufferSize());
    setQueueSize(attrs.getQueueSize());
    setDiskDirs(cloneArray(attrs.getDiskDirs()));
    setDiskDirsAndSizes(cloneArray(attrs.getDiskDirs()), cloneArray(attrs.getDiskDirSizes()));
    setDiskUsageWarningPercentage(attrs.getDiskUsageWarningPercentage());
    setDiskUsageCriticalPercentage(attrs.getDiskUsageCriticalPercentage());
    this.cache = cache;
  }

  private static File[] cloneArray(File[] o) {
    File[] result = null;
    if (o != null) {
      result = new File[o.length];
      System.arraycopy(o, 0, result, 0, o.length);
    }
    return result;
  }

  private static int[] cloneArray(int[] o) {
    int[] result = null;
    if (o != null) {
      result = new int[o.length];
      System.arraycopy(o, 0, result, 0, o.length);
    }
    return result;
  }

  @VisibleForTesting
  public DiskStoreFactory setDiskDirSizesUnit(DiskDirSizesUnit unit) {
    this.attrs.setDiskDirSizesUnit(unit);
    return this;
  }

  @Override
  public DiskStoreFactory setAutoCompact(boolean autoCompact) {
    this.attrs.autoCompact = autoCompact;
    return this;
  }

  @Override
  public DiskStoreFactory setAllowForceCompaction(boolean allowForceCompaction) {
    this.attrs.allowForceCompaction = allowForceCompaction;
    return this;
  }

  @Override
  public DiskStoreFactory setCompactionThreshold(int compactionThreshold) {
    if (compactionThreshold < 0) {
      throw new IllegalArgumentException(
          String.format("%s has to be positive number and the value given %s is not acceptable",
              CacheXml.COMPACTION_THRESHOLD, compactionThreshold));
    } else if (compactionThreshold > 100) {
      throw new IllegalArgumentException(
          String.format(
              "%s has to be a number that does not exceed %s so the value given %s is not acceptable",
              CacheXml.COMPACTION_THRESHOLD, compactionThreshold, 100));
    }
    this.attrs.compactionThreshold = compactionThreshold;
    return this;
  }

  @Override
  public DiskStoreFactory setTimeInterval(long timeInterval) {
    checkTimeInterval(timeInterval);
    this.attrs.timeInterval = timeInterval;
    return this;
  }

  DiskStoreImpl createOwnedByRegion(String name, boolean isOwnedByPR,
      InternalRegionArguments internalRegionArgs) {
    this.attrs.name = name;
    synchronized (this.cache) {
      DiskStoreImpl ds =
          new DiskStoreImpl(this.cache, this.attrs, true/* ownedByRegion */, internalRegionArgs);
      if (isOwnedByPR) {
        initializeDiskStore(ds);
      }
      this.cache.addRegionOwnedDiskStore(ds);
      return ds;
    }
  }

  @Override
  public DiskStore create(String name) {
    this.attrs.name = name;
    DiskStore result;
    try {
      this.cache.lockDiskStore(name);
      result = findExisting(name);
      if (result == null) {
        if (this.cache instanceof GemFireCacheImpl) {
          TypeRegistry registry = this.cache.getPdxRegistry();
          DiskStoreImpl dsi = new DiskStoreImpl(this.cache, this.attrs);
          result = dsi;
          // Added for M&M
          this.cache.getInternalDistributedSystem()
              .handleResourceEvent(ResourceEvent.DISKSTORE_CREATE, dsi);
          initializeDiskStore(dsi);
          this.cache.addDiskStore(dsi);
          if (registry != null) {
            registry.creatingDiskStore(dsi);
          }
        } else if (this.cache instanceof CacheCreation) {
          CacheCreation creation = (CacheCreation) this.cache;
          result = new DiskStoreAttributesCreation(this.attrs);
          creation.addDiskStore(result);
        }
      }
    } finally {
      this.cache.unlockDiskStore(name);
    }

    // Don't allow this disk store to be created
    // until an in progress backup is completed. This
    // ensures that nothing that is backed up on another
    // member depends on state that goes into this disk store
    // that isn't backed up.
    if (this.cache instanceof GemFireCacheImpl) {
      BackupService backup = this.cache.getBackupService();
      if (backup != null) {
        backup.waitForBackup();
      }
    }
    return result;
  }

  /**
   * Protected for testing purposes. If during the initial recovery for the disk store, an uncaught
   * exception is thrown, the disk store will not be in a valid state. In this case, we want to
   * ensure the resources of the disk store are cleaned up.
   */
  protected void initializeDiskStore(DiskStoreImpl diskStore) {
    try {
      diskStore.doInitialRecovery();
    } catch (RuntimeException e) {
      diskStore.close();
      throw e;
    }
  }

  private DiskStore findExisting(String name) {
    DiskStore existing;
    if (this.cache instanceof GemFireCacheImpl) {
      existing = this.cache.findDiskStore(name);
      if (existing != null) {
        if (((DiskStoreImpl) existing).sameAs(this.attrs)) {
          return existing;
        } else {
          throw new IllegalStateException("DiskStore named \"" + name + "\" already exists");
        }
      }
    }
    return null;
  }

  @Override
  public DiskStoreFactory setDiskDirsAndSizes(File[] diskDirs, int[] diskDirSizes) {
    if (diskDirSizes.length != diskDirs.length) {
      throw new IllegalArgumentException(
          String.format(
              "Number of diskSizes is %s which is not equal to number of disk Dirs which is %s",
              diskDirSizes.length, diskDirs.length));
    }
    verifyNonNegativeDirSize(diskDirSizes);
    checkIfDirectoriesExist(diskDirs);

    this.attrs.diskDirs = new File[diskDirs.length];
    System.arraycopy(diskDirs, 0, this.attrs.diskDirs, 0, diskDirs.length);
    this.attrs.diskDirSizes = new int[diskDirSizes.length];
    System.arraycopy(diskDirSizes, 0, this.attrs.diskDirSizes, 0, diskDirSizes.length);
    return this;
  }

  /**
   * Checks if directories exist, if they don't then create those directories
   */
  public static void checkIfDirectoriesExist(File[] diskDirs) {
    for (File diskDir : diskDirs) {
      if (!diskDir.isDirectory()) {
        if (!diskDir.mkdirs()) {
          throw new GemFireIOException(
              String.format("Unable to create directory : %s",
                  diskDir));
        }
      }
    }
  }



  @Override
  public DiskStoreFactory setDiskDirs(File[] diskDirs) {
    checkIfDirectoriesExist(diskDirs);
    int[] diskSizes = new int[diskDirs.length];
    Arrays.fill(diskSizes, DEFAULT_DISK_DIR_SIZE);
    return setDiskDirsAndSizes(diskDirs, diskSizes);
  }

  @Override
  public DiskStoreFactory setMaxOplogSize(long maxOplogSize) {
    checkMinAndMaxOplogSize(maxOplogSize);
    this.attrs.maxOplogSizeInBytes = maxOplogSize * (1024 * 1024);
    return this;
  }

  /**
   * Used by unit tests
   */
  public DiskStoreFactory setMaxOplogSizeInBytes(long maxOplogSizeInBytes) {
    checkMinOplogSize(maxOplogSizeInBytes);
    this.attrs.maxOplogSizeInBytes = maxOplogSizeInBytes;
    return this;
  }

  @Override
  public DiskStoreFactory setQueueSize(int queueSize) {
    checkQueueSize(queueSize);
    this.attrs.queueSize = queueSize;
    return this;
  }

  @Override
  public DiskStoreFactory setWriteBufferSize(int writeBufferSize) {
    checkWriteBufferSize(writeBufferSize);
    this.attrs.writeBufferSize = writeBufferSize;
    return this;
  }

  // used by hydra
  public DiskStoreAttributes getDiskStoreAttributes() {
    return this.attrs;
  }

  @Override
  public DiskStoreFactory setDiskUsageWarningPercentage(float warningPercent) {
    this.attrs.setDiskUsageWarningPercentage(warningPercent);
    return this;
  }

  @Override
  public DiskStoreFactory setDiskUsageCriticalPercentage(float criticalPercent) {
    this.attrs.setDiskUsageCriticalPercentage(criticalPercent);
    return this;
  }
}
