package iitb.con.indexing;
import iitb.con.indexing.isam.ISAMTree;
import iitb.con.indexing.isam.LeafNode;
import iitb.con.io.BufferedFileAdapter;
import iitb.con.io.IOAdapter;
import iitb.con.util.KeyList;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
public class IndexCache {
private Map<String,KeyList> cacheList;
private static final int BLOCK_SIZE = 4096;
private static IndexCache indexCacheInstance = null;
private Map<String, IOAdapter> openedFileCache;
private IndexCache(){
cacheList = new HashMap<String, KeyList>();
openedFileCache = new HashMap<String, IOAdapter>();
}
public static IndexCache getInstance() {
if(indexCacheInstance == null)
indexCacheInstance = new IndexCache();
return indexCacheInstance;
}
public <K extends Comparable<K>> int[] getInstancesIds(short typeId, String attributeName,
K value) {
String fileName = IndexBuilder.getIndexFileName(typeId, attributeName);
String indexName = typeId + "_" + attributeName;
KeyList<K,Short> metaIndex = cacheList.get(indexName);
try {
if(metaIndex != null) {
return getValues(fileName, metaIndex, value);
} else {
if(IndexBuilder.hasIndex(typeId, attributeName)) {
IndexTree<K> isamTree = new ISAMTree(fileName,"r");
metaIndex = isamTree.getMetaIndex(value);
if(metaIndex != null) {
cacheList.put(indexName, metaIndex);
return getValues(fileName, metaIndex, value);
}
isamTree.close();
}else {
return null;
}
}
}catch(IOException ie) {
ie.printStackTrace();
}
return null;
}
private <K extends Comparable<K>> int[] getValues(String fileName, KeyList<K,Short> metaIndex, K key)
throws IOException {
Short blockId = (Short) metaIndex.getPrev(key);
if(blockId != null) {
IOAdapter leafNodesFile = getFile(fileName);
byte[] b = leafNodesFile.read(getLocation(blockId), BLOCK_SIZE);
LeafNode<K> leafNode = new LeafNode<K>(key);
ByteBuffer buf = ByteBuffer.wrap(b);
int blockSize = buf.getInt();
buf.limit(blockSize);
while(buf.hasRemaining()) {
if(leafNode.attributeDeSerialize(buf, key) != null)
return leafNode.instanceId;
}
}
return null;
}
private IOAdapter getFile(String fileName) throws IOException {
if(openedFileCache.containsKey(fileName))
return openedFileCache.get(fileName);
IOAdapter leafNodesFile = new BufferedFileAdapter(fileName + IndexTree.LEAF_EXT, "r");
openedFileCache.put(fileName, leafNodesFile);
return leafNodesFile;
}
private long getLocation(int blockId) {
return ((blockId * BLOCK_SIZE) - BLOCK_SIZE);
}
public void clear(){
cacheList.clear();
openedFileCache.clear();
indexCacheInstance = null;
}
}