001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 2007.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.sail.nativerdf;
007:
008: import java.io.File;
009: import java.io.IOException;
010: import java.io.RandomAccessFile;
011: import java.nio.ByteBuffer;
012: import java.nio.channels.FileChannel;
013: import java.util.NoSuchElementException;
014:
015: import org.openrdf.sail.nativerdf.btree.RecordIterator;
016:
017: /**
018: * A cache for fixed size byte array records. This cache uses a temporary file
019: * to store the records. This file is deleted upon calling {@link #discard()}.
020: *
021: * @author Arjohn Kampman
022: */
023: class SequentialRecordCache extends RecordCache {
024:
025: /*-----------*
026: * Constants *
027: *-----------*/
028:
029: protected final RandomAccessFile raf;
030:
031: protected final FileChannel fileChannel;
032:
033: protected final int recordSize;
034:
035: /*--------------*
036: * Constructors *
037: *--------------*/
038:
039: public SequentialRecordCache(File cacheDir, int recordSize)
040: throws IOException {
041: this (cacheDir, recordSize, Long.MAX_VALUE);
042: }
043:
044: public SequentialRecordCache(File cacheDir, int recordSize,
045: long maxRecords) throws IOException {
046: super (cacheDir, maxRecords);
047:
048: this .recordSize = recordSize;
049: raf = new RandomAccessFile(cacheFile, "rw");
050: fileChannel = raf.getChannel();
051: }
052:
053: /*---------*
054: * Methods *
055: *---------*/
056:
057: @Override
058: public void discard() throws IOException {
059: try {
060: try {
061: fileChannel.close();
062: } finally {
063: raf.close();
064: }
065: } finally {
066: super .discard();
067: }
068: }
069:
070: public void storeRecordInternal(byte[] data) throws IOException {
071: fileChannel.write(ByteBuffer.wrap(data), fileChannel.size());
072: }
073:
074: public RecordIterator getRecordsInternal() {
075: return new RecordCacheIterator();
076: }
077:
078: /*---------------------------------*
079: * Inner class RecordCacheIterator *
080: *---------------------------------*/
081:
082: protected class RecordCacheIterator implements RecordIterator {
083:
084: private long position = 0L;
085:
086: public byte[] next() throws IOException {
087: if (position + recordSize <= fileChannel.size()) {
088: byte[] data = new byte[recordSize];
089: ByteBuffer buf = ByteBuffer.wrap(data);
090:
091: int bytesRead = fileChannel.read(buf, position);
092:
093: if (bytesRead < 0) {
094: throw new NoSuchElementException(
095: "No more elements available");
096: }
097:
098: position += bytesRead;
099:
100: return data;
101: }
102:
103: return null;
104: }
105:
106: public void set(byte[] value) throws IOException {
107: if (position >= recordSize
108: && position <= fileChannel.size()) {
109: fileChannel.write(ByteBuffer.wrap(value), position
110: - recordSize);
111: }
112: }
113:
114: public void close() throws IOException {
115: }
116: }
117: }
|