added IIndexArtifactMap interface in order to support permanent resourceIds

git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_lsm_tree@1591 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/RuntimeContext.java b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/RuntimeContext.java
index 3336d6d..1e81763 100644
--- a/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/RuntimeContext.java
+++ b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/RuntimeContext.java
@@ -27,19 +27,22 @@
 import edu.uci.ics.hyracks.storage.common.buffercache.IPageReplacementStrategy;
 import edu.uci.ics.hyracks.storage.common.file.IFileMapManager;
 import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
+import edu.uci.ics.hyracks.storage.common.file.IIndexArtifactMap;
 import edu.uci.ics.hyracks.storage.common.smi.TransientFileMapManager;
 
 public class RuntimeContext {
     private IndexRegistry<IIndex> indexRegistry;
     private IBufferCache bufferCache;
     private IFileMapManager fileMapManager;
-
+    private IIndexArtifactMap indexArtifactMap;
+    
     public RuntimeContext(INCApplicationContext appCtx) {
         fileMapManager = new TransientFileMapManager();
         ICacheMemoryAllocator allocator = new HeapBufferAllocator();
         IPageReplacementStrategy prs = new ClockPageReplacementStrategy();
         bufferCache = new BufferCache(appCtx.getRootContext().getIOManager(), allocator, prs, fileMapManager, 32768, 50, 100);
         indexRegistry = new IndexRegistry<IIndex>();
+        indexArtifactMap = new TransientIndexArtifactMap();
     }
 
     public void close() {
@@ -61,4 +64,8 @@
     public static RuntimeContext get(IHyracksTaskContext ctx) {
         return (RuntimeContext) ctx.getJobletContext().getApplicationContext().getApplicationObject();
     }
+    
+    public IIndexArtifactMap getIndexArtifactMap() {
+        return indexArtifactMap;
+    }
 }
\ No newline at end of file
diff --git a/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/StorageManagerInterface.java b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/StorageManagerInterface.java
index 4c6363b..a1e94d2 100644
--- a/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/StorageManagerInterface.java
+++ b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/StorageManagerInterface.java
@@ -19,6 +19,7 @@
 import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
 import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
+import edu.uci.ics.hyracks.storage.common.file.IIndexArtifactMap;
 
 public class StorageManagerInterface implements IStorageManagerInterface {
     private static final long serialVersionUID = 1L;
@@ -37,4 +38,9 @@
     public IFileMapProvider getFileMapProvider(IHyracksTaskContext ctx) {
         return RuntimeContext.get(ctx).getFileMapManager();
     }
+    
+    @Override
+    public IIndexArtifactMap getIndexArtifactMap(IHyracksTaskContext ctx) {
+        return RuntimeContext.get(ctx).getIndexArtifactMap();
+    }
 }
\ No newline at end of file
diff --git a/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/TransientIndexArtifactMap.java b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/TransientIndexArtifactMap.java
new file mode 100644
index 0000000..c4a7561
--- /dev/null
+++ b/hyracks-examples/btree-example/btreehelper/src/main/java/edu/uci/ics/hyracks/examples/btree/helper/TransientIndexArtifactMap.java
@@ -0,0 +1,84 @@
+/*
+ * 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.hyracks.examples.btree.helper;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import edu.uci.ics.hyracks.api.io.IODeviceHandle;
+import edu.uci.ics.hyracks.storage.common.file.IIndexArtifactMap;
+
+public class TransientIndexArtifactMap implements IIndexArtifactMap {
+    private long counter = 0;
+    private Map<String, Long> name2IdMap = new HashMap<String, Long>();
+
+    @Override
+    public long create(String baseDir, List<IODeviceHandle> IODeviceHandles) throws IOException {
+        long resourceId = counter++;
+        String fullDir;
+        synchronized (name2IdMap) {
+            for (IODeviceHandle dev : IODeviceHandles) {
+                fullDir = dev.getPath().toString();
+                if (!fullDir.endsWith(System.getProperty("file.separator"))) {
+                    fullDir += System.getProperty("file.separator");
+                }
+                fullDir += baseDir;
+                if (name2IdMap.containsKey(fullDir)) {
+                    throw new IOException();
+                }
+                name2IdMap.put(fullDir, resourceId);
+            }
+        }
+        return resourceId;
+    }
+
+    /**
+     * Search and return the resourceId indicated by fullDir from in-memory hashMap, name2IdMap.
+     * When there is no corresponding id in name2IdMap, return -1;
+     */
+    @Override
+    public long get(String fullDir) {
+        Long resourceId = -1L;
+
+        synchronized (name2IdMap) {
+            resourceId = name2IdMap.get(fullDir);
+        }
+
+        if (resourceId == null) {
+            return -1;
+        } else {
+            return resourceId;
+        }
+    }
+
+    @Override
+    public void delete(String baseDir, List<IODeviceHandle> IODeviceHandles) {
+        String fullDir;
+        synchronized (name2IdMap) {
+            for (IODeviceHandle dev : IODeviceHandles) {
+                fullDir = dev.getPath().toString();
+                if (!fullDir.endsWith(System.getProperty("file.separator"))) {
+                    fullDir += System.getProperty("file.separator");
+                }
+                fullDir += baseDir;
+                name2IdMap.remove(fullDir);
+            }
+        }
+    }
+}
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java
index f98aea2..9d45cb2 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java
@@ -15,18 +15,24 @@
 
 package edu.uci.ics.hyracks.storage.am.common.dataflow;
 
+import java.io.IOException;
+import java.util.List;
+
 import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 import edu.uci.ics.hyracks.api.io.FileReference;
+import edu.uci.ics.hyracks.api.io.IIOManager;
+import edu.uci.ics.hyracks.api.io.IODeviceHandle;
 import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
 import edu.uci.ics.hyracks.storage.am.common.api.IOperationCallbackProvider;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
 import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
+import edu.uci.ics.hyracks.storage.common.file.IIndexArtifactMap;
 
 public abstract class IndexDataflowHelper {
     protected IIndex index;
     protected int indexFileId = -1;
-    
+
     protected final int partition;
     protected final IIndexOperatorDescriptor opDesc;
     protected final IHyracksTaskContext ctx;
@@ -38,50 +44,79 @@
     }
 
     public void init(boolean forceCreate) throws HyracksDataException {
-    	IBufferCache bufferCache = opDesc.getStorageManager().getBufferCache(ctx);
-    	IFileMapProvider fileMapProvider = opDesc.getStorageManager().getFileMapProvider(ctx);
-    	IndexRegistry<IIndex> indexRegistry = opDesc.getIndexRegistryProvider().getRegistry(ctx);
-    	FileReference fileRef = getFilereference();
-    	int fileId = -1;
-    	boolean fileIsMapped = false;
-    	synchronized (fileMapProvider) {
-    		fileIsMapped = fileMapProvider.isMapped(fileRef);
-    		if (!fileIsMapped) {
-    			bufferCache.createFile(fileRef);
-    		}            
-    		fileId = fileMapProvider.lookupFileId(fileRef);
-    		try {
-    	    	// Also creates the file if it doesn't exist yet.
-    			bufferCache.openFile(fileId);
-    		} catch (HyracksDataException e) {
-    			// Revert state of buffer cache since file failed to open.
-    			if (!fileIsMapped) {
-    				bufferCache.deleteFile(fileId, false);
-    			}
-    			throw e;
-    		}
-    	}
-    	// Only set indexFileId member after openFile() succeeds.
-    	indexFileId = fileId;    	
-    	// Create new index instance and register it.
-    	synchronized (indexRegistry) {
-    		// Check if the index has already been registered.
-    		boolean register = false;
-    	    index = indexRegistry.get(indexFileId);
-    		if (index == null) {
-    		    index = createIndexInstance();
-    		    register = true;
-    		}
-    		if (forceCreate) {
-    		    index.create(indexFileId);
-    		}
-    		index.open(indexFileId);
-    		if (register) {
-    		    indexRegistry.register(indexFileId, index);
-    		}
-    	}
+        IBufferCache bufferCache = opDesc.getStorageManager().getBufferCache(ctx);
+        IFileMapProvider fileMapProvider = opDesc.getStorageManager().getFileMapProvider(ctx);
+        IndexRegistry<IIndex> indexRegistry = opDesc.getIndexRegistryProvider().getRegistry(ctx);
+        FileReference fileRef = getFilereference();
+        IIndexArtifactMap indexArtifactMap = opDesc.getStorageManager().getIndexArtifactMap(ctx);
+        int fileId = -1;
+        boolean fileIsMapped = false;
+        synchronized (fileMapProvider) {
+            fileIsMapped = fileMapProvider.isMapped(fileRef);
+            if (!fileIsMapped) {
+                bufferCache.createFile(fileRef);
+            }
+            fileId = fileMapProvider.lookupFileId(fileRef);
+            try {
+                // Also creates the file if it doesn't exist yet.
+                bufferCache.openFile(fileId);
+            } catch (HyracksDataException e) {
+                // Revert state of buffer cache since file failed to open.
+                if (!fileIsMapped) {
+                    bufferCache.deleteFile(fileId, false);
+                }
+                throw e;
+            }
+        }
+
+        // check whether the requested index instance already exists by
+        // retrieving indexRegistry with resourceId
+        // To do so, checking the index directory in the first ioDevice is
+        // sufficient.
+
+        // create a fullDir(= IODeviceDir + baseDir) for the requested index
+        IIOManager ioManager = ctx.getIOManager();
+        List<IODeviceHandle> ioDeviceHandles = ioManager.getIODevices();
+        String fullDir = ioDeviceHandles.get(0).getPath().toString();
+        if (!fullDir.endsWith(System.getProperty("file.separator"))) {
+            fullDir += System.getProperty("file.separator");
+        }
+        String baseDir = fileRef.getFile().getPath();
+        if (!baseDir.endsWith(System.getProperty("file.separator"))) {
+            baseDir += System.getProperty("file.separator");
+        }
+        fullDir += baseDir;
+
+        // get the corresponding resourceId with the fullDir
+        long resourceId = indexArtifactMap.get(fullDir);
+
+        // Only set indexFileId member after openFile() succeeds.
+        indexFileId = fileId;
+        // Create new index instance and register it.
+        synchronized (indexRegistry) {
+            // Check if the index has already been registered.
+            boolean register = false;
+            index = indexRegistry.get(resourceId);
+            if (index == null) {
+                index = createIndexInstance();
+                register = true;
+            }
+            if (forceCreate) {
+                index.create(indexFileId);
+                // Create new resourceId
+                try {
+                    resourceId = indexArtifactMap.create(baseDir, ioDeviceHandles);
+                } catch (IOException e) {
+                    throw new HyracksDataException(e);
+                }
+            }
+            index.open(indexFileId);
+            if (register) {
+                indexRegistry.register(resourceId, index);
+            }
+        }
     }
-    
+
     public abstract IIndex createIndexInstance() throws HyracksDataException;
 
     public FileReference getFilereference() {
@@ -96,7 +131,7 @@
             indexFileId = -1;
         }
     }
-    
+
     public IIndex getIndex() {
         return index;
     }
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexRegistry.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexRegistry.java
index 9aba0be..7a95572 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexRegistry.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexRegistry.java
@@ -19,17 +19,17 @@
 
 public class IndexRegistry<IndexType> {
 
-    private HashMap<Integer, IndexType> map = new HashMap<Integer, IndexType>();
+    private HashMap<Long, IndexType> map = new HashMap<Long, IndexType>();
 
-    public IndexType get(int indexId) {
+    public IndexType get(long indexId) {
         return map.get(indexId);
     }
 
-    public void register(int indexId, IndexType index) {
+    public void register(long indexId, IndexType index) {
         map.put(indexId, index);
     }
 
-    public void unregister(int indexId) {
+    public void unregister(long indexId) {
         map.remove(indexId);
     }
 
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorNodePushable.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorNodePushable.java
index 5c96af8..e866c34 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorNodePushable.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorNodePushable.java
@@ -15,6 +15,7 @@
 
 package edu.uci.ics.hyracks.storage.am.common.dataflow;
 
+import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -23,11 +24,14 @@
 import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 import edu.uci.ics.hyracks.api.io.FileReference;
+import edu.uci.ics.hyracks.api.io.IIOManager;
+import edu.uci.ics.hyracks.api.io.IODeviceHandle;
 import edu.uci.ics.hyracks.dataflow.std.base.AbstractOperatorNodePushable;
 import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
 import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
 import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
+import edu.uci.ics.hyracks.storage.common.file.IIndexArtifactMap;
 
 public class TreeIndexDropOperatorNodePushable extends AbstractOperatorNodePushable {
     private static final Logger LOGGER = Logger.getLogger(TreeIndexDropOperatorNodePushable.class.getName());
@@ -68,8 +72,29 @@
             IndexRegistry<IIndex> treeIndexRegistry = treeIndexRegistryProvider.getRegistry(ctx);
             IBufferCache bufferCache = storageManager.getBufferCache(ctx);
             IFileMapProvider fileMapProvider = storageManager.getFileMapProvider(ctx);
-            
+            IIndexArtifactMap indexArtifactMap = storageManager.getIndexArtifactMap(ctx);
+
             FileReference f = fileSplitProvider.getFileSplits()[partition].getLocalFile();
+
+            //check whether the requested index instance already exists by retrieving indexRegistry with resourceId
+            //To do so, checking the index directory in the first ioDevice is sufficient.
+
+            //create a fullDir(= IODeviceDir + baseDir) for the requested index
+            IIOManager ioManager = ctx.getIOManager();
+            List<IODeviceHandle> ioDeviceHandles = ioManager.getIODevices();
+            String fullDir = ioDeviceHandles.get(0).getPath().toString();
+            if (!fullDir.endsWith(System.getProperty("file.separator"))) {
+                fullDir += System.getProperty("file.separator");
+            }
+            String baseDir = f.getFile().getPath();
+            if (!baseDir.endsWith(System.getProperty("file.separator"))) {
+                baseDir += System.getProperty("file.separator");
+            }
+            fullDir += baseDir;
+
+            //get the corresponding resourceId with the fullDir
+            long resourceId = indexArtifactMap.get(fullDir);
+
             int indexFileId = -1;
             synchronized (fileMapProvider) {
                 boolean fileIsMapped = fileMapProvider.isMapped(f);
@@ -81,7 +106,8 @@
             }
             // Unregister tree instance.
             synchronized (treeIndexRegistry) {
-                treeIndexRegistry.unregister(indexFileId);
+                treeIndexRegistry.unregister(resourceId);
+                indexArtifactMap.delete(baseDir, ioDeviceHandles);
             }
 
             // remove name to id mapping
diff --git a/hyracks-storage-common/src/main/java/edu/uci/ics/hyracks/storage/common/IStorageManagerInterface.java b/hyracks-storage-common/src/main/java/edu/uci/ics/hyracks/storage/common/IStorageManagerInterface.java
index 562305e..aae9d67 100644
--- a/hyracks-storage-common/src/main/java/edu/uci/ics/hyracks/storage/common/IStorageManagerInterface.java
+++ b/hyracks-storage-common/src/main/java/edu/uci/ics/hyracks/storage/common/IStorageManagerInterface.java
@@ -19,9 +19,12 @@
 import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
 import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
+import edu.uci.ics.hyracks.storage.common.file.IIndexArtifactMap;
 
 public interface IStorageManagerInterface extends Serializable {
-    public IBufferCache getBufferCache(IHyracksTaskContext ctx);
+	public IBufferCache getBufferCache(IHyracksTaskContext ctx);
 
-    public IFileMapProvider getFileMapProvider(IHyracksTaskContext ctx);
+	public IFileMapProvider getFileMapProvider(IHyracksTaskContext ctx);
+
+	public IIndexArtifactMap getIndexArtifactMap(IHyracksTaskContext ctx);
 }
\ No newline at end of file
diff --git a/hyracks-storage-common/src/main/java/edu/uci/ics/hyracks/storage/common/file/IIndexArtifactMap.java b/hyracks-storage-common/src/main/java/edu/uci/ics/hyracks/storage/common/file/IIndexArtifactMap.java
new file mode 100644
index 0000000..428d11f
--- /dev/null
+++ b/hyracks-storage-common/src/main/java/edu/uci/ics/hyracks/storage/common/file/IIndexArtifactMap.java
@@ -0,0 +1,54 @@
+/*
+ * 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.hyracks.storage.common.file;
+
+import java.io.IOException;
+import java.util.List;
+
+import edu.uci.ics.hyracks.api.io.IODeviceHandle;
+
+/**
+ * IIndexArtifactMap provides interface to create an index artifact(that is a resourceId, but can be generalized to accommodate any artifact later) and retrieve it.
+ * 
+ * @author kisskys
+ */
+public interface IIndexArtifactMap {
+    /**
+     * Creates an artifact(resourceId) indicated by @param baseDir and @param ioDeviceHandles and return it.
+     * 
+     * @param baseDir
+     * @param ioDeviceHandles
+     * @return a created artifact if it is created successfully.
+     * @throws IOException
+     *             if the corresponding artifact already exists
+     */
+    public long create(String baseDir, List<IODeviceHandle> ioDeviceHandles) throws IOException;
+
+    /**
+     * Retrieves the artifact(resourceId) indicated by @param fullDir
+     * 
+     * @param fullDir
+     * @return the retrieved artifact if it exists, -1 otherwise.
+     */
+    public long get(String fullDir);
+
+    /**
+     * Deletes an artifact(resourceId) indicated by @param baseDir and @param ioDeviceHandles.
+     * 
+     * @param fullDir
+     */
+    public void delete(String baseDir, List<IODeviceHandle> ioDeviceHandles);
+}
diff --git a/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/test/support/TestIndexArtifactMap.java b/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/test/support/TestIndexArtifactMap.java
new file mode 100644
index 0000000..e10ea4e
--- /dev/null
+++ b/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/test/support/TestIndexArtifactMap.java
@@ -0,0 +1,85 @@
+/*
+ * 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.hyracks.test.support;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import edu.uci.ics.hyracks.api.io.IODeviceHandle;
+import edu.uci.ics.hyracks.storage.common.file.IIndexArtifactMap;
+
+public class TestIndexArtifactMap implements IIndexArtifactMap {
+
+    private long counter = 0;
+    private Map<String, Long> name2IdMap = new HashMap<String, Long>();
+
+    @Override
+    public long create(String baseDir, List<IODeviceHandle> IODeviceHandles) throws IOException {
+        long resourceId = counter++;
+        String fullDir;
+        synchronized (name2IdMap) {
+            for (IODeviceHandle dev : IODeviceHandles) {
+                fullDir = dev.getPath().toString();
+                if (!fullDir.endsWith(System.getProperty("file.separator"))) {
+                    fullDir += System.getProperty("file.separator");
+                }
+                fullDir += baseDir;
+                if (name2IdMap.containsKey(fullDir)) {
+                    throw new IOException();
+                }
+                name2IdMap.put(fullDir, resourceId);
+            }
+        }
+        return resourceId;
+    }
+
+    /**
+     * Search and return the resourceId indicated by fullDir from in-memory
+     * hashMap, name2IdMap. When there is no corresponding id in name2IdMap,
+     * return -1;
+     */
+    @Override
+    public long get(String fullDir) {
+        Long resourceId = -1L;
+
+        synchronized (name2IdMap) {
+            resourceId = name2IdMap.get(fullDir);
+        }
+
+        if (resourceId == null) {
+            return -1;
+        } else {
+            return resourceId;
+        }
+    }
+
+    @Override
+    public void delete(String baseDir, List<IODeviceHandle> IODeviceHandles) {
+        String fullDir;
+        synchronized (name2IdMap) {
+            for (IODeviceHandle dev : IODeviceHandles) {
+                fullDir = dev.getPath().toString();
+                if (!fullDir.endsWith(System.getProperty("file.separator"))) {
+                    fullDir += System.getProperty("file.separator");
+                }
+                fullDir += baseDir;
+                name2IdMap.remove(fullDir);
+            }
+        }
+    }
+}
diff --git a/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/test/support/TestStorageManagerComponentHolder.java b/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/test/support/TestStorageManagerComponentHolder.java
index ccbe862..5d250c8 100644
--- a/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/test/support/TestStorageManagerComponentHolder.java
+++ b/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/test/support/TestStorageManagerComponentHolder.java
@@ -33,6 +33,7 @@
 import edu.uci.ics.hyracks.storage.common.buffercache.IPageReplacementStrategy;
 import edu.uci.ics.hyracks.storage.common.file.IFileMapManager;
 import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
+import edu.uci.ics.hyracks.storage.common.file.IIndexArtifactMap;
 import edu.uci.ics.hyracks.storage.common.smi.TransientFileMapManager;
 
 public class TestStorageManagerComponentHolder {
@@ -40,7 +41,8 @@
     private static IFileMapProvider fileMapProvider;
     private static IndexRegistry<IIndex> indexRegistry;
     private static IOManager ioManager;
-    
+    private static IIndexArtifactMap indexArtifactMap;
+
     private static int pageSize;
     private static int numPages;
     private static int maxOpenFiles;
@@ -52,6 +54,7 @@
         bufferCache = null;
         fileMapProvider = null;
         indexRegistry = null;
+        indexArtifactMap = null;
     }
 
     public synchronized static IBufferCache getBufferCache(IHyracksTaskContext ctx) {
@@ -78,13 +81,20 @@
         }
         return indexRegistry;
     }
-    
+
     public synchronized static IOManager getIOManager() throws HyracksException {
-    	if (ioManager == null) {
-    		List<IODeviceHandle> devices = new ArrayList<IODeviceHandle>();
-    		devices.add(new IODeviceHandle(new File(System.getProperty("java.io.tmpdir")), "iodev_test_wa"));
-    		ioManager = new IOManager(devices, Executors.newCachedThreadPool());
-    	}
-    	return ioManager;
+        if (ioManager == null) {
+            List<IODeviceHandle> devices = new ArrayList<IODeviceHandle>();
+            devices.add(new IODeviceHandle(new File(System.getProperty("java.io.tmpdir")), "iodev_test_wa"));
+            ioManager = new IOManager(devices, Executors.newCachedThreadPool());
+        }
+        return ioManager;
+    }
+
+    public synchronized static IIndexArtifactMap getIndexArtifactMap(IHyracksTaskContext ctx) {
+        if (indexArtifactMap == null) {
+            indexArtifactMap = new TestIndexArtifactMap();
+        }
+        return indexArtifactMap;
     }
 }
\ No newline at end of file
diff --git a/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/test/support/TestStorageManagerInterface.java b/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/test/support/TestStorageManagerInterface.java
index 4059ef0..3ee93a4 100644
--- a/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/test/support/TestStorageManagerInterface.java
+++ b/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/test/support/TestStorageManagerInterface.java
@@ -18,6 +18,7 @@
 import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
 import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
+import edu.uci.ics.hyracks.storage.common.file.IIndexArtifactMap;
 
 public class TestStorageManagerInterface implements IStorageManagerInterface {
     private static final long serialVersionUID = 1L;
@@ -31,4 +32,9 @@
     public IFileMapProvider getFileMapProvider(IHyracksTaskContext ctx) {
         return TestStorageManagerComponentHolder.getFileMapProvider(ctx);
     }
+
+    @Override
+    public IIndexArtifactMap getIndexArtifactMap(IHyracksTaskContext ctx) {
+        return TestStorageManagerComponentHolder.getIndexArtifactMap(ctx);
+    }
 }
\ No newline at end of file