package com.jivesoftware.os.lab;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.jivesoftware.os.lab.api.ValueIndex;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;

/**
 *
 * @author jonathan.colt
 */
public class LABEnvironment {

    private final File rootFile;
    private final ExecutorService compact = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("lab-compact-%d").build()); // TODO config 'maybe'
    private final ExecutorService destroy = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("lab-destroy-%d").build()); // TODO config 'maybe'
    private final LABValueMerger valueMerger;
    private final boolean useMemMap;
    private final int minMergeDebt;
    private final int maxMergeDebt;
    private final int concurrency;

    public LABEnvironment(File rootFile, LABValueMerger valueMerger, boolean useMemMap, int minMergeDebt, int maxMergeDebt, int concurrency) {
        this.rootFile = rootFile;
        this.valueMerger = valueMerger;
        this.useMemMap = useMemMap;
        this.minMergeDebt = minMergeDebt;
        this.maxMergeDebt = maxMergeDebt;
        this.concurrency = concurrency;
    }

    public ValueIndex open(String primaryName,
        int entriesBetweenLeaps,
        int maxUpdatesBeforeFlush,
        long splitWhenKeysTotalExceedsNBytes,
        long splitWhenValuesTotalExceedsNBytes,
        long splitWhenValuesAndKeysTotalExceedsNBytes) throws Exception {
        return new LAB(valueMerger,
            compact,
            destroy,
            rootFile,
            primaryName,
            useMemMap,
            entriesBetweenLeaps,
            maxUpdatesBeforeFlush,
            minMergeDebt,
            maxMergeDebt,
            splitWhenKeysTotalExceedsNBytes,
            splitWhenValuesTotalExceedsNBytes,
            splitWhenValuesAndKeysTotalExceedsNBytes,
            concurrency);
    }

    public void rename(String oldName, String newName) throws IOException {
        File oldFileName = new File(rootFile, oldName);
        File newFileName = new File(rootFile, newName);
        FileUtils.moveDirectory(oldFileName, newFileName);
        FileUtils.deleteDirectory(oldFileName);
    }

    public void remove(String primaryName) throws IOException {
        File fileName = new File(rootFile, primaryName);
        FileUtils.deleteDirectory(fileName);
    }

    public void shutdown() throws InterruptedException {
        compact.shutdown();
        destroy.shutdown();
        compact.awaitTermination(30, TimeUnit.SECONDS);
        destroy.awaitTermination(30, TimeUnit.SECONDS);
    }
}

@@ -2101,20 +2101,23 @@
  public 
-void
+boolean
  rename(
@@ -2277,24 +2277,64 @@
 , newName);%0A
+        if (oldFileName.exists()) %7B%0A    
         File
@@ -2380,32 +2380,36 @@
 eName);%0A        
+    
 FileUtils.delete
@@ -2424,32 +2424,110 @@
 y(oldFileName);%0A
+            return true;%0A        %7D else %7B%0A            return false;%0A        %7D%0A
     %7D%0A%0A    publi

handle index renames for empty/nonexistent indexes