You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2008/11/17 12:03:42 UTC
svn commit: r718218 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/query/lucene/
main/java/org/apache/jackrabbit/core/query/lucene/directory/
test/java/org/apache/jackrabbit/core/query/lucene/directory/
Author: mreutegg
Date: Mon Nov 17 03:03:41 2008
New Revision: 718218
URL: http://svn.apache.org/viewvc?rev=718218&view=rev
Log:
JCR-1747: org.apache.jackrabbit.core.query.lucene.SearchIndex with in-memory lucene index
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/DirectoryManager.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/FSDirectoryManager.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/IndexInputStream.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/IndexOutputStream.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/RAMDirectoryManager.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/DirectoryManagerTest.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/IndexInputStreamTest.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/IndexOutputStreamTest.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/TestAll.java (with props)
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexInfos.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexMigration.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexingQueueStore.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndex.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PersistentIndex.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/RedoLog.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexInfos.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexInfos.java?rev=718218&r1=718217&r2=718218&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexInfos.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexInfos.java Mon Nov 17 03:03:41 2008
@@ -19,16 +19,17 @@
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.InputStream;
-import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
+import org.apache.lucene.store.Directory;
+import org.apache.jackrabbit.core.query.lucene.directory.IndexInputStream;
+import org.apache.jackrabbit.core.query.lucene.directory.IndexOutputStream;
+
/**
* Stores a sequence of index names.
*/
@@ -74,9 +75,10 @@
*
* @param dir the directory where to look for the index infos.
* @return <code>true</code> if it exists; <code>false</code> otherwise.
+ * @throws IOException if an error occurs while reading from the directory.
*/
- boolean exists(File dir) {
- return new File(dir, name).exists();
+ boolean exists(Directory dir) throws IOException {
+ return dir.fileExists(name);
}
/**
@@ -94,8 +96,8 @@
* @param dir the directory from where to read the index infos.
* @throws IOException if an error occurs.
*/
- void read(File dir) throws IOException {
- InputStream in = new FileInputStream(new File(dir, name));
+ void read(Directory dir) throws IOException {
+ InputStream in = new IndexInputStream(dir.openInput(name));
try {
DataInputStream di = new DataInputStream(in);
counter = di.readInt();
@@ -115,14 +117,13 @@
* @param dir the directory where to write the index infos.
* @throws IOException if an error occurs.
*/
- void write(File dir) throws IOException {
+ void write(Directory dir) throws IOException {
// do not write if not dirty
if (!dirty) {
return;
}
- File nu = new File(dir, name + ".new");
- OutputStream out = new FileOutputStream(nu);
+ OutputStream out = new IndexOutputStream(dir.createOutput(name + ".new"));
try {
DataOutputStream dataOut = new DataOutputStream(out);
dataOut.writeInt(counter);
@@ -134,13 +135,10 @@
out.close();
}
// delete old
- File old = new File(dir, name);
- if (old.exists() && !old.delete()) {
- throw new IOException("Unable to delete file: " + old.getAbsolutePath());
- }
- if (!nu.renameTo(old)) {
- throw new IOException("Unable to rename file: " + nu.getAbsolutePath());
+ if (dir.fileExists(name)) {
+ dir.deleteFile(name);
}
+ dir.renameFile(name + ".new", name);
dirty = false;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexMigration.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexMigration.java?rev=718218&r1=718217&r2=718218&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexMigration.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexMigration.java Mon Nov 17 03:03:41 2008
@@ -23,18 +23,16 @@
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.TermPositions;
import org.apache.lucene.index.IndexWriter;
-import org.apache.lucene.store.FSDirectory;
-import org.apache.lucene.store.NoLockFactory;
+import org.apache.lucene.store.Directory;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.FieldSelector;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.document.Field;
-import org.apache.jackrabbit.core.fs.local.FileUtil;
+import org.apache.jackrabbit.core.query.lucene.directory.DirectoryManager;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import java.io.IOException;
-import java.io.File;
/**
* <code>IndexMigration</code> implements a utility that migrates a Jackrabbit
@@ -56,11 +54,14 @@
* Checks if the given <code>index</code> needs to be migrated.
*
* @param index the index to check and migration if needed.
- * @param indexDir the directory where the index is stored.
+ * @param directoryManager the directory manager.
* @throws IOException if an error occurs while migrating the index.
*/
- public static void migrate(PersistentIndex index, File indexDir) throws IOException {
- log.debug("Checking {} ...", indexDir.getAbsolutePath());
+ public static void migrate(PersistentIndex index,
+ DirectoryManager directoryManager)
+ throws IOException {
+ Directory indexDir = index.getDirectory();
+ log.debug("Checking {} ...", indexDir);
ReadOnlyIndexReader reader = index.getReadOnlyIndexReader();
try {
if (IndexFormatVersion.getVersion(reader).getVersion() >=
@@ -87,24 +88,20 @@
}
// if we get here then the index must be migrated
- log.debug("Index requires migration {}", indexDir.getAbsolutePath());
+ log.debug("Index requires migration {}", indexDir);
// make sure readers are closed, otherwise the directory
// cannot be deleted
index.releaseWriterAndReaders();
- File migrationDir = new File(indexDir.getAbsoluteFile().getParentFile(), indexDir.getName() + "_v2.3");
- if (migrationDir.exists()) {
- FileUtil.delete(migrationDir);
- }
- if (!migrationDir.mkdirs()) {
- throw new IOException("failed to create directory " +
- migrationDir.getAbsolutePath());
+ String migrationName = index.getName() + "_v2.3";
+ if (directoryManager.hasDirectory(migrationName)) {
+ directoryManager.delete(migrationName);
}
- FSDirectory fsDir = FSDirectory.getDirectory(migrationDir,
- NoLockFactory.getNoLockFactory());
+
+ Directory migrationDir = directoryManager.getDirectory(migrationName);
try {
- IndexWriter writer = new IndexWriter(fsDir, new JackrabbitAnalyzer());
+ IndexWriter writer = new IndexWriter(migrationDir, new JackrabbitAnalyzer());
try {
IndexReader r = new MigrationIndexReader(
IndexReader.open(index.getDirectory()));
@@ -118,14 +115,14 @@
writer.close();
}
} finally {
- fsDir.close();
+ migrationDir.close();
}
- FileUtil.delete(indexDir);
- if (!migrationDir.renameTo(indexDir)) {
+ directoryManager.delete(index.getName());
+ if (!directoryManager.rename(migrationName, index.getName())) {
throw new IOException("failed to move migrated directory " +
- migrationDir.getAbsolutePath());
+ migrationDir);
}
- log.info("Migrated " + indexDir.getAbsolutePath());
+ log.info("Migrated " + index.getName());
}
//---------------------------< internal helper >----------------------------
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexingQueueStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexingQueueStore.java?rev=718218&r1=718217&r2=718218&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexingQueueStore.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexingQueueStore.java Mon Nov 17 03:03:41 2008
@@ -16,8 +16,8 @@
*/
package org.apache.jackrabbit.core.query.lucene;
-import org.apache.jackrabbit.core.fs.FileSystem;
-import org.apache.jackrabbit.core.fs.FileSystemException;
+import org.apache.jackrabbit.core.query.lucene.directory.IndexInputStream;
+import org.apache.lucene.store.Directory;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
@@ -31,7 +31,7 @@
/**
* <code>IndexingQueueStore</code> implements a store that keeps the uuids of
* nodes that are pending in the indexing queue. Until Jackrabbit 1.4 this store
- * was also persisted to a {@link FileSystem}. Starting with 1.5 the pending
+ * was also persisted to disk. Starting with 1.5 the pending
* nodes are marked directly in the index with a special field.
* See {@link FieldNames#REINDEXING_REQUIRED}.
*/
@@ -58,33 +58,28 @@
private static final String REMOVE = "REMOVE";
/**
- * The UUID Strings of the pending documents.
+ * Name of the file that contains the indexing queue log.
*/
- private final Set pending = new HashSet();
+ private static final String INDEXING_QUEUE_FILE = "indexing_queue.log";
/**
- * The file system from where to read pending document UUIDs.
+ * The UUID Strings of the pending documents.
*/
- private final FileSystem fs;
+ private final Set pending = new HashSet();
/**
- * The name of the file for the pending document UUIDs.
+ * The directory from where to read pending document UUIDs.
*/
- private final String fileName;
+ private final Directory dir;
/**
- * Creates a new <code>IndexingQueueStore</code> using the given file
- * system.
+ * Creates a new <code>IndexingQueueStore</code> using the given directory.
*
- * @param fs the file system to use.
- * @param fileName the name of the file where to write the pending UUIDs
- * to.
- * @throws FileSystemException if an error ocurrs while reading pending
- * UUIDs.
- */
- IndexingQueueStore(FileSystem fs, String fileName) throws FileSystemException {
- this.fs = fs;
- this.fileName = fileName;
+ * @param directory the directory to use.
+ * @throws IOException if an error ocurrs while reading pending UUIDs.
+ */
+ IndexingQueueStore(Directory directory) throws IOException {
+ this.dir = directory;
readStore();
}
@@ -119,11 +114,11 @@
public void close() {
if (pending.isEmpty()) {
try {
- if (fs.exists(fileName)) {
- fs.deleteFile(fileName);
+ if (dir.fileExists(INDEXING_QUEUE_FILE)) {
+ dir.deleteFile(INDEXING_QUEUE_FILE);
}
- } catch (FileSystemException e) {
- log.warn("unable to delete " + fileName);
+ } catch (IOException e) {
+ log.warn("unable to delete " + INDEXING_QUEUE_FILE);
}
}
}
@@ -134,39 +129,35 @@
* Reads all pending UUIDs from the file and puts them into {@link
* #pending}.
*
- * @throws FileSystemException if an error occurs while reading.
+ * @throws IOException if an error occurs while reading.
*/
- private void readStore() throws FileSystemException {
- if (fs.exists(fileName)) {
+ private void readStore() throws IOException {
+ if (dir.fileExists(INDEXING_QUEUE_FILE)) {
+ InputStream in = new IndexInputStream(dir.openInput(INDEXING_QUEUE_FILE));
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(in, ENCODING));
try {
- InputStream in = fs.getInputStream(fileName);
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(in, ENCODING));
- try {
- String line;
- while ((line = reader.readLine()) != null) {
- int idx = line.indexOf(' ');
- if (idx == -1) {
- // invalid line
- log.warn("invalid line in {}: {}", fileName, line);
+ String line;
+ while ((line = reader.readLine()) != null) {
+ int idx = line.indexOf(' ');
+ if (idx == -1) {
+ // invalid line
+ log.warn("invalid line in {}: {}", INDEXING_QUEUE_FILE, line);
+ } else {
+ String cmd = line.substring(0, idx);
+ String uuid = line.substring(idx + 1, line.length());
+ if (ADD.equals(cmd)) {
+ pending.add(uuid);
+ } else if (REMOVE.equals(cmd)) {
+ pending.remove(uuid);
} else {
- String cmd = line.substring(0, idx);
- String uuid = line.substring(idx + 1, line.length());
- if (ADD.equals(cmd)) {
- pending.add(uuid);
- } else if (REMOVE.equals(cmd)) {
- pending.remove(uuid);
- } else {
- // invalid line
- log.warn("invalid line in {}: {}", fileName, line);
- }
+ // invalid line
+ log.warn("invalid line in {}: {}", INDEXING_QUEUE_FILE, line);
}
}
- } finally {
- in.close();
}
- } catch (IOException e) {
- throw new FileSystemException(e.getMessage(), e);
+ } finally {
+ in.close();
}
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndex.java?rev=718218&r1=718217&r2=718218&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndex.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndex.java Mon Nov 17 03:03:41 2008
@@ -17,8 +17,7 @@
package org.apache.jackrabbit.core.query.lucene;
import org.apache.jackrabbit.core.NodeId;
-import org.apache.jackrabbit.core.fs.FileSystemException;
-import org.apache.jackrabbit.core.fs.local.LocalFileSystem;
+import org.apache.jackrabbit.core.query.lucene.directory.DirectoryManager;
import org.apache.jackrabbit.core.state.ItemStateException;
import org.apache.jackrabbit.core.state.ItemStateManager;
import org.apache.jackrabbit.core.state.NoSuchItemStateException;
@@ -35,11 +34,10 @@
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
+import org.apache.lucene.store.Directory;
import javax.jcr.RepositoryException;
import java.io.IOException;
-import java.io.File;
-import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -90,16 +88,6 @@
private static final PathFactory PATH_FACTORY = PathFactoryImpl.getInstance();
/**
- * Default name of the redo log file
- */
- private static final String REDO_LOG = "redo.log";
-
- /**
- * Name of the file that contains the indexing queue log.
- */
- private static final String INDEXING_QUEUE_FILE = "indexing_queue.log";
-
- /**
* Names of active persistent index directories.
*/
private final IndexInfos indexNames = new IndexInfos("indexes");
@@ -123,9 +111,14 @@
private final NamespaceMappings nsMappings;
/**
- * The base filesystem to store the index.
+ * The directory manager.
+ */
+ private final DirectoryManager directoryManager;
+
+ /**
+ * The base directory to store the index.
*/
- private final File indexDir;
+ private final Directory indexDir;
/**
* The query handler
@@ -223,24 +216,20 @@
/**
* Creates a new MultiIndex.
*
- * @param indexDir the base file system
* @param handler the search handler
* @param excludedIDs Set<NodeId> that contains uuids that should not
* be indexed nor further traversed.
- * @param mapping the namespace mapping to use
* @throws IOException if an error occurs
*/
- MultiIndex(File indexDir,
- SearchIndex handler,
- Set excludedIDs,
- NamespaceMappings mapping) throws IOException {
-
- this.indexDir = indexDir;
+ MultiIndex(SearchIndex handler,
+ Set excludedIDs) throws IOException {
+ this.directoryManager = handler.getDirectoryManager();
+ this.indexDir = directoryManager.getDirectory(".");
this.handler = handler;
this.cache = new DocNumberCache(handler.getCacheSize());
- this.redoLog = new RedoLog(new File(indexDir, REDO_LOG));
+ this.redoLog = new RedoLog(indexDir);
this.excludedIDs = new HashSet(excludedIDs);
- this.nsMappings = mapping;
+ this.nsMappings = handler.getNamespaceMappings();
if (indexNames.exists(indexDir)) {
indexNames.read(indexDir);
@@ -255,34 +244,26 @@
merger.setMergeFactor(handler.getMergeFactor());
merger.setMinMergeDocs(handler.getMinMergeDocs());
- IndexingQueueStore store;
- try {
- LocalFileSystem fs = new LocalFileSystem();
- fs.setRoot(indexDir);
- fs.init();
- store = new IndexingQueueStore(fs, INDEXING_QUEUE_FILE);
- } catch (FileSystemException e) {
- throw Util.createIOException(e);
- }
+ IndexingQueueStore store = new IndexingQueueStore(indexDir);
// initialize indexing queue
this.indexingQueue = new IndexingQueue(store);
// open persistent indexes
for (int i = 0; i < indexNames.size(); i++) {
- File sub = new File(indexDir, indexNames.getName(i));
+ String name = indexNames.getName(i);
// only open if it still exists
// it is possible that indexNames still contains a name for
// an index that has been deleted, but indexNames has not been
// written to disk.
- if (!sub.exists()) {
- log.debug("index does not exist anymore: " + sub.getAbsolutePath());
+ if (!directoryManager.hasDirectory(name)) {
+ log.debug("index does not exist anymore: " + name);
// move on to next index
continue;
}
- PersistentIndex index = new PersistentIndex(indexNames.getName(i),
- sub, handler.getTextAnalyzer(), handler.getSimilarity(),
- cache, indexingQueue);
+ PersistentIndex index = new PersistentIndex(name,
+ handler.getTextAnalyzer(), handler.getSimilarity(),
+ cache, indexingQueue, directoryManager);
index.setMaxMergeDocs(handler.getMaxMergeDocs());
index.setMergeFactor(handler.getMergeFactor());
index.setMinMergeDocs(handler.getMinMergeDocs());
@@ -580,16 +561,14 @@
}
// otherwise open / create it
- File sub;
if (indexName == null) {
- sub = newIndexFolder();
- indexName = sub.getName();
- } else {
- sub = new File(indexDir, indexName);
+ do {
+ indexName = indexNames.newName();
+ } while (directoryManager.hasDirectory(indexName));
}
- PersistentIndex index = new PersistentIndex(indexName, sub,
+ PersistentIndex index = new PersistentIndex(indexName,
handler.getTextAnalyzer(), handler.getSimilarity(),
- cache, indexingQueue);
+ cache, indexingQueue, directoryManager);
index.setMaxMergeDocs(handler.getMaxMergeDocs());
index.setMergeFactor(handler.getMergeFactor());
index.setMinMergeDocs(handler.getMinMergeDocs());
@@ -608,8 +587,10 @@
*
* @param indexName the name of the index segment.
* @return <code>true</code> if it exists; otherwise <code>false</code>.
+ * @throws IOException if an error occurs while checking existence of
+ * directory.
*/
- synchronized boolean hasIndex(String indexName) {
+ synchronized boolean hasIndex(String indexName) throws IOException {
// check existing
for (Iterator it = indexes.iterator(); it.hasNext();) {
PersistentIndex idx = (PersistentIndex) it.next();
@@ -618,7 +599,7 @@
}
}
// check if it exists on disk
- return new File(indexDir, indexName).exists();
+ return directoryManager.hasDirectory(indexName);
}
/**
@@ -920,18 +901,15 @@
* Enqueues unused segments for deletion in {@link #deletable}. This method
* does not synchronize on {@link #deletable}! A caller must ensure that it
* is the only one acting on the {@link #deletable} map.
+ *
+ * @throws IOException if an error occurs while reading directories.
*/
- private void enqueueUnusedSegments() {
+ private void enqueueUnusedSegments() throws IOException {
// walk through index segments
- File[] segmentDirs = indexDir.listFiles(new FileFilter() {
- public boolean accept(File pathname) {
- return pathname.isDirectory() && pathname.getName().startsWith("_");
- }
- });
- for (int i = 0; i < segmentDirs.length; i++) {
- String name = segmentDirs[i].getName();
- if (!indexNames.contains(name)) {
- deletable.add(name);
+ String[] dirNames = directoryManager.getDirectoryNames();
+ for (int i = 0; i < dirNames.length; i++) {
+ if (dirNames[i].startsWith("_") && !indexNames.contains(dirNames[i])) {
+ deletable.add(dirNames[i]);
}
}
}
@@ -1078,8 +1056,7 @@
synchronized (deletable) {
for (Iterator it = deletable.iterator(); it.hasNext(); ) {
String indexName = (String) it.next();
- File dir = new File(indexDir, indexName);
- if (deleteIndex(dir)) {
+ if (directoryManager.delete(indexName)) {
it.remove();
} else {
log.info("Unable to delete obsolete index: " + indexName);
@@ -1093,52 +1070,14 @@
* in Jackrabbit versions >= 1.5.
*/
private void removeDeletable() {
- File deletable = new File(indexDir, "deletable");
- if (deletable.exists()) {
- deletable.delete();
- }
- }
-
- /**
- * Deletes the index <code>directory</code>.
- *
- * @param directory the index directory to delete.
- * @return <code>true</code> if the delete was successful,
- * <code>false</code> otherwise.
- */
- private boolean deleteIndex(File directory) {
- // trivial if it does not exist anymore
- if (!directory.exists()) {
- return true;
- }
- // delete files first
- File[] files = directory.listFiles();
- for (int i = 0; i < files.length; i++) {
- if (!files[i].delete()) {
- return false;
+ String fileName = "deletable";
+ try {
+ if (indexDir.fileExists(fileName)) {
+ indexDir.deleteFile(fileName);
}
+ } catch (IOException e) {
+ log.warn("Unable to remove file 'deletable'.", e);
}
- // now delete directory itself
- return directory.delete();
- }
-
- /**
- * Returns an new index folder which is empty.
- *
- * @return the new index folder.
- * @throws IOException if the folder cannot be created.
- */
- private File newIndexFolder() throws IOException {
- // create new index folder. make sure it does not exist
- File sub;
- do {
- sub = new File(indexDir, indexNames.newName());
- } while (sub.exists());
-
- if (!sub.mkdir()) {
- throw new IOException("Unable to create directory: " + sub.getAbsolutePath());
- }
- return sub;
}
/**
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PersistentIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PersistentIndex.java?rev=718218&r1=718217&r2=718218&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PersistentIndex.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PersistentIndex.java Mon Nov 17 03:03:41 2008
@@ -22,12 +22,10 @@
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
-import org.apache.lucene.store.FSDirectory;
-import org.apache.lucene.store.NativeFSLockFactory;
import org.apache.lucene.search.Similarity;
+import org.apache.jackrabbit.core.query.lucene.directory.DirectoryManager;
import java.io.IOException;
-import java.io.File;
/**
* Implements a lucene index which is based on a
@@ -45,26 +43,27 @@
private IndexListener listener;
/**
- * Creates a new <code>PersistentIndex</code> based on the file system
- * <code>indexDir</code>.
+ * Creates a new <code>PersistentIndex</code>.
+ *
* @param name the name of this index.
- * @param indexDir the directory to store the index.
* @param analyzer the analyzer for text tokenizing.
* @param similarity the similarity implementation.
* @param cache the document number cache
* @param indexingQueue the indexing queue.
+ * @param directoryManager the directory manager.
* @throws IOException if an error occurs while opening / creating the
* index.
*/
- PersistentIndex(String name, File indexDir, Analyzer analyzer,
+ PersistentIndex(String name, Analyzer analyzer,
Similarity similarity, DocNumberCache cache,
- IndexingQueue indexingQueue)
+ IndexingQueue indexingQueue,
+ DirectoryManager directoryManager)
throws IOException {
- super(analyzer, similarity, FSDirectory.getDirectory(indexDir, new NativeFSLockFactory(indexDir)),
+ super(analyzer, similarity, directoryManager.getDirectory(name),
cache, indexingQueue);
this.name = name;
if (isExisting()) {
- IndexMigration.migrate(this, indexDir);
+ IndexMigration.migrate(this, directoryManager);
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/RedoLog.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/RedoLog.java?rev=718218&r1=718217&r2=718218&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/RedoLog.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/RedoLog.java Mon Nov 17 03:03:41 2008
@@ -18,6 +18,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.lucene.store.Directory;
+import org.apache.jackrabbit.core.query.lucene.directory.IndexOutputStream;
+import org.apache.jackrabbit.core.query.lucene.directory.IndexInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@@ -26,10 +29,7 @@
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.OutputStream;
-import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
@@ -50,6 +50,11 @@
private static final Logger log = LoggerFactory.getLogger(RedoLog.class);
/**
+ * Default name of the redo log file
+ */
+ private static final String REDO_LOG = "redo.log";
+
+ /**
* Implements a {@link ActionCollector} that counts all entries and sets
* {@link #entryCount}.
*/
@@ -60,9 +65,9 @@
};
/**
- * The log file
+ * The directory where the log file is stored.
*/
- private final File logFile;
+ private final Directory dir;
/**
* The number of log entries in the log file
@@ -75,17 +80,14 @@
private Writer out;
/**
- * Creates a new <code>RedoLog</code> instance based on the file
- * <code>logFile</code>
- * @param log the redo log file.
- */
- RedoLog(File log) throws IOException {
- this.logFile = log;
- // create the log file if not there
- if (!log.exists()) {
- log.getParentFile().mkdirs();
- log.createNewFile();
- }
+ * Creates a new <code>RedoLog</code> instance, which stores its log in the
+ * given directory.
+ *
+ * @param dir the directory where the redo log file is located.
+ * @throws IOException if an error occurs while reading the redo log.
+ */
+ RedoLog(Directory dir) throws IOException {
+ this.dir = dir;
read(ENTRY_COUNTER);
}
@@ -157,8 +159,7 @@
out.close();
out = null;
}
- // truncate file
- new FileOutputStream(logFile).close();
+ dir.deleteFile(REDO_LOG);
entryCount = 0;
}
@@ -169,7 +170,7 @@
*/
private void initOut() throws IOException {
if (out == null) {
- OutputStream os = new FileOutputStream(logFile, true);
+ OutputStream os = new IndexOutputStream(dir.createOutput(REDO_LOG));
out = new BufferedWriter(new OutputStreamWriter(os));
}
}
@@ -182,7 +183,10 @@
* log file.
*/
private void read(ActionCollector collector) throws IOException {
- InputStream in = new FileInputStream(logFile);
+ if (!dir.fileExists(REDO_LOG)) {
+ return;
+ }
+ InputStream in = new IndexInputStream(dir.openInput(REDO_LOG));
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java?rev=718218&r1=718217&r2=718218&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java Mon Nov 17 03:03:41 2008
@@ -28,6 +28,8 @@
import org.apache.jackrabbit.core.query.ExecutableQuery;
import org.apache.jackrabbit.core.query.QueryHandler;
import org.apache.jackrabbit.core.query.QueryHandlerContext;
+import org.apache.jackrabbit.core.query.lucene.directory.DirectoryManager;
+import org.apache.jackrabbit.core.query.lucene.directory.FSDirectoryManager;
import org.apache.jackrabbit.core.state.NodeState;
import org.apache.jackrabbit.core.state.NodeStateIterator;
import org.apache.jackrabbit.core.state.ItemStateManager;
@@ -405,6 +407,16 @@
private Similarity similarity = Similarity.getDefault();
/**
+ * The name of the directory manager class implementation.
+ */
+ private String directoryManagerClass = FSDirectoryManager.class.getName();
+
+ /**
+ * The directory manager.
+ */
+ private DirectoryManager directoryManager;
+
+ /**
* Indicates if this <code>SearchIndex</code> is closed and cannot be used
* anymore.
*/
@@ -437,8 +449,7 @@
extractor = createTextExtractor();
synProvider = createSynonymProvider();
-
- File indexDir = new File(path);
+ directoryManager = createDirectoryManager();
if (context.getParentHandler() instanceof SearchIndex) {
// use system namespace mappings
@@ -446,7 +457,7 @@
nsMappings = sysIndex.getNamespaceMappings();
} else {
// read local namespace mappings
- File mapFile = new File(indexDir, NS_MAPPING_FILE);
+ File mapFile = new File(new File(path), NS_MAPPING_FILE);
if (mapFile.exists()) {
// be backward compatible and use ns_mappings.properties from
// index folder
@@ -463,7 +474,7 @@
indexingConfig = createIndexingConfiguration(nsMappings);
analyzer.setIndexingConfig(indexingConfig);
- index = new MultiIndex(indexDir, this, excludedIDs, nsMappings);
+ index = new MultiIndex(this, excludedIDs);
if (index.numDocs() == 0) {
Path rootPath;
if (excludedIDs.isEmpty()) {
@@ -849,6 +860,13 @@
}
/**
+ * @return the directory manager for this search index.
+ */
+ public DirectoryManager getDirectoryManager() {
+ return directoryManager;
+ }
+
+ /**
* Returns an index reader for this search index. The caller of this method
* is responsible for closing the index reader when he is finished using
* it.
@@ -1002,6 +1020,31 @@
}
/**
+ * @return an initialized {@link DirectoryManager}.
+ * @throws IOException if the directory manager cannot be instantiated or
+ * an exception occurs while initializing the manager.
+ */
+ protected DirectoryManager createDirectoryManager()
+ throws IOException {
+ try {
+ Class clazz = Class.forName(directoryManagerClass);
+ if (!DirectoryManager.class.isAssignableFrom(clazz)) {
+ throw new IOException(directoryManagerClass +
+ " is not a DirectoryManager implementation");
+ }
+ DirectoryManager df = (DirectoryManager) clazz.newInstance();
+ df.init(this);
+ return df;
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ IOException ex = new IOException();
+ ex.initCause(e);
+ throw ex;
+ }
+ }
+
+ /**
* Creates a file system resource to the synonym provider configuration.
*
* @return a file system resource or <code>null</code> if no path was
@@ -1898,6 +1941,23 @@
return maxVolatileIndexSize;
}
+ /**
+ * @return the name of the directory manager class.
+ */
+ public String getDirectoryManagerClass() {
+ return directoryManagerClass;
+ }
+
+ /**
+ * Sets name of the directory manager class. The class must implement
+ * {@link DirectoryManager}.
+ *
+ * @param className the name of the class that implements directory manager.
+ */
+ public void setDirectoryManagerClass(String className) {
+ this.directoryManagerClass = className;
+ }
+
//----------------------------< internal >----------------------------------
/**
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/DirectoryManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/DirectoryManager.java?rev=718218&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/DirectoryManager.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/DirectoryManager.java Mon Nov 17 03:03:41 2008
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene.directory;
+
+import org.apache.lucene.store.Directory;
+import org.apache.jackrabbit.core.query.lucene.SearchIndex;
+
+import java.io.IOException;
+
+/**
+ * <code>DirectoryManager</code> defines an interface for managing directory
+ * instances used by the search index.
+ */
+public interface DirectoryManager {
+
+ /**
+ * Initializes the directory manager with a reference to the search index.
+ *
+ * @param handler the query handler implementation.
+ * @throws IOException if an error occurs while initializing the directory
+ * manager.
+ */
+ void init(SearchIndex handler) throws IOException;
+
+ /**
+ * Checks if there exists a directory with the given <code>name</code>.
+ *
+ * @param name the name of a directory.
+ * @return <code>true</code> if the directory exists; <code>false</code>
+ * otherwise.
+ * @throws IOException if an error occurs while looking up directories.
+ */
+ boolean hasDirectory(String name) throws IOException;
+
+ /**
+ * Gets the directory with the given <code>name</code>. If the directory
+ * does not yet exist then it will be created.
+ *
+ * @param name the name of a directory.
+ * @return the directory.
+ * @throws IOException if an error occurs while getting or creating the
+ * directory.
+ */
+ Directory getDirectory(String name) throws IOException;
+
+ /**
+ * Returns the names of the currently available directories.
+ *
+ * @return names of the currently available directories.
+ * @throws IOException if an error occurs while retrieving the directory
+ * names.
+ */
+ String[] getDirectoryNames() throws IOException;
+
+ /**
+ * Deletes the directory with the given name.
+ *
+ * @param name the name of the directory to delete.
+ * @return <code>true</code> if the directory could be deleted successfully,
+ * <code>false</code> otherwise. This method also returns
+ * <code>false</code> when the directory with the given
+ * <code>name</code> does not exist.
+ */
+ boolean delete(String name);
+
+ /**
+ * Renames a directory.
+ *
+ * @param from the name of the directory to rename.
+ * @param to the new name for the directory.
+ * @return <code>true</code> if the directory was successfully renamed.
+ * Returns <code>false</code> if there is no directory with name
+ * <code>from</code> or there already exists a directory with name
+ * <code>to</code> or an error occurs while renaming the directory.
+ */
+ boolean rename(String from, String to);
+
+ /**
+ * Frees resources associated with this directory manager.
+ */
+ void dispose();
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/DirectoryManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/FSDirectoryManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/FSDirectoryManager.java?rev=718218&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/FSDirectoryManager.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/FSDirectoryManager.java Mon Nov 17 03:03:41 2008
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene.directory;
+
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+import org.apache.lucene.store.NativeFSLockFactory;
+import org.apache.jackrabbit.core.query.lucene.SearchIndex;
+
+import java.io.IOException;
+import java.io.File;
+import java.io.FileFilter;
+
+/**
+ * <code>FSDirectoryManager</code> implements a directory manager for
+ * {@link FSDirectory} instances.
+ */
+public class FSDirectoryManager implements DirectoryManager {
+
+ /**
+ * The base directory.
+ */
+ private File baseDir;
+
+ /**
+ * {@inheritDoc}
+ */
+ public void init(SearchIndex handler) throws IOException {
+ baseDir = new File(handler.getPath());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasDirectory(String name) throws IOException {
+ return new File(baseDir, name).exists();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Directory getDirectory(String name)
+ throws IOException {
+ File dir = new File(baseDir, name);
+ return FSDirectory.getDirectory(dir, new NativeFSLockFactory(dir));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getDirectoryNames() throws IOException {
+ File[] dirs = baseDir.listFiles(new FileFilter() {
+ public boolean accept(File pathname) {
+ return pathname.isDirectory();
+ }
+ });
+ String[] names = new String[dirs.length];
+ for (int i = 0; i < dirs.length; i++) {
+ names[i] = dirs[i].getName();
+ }
+ return names;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean delete(String name) {
+ File directory = new File(baseDir, name);
+ // trivial if it does not exist anymore
+ if (!directory.exists()) {
+ return true;
+ }
+ // delete files first
+ File[] files = directory.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ if (!files[i].delete()) {
+ return false;
+ }
+ }
+ // now delete directory itself
+ return directory.delete();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean rename(String from, String to) {
+ File src = new File(baseDir, from);
+ File dest = new File(baseDir, to);
+ return src.renameTo(dest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dispose() {
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/FSDirectoryManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/IndexInputStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/IndexInputStream.java?rev=718218&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/IndexInputStream.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/IndexInputStream.java Mon Nov 17 03:03:41 2008
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene.directory;
+
+import org.apache.lucene.store.IndexInput;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * <code>IndexInputStream</code> implements an {@link InputStream} that wraps
+ * a lucene {@link IndexInput}.
+ */
+public class IndexInputStream extends InputStream {
+
+ /**
+ * The underlying index input.
+ */
+ private final IndexInput in;
+
+ /**
+ * The length of the index input.
+ */
+ private final long len;
+
+ /**
+ * The position where the next read will occur.
+ */
+ private long pos;
+
+ /**
+ * Creates a new index input stream wrapping the given lucene index
+ * <code>input</code>.
+ *
+ * @param input the index input to wrap.
+ */
+ public IndexInputStream(IndexInput input) {
+ this.in = input;
+ this.len = input.length();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int read() throws IOException {
+ byte[] buf = new byte[1];
+ if (read(buf, 0, 1) == -1) {
+ return -1;
+ } else {
+ return buf[0] & 0xff;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int read(byte b[], int off, int len) throws IOException {
+ if (pos >= this.len) {
+ // EOF
+ return -1;
+ }
+ int num = (int) Math.min(len - off, this.len - pos);
+ in.readBytes(b, off, num);
+ pos += num;
+ return num;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Closes the underlying index input.
+ */
+ public void close() throws IOException {
+ in.close();
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/IndexInputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/IndexOutputStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/IndexOutputStream.java?rev=718218&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/IndexOutputStream.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/IndexOutputStream.java Mon Nov 17 03:03:41 2008
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene.directory;
+
+import java.io.OutputStream;
+import java.io.IOException;
+
+import org.apache.lucene.store.IndexOutput;
+
+/**
+ * <code>IndexOutputStream</code> wraps an {@link IndexOutput} and exposes it
+ * as a regular {@link OutputStream}.
+ */
+public class IndexOutputStream extends OutputStream {
+
+ /**
+ * The underlying index output.
+ */
+ private final IndexOutput out;
+
+ /**
+ * Creates a new index output stream and wraps the given
+ * <code>output</code>. Bytes will always be written at the end of the
+ * <code>output</code>.
+ *
+ * @param output the lucene index output.
+ * @throws IOException if an error occurs while seeking to the end of the
+ * index <code>output</code>.
+ */
+ public IndexOutputStream(IndexOutput output)
+ throws IOException {
+ this.out = output;
+ this.out.seek(output.length());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void write(int b) throws IOException {
+ byte[] buf = new byte[]{(byte) (b & 0xff)};
+ write(buf, 0, 1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void write(byte b[], int off, int len) throws IOException {
+ out.writeBytes(b, off, len);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Flushes the underlying index output.
+ */
+ public void flush() throws IOException {
+ out.flush();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Closes the underlying index output.
+ */
+ public void close() throws IOException {
+ out.close();
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/IndexOutputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/RAMDirectoryManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/RAMDirectoryManager.java?rev=718218&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/RAMDirectoryManager.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/RAMDirectoryManager.java Mon Nov 17 03:03:41 2008
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene.directory;
+
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.RAMDirectory;
+import org.apache.jackrabbit.core.query.lucene.SearchIndex;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.io.IOException;
+
+/**
+ * <code>RAMDirectoryManager</code> implements a directory manager for
+ * {@link RAMDirectory} instances.
+ */
+public class RAMDirectoryManager implements DirectoryManager {
+
+ /**
+ * Map of directories. Key=String(directory name), Value=Directory.
+ */
+ private final Map directories = new HashMap();
+
+ /**
+ * {@inheritDoc}
+ */
+ public void init(SearchIndex handler) throws IOException {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasDirectory(String name) throws IOException {
+ synchronized (directories) {
+ return directories.containsKey(name);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Directory getDirectory(String name) {
+ synchronized (directories) {
+ Directory dir = (Directory) directories.get(name);
+ if (dir == null) {
+ dir = new RAMDirectory();
+ directories.put(name, dir);
+ }
+ return dir;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getDirectoryNames() throws IOException {
+ synchronized (directories) {
+ return (String[]) directories.keySet().toArray(
+ new String[directories.size()]);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean delete(String name) {
+ synchronized (directories) {
+ directories.remove(name);
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean rename(String from, String to) {
+ synchronized (directories) {
+ if (directories.containsKey(to)) {
+ return false;
+ }
+ Directory dir = (Directory) directories.remove(from);
+ if (dir == null) {
+ return false;
+ }
+ directories.put(to, dir);
+ return true;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dispose() {
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/directory/RAMDirectoryManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/DirectoryManagerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/DirectoryManagerTest.java?rev=718218&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/DirectoryManagerTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/DirectoryManagerTest.java Mon Nov 17 03:03:41 2008
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene.directory;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.io.File;
+
+import org.apache.jackrabbit.core.query.lucene.SearchIndex;
+import org.apache.lucene.store.Directory;
+
+import junit.framework.TestCase;
+
+/**
+ * <code>DirectoryManagerTest</code> performs tests on directory manager
+ * implementations.
+ */
+public class DirectoryManagerTest extends TestCase {
+
+ private static final Collection IMPLEMENTATIONS = Arrays.asList(
+ new Class[]{FSDirectoryManager.class, RAMDirectoryManager.class});
+
+ private static final SearchIndex INDEX = new SearchIndex();
+
+ static {
+ INDEX.setPath(new File(new File("target"), "directory-factory-test").getAbsolutePath());
+ }
+
+ public void testHasDirectory() throws Exception {
+ execute(new Callable(){
+ public void call(DirectoryManager directoryManager) throws Exception {
+ Directory dir = directoryManager.getDirectory("test");
+ assertTrue(directoryManager.hasDirectory("test"));
+ dir.close();
+ }
+ });
+ }
+
+ public void testDelete() throws Exception {
+ execute(new Callable(){
+ public void call(DirectoryManager directoryManager) throws Exception {
+ directoryManager.getDirectory("test").close();
+ directoryManager.delete("test");
+ assertFalse(directoryManager.hasDirectory("test"));
+ }
+ });
+ }
+
+ public void testGetDirectoryNames() throws Exception {
+ execute(new Callable(){
+ public void call(DirectoryManager directoryManager) throws Exception {
+ directoryManager.getDirectory("test").close();
+ assertTrue(Arrays.asList(directoryManager.getDirectoryNames()).contains("test"));
+ }
+ });
+ }
+
+ public void testRename() throws Exception {
+ execute(new Callable(){
+ public void call(DirectoryManager directoryManager) throws Exception {
+ directoryManager.getDirectory("test").close();
+ directoryManager.rename("test", "renamed");
+ assertTrue(directoryManager.hasDirectory("renamed"));
+ assertFalse(directoryManager.hasDirectory("test"));
+ }
+ });
+ }
+
+ private void execute(Callable callable) throws Exception {
+ for (Iterator it = IMPLEMENTATIONS.iterator(); it.hasNext(); ) {
+ Class clazz = (Class) it.next();
+ DirectoryManager dirMgr = (DirectoryManager) clazz.newInstance();
+ dirMgr.init(INDEX);
+ try {
+ callable.call(dirMgr);
+ } finally {
+ dirMgr.dispose();
+ }
+ }
+ }
+
+ private interface Callable {
+
+ public void call(DirectoryManager directoryManager) throws Exception;
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/DirectoryManagerTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/IndexInputStreamTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/IndexInputStreamTest.java?rev=718218&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/IndexInputStreamTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/IndexInputStreamTest.java Mon Nov 17 03:03:41 2008
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene.directory;
+
+import java.io.IOException;
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.util.Random;
+
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.RAMDirectory;
+import org.apache.lucene.store.IndexOutput;
+
+import junit.framework.TestCase;
+
+/**
+ * <code>IndexInputStreamTest</code> performs tests on {@link IndexInputStream}.
+ */
+public class IndexInputStreamTest extends TestCase {
+
+ public void testIndexInputStream() throws IOException {
+ checkStream(0, 0);
+ checkStream(0, 128);
+ checkStream(128, 0);
+ checkStream(128, 128);
+ checkStream(127, 128);
+ checkStream(129, 128);
+ checkStream(300, 128);
+ }
+
+ private void checkStream(int size, int buffer) throws IOException {
+ Random rand = new Random();
+ byte[] data = new byte[size];
+ rand.nextBytes(data);
+ Directory dir = new RAMDirectory();
+ IndexOutput out = dir.createOutput("test");
+ out.writeBytes(data, data.length);
+ out.close();
+ InputStream in = new IndexInputStream(dir.openInput("test"));
+ if (buffer != 0) {
+ in = new BufferedInputStream(in, buffer);
+ }
+ byte[] buf = new byte[3];
+ int len;
+ int pos = 0;
+ while ((len = in.read(buf)) > -1) {
+ for (int i = 0; i < len; i++, pos++) {
+ assertEquals(data[pos], buf[i]);
+ }
+ }
+ in.close();
+ // assert length
+ assertEquals(data.length, pos);
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/IndexInputStreamTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/IndexOutputStreamTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/IndexOutputStreamTest.java?rev=718218&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/IndexOutputStreamTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/IndexOutputStreamTest.java Mon Nov 17 03:03:41 2008
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene.directory;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.BufferedOutputStream;
+import java.util.Random;
+
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.RAMDirectory;
+import org.apache.lucene.store.IndexInput;
+
+import junit.framework.TestCase;
+
+/**
+ * <code>IndexOutputStreamTest</code> performs tests on {@link IndexOutputStream}.
+ */
+public class IndexOutputStreamTest extends TestCase {
+
+ public void testIndexOutputStream() throws IOException {
+ checkStream(0, 0);
+ checkStream(0, 128);
+ checkStream(128, 0);
+ checkStream(127, 128);
+ checkStream(128, 128);
+ checkStream(129, 128);
+ checkStream(300, 128);
+ }
+
+ private void checkStream(int size, int buffer) throws IOException {
+ Random rand = new Random();
+ byte[] data = new byte[size];
+ rand.nextBytes(data);
+ Directory dir = new RAMDirectory();
+ OutputStream out = new IndexOutputStream(dir.createOutput("test"));
+ if (buffer != 0) {
+ out = new BufferedOutputStream(out, buffer);
+ }
+ out.write(data);
+ out.close();
+
+ byte[] buf = new byte[3];
+ int pos = 0;
+ IndexInput in = dir.openInput("test");
+ for (;;) {
+ int len = (int) Math.min(buf.length, in.length() - pos);
+ in.readBytes(buf, 0, len);
+ for (int i = 0; i < len; i++, pos++) {
+ assertEquals(data[pos], buf[i]);
+ }
+ if (len == 0) {
+ // EOF
+ break;
+ }
+ }
+ in.close();
+
+ // assert length
+ assertEquals(data.length, pos);
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/IndexOutputStreamTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/TestAll.java?rev=718218&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/TestAll.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/TestAll.java Mon Nov 17 03:03:41 2008
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene.directory;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes all testcases for the directory module.
+ */
+public class TestAll extends TestCase {
+
+ /**
+ * Returns a <code>Test</code> suite that executes all tests inside this
+ * package.
+ *
+ * @return a <code>Test</code> suite that executes all tests inside this
+ * package.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("Directory tests");
+
+ suite.addTestSuite(IndexInputStreamTest.class);
+ suite.addTestSuite(IndexOutputStreamTest.class);
+ suite.addTestSuite(DirectoryManagerTest.class);
+
+ return suite;
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/directory/TestAll.java
------------------------------------------------------------------------------
svn:eol-style = native