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.coherence;
018:
019: import java.io.File;
020: import java.io.IOException;
021: import java.io.RandomAccessFile;
022:
023: import org.apache.lucene.store.BufferedIndexOutput;
024:
025: /**
026: * @author kimchy
027: */
028: class CoherenceFileIndexOutput extends BufferedIndexOutput {
029:
030: private CoherenceDirectory dir;
031:
032: private File tempFile;
033:
034: private RandomAccessFile file = null;
035:
036: private String fileName;
037:
038: // remember if the file is open, so that we don't try to close it
039: // more than once
040: private boolean isOpen;
041:
042: public CoherenceFileIndexOutput(CoherenceDirectory dir,
043: String fileName) throws IOException {
044: this .dir = dir;
045: this .fileName = fileName;
046: tempFile = File.createTempFile(dir.getIndexName() + "_"
047: + fileName + "_" + System.currentTimeMillis(),
048: ".lucene-coherencedir");
049: this .file = new RandomAccessFile(tempFile, "rw");
050: isOpen = true;
051: }
052:
053: /**
054: * output methods:
055: */
056: public void flushBuffer(byte[] b, int offset, int size)
057: throws IOException {
058: file.write(b, offset, size);
059: }
060:
061: public void close() throws IOException {
062: // only close the file if it has not been closed yet
063: if (isOpen) {
064: super .close();
065:
066: // this file is overridden by Lucene, so delete it first
067: if (fileName.equals("segments.gen")) {
068: dir.deleteFile(fileName);
069: }
070:
071: // go over the file and write it to the space
072: file.seek(0);
073: byte[] buffer = new byte[dir.getBucketSize()];
074:
075: // TODO consider using transactions to wrap all the writes
076: int offset = 0;
077: int length = dir.getBucketSize();
078: long bucketIndex = 0;
079: while (true) {
080: int sizeRead = file.read(buffer, offset, length);
081: if (sizeRead == -1) {
082: flushBucket(bucketIndex, buffer, offset);
083: break;
084: }
085: offset += sizeRead;
086: length -= sizeRead;
087: if (length <= 0) {
088: flushBucket(bucketIndex++, buffer, dir
089: .getBucketSize());
090: offset = 0;
091: length = dir.getBucketSize();
092: }
093: }
094: FileHeaderKey fileHeaderKey = new FileHeaderKey(dir
095: .getIndexName(), fileName);
096: FileHeaderValue fileHeaderValue = new FileHeaderValue(
097: System.currentTimeMillis(), file.length());
098: dir.getCache().put(fileHeaderKey, fileHeaderValue);
099: file.close();
100: tempFile.delete();
101: isOpen = false;
102: }
103: }
104:
105: /**
106: * Random-access methods
107: */
108: public void seek(long pos) throws IOException {
109: super .seek(pos);
110: file.seek(pos);
111: }
112:
113: public long length() throws IOException {
114: return file.length();
115: }
116:
117: private void flushBucket(long bucketIndex, byte[] buffer, int length)
118: throws IOException {
119: FileBucketKey fileBucketKey = new FileBucketKey(dir
120: .getIndexName(), fileName, bucketIndex);
121: byte[] data = new byte[length];
122: System.arraycopy(buffer, 0, data, 0, length);
123: FileBucketValue fileBucketValue = new FileBucketValue(data);
124: dir.getCache().put(fileBucketKey, fileBucketValue);
125: }
126: }
|