package be.bagofwords.db.filedb; import be.bagofwords.ui.UI; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class FileBucket implements Comparable<FileBucket> { private static final int NUMBER_OF_READ_PERMITS = 1000; private long firstKey; //inclusive private long lastKey; //inclusive private List<FileInfo> files; private final ReadWriteLock lock; private boolean shouldBeCleanedBeforeRead; public FileBucket(long firstKey, long lastKey) { this(); this.firstKey = firstKey; this.lastKey = lastKey; this.files = new ArrayList<>(); this.shouldBeCleanedBeforeRead = false; } public List<FileInfo> getFiles() { return files; } public int getFileInd(long key) { if (files.size() < 10) { for (int i = 0; i < files.size(); i++) { if (files.get(i).getFirstKey() > key) { if (i == 0) { throw new RuntimeException("Incorrect bucket starting from " + getFirstKey() + " for key " + key); } else { return i - 1; } } } return files.size() - 1; } else { int pos = Collections.binarySearch((List) files, key); if (pos < 0) { pos = -(pos + 2); } if (pos == -1) { UI.write("ARRAY INDEX OUT OF BOUNDS!!!!"); UI.write("Was looking for key " + key); UI.write("In bucket starting with key " + getFirstKey()); UI.write("In files "); for (FileInfo file : files) { UI.write(" " + file.getFirstKey()); } } return pos; } } public long getFirstKey() { return firstKey; } public FileInfo getFile(long key) { return files.get(getFileInd(key)); } public long getLastKey() { return lastKey; } public void lockRead() { lock.readLock().lock(); } public void unlockRead() { lock.readLock().unlock(); } public void lockWrite() { lock.writeLock().lock(); } public boolean tryLockWrite() { return lock.writeLock().tryLock(); } public void unlockWrite() { lock.writeLock().unlock(); } public String toString() { return super.toString() + " " + firstKey; } @Override public int compareTo(FileBucket o) { return Long.compare(firstKey, o.getFirstKey()); } public boolean shouldBeCleanedBeforeRead() { return shouldBeCleanedBeforeRead; } public void setShouldBeCleanedBeforeRead(boolean shouldBeCleanedBeforeRead) { this.shouldBeCleanedBeforeRead = shouldBeCleanedBeforeRead; } /** * Serialization: */ public FileBucket() { this.lock = new ReentrantReadWriteLock(); } public void setFiles(List<FileInfo> files) { this.files = files; } public boolean isShouldBeCleanedBeforeRead() { return shouldBeCleanedBeforeRead; } public void setFirstKey(long firstKey) { this.firstKey = firstKey; } public void setLastKey(long lastKey) { this.lastKey = lastKey; } }