package de.hub.emffrag.datastore; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.TreeMap; import org.apache.commons.codec.binary.Base32; import com.google.common.base.Throwables; /** * A file system based implementation of {@link IDataStore}. It stores all * fragments in a given directory. * * It has one major flaw: to provide features based on key order, this * implementation maintains a {@link TreeMap} and does not rely on (non * existing) file system features. Thus this implementation will consume main * memory proportionally to number of fragments. * * TODO this implementation is broken. It definitely does not work in linux and * may also not work on other systems. */ public class FileSystemDataStore implements IBaseDataStore { private static final Base32 base32url = new Base32(Integer.MAX_VALUE, new byte[] {}); private final File directory; private final TreeMap<byte[], File> fileTree = new TreeMap<byte[], File>(InMemoryDataStore.byteComparator); public FileSystemDataStore(String name, File directory, boolean clear) { this.directory = directory; if (clear) { for (File file : directory.listFiles()) { file.delete(); } } else { for (File file : directory.listFiles()) { fileTree.put(base32url.decode(file.getName()), file); } } } @Override public void close() { // do nothing } @Override public void flush() { // do nothing } @Override public byte[] ceiling(byte[] key) { return fileTree.ceilingKey(key); } @Override public byte[] floor(byte[] key) { return fileTree.floorKey(key); } @Override public InputStream openInputStream(byte[] key) { String fileName = new String(base32url.encode(key)); File file = new File(directory, fileName); if (!file.exists()) { return null; } try { return new FileInputStream(file); } catch (FileNotFoundException e) { Throwables.propagate(e); return null; } } @Override public OutputStream openOutputStream(byte[] key) { String fileName = new String(base32url.encode(key)); File file = new File(directory, fileName); if (!file.exists()) { try { file.createNewFile(); fileTree.put(base32url.decode(file.getName()), file); } catch (IOException e) { Throwables.propagate(e); } } try { return new FileOutputStream(file); } catch (FileNotFoundException e) { Throwables.propagate(e); return null; } } @Override public boolean check(byte[] key) { String fileName = new String(base32url.encode(key)); File file = new File(directory, fileName); return !file.exists(); } @Override public boolean checkAndCreate(byte[] key) { String fileName = new String(base32url.encode(key)); File file = new File(directory, fileName); if (!file.exists()) { try { file.createNewFile(); fileTree.put(key, file); return true; } catch (IOException e) { Throwables.propagate(e); return false; } } else { return false; } } @Override public void delete(byte[] key) { String fileName = new String(base32url.encode(key)); File file = new File(directory, fileName); if (file.exists()) { file.delete(); fileTree.remove(key); } } @Override public void drop() { throw new UnsupportedOperationException("Not implemented."); } }