changes for 1)fixing recovery bugs(still need more tests), 2) not using NewUniverse property from AsterixProperties file, and 3) moved persistenLocalResourceRepository classes from hyracks to asterix

git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_lsm_stabilization@1408 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/NCApplicationEntryPoint.java b/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/NCApplicationEntryPoint.java
index f728abe..7e910be 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/NCApplicationEntryPoint.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/NCApplicationEntryPoint.java
@@ -11,10 +11,12 @@
 import edu.uci.ics.asterix.metadata.api.IAsterixStateProxy;
 import edu.uci.ics.asterix.metadata.api.IMetadataNode;
 import edu.uci.ics.asterix.metadata.bootstrap.MetadataBootstrap;
+import edu.uci.ics.asterix.transaction.management.resource.PersistentLocalResourceRepository;
 import edu.uci.ics.asterix.transaction.management.service.recovery.IRecoveryManager;
 import edu.uci.ics.asterix.transaction.management.service.recovery.IRecoveryManager.SystemState;
 import edu.uci.ics.hyracks.api.application.INCApplicationContext;
 import edu.uci.ics.hyracks.api.application.INCApplicationEntryPoint;
+import edu.uci.ics.hyracks.storage.common.file.ILocalResourceRepository;
 
 public class NCApplicationEntryPoint implements INCApplicationEntryPoint {
     private static final Logger LOGGER = Logger.getLogger(NCApplicationEntryPoint.class.getName());
@@ -39,10 +41,15 @@
         ncApplicationContext.setApplicationObject(runtimeContext);
         JVMShutdownHook sHook = new JVMShutdownHook(this);
         Runtime.getRuntime().addShutdownHook(sHook);
-        
+
         //#. recover if the system is corrupted by checking system state.
         IRecoveryManager recoveryMgr = runtimeContext.getTransactionSubsystem().getRecoveryManager();
         systemState = recoveryMgr.getSystemState();
+        if (systemState != SystemState.NEW_UNIVERSE) {
+            PersistentLocalResourceRepository localResourceRepository = (PersistentLocalResourceRepository) runtimeContext
+                    .getLocalResourceRepository();
+            localResourceRepository.initialize(nodeId, null, false, runtimeContext.getResourceIdFactory());
+        }
         if (systemState == SystemState.CORRUPTED) {
             recoveryMgr.startRecovery(true);
         } else if (systemState == SystemState.NEW_UNIVERSE) {
@@ -72,6 +79,13 @@
     @Override
     public void notifyStartupComplete() throws Exception {
         IAsterixStateProxy proxy = (IAsterixStateProxy) ncApplicationContext.getDistributedState();
+
+        if (systemState == SystemState.NEW_UNIVERSE) {
+            PersistentLocalResourceRepository localResourceRepository = (PersistentLocalResourceRepository) runtimeContext
+                    .getLocalResourceRepository();
+            localResourceRepository.initialize(nodeId, proxy.getAsterixProperties().getStores().get(nodeId)[0], true, null);
+        }
+
         isMetadataNode = nodeId.equals(proxy.getAsterixProperties().getMetadataNodeName());
         if (isMetadataNode) {
             registerRemoteMetadataNode(proxy);
@@ -81,13 +95,14 @@
             }
             MetadataManager.INSTANCE = new MetadataManager(proxy);
             MetadataManager.INSTANCE.init();
-            MetadataBootstrap.startUniverse(proxy.getAsterixProperties(), ncApplicationContext);
+            MetadataBootstrap.startUniverse(proxy.getAsterixProperties(), ncApplicationContext,
+                    systemState == SystemState.NEW_UNIVERSE);
             MetadataBootstrap.startDDLRecovery();
         }
-        
+
         IRecoveryManager recoveryMgr = runtimeContext.getTransactionSubsystem().getRecoveryManager();
         recoveryMgr.checkpoint(true);
-        
+
         //TODO
         //reclaim storage for orphaned index artifacts in NCs.
     }
diff --git a/asterix-app/src/test/java/edu/uci/ics/asterix/test/metadata/MetadataTest.java b/asterix-app/src/test/java/edu/uci/ics/asterix/test/metadata/MetadataTest.java
index 83cb925..dbc326a 100644
--- a/asterix-app/src/test/java/edu/uci/ics/asterix/test/metadata/MetadataTest.java
+++ b/asterix-app/src/test/java/edu/uci/ics/asterix/test/metadata/MetadataTest.java
@@ -86,10 +86,9 @@
         outdir.mkdirs();
 
         File log = new File("asterix_logs");
-        if (log.exists())
-            FileUtils.deleteDirectory(log);
-        File lsn = new File("last_checkpoint_lsn");
-        lsn.deleteOnExit();
+        if (log.exists()) {
+            FileUtils.deleteDirectory(log); 
+        }
 
         AsterixHyracksIntegrationUtil.init();
 
@@ -110,10 +109,9 @@
         }
 
         File log = new File("asterix_logs");
-        if (log.exists())
-            FileUtils.deleteDirectory(log);
-        File lsn = new File("last_checkpoint_lsn");
-        lsn.deleteOnExit();
+        if (log.exists()) {
+            FileUtils.deleteDirectory(log); 
+        }
     }
 
     @Parameters
diff --git a/asterix-app/src/test/java/edu/uci/ics/asterix/test/optimizer/OptimizerTest.java b/asterix-app/src/test/java/edu/uci/ics/asterix/test/optimizer/OptimizerTest.java
index 992e77d..8530ba1 100644
--- a/asterix-app/src/test/java/edu/uci/ics/asterix/test/optimizer/OptimizerTest.java
+++ b/asterix-app/src/test/java/edu/uci/ics/asterix/test/optimizer/OptimizerTest.java
@@ -60,10 +60,9 @@
         outdir.mkdirs();
         
         File log = new File("asterix_logs");
-        if (log.exists())
-            FileUtils.deleteDirectory(log);
-        File lsn = new File("last_checkpoint_lsn");
-        lsn.deleteOnExit();
+        if (log.exists()) {
+            FileUtils.deleteDirectory(log); 
+        }
         
         AsterixHyracksIntegrationUtil.init();
         // Set the node resolver to be the identity resolver that expects node names 
@@ -80,6 +79,11 @@
         if (files == null || files.length == 0) {
             outdir.delete();
         }
+        
+        File log = new File("asterix_logs");
+        if (log.exists()) {
+            FileUtils.deleteDirectory(log); 
+        }
     }
 
     private static void suiteBuild(File dir, Collection<Object[]> testArgs, String path) {
diff --git a/asterix-app/src/test/java/edu/uci/ics/asterix/test/runtime/ExecutionTest.java b/asterix-app/src/test/java/edu/uci/ics/asterix/test/runtime/ExecutionTest.java
index 2200e07..c0d3585 100644
--- a/asterix-app/src/test/java/edu/uci/ics/asterix/test/runtime/ExecutionTest.java
+++ b/asterix-app/src/test/java/edu/uci/ics/asterix/test/runtime/ExecutionTest.java
@@ -56,10 +56,9 @@
         outdir.mkdirs();
 
         File log = new File("asterix_logs");
-        if (log.exists())
-            FileUtils.deleteDirectory(log);
-        File lsn = new File("last_checkpoint_lsn");
-        lsn.deleteOnExit();
+        if (log.exists()) {
+            FileUtils.deleteDirectory(log); 
+        }
 
         AsterixHyracksIntegrationUtil.init();
 
@@ -87,10 +86,9 @@
         }
 
         File log = new File("asterix_logs");
-        if (log.exists())
-            FileUtils.deleteDirectory(log);
-        File lsn = new File("last_checkpoint_lsn");
-        lsn.deleteOnExit();
+        if (log.exists()) {
+            FileUtils.deleteDirectory(log); 
+        }
         HDFSCluster.getInstance().cleanup();
     }
 
@@ -234,6 +232,11 @@
         List<CompilationUnit> cUnits = tcCtx.getTestCase().getCompilationUnit();
         for (CompilationUnit cUnit : cUnits) {
             LOGGER.info("[TEST]: " + tcCtx.getTestCase().getFilePath() + "/" + cUnit.getName());
+            
+//            if (!tcCtx.getTestCase().getFilePath().contains("failure")) {
+//            	continue;
+//            }
+            
             testFileCtxs = tcCtx.getTestFiles(cUnit);
             expectedResultFileCtxs = tcCtx.getExpectedResultFiles(cUnit);
 
diff --git a/asterix-common/src/main/java/edu/uci/ics/asterix/common/context/AsterixAppRuntimeContext.java b/asterix-common/src/main/java/edu/uci/ics/asterix/common/context/AsterixAppRuntimeContext.java
index 85fb784..21aa203 100644
--- a/asterix-common/src/main/java/edu/uci/ics/asterix/common/context/AsterixAppRuntimeContext.java
+++ b/asterix-common/src/main/java/edu/uci/ics/asterix/common/context/AsterixAppRuntimeContext.java
@@ -9,6 +9,8 @@
 import edu.uci.ics.asterix.transaction.management.ioopcallbacks.LSMInvertedIndexIOOperationCallbackFactory;
 import edu.uci.ics.asterix.transaction.management.ioopcallbacks.LSMRTreeIOOperationCallbackFactory;
 import edu.uci.ics.asterix.transaction.management.opcallbacks.IndexOperationTrackerFactory;
+import edu.uci.ics.asterix.transaction.management.resource.PersistentLocalResourceRepository;
+import edu.uci.ics.asterix.transaction.management.resource.PersistentLocalResourceRepositoryFactory;
 import edu.uci.ics.asterix.transaction.management.service.recovery.IAsterixAppRuntimeContextProvider;
 import edu.uci.ics.asterix.transaction.management.service.transaction.TransactionSubsystem;
 import edu.uci.ics.hyracks.api.application.INCApplicationContext;
@@ -33,7 +35,6 @@
 import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
 import edu.uci.ics.hyracks.storage.common.file.ILocalResourceRepository;
 import edu.uci.ics.hyracks.storage.common.file.ILocalResourceRepositoryFactory;
-import edu.uci.ics.hyracks.storage.common.file.PersistentLocalResourceRepositoryFactory;
 import edu.uci.ics.hyracks.storage.common.file.ResourceIdFactory;
 import edu.uci.ics.hyracks.storage.common.file.ResourceIdFactoryProvider;
 
@@ -53,7 +54,7 @@
     private ILSMOperationTrackerFactory lsmRTreeOpTrackerFactory;
     private ILSMOperationTrackerFactory lsmInvertedIndexOpTrackerFactory;
     private ILSMIOOperationScheduler lsmIOScheduler;
-    private ILocalResourceRepository localResourceRepository;
+    private PersistentLocalResourceRepository localResourceRepository;
     private ResourceIdFactory resourceIdFactory;
     private IIOManager ioManager;
 
@@ -86,7 +87,8 @@
 
         ILocalResourceRepositoryFactory persistentLocalResourceRepositoryFactory = new PersistentLocalResourceRepositoryFactory(
                 ioManager);
-        localResourceRepository = persistentLocalResourceRepositoryFactory.createRepository();
+        localResourceRepository = (PersistentLocalResourceRepository) persistentLocalResourceRepositoryFactory
+                .createRepository();
         resourceIdFactory = (new ResourceIdFactoryProvider(localResourceRepository)).createResourceIdFactory();
     }
 
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataBootstrap.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataBootstrap.java
index 69fdbbb..55c3341 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataBootstrap.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataBootstrap.java
@@ -125,7 +125,7 @@
                 MetadataSecondaryIndexes.DATATYPENAME_ON_DATATYPE_INDEX };
     }
 
-    public static void startUniverse(AsterixProperties asterixProperties, INCApplicationContext ncApplicationContext)
+    public static void startUniverse(AsterixProperties asterixProperties, INCApplicationContext ncApplicationContext, boolean isNewUniverse)
             throws Exception {
         runtimeContext = (AsterixAppRuntimeContext) ncApplicationContext.getApplicationObject();
 
@@ -138,7 +138,6 @@
         MetadataSecondaryIndexes.init();
         initLocalIndexArrays();
 
-        boolean isNewUniverse = true;
         TransactionalResourceManagerRepository resourceRepository = runtimeContext.getTransactionSubsystem()
                 .getTransactionalResourceRepository();
         resourceRepository.registerTransactionalResourceManager(ResourceType.LSM_BTREE, new IndexResourceManager(
@@ -149,7 +148,6 @@
                 new IndexResourceManager(ResourceType.LSM_INVERTED_INDEX, runtimeContext.getTransactionSubsystem()));
 
         metadataNodeName = asterixProperties.getMetadataNodeName();
-        isNewUniverse = asterixProperties.isNewUniverse();
         metadataStore = asterixProperties.getMetadataStore();
         nodeNames = asterixProperties.getNodeNames();
         // nodeStores = asterixProperity.getStores();
@@ -167,7 +165,7 @@
 
         if (isNewUniverse) {
             //Do checkpoint only if it is new universe
-            runtimeContext.getTransactionSubsystem().getRecoveryManager().checkpoint(false);
+            //runtimeContext.getTransactionSubsystem().getRecoveryManager().checkpoint(false);
             MetadataTransactionContext mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
             try {
                 // Begin a transaction against the metadata.
diff --git a/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/resource/PersistentLocalResourceRepository.java b/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/resource/PersistentLocalResourceRepository.java
new file mode 100644
index 0000000..cf47740
--- /dev/null
+++ b/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/resource/PersistentLocalResourceRepository.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed 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 from
+ * 
+ *     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 edu.uci.ics.asterix.transaction.management.resource;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.storage.common.file.ILocalResourceRepository;
+import edu.uci.ics.hyracks.storage.common.file.LocalResource;
+import edu.uci.ics.hyracks.storage.common.file.ResourceIdFactory;
+
+public class PersistentLocalResourceRepository implements ILocalResourceRepository {
+
+    private final String mountPoint;
+    private static final String ROOT_METADATA_FILE_NAME_PREFIX = ".asterix_root_metadata_";
+    private static final long ROOT_LOCAL_RESOURCE_ID = -4321;
+    private static final String METADATA_FILE_NAME = ".metadata";
+    private Map<String, LocalResource> name2ResourceMap = new HashMap<String, LocalResource>();
+    private Map<Long, LocalResource> id2ResourceMap = new HashMap<Long, LocalResource>();
+    private String rootMetadataFileName;
+    private String rootDir;
+
+    public PersistentLocalResourceRepository(String mountPoint) throws HyracksDataException {
+        File mountPointDir = new File(mountPoint);
+        if (!mountPointDir.exists()) {
+            throw new HyracksDataException(mountPointDir.getAbsolutePath() + "doesn't exist.");
+        }
+        if (!mountPoint.endsWith(System.getProperty("file.separator"))) {
+            this.mountPoint = new String(mountPoint + System.getProperty("file.separator"));
+        } else {
+            this.mountPoint = new String(mountPoint);
+        }
+    }
+
+    public void initialize(String nodeId, String rootDir, boolean isNewUniverse, ResourceIdFactory resourceIdFactory) throws HyracksDataException {
+        LocalResource rootLocalResource = null;
+
+        //#. if the rootMetadataFile doesn't exist, create it and return.
+        rootMetadataFileName = new String(mountPoint + ROOT_METADATA_FILE_NAME_PREFIX + nodeId);
+        File rootMetadataFile = new File(rootMetadataFileName);
+        if (isNewUniverse) {
+            rootMetadataFile.delete();
+            if (rootDir.startsWith(System.getProperty("file.separator"))) {
+                this.rootDir = new String(mountPoint + rootDir.substring(System.getProperty("file.separator").length()));
+            } else {
+                this.rootDir = new String(mountPoint + rootDir);
+            }
+            rootLocalResource = new LocalResource(ROOT_LOCAL_RESOURCE_ID, rootMetadataFileName, 0, 0, this.rootDir);
+            insert(rootLocalResource);
+            return;
+        }
+
+        //#. if the rootMetadataFile exists, read it and set this.rootDir.
+        rootLocalResource = readLocalResource(rootMetadataFile);
+        this.rootDir = (String) rootLocalResource.getResourceObject();
+
+        //#. load all local resources. 
+        File rootDirFile = new File(this.rootDir);
+        if (!rootDirFile.exists()) {
+            throw new HyracksDataException(rootDirFile.getAbsolutePath() + "doesn't exist.");
+        }
+
+        FilenameFilter filter = new FilenameFilter() {
+            public boolean accept(File dir, String name) {
+                if (name.equalsIgnoreCase(METADATA_FILE_NAME)) {
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+        };
+
+        long maxResourceId = 0;
+        File[] dataverseFileList = rootDirFile.listFiles();
+        if (dataverseFileList == null) {
+            throw new HyracksDataException("Metadata dataverse doesn't exist.");
+        }
+        for (File dataverseFile : dataverseFileList) {
+            if (dataverseFile.isDirectory()) {
+                File[] indexFileList = dataverseFile.listFiles();
+                if (indexFileList != null) {
+                    for (File indexFile : indexFileList) {
+                        if (indexFile.isDirectory()) {
+                            File[] metadataFiles = indexFile.listFiles(filter);
+                            if (metadataFiles != null) {
+                                for (File metadataFile : metadataFiles) {
+                                    LocalResource localResource = readLocalResource(metadataFile);
+                                    id2ResourceMap.put(localResource.getResourceId(), localResource);
+                                    name2ResourceMap.put(localResource.getResourceName(), localResource);
+                                    maxResourceId = Math.max(localResource.getResourceId(), maxResourceId);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        resourceIdFactory.initId(maxResourceId+1);
+    }
+
+    @Override
+    public LocalResource getResourceById(long id) throws HyracksDataException {
+        return id2ResourceMap.get(id);
+    }
+
+    @Override
+    public LocalResource getResourceByName(String name) throws HyracksDataException {
+        return name2ResourceMap.get(name);
+    }
+
+    @Override
+    public synchronized void insert(LocalResource resource) throws HyracksDataException {
+        long id = resource.getResourceId();
+
+        if (id2ResourceMap.containsKey(id)) {
+            throw new HyracksDataException("Duplicate resource");
+        }
+
+        if (resource.getResourceId() != ROOT_LOCAL_RESOURCE_ID) {
+            id2ResourceMap.put(id, resource);
+            name2ResourceMap.put(resource.getResourceName(), resource);
+        }
+
+        FileOutputStream fos = null;
+        ObjectOutputStream oosToFos = null;
+        try {
+            fos = new FileOutputStream(getFileName(mountPoint, resource.getResourceName(), resource.getResourceId()));
+            oosToFos = new ObjectOutputStream(fos);
+            oosToFos.writeObject(resource);
+            oosToFos.flush();
+        } catch (IOException e) {
+            throw new HyracksDataException(e);
+        } finally {
+            if (oosToFos != null) {
+                try {
+                    oosToFos.close();
+                } catch (IOException e) {
+                    throw new HyracksDataException(e);
+                }
+            }
+            if (oosToFos == null && fos != null) {
+                try {
+                    fos.close();
+                } catch (IOException e) {
+                    throw new HyracksDataException(e);
+                }
+            }
+        }
+    }
+
+    @Override
+    public synchronized void deleteResourceById(long id) throws HyracksDataException {
+        LocalResource resource = id2ResourceMap.get(id);
+        if (resource == null) {
+            throw new HyracksDataException("Resource doesn't exist");
+        }
+        id2ResourceMap.remove(id);
+        name2ResourceMap.remove(resource.getResourceName());
+        File file = new File(getFileName(mountPoint, resource.getResourceName(), resource.getResourceId()));
+        file.delete();
+    }
+
+    @Override
+    public synchronized void deleteResourceByName(String name) throws HyracksDataException {
+        LocalResource resource = name2ResourceMap.get(name);
+        if (resource == null) {
+            throw new HyracksDataException("Resource doesn't exist");
+        }
+        id2ResourceMap.remove(resource.getResourceId());
+        name2ResourceMap.remove(name);
+        File file = new File(getFileName(mountPoint, resource.getResourceName(), resource.getResourceId()));
+        file.delete();
+    }
+
+    @Override
+    public List<LocalResource> getAllResources() throws HyracksDataException {
+        List<LocalResource> resources = new ArrayList<LocalResource>();
+        for (LocalResource resource : id2ResourceMap.values()) {
+            resources.add(resource);
+        }
+        return resources;
+    }
+
+    private String getFileName(String mountPoint, String baseDir, long resourceId) {
+
+        if (resourceId == ROOT_LOCAL_RESOURCE_ID) {
+            return baseDir;
+        } else {
+            String fileName = new String(mountPoint);
+            if (!baseDir.endsWith(System.getProperty("file.separator"))) {
+                baseDir += System.getProperty("file.separator");
+            }
+            fileName += baseDir + METADATA_FILE_NAME;
+            return fileName;
+        }
+    }
+
+    private LocalResource readLocalResource(File file) throws HyracksDataException {
+        FileInputStream fis = null;
+        ObjectInputStream oisFromFis = null;
+
+        try {
+            fis = new FileInputStream(file);
+            oisFromFis = new ObjectInputStream(fis);
+            LocalResource resource = (LocalResource) oisFromFis.readObject();
+            return resource;
+        } catch (Exception e) {
+            throw new HyracksDataException(e);
+        } finally {
+            if (oisFromFis != null) {
+                try {
+                    oisFromFis.close();
+                } catch (IOException e) {
+                    throw new HyracksDataException(e);
+                }
+            }
+            if (oisFromFis == null && fis != null) {
+                try {
+                    fis.close();
+                } catch (IOException e) {
+                    throw new HyracksDataException(e);
+                }
+            }
+        }
+    }
+}
diff --git a/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/resource/PersistentLocalResourceRepositoryFactory.java b/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/resource/PersistentLocalResourceRepositoryFactory.java
new file mode 100644
index 0000000..c7efca5
--- /dev/null
+++ b/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/resource/PersistentLocalResourceRepositoryFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed 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 from
+ * 
+ *     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 edu.uci.ics.asterix.transaction.management.resource;
+
+import java.util.List;
+
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.api.io.IIOManager;
+import edu.uci.ics.hyracks.api.io.IODeviceHandle;
+import edu.uci.ics.hyracks.storage.common.file.ILocalResourceRepository;
+import edu.uci.ics.hyracks.storage.common.file.ILocalResourceRepositoryFactory;
+
+public class PersistentLocalResourceRepositoryFactory implements ILocalResourceRepositoryFactory {
+    private IIOManager ioManager;
+
+    public PersistentLocalResourceRepositoryFactory(IIOManager ioManager) {
+        this.ioManager = ioManager;
+    }
+
+    @Override
+    public ILocalResourceRepository createRepository() throws HyracksDataException {
+        List<IODeviceHandle> devices = ioManager.getIODevices();
+        return new PersistentLocalResourceRepository(devices.get(0).getPath().getPath());
+    }
+}
diff --git a/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/service/recovery/RecoveryManager.java b/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/service/recovery/RecoveryManager.java
index dee1df3..77f9da5 100644
--- a/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/service/recovery/RecoveryManager.java
+++ b/asterix-transactions/src/main/java/edu/uci/ics/asterix/transaction/management/service/recovery/RecoveryManager.java
@@ -141,6 +141,10 @@
         ILogManager logManager = txnSubsystem.getLogManager();
         ILogRecordHelper logRecordHelper = logManager.getLogRecordHelper();
 
+        if (LOGGER.isLoggable(Level.INFO)) {
+            LOGGER.info("[RecoveryMgr] starting recovery ...");
+        }
+        
         //winnerTxnTable is used to add pairs, <committed TxnId, the most recent commit LSN of the TxnId>
         Map<TxnId, Long> winnerTxnTable = new HashMap<TxnId, Long>();
         TxnId tempKeyTxnId = new TxnId(-1, -1, -1);
@@ -149,6 +153,9 @@
         //#. read checkpoint file and set lowWaterMark where anaylsis and redo start
         CheckpointObject checkpointObject = readCheckpoint();
         long lowWaterMarkLSN = checkpointObject.getMinMCTFirstLSN();
+        if (lowWaterMarkLSN == -1) {
+        	lowWaterMarkLSN = 0;
+        }
         int maxJobId = checkpointObject.getMaxJobId();
         int currentJobId;
 
@@ -158,7 +165,10 @@
         //  - if there are duplicate commits for the same TxnId, 
         //    keep only the mostRecentCommitLSN among the duplicates.
         //-------------------------------------------------------------------------
-
+        if (LOGGER.isLoggable(Level.INFO)) {
+            LOGGER.info("[RecoveryMgr] in analysis phase");
+        }
+        
         //#. set log cursor to the lowWaterMarkLSN
         ILogCursor logCursor = logManager.readLog(new PhysicalLogLocator(lowWaterMarkLSN, logManager),
                 new ILogFilter() {
@@ -208,7 +218,9 @@
         //      &&  
         //    2) the currentLSN > maxDiskLastLSN of the index --> guarantee idempotance
         //-------------------------------------------------------------------------
-
+        if (LOGGER.isLoggable(Level.INFO)) {
+            LOGGER.info("[RecoveryMgr] in redo phase");
+        }
         //#. set log cursor to the lowWaterMarkLSN again.
         logCursor = logManager.readLog(new PhysicalLogLocator(lowWaterMarkLSN, logManager), new ILogFilter() {
             public boolean accept(IBuffer logs, long startOffset, int endOffset) {
@@ -357,6 +369,10 @@
         for (long r : resourceIdList) {
             indexLifecycleManager.close(r);
         }
+        
+        if (LOGGER.isLoggable(Level.INFO)) {
+            LOGGER.info("[RecoveryMgr] recovery is over");
+        }
     }
 
     //TODO