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 boolean rename(String oldName, String newName) throws IOException {
        File oldFileName = new File(rootFile, oldName);
        File newFileName = new File(rootFile, newName);
        if (oldFileName.exists()) {
            FileUtils.moveDirectory(oldFileName, newFileName);
            FileUtils.deleteDirectory(oldFileName);
            return true;
        } else {
            return false;
        }
    }

    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);
    }
}

@@ -510,12 +510,11 @@
 .new
-Cach
+Fix
 edTh
@@ -522,16 +522,68 @@
 eadPool(
+Runtime.getRuntime().availableProcessors(),%0A        
 new Thre
@@ -744,16 +744,25 @@
 xecutor(
+%0A        
 new Thre

use fixed thread pool