package org.elasticsearch.common.compress; import com.google.common.collect.ImmutableSet; import org.apache.lucene.store.*; import org.elasticsearch.index.store.support.ForceSyncDirectory; import java.io.IOException; import java.util.Collection; /** */ public class CompressedDirectory extends Directory implements ForceSyncDirectory { private final Directory dir; private final Compressor compressor; private final boolean actualLength; private final ImmutableSet<String> compressExtensions; private final ImmutableSet<String> decompressExtensions; private volatile boolean compress = true; public CompressedDirectory(Directory dir, Compressor compressor, boolean actualLength, String... extensions) { this(dir, compressor, actualLength, extensions, extensions); } public CompressedDirectory(Directory dir, Compressor compressor, boolean actualLength, String[] compressExtensions, String[] decompressExtensions) { this.dir = dir; this.actualLength = actualLength; this.compressor = compressor; this.compressExtensions = ImmutableSet.copyOf(compressExtensions); this.decompressExtensions = ImmutableSet.copyOf(decompressExtensions); this.lockFactory = dir.getLockFactory(); } @Override public String[] listAll() throws IOException { return dir.listAll(); } public void setCompress(boolean compress) { this.compress = compress; } /** * Utility method to return a file's extension. */ public static String getExtension(String name) { int i = name.lastIndexOf('.'); if (i == -1) { return ""; } return name.substring(i + 1, name.length()); } @Override public boolean fileExists(String name) throws IOException { return dir.fileExists(name); } @Override public long fileModified(String name) throws IOException { return dir.fileModified(name); } @Override public void touchFile(String name) throws IOException { dir.touchFile(name); } @Override public void deleteFile(String name) throws IOException { dir.deleteFile(name); } /** * Returns the actual file size, so will work with compound file format * when compressed. Its the only one that really uses it for offsets... */ @Override public long fileLength(String name) throws IOException { if (actualLength && decompressExtensions.contains(getExtension(name))) { IndexInput in = openInput(name); try { return in.length(); } catch (Exception e) { in.close(); } } return dir.fileLength(name); } @Override public void sync(Collection<String> names) throws IOException { dir.sync(names); } @Override public void sync(String name) throws IOException { dir.sync(name); } @Override public void forceSync(String name) throws IOException { if (dir instanceof ForceSyncDirectory) { ((ForceSyncDirectory) dir).forceSync(name); } else { dir.sync(name); } } @Override public IndexInput openInput(String name) throws IOException { if (decompressExtensions.contains(getExtension(name))) { IndexInput in = dir.openInput(name); Compressor compressor1 = CompressorFactory.compressor(in); if (compressor1 != null) { return compressor1.indexInput(in); } else { return in; } } return dir.openInput(name); } @Override public IndexInput openInput(String name, int bufferSize) throws IOException { if (decompressExtensions.contains(getExtension(name))) { IndexInput in = dir.openInput(name, bufferSize); Compressor compressor1 = CompressorFactory.compressor(in); if (compressor1 != null) { return compressor1.indexInput(in); } else { return in; } } return dir.openInput(name, bufferSize); } @Override public IndexOutput createOutput(String name) throws IOException { if (compress && compressExtensions.contains(getExtension(name))) { return compressor.indexOutput(dir.createOutput(name)); } return dir.createOutput(name); } // can't override this one, we need to open the correct compression // @Override // public void copy(Directory to, String src, String dest) throws IOException { // dir.copy(to, src, dest); // } @Override public void close() throws IOException { dir.close(); } @Override public void setLockFactory(LockFactory lockFactory) throws IOException { dir.setLockFactory(lockFactory); } @Override public LockFactory getLockFactory() { return dir.getLockFactory(); } @Override public String getLockID() { return dir.getLockID(); } @Override public Lock makeLock(String name) { return dir.makeLock(name); } @Override public void clearLock(String name) throws IOException { dir.clearLock(name); } @Override public String toString() { return "compressed(" + compressExtensions + "):" + dir.toString(); } }