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.apache.lucene.store.jdbc.index;
018:
019: import java.io.IOException;
020:
021: import org.apache.lucene.store.IndexOutput;
022: import org.apache.lucene.store.jdbc.JdbcDirectory;
023: import org.apache.lucene.store.jdbc.JdbcFileEntrySettings;
024:
025: /**
026: * An <code>IndexOutput</code> implementation that initially writes the data to a memory buffer. Once it exceeds
027: * the configured threshold ({@link #INDEX_OUTPUT_THRESHOLD_SETTING}, will start working with a temporary file,
028: * releasing the previous buffer.
029: *
030: * @author kimchy
031: */
032: public class RAMAndFileJdbcIndexOutput extends IndexOutput implements
033: JdbcIndexConfigurable {
034:
035: /**
036: * The threshold setting name. See {@link JdbcFileEntrySettings#setLongSetting(String, long)}.
037: * Should be set in bytes.
038: */
039: public static final String INDEX_OUTPUT_THRESHOLD_SETTING = "indexOutput.threshold";
040:
041: /**
042: * The default value for the threshold (in bytes). Currently 16K.
043: */
044: public static final long DEFAULT_THRESHOLD = 16 * 1024;
045:
046: private long threshold;
047:
048: private RAMJdbcIndexOutput ramIndexOutput;
049:
050: private FileJdbcIndexOutput fileIndexOutput;
051:
052: private JdbcDirectory jdbcDirectory;
053:
054: private String name;
055:
056: private JdbcFileEntrySettings settings;
057:
058: private long position;
059:
060: public void configure(String name, JdbcDirectory jdbcDirectory,
061: JdbcFileEntrySettings settings) throws IOException {
062: this .jdbcDirectory = jdbcDirectory;
063: this .name = name;
064: this .settings = settings;
065: this .threshold = settings.getSettingAsLong(
066: INDEX_OUTPUT_THRESHOLD_SETTING, DEFAULT_THRESHOLD);
067: ramIndexOutput = createRamJdbcIndexOutput();
068: ramIndexOutput.configure(name, jdbcDirectory, settings);
069: }
070:
071: public void writeByte(byte b) throws IOException {
072: switchIfNeeded(1).writeByte(b);
073: }
074:
075: public void writeBytes(byte[] b, int offset, int length)
076: throws IOException {
077: switchIfNeeded(length).writeBytes(b, offset, length);
078: }
079:
080: public void flush() throws IOException {
081: actualOutput().flush();
082: }
083:
084: public void close() throws IOException {
085: actualOutput().close();
086: }
087:
088: public long getFilePointer() {
089: return actualOutput().getFilePointer();
090: }
091:
092: public void seek(long pos) throws IOException {
093: position = pos;
094: actualOutput().seek(pos);
095: }
096:
097: public long length() throws IOException {
098: return actualOutput().length();
099: }
100:
101: private IndexOutput actualOutput() {
102: if (fileIndexOutput != null) {
103: return fileIndexOutput;
104: }
105: return ramIndexOutput;
106: }
107:
108: private IndexOutput switchIfNeeded(int length) throws IOException {
109: if (fileIndexOutput != null) {
110: return fileIndexOutput;
111: }
112: position += length;
113: if (position < threshold) {
114: return ramIndexOutput;
115: }
116: fileIndexOutput = createFileJdbcIndexOutput();
117: fileIndexOutput.configure(name, jdbcDirectory, settings);
118: ramIndexOutput.flushToIndexOutput(fileIndexOutput);
119: // let it be garbage collected
120: ramIndexOutput = null;
121:
122: return fileIndexOutput;
123: }
124:
125: protected FileJdbcIndexOutput createFileJdbcIndexOutput() {
126: return new FileJdbcIndexOutput();
127: }
128:
129: protected RAMJdbcIndexOutput createRamJdbcIndexOutput() {
130: return new RAMJdbcIndexOutput();
131: }
132: }
|