001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.needle.gigaspaces.store;
018:
019: import java.io.IOException;
020:
021: import org.apache.lucene.store.IndexInput;
022:
023: /**
024: * An index input using the {@link org.compass.needle.gigaspaces.store.FileEntry} as the
025: * "header" information and load buckets as needed.
026: *
027: * @author kimchy
028: */
029: class GigaSpaceIndexInput extends IndexInput {
030:
031: private GigaSpaceDirectory dir;
032:
033: private FileEntry fileEntry;
034:
035: private long position;
036:
037: private FileBucketEntry bucketEntry;
038:
039: private int currentBucketPosition;
040:
041: public GigaSpaceIndexInput(GigaSpaceDirectory dir,
042: FileEntry fileEntry) {
043: this .dir = dir;
044: this .fileEntry = fileEntry;
045: this .bucketEntry = new FileBucketEntry(fileEntry.indexName,
046: fileEntry.fileName, -1, null);
047: }
048:
049: public void close() throws IOException {
050: }
051:
052: /**
053: * Returns the current position in this file, where the next read will
054: * occur.
055: *
056: * @see #seek(long)
057: */
058: public long getFilePointer() {
059: return this .position;
060: }
061:
062: /**
063: * The number of bytes in the file.
064: */
065: public long length() {
066: return fileEntry.getSize();
067: }
068:
069: /**
070: * Reads and returns a single byte.
071: *
072: * @see org.apache.lucene.store.IndexOutput#writeByte(byte)
073: */
074: public byte readByte() throws IOException {
075: loadBucketIfNeeded();
076: position++;
077: return bucketEntry.data[currentBucketPosition++];
078: }
079:
080: /**
081: * Reads a specified number of bytes into an array at the specified
082: * offset.
083: *
084: * @param b the array to read bytes into
085: * @param offset the offset in the array to start storing bytes
086: * @param len the number of bytes to read
087: * @see org.apache.lucene.store.IndexOutput#writeBytes(byte[],int)
088: */
089: public void readBytes(byte[] b, int offset, int len)
090: throws IOException {
091: loadBucketIfNeeded();
092: // if there is enough place to load at once
093: if (len <= (dir.getBucketSize() - currentBucketPosition)) {
094: if (len > 0) {
095: System.arraycopy(bucketEntry.data,
096: currentBucketPosition, b, offset, len);
097: }
098: currentBucketPosition += len;
099: position += len;
100: return;
101: }
102:
103: // cycle through the reads
104: while (true) {
105: int available = dir.getBucketSize() - currentBucketPosition;
106: int sizeToRead = (len <= available) ? len : available;
107: System.arraycopy(bucketEntry.data, currentBucketPosition,
108: b, offset, sizeToRead);
109: len -= sizeToRead;
110: offset += sizeToRead;
111: position += sizeToRead;
112: currentBucketPosition += sizeToRead;
113: // check if we read enough, if we did, bail
114: if (len <= 0) {
115: break;
116: }
117: loadBucketIfNeeded();
118: }
119: }
120:
121: /**
122: * Sets current position in this file, where the next read will occur.
123: *
124: * @see #getFilePointer()
125: */
126: public void seek(long pos) throws IOException {
127: position = pos;
128: }
129:
130: private void loadBucketIfNeeded()
131: throws GigaSpaceDirectoryException {
132: currentBucketPosition = (int) position % dir.getBucketSize();
133: long bucketIndex = position / dir.getBucketSize();
134: // check if we need to load the bucket
135: if (bucketIndex == bucketEntry.bucketIndex) {
136: return;
137: }
138: // reuse the current bucket entry as the template
139: bucketEntry.data = null;
140: bucketEntry.bucketIndex = bucketIndex;
141: try {
142: bucketEntry = (FileBucketEntry) dir.getSpace().read(
143: bucketEntry, null, 0);
144: } catch (Exception e) {
145: throw new GigaSpaceDirectoryException(fileEntry.indexName,
146: fileEntry.fileName, "Failed to read bucket ["
147: + bucketIndex + "]", e);
148: }
149: if (bucketEntry == null) {
150: throw new GigaSpaceDirectoryException(fileEntry.indexName,
151: fileEntry.fileName, "Bucket [" + bucketIndex
152: + "] not found");
153: }
154: }
155: }
|