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.File;
020: import java.io.IOException;
021: import java.io.RandomAccessFile;
022:
023: import net.jini.core.lease.Lease;
024: import org.apache.lucene.store.BufferedIndexOutput;
025:
026: /**
027: * Writes the output to a file and then when closed will flush it to the Space.
028: *
029: * <p>Not optimial, but allows for random seeking outside of just the first bucket.
030: * Not used since Lucene only seeks to the first buffer (with proper bucket size).
031: *
032: * @author kimchy
033: */
034: class GigaSpaceFileIndexOutput extends BufferedIndexOutput {
035:
036: private GigaSpaceDirectory dir;
037:
038: private File tempFile;
039:
040: private RandomAccessFile file = null;
041:
042: private String fileName;
043:
044: // remember if the file is open, so that we don't try to close it
045: // more than once
046: private boolean isOpen;
047:
048: public GigaSpaceFileIndexOutput(GigaSpaceDirectory dir,
049: String fileName) throws IOException {
050: this .dir = dir;
051: this .fileName = fileName;
052: tempFile = File.createTempFile(dir.getIndexName() + "_"
053: + fileName + "_" + System.currentTimeMillis(),
054: ".lucene-gigaspacesdir");
055: this .file = new RandomAccessFile(tempFile, "rw");
056: isOpen = true;
057: }
058:
059: /**
060: * output methods:
061: */
062: public void flushBuffer(byte[] b, int offset, int size)
063: throws IOException {
064: file.write(b, offset, size);
065: }
066:
067: public void close() throws IOException {
068: // only close the file if it has not been closed yet
069: if (isOpen) {
070: super .close();
071:
072: // this file is overridden by Lucene, so delete it first
073: if (fileName.equals("segments.gen")) {
074: dir.deleteFile(fileName);
075: }
076:
077: // go over the file and write it to the space
078: file.seek(0);
079: byte[] buffer = new byte[dir.getBucketSize()];
080:
081: // TODO consider using transactions to wrap all the writes
082: int offset = 0;
083: int length = dir.getBucketSize();
084: long bucketIndex = 0;
085: while (true) {
086: int sizeRead = file.read(buffer, offset, length);
087: if (sizeRead == -1) {
088: flushBucket(bucketIndex, buffer, offset);
089: break;
090: }
091: offset += sizeRead;
092: length -= sizeRead;
093: if (length <= 0) {
094: flushBucket(bucketIndex++, buffer, dir
095: .getBucketSize());
096: offset = 0;
097: length = dir.getBucketSize();
098: }
099: }
100: try {
101: dir.getSpace().write(
102: new FileEntry(dir.getIndexName(), fileName,
103: file.length()), null, Lease.FOREVER);
104: } catch (Exception e) {
105: throw new GigaSpaceDirectoryException(dir
106: .getIndexName(), fileName,
107: "Failed to write file entry", e);
108: }
109: file.close();
110: tempFile.delete();
111: isOpen = false;
112: }
113: }
114:
115: /**
116: * Random-access methods
117: */
118: public void seek(long pos) throws IOException {
119: super .seek(pos);
120: file.seek(pos);
121: }
122:
123: public long length() throws IOException {
124: return file.length();
125: }
126:
127: private void flushBucket(long bucketIndex, byte[] buffer, int length)
128: throws IOException {
129: FileBucketEntry fileBucketEntry = new FileBucketEntry(dir
130: .getIndexName(), fileName, bucketIndex, null);
131: fileBucketEntry.data = new byte[length];
132: System.arraycopy(buffer, 0, fileBucketEntry.data, 0, length);
133: try {
134: dir.getSpace().write(fileBucketEntry, null, Lease.FOREVER);
135: } catch (Exception e) {
136: throw new GigaSpaceDirectoryException(dir.getIndexName(),
137: fileName, "Failed to write bucket [" + bucketIndex
138: + "]", e);
139: }
140: }
141: }
|