001: package org.apache.lucene.store.db;
002:
003: /**
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: import java.io.IOException;
021: import java.io.ByteArrayInputStream;
022: import java.io.DataInputStream;
023: import java.util.Set;
024: import java.util.HashSet;
025: import java.util.List;
026: import java.util.ArrayList;
027: import java.util.Iterator;
028: import java.util.Collections;
029:
030: import org.apache.lucene.store.Directory;
031: import org.apache.lucene.store.Lock;
032: import org.apache.lucene.store.IndexOutput;
033: import org.apache.lucene.store.IndexInput;
034:
035: import com.sleepycat.db.internal.DbEnv;
036: import com.sleepycat.db.internal.Db;
037: import com.sleepycat.db.internal.DbConstants;
038: import com.sleepycat.db.DatabaseEntry;
039: import com.sleepycat.db.internal.Dbc;
040: import com.sleepycat.db.internal.DbTxn;
041: import com.sleepycat.db.DatabaseException;
042:
043: import com.sleepycat.db.Database;
044: import com.sleepycat.db.Transaction;
045: import com.sleepycat.db.DbHandleExtractor;
046:
047: /**
048: * A DbDirectory is a Berkeley DB 4.3 based implementation of
049: * {@link org.apache.lucene.store.Directory Directory}. It uses two
050: * {@link com.sleepycat.db.internal.Db Db} database handles, one for storing file
051: * records and another for storing file data blocks.
052: *
053: * @author Andi Vajda
054: */
055:
056: public class DbDirectory extends Directory {
057:
058: protected Set openFiles = Collections
059: .synchronizedSet(new HashSet());
060: protected Db files, blocks;
061: protected DbTxn txn;
062: protected int flags;
063:
064: /**
065: * Instantiate a DbDirectory. The same threading rules that apply to
066: * Berkeley DB handles apply to instances of DbDirectory.
067: *
068: * @param txn a transaction handle that is going to be used for all db
069: * operations done by this instance. This parameter may be
070: * <code>null</code>.
071: * @param files a db handle to store file records.
072: * @param blocks a db handle to store file data blocks.
073: * @param flags flags used for db read operations.
074: */
075:
076: public DbDirectory(DbTxn txn, Db files, Db blocks, int flags) {
077: super ();
078:
079: this .txn = txn;
080: this .files = files;
081: this .blocks = blocks;
082: this .flags = flags;
083: }
084:
085: public DbDirectory(Transaction txn, Database files,
086: Database blocks, int flags) {
087: super ();
088:
089: this .txn = txn != null ? DbHandleExtractor.getDbTxn(txn) : null;
090: this .files = DbHandleExtractor.getDb(files);
091: this .blocks = DbHandleExtractor.getDb(blocks);
092: this .flags = flags;
093: }
094:
095: public DbDirectory(Transaction txn, Database files, Database blocks) {
096: this (txn, files, blocks, 0);
097: }
098:
099: public void close() throws IOException {
100: flush();
101: }
102:
103: /**
104: * Flush the currently open files. After they have been flushed it is
105: * safe to commit the transaction without closing this DbDirectory
106: * instance first.
107: * @see #setTransaction
108: */
109: public void flush() throws IOException {
110: Iterator iterator = openFiles.iterator();
111:
112: while (iterator.hasNext())
113: ((IndexOutput) iterator.next()).flush();
114: }
115:
116: public IndexOutput createOutput(String name) throws IOException {
117: return new DbIndexOutput(this , name, true);
118: }
119:
120: public void deleteFile(String name) throws IOException {
121: new File(name).delete(this );
122: }
123:
124: public boolean fileExists(String name) throws IOException {
125: return new File(name).exists(this );
126: }
127:
128: public long fileLength(String name) throws IOException {
129: File file = new File(name);
130:
131: if (file.exists(this ))
132: return file.getLength();
133:
134: throw new IOException("File does not exist: " + name);
135: }
136:
137: public long fileModified(String name) throws IOException {
138: File file = new File(name);
139:
140: if (file.exists(this ))
141: return file.getTimeModified();
142:
143: throw new IOException("File does not exist: " + name);
144: }
145:
146: public String[] list() throws IOException {
147: Dbc cursor = null;
148: List list = new ArrayList();
149:
150: try {
151: try {
152: DatabaseEntry key = new DatabaseEntry(new byte[0]);
153: DatabaseEntry data = new DatabaseEntry((byte[]) null);
154:
155: data.setPartial(true);
156:
157: cursor = files.cursor(txn, flags);
158:
159: if (cursor.get(key, data, DbConstants.DB_SET_RANGE
160: | flags) != DbConstants.DB_NOTFOUND) {
161: ByteArrayInputStream buffer = new ByteArrayInputStream(
162: key.getData());
163: DataInputStream in = new DataInputStream(buffer);
164: String name = in.readUTF();
165:
166: in.close();
167: list.add(name);
168:
169: while (cursor.get(key, data, DbConstants.DB_NEXT
170: | flags) != DbConstants.DB_NOTFOUND) {
171: buffer = new ByteArrayInputStream(key.getData());
172: in = new DataInputStream(buffer);
173: name = in.readUTF();
174: in.close();
175:
176: list.add(name);
177: }
178: }
179: } finally {
180: if (cursor != null)
181: cursor.close();
182: }
183: } catch (DatabaseException e) {
184: throw new IOException(e.getMessage());
185: }
186:
187: return (String[]) list.toArray(new String[list.size()]);
188: }
189:
190: public IndexInput openInput(String name) throws IOException {
191: return new DbIndexInput(this , name);
192: }
193:
194: public Lock makeLock(String name) {
195: return new DbLock();
196: }
197:
198: public void renameFile(String from, String to) throws IOException {
199: new File(from).rename(this , to);
200: }
201:
202: public void touchFile(String name) throws IOException {
203: File file = new File(name);
204: long length = 0L;
205:
206: if (file.exists(this ))
207: length = file.getLength();
208:
209: file.modify(this , length, System.currentTimeMillis());
210: }
211:
212: /**
213: * Once a transaction handle was committed it is no longer valid. In
214: * order to continue using this DbDirectory instance after a commit, the
215: * transaction handle has to be replaced.
216: * @param txn the new transaction handle to use
217: */
218: public void setTransaction(Transaction txn) {
219: setTransaction(txn != null ? DbHandleExtractor.getDbTxn(txn)
220: : null);
221: }
222:
223: /**
224: * Once a transaction handle was committed it is no longer valid. In
225: * order to continue using this DbDirectory instance after a commit, the
226: * transaction handle has to be replaced.
227: * @param txn the new transaction handle to use
228: */
229: public void setTransaction(DbTxn txn) {
230: this.txn = txn;
231: }
232: }
|