package iitb.con.ds;
import iitb.con.core.ConStoreConstants;
import iitb.con.core.Instance;
import iitb.con.core.Type;
import iitb.con.io.BufferedFileAdapter;
import iitb.con.io.IOAdapter;
import iitb.con.util.ArrayFreeSpaceList;
import iitb.con.util.FreeSpaceList;
import iitb.con.util.MultiKeyHashMap;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
public class InstanceTable implements ItemTable<Short, Integer, InstanceMetaItem> {
private IOAdapter ntabFile;
private IOAdapter netFile;
private FreeSpaceList nfsList;
private ItemTable<String, Short, Type> typeTable;
private ActionBufferList<InstanceMetaItem> instanceBufferList;
private MultiKeyHashMap<Short, Integer, InstanceMetaItem> instanceItemTable;
ItemSerializer<Instance> instanceSerializer;
public InstanceTable(String dirName, String mode)
throws FileNotFoundException, IOException
{
ntabFile = new BufferedFileAdapter(dirName + ConStoreConstants.INSTANCE_TABLE_FILE, mode);
typeTable = TypeTableFactory.getTypeTable(dirName + ConStoreConstants.META_FILE, mode);
netFile = new BufferedFileAdapter(dirName + ConStoreConstants.NET_FILE, mode);
nfsList = new ArrayFreeSpaceList(dirName + ConStoreConstants.NET_FSL_FILE, mode);
instanceBufferList = new ActionBufferList<InstanceMetaItem>();
instanceItemTable = new MultiKeyHashMap<Short, Integer, InstanceMetaItem>();
instanceSerializer = new InstanceSerializer(typeTable);
}
public void commit() throws IOException {
for(InstanceMetaItem item : instanceBufferList.getRemoveList()) {
nfsList.freeTheBlock(item.location, item.size);
ByteBuffer buf = ByteBuffer.allocate(InstanceMetaItem.headerSize());
buf.putShort((short)0);
buf.putShort((short)-1);
buf.putInt(0);
buf.putLong(0);
buf.putInt(0);
buf.rewind();
ntabFile.write(buf, item.itemLocation);
instanceItemTable.remove(item.typeId,item.instanceId);
}
for(InstanceMetaItem item : instanceBufferList.getAddList()) {
long location = nfsList.getFreeBlock(item.size);
item.location = location;
netFile.write(item.instanceBytes, location);
item.instance = null;
item.instanceBytes = null;
this.setItem(item.typeId,item.instanceId, item);
writeInstanceMetaItem(item);
}
for(InstanceMetaItem item : instanceBufferList.getUpdateList()) {
netFile.write(item.instanceBytes, item.location);
item.instance = null;
item.instanceBytes = null;
this.setItem(item.typeId,item.instanceId, item);
writeInstanceMetaItem(item);
}
for(InstanceMetaItem item : instanceBufferList.getMetaUpdateList()) {
this.setItem(item.typeId,item.instanceId, item);
writeInstanceMetaItem(item);
}
nfsList.commit();
instanceBufferList.clear();
}
private void writeInstanceMetaItem(InstanceMetaItem item) throws IOException {
ByteBuffer buf = ByteBuffer.allocate(InstanceMetaItem.headerSize());
buf.putShort(item.typeId);
buf.putShort(item.clusterId);
buf.putInt(item.instanceId);
buf.putLong(item.location);
buf.putInt(item.size);
buf.rewind();
if(item.itemLocation < 0)
item.itemLocation = ntabFile.getFileLength();
ntabFile.write(buf, item.itemLocation);
}
public InstanceMetaItem get(Short typeId, Integer instanceId) {
return instanceItemTable.get(typeId, instanceId);
}
public Map<Integer, InstanceMetaItem> get(Short typeId) {
return instanceItemTable.get(typeId);
}
public InstanceMetaItem get(Integer instanceId) {
return instanceItemTable.getBySubKey(instanceId);
}
public Object getObject(Object o) {
if(o instanceof Short)
return instanceItemTable.get((Short)o);
return null;
}
public List<InstanceMetaItem> getAllItems() {
return instanceItemTable.getAllItems();
}
public void setItem(Short typeId, Integer instanceId, InstanceMetaItem item ){
instanceItemTable.put(typeId,instanceId, item);
}
public void put(Short typeId, Integer instanceId, InstanceMetaItem item){
this.put(item);
}
public void put(Short typeId, InstanceMetaItem item) {
this.put(item);
}
public void put(InstanceMetaItem item) {
if(item.instance == null) {
instanceBufferList.add(item, item.size, ActionBufferList.Action.UPDATE_META);
} else {
item.instanceBytes = instanceSerializer.serialize(item.instance);
if(!instanceItemTable.containsKey(item.typeId,item.instanceId)) {
item.size = item.instanceBytes.capacity();
instanceBufferList.add(item, item.size, ActionBufferList.Action.ADD);
}
else{
if(item.size == item.instanceBytes.capacity())
instanceBufferList.add(item, item.size, ActionBufferList.Action.UPDATE);
else {
remove(item);
item.size = item.instanceBytes.capacity();
instanceBufferList.add(item, item.size, ActionBufferList.Action.ADD);
}
}
}
}
public boolean remove(Integer instanceId) {
InstanceMetaItem item = get(instanceId);
if(item != null)
return remove(item);
return false;
}
public boolean remove(Short typeId, Integer instanceId) {
instanceItemTable.containsKey(typeId, instanceId);
InstanceMetaItem item = instanceItemTable.get(typeId, instanceId);
if(item != null)
return remove(item);
return false;
}
public boolean remove(InstanceMetaItem item){
InstanceMetaItem tempItem = new InstanceMetaItem(item);
return instanceBufferList.add(tempItem,tempItem.size,ActionBufferList.Action.REMOVE);
}
public void close() throws IOException
{
if(ntabFile != null)
ntabFile.close();
if(netFile != null)
netFile.close();
if(nfsList != null)
nfsList.close();
instanceItemTable.clear();
instanceBufferList.clear();
}
public int size() {
return instanceItemTable.size();
}
}