001: package de.regnis.q.sequence.line;
002:
003: import java.io.File;
004: import java.io.IOException;
005: import java.io.RandomAccessFile;
006: import java.util.ArrayList;
007: import java.util.LinkedList;
008: import java.util.List;
009:
010: import de.regnis.q.sequence.core.QSequenceAssert;
011:
012: /**
013: * @author Marc Strapetz
014: */
015: class QSequenceLineFileSystemCacheSegments {
016:
017: // Fields =================================================================
018:
019: private final QSequenceLineTempDirectoryFactory tempDirectoryFactory;
020: private final int maximumEntriesPerSegment;
021: private final int maximumSegmentsInMemory;
022: private final List segments;
023: private final List memorySegments;
024:
025: private File filePath;
026: private RandomAccessFile file;
027:
028: // Setup ==================================================================
029:
030: public QSequenceLineFileSystemCacheSegments(
031: QSequenceLineTempDirectoryFactory tempDirectoryFactory,
032: int maximumBytesInMemory, int segmentBytesSize) {
033: QSequenceAssert
034: .assertTrue(segmentBytesSize >= QSequenceLineMedia.SEGMENT_ENTRY_SIZE);
035: QSequenceAssert
036: .assertTrue(maximumBytesInMemory >= segmentBytesSize);
037:
038: this .tempDirectoryFactory = tempDirectoryFactory;
039: this .maximumEntriesPerSegment = segmentBytesSize
040: / QSequenceLineMedia.SEGMENT_ENTRY_SIZE;
041: this .maximumSegmentsInMemory = maximumBytesInMemory
042: / (maximumEntriesPerSegment * QSequenceLineMedia.SEGMENT_ENTRY_SIZE);
043: this .segments = new ArrayList();
044: this .memorySegments = new LinkedList();
045:
046: final QSequenceLineFileSystemCacheSegment segment = new QSequenceLineFileSystemCacheSegment(
047: 0, maximumEntriesPerSegment);
048: segments.add(segment);
049: memorySegments.add(segment);
050: }
051:
052: // Accessing ==============================================================
053:
054: public long getFrom(int index) throws IOException {
055: final int segmentIndex = index / maximumEntriesPerSegment;
056: final int relativeIndex = index % maximumEntriesPerSegment;
057: return getSegment(segmentIndex).getFrom(relativeIndex);
058: }
059:
060: public int getLength(int index) throws IOException {
061: final int segmentIndex = index / maximumEntriesPerSegment;
062: final int relativeIndex = index % maximumEntriesPerSegment;
063: return getSegment(segmentIndex).getLength(relativeIndex);
064: }
065:
066: public int getHash(int index) throws IOException {
067: final int segmentIndex = index / maximumEntriesPerSegment;
068: final int relativeIndex = index % maximumEntriesPerSegment;
069: return getSegment(segmentIndex).getHash(relativeIndex);
070: }
071:
072: public void setFromLengthHash(int index, long from, int length,
073: int hash) throws IOException {
074: final int segmentIndex = index / maximumEntriesPerSegment;
075: final int relativeIndex = index % maximumEntriesPerSegment;
076: final QSequenceLineFileSystemCacheSegment segment = getSegment(segmentIndex);
077: segment.setFromLengthHash(relativeIndex, from, length, hash);
078: }
079:
080: public void close() throws IOException {
081: if (file == null) {
082: return;
083: }
084:
085: file.close();
086: filePath.delete();
087: tempDirectoryFactory.close();
088: }
089:
090: // Utils ==================================================================
091:
092: private QSequenceLineFileSystemCacheSegment getSegment(
093: int segmentIndex) throws IOException {
094: if (segmentIndex >= segments.size()) {
095: final QSequenceLineFileSystemCacheSegment segment = new QSequenceLineFileSystemCacheSegment(
096: segmentIndex, maximumEntriesPerSegment);
097: segments.add(segment);
098: memorySegments.add(0, segment);
099: maybeUnloadSegments();
100: return segment;
101: }
102:
103: final QSequenceLineFileSystemCacheSegment segment = (QSequenceLineFileSystemCacheSegment) segments
104: .get(segmentIndex);
105: if (!segment.isLoaded()) {
106: segment.load(getFile());
107: memorySegments.add(0, segment);
108: maybeUnloadSegments();
109: }
110:
111: return segment;
112: }
113:
114: private void maybeUnloadSegments() throws IOException {
115: while (memorySegments.size() > maximumSegmentsInMemory) {
116: final QSequenceLineFileSystemCacheSegment segment = (QSequenceLineFileSystemCacheSegment) memorySegments
117: .remove(memorySegments.size() - 1);
118: segment.unload(getFile());
119: }
120: }
121:
122: private RandomAccessFile getFile() throws IOException {
123: if (file == null) {
124: final File tempDirectory = tempDirectoryFactory
125: .getTempDirectory();
126: if (!tempDirectory.isDirectory()) {
127: tempDirectory.mkdirs();
128: }
129:
130: filePath = File.createTempFile("sequence", null,
131: tempDirectory);
132: file = QSequenceLineRandomAccessFileFactory
133: .createRandomAccessFile(filePath, "rw");
134: }
135:
136: return file;
137: }
138: }
|