jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mreut...@apache.org
Subject svn commit: rev 53863 - in incubator/jackrabbit/trunk: applications/test src/conf src/java/org/apache/jackrabbit/core src/java/org/apache/jackrabbit/core/fs src/java/org/apache/jackrabbit/core/fs/local src/java/org/apache/jackrabbit/core/search src/java/org/apache/jackrabbit/core/search/lucene
Date Wed, 06 Oct 2004 13:45:01 GMT
Author: mreutegg
Date: Wed Oct  6 06:44:59 2004
New Revision: 53863

Added:
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/RandomAccessOutputStream.java
  (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/RAFOutputStream.java
  (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FileSystemDirectory.java
  (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FileSystemInputStream.java
  (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FileSystemOutputStream.java
  (contents, props changed)
Modified:
   incubator/jackrabbit/trunk/applications/test/config.xml
   incubator/jackrabbit/trunk/src/conf/config.xml
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryFactory.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/BasedFileSystem.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/FileSystem.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/FileSystemResource.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/FileUtil.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/LocalFileSystem.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NamespaceMappings.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/AbstractIndex.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PersistentIndex.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java
Log:
- Implemented a lucene Directory which works on top of the jackrabbit FileSystem abstraction.
- Changed location of lucene locks to index directory, instead of user temp dir.
- Changed order of module shutdown in RepositryImpl. shutdown sequence is now: observation,
search, filesystem.

Modified: incubator/jackrabbit/trunk/applications/test/config.xml
==============================================================================
--- incubator/jackrabbit/trunk/applications/test/config.xml	(original)
+++ incubator/jackrabbit/trunk/applications/test/config.xml	Wed Oct  6 06:44:59 2004
@@ -48,7 +48,7 @@
 		    <param name="path" value="${factory.home}/repositories/localfs/workspaces/default/blobs"/>
 		</FileSystem>
 	    </BLOBStore>
-	    <SearchIndex path="${factory.home}/repositories/localfs/workspaces/default/index"/>
+	    <SearchIndex path="/index"/>
 	</StableWorkspace>
     </Repository>
 </Repositories>

Modified: incubator/jackrabbit/trunk/src/conf/config.xml
==============================================================================
--- incubator/jackrabbit/trunk/src/conf/config.xml	(original)
+++ incubator/jackrabbit/trunk/src/conf/config.xml	Wed Oct  6 06:44:59 2004
@@ -48,7 +48,7 @@
 		    <param name="path" value="${factory.home}/repositories/localfs/workspaces/default/blobs"/>
 		</FileSystem>
 	    </BLOBStore>
-	    <SearchIndex path="${factory.home}/repositories/localfs/workspaces/default/index"/>
+	    <SearchIndex path="/index"/>
 	</StableWorkspace>
     </Repository>
 </Repositories>

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryFactory.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryFactory.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryFactory.java
Wed Oct  6 06:44:59 2004
@@ -351,7 +351,6 @@
         String searchIndexPath = null;
         if (stableWspConfig.getChild(SEARCH_INDEX_ELEMENT) != null) {
             searchIndexPath = stableWspConfig.getChild(SEARCH_INDEX_ELEMENT).getAttributeValue(PATH_ATTRIB);
-            searchIndexPath = searchIndexPath.replaceAll("\\$\\{factory\\.home\\}", factoryHomeDir.replace('\\',
'/'));
         }
 
         return new StableWorkspaceDef(name, wspStore, blobStore,

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java	Wed
Oct  6 06:44:59 2004
@@ -427,7 +427,8 @@
                 }
                 ItemStateProvider stateProvider = getWorkspaceStateManager(workspaceName);
                 SystemSession s = getSystemSession(workspaceName);
-                searchMgr = new SearchManager(stateProvider, s.hierMgr, s, wspDef.getSearchIndexPath());
+                searchMgr = new SearchManager(stateProvider, s.hierMgr, s,
+                        wspDef.getWorkspaceStore(), wspDef.getSearchIndexPath());
             } catch (IOException e) {
                 throw new RepositoryException("Exception opening search index.", e);
             }
@@ -488,17 +489,6 @@
             log.error("failed to persist repository properties", e);
         }
 
-        /**
-         * todo free resources, shutdown workspaces, close sessions,
-         * shutdown item state mgr's, persistence mgr's, etc.
-         */
-        try {
-            // close master file system (this will also invalidate sub file systems)
-            repStore.close();
-        } catch (FileSystemException e) {
-            log.error("Error while closing filesystem", e);
-        }
-
         // stop / dispose all ObservationManagers
         for (Iterator it = wspObsMgrFactory.values().iterator(); it.hasNext();) {
             ObservationManagerFactory obsMgr = (ObservationManagerFactory) it.next();
@@ -509,6 +499,17 @@
         for (Iterator it = wspSearchMgrs.values().iterator(); it.hasNext();) {
             SearchManager searchMgr = (SearchManager) it.next();
             searchMgr.close();
+        }
+
+        /**
+         * todo free resources, shutdown workspaces, close sessions,
+         * shutdown item state mgr's, persistence mgr's, etc.
+         */
+        try {
+            // close master file system (this will also invalidate sub file systems)
+            repStore.close();
+        } catch (FileSystemException e) {
+            log.error("Error while closing filesystem", e);
         }
     }
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java	Wed
Oct  6 06:44:59 2004
@@ -24,6 +24,8 @@
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.ItemStateProvider;
 import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
 import org.apache.log4j.Logger;
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
 import org.apache.lucene.document.Document;
@@ -35,9 +37,13 @@
 import javax.jcr.access.Permission;
 import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.EventType;
-import java.io.File;
 import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collections;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Iterator;
 
 /**
  * Acts as a global entry point to execute queries and index nodes.
@@ -59,12 +65,15 @@
     public SearchManager(ItemStateProvider stateProvider,
                          HierarchyManager hmgr,
                          SessionImpl session,
+                         FileSystem fs,
                          String indexPath) throws IOException {
         this.stateProvider = stateProvider;
         this.hmgr = hmgr;
         this.session = session;
-        index = new SearchIndex(indexPath, new StandardAnalyzer());
-        nsMappings = new NamespaceMappings(new File(indexPath, "ns_mappings.properties"));
+        index = new SearchIndex(fs, indexPath, new StandardAnalyzer());
+        String mapFileName = indexPath + FileSystem.SEPARATOR + "ns_mappings.properties";
+        FileSystemResource mapFile = new FileSystemResource(fs, mapFileName);
+        nsMappings = new NamespaceMappings(mapFile);
     }
 
     public void addNode(NodeState node, Path path) throws IOException {
@@ -142,10 +151,13 @@
 
     public void onEvent(EventIterator events) {
         Set modified = new HashSet();
+        log.debug("onEvent: indexing started");
+        long time = System.currentTimeMillis();
 
-        // FIXME optimize operations on index.
-        // only one cycle of document removes and document adds
+        // remember nodes we have to index at the end.
+        Set pendingNodes = new HashSet();
 
+        // delete removed and modified nodes from index
         while (events.hasNext()) {
             try {
                 EventImpl e = (EventImpl) events.nextEvent();
@@ -155,13 +167,7 @@
                     Path path = Path.create(e.getNodePath() + ((e.getNodePath().length()
> 1) ? "/" : "") + e.getChildName(),
                             session.getNamespaceResolver(),
                             true);
-
-                    path = getIndexlessPath(path);
-
-                    ItemId id = new NodeId(e.getChildUUID());
-                    addNode((NodeState) stateProvider.getItemState(id), path);
-
-
+                    pendingNodes.add(path);
                 } else if (type == EventType.CHILD_NODE_REMOVED) {
 
                     Path path = Path.create(e.getNodePath() + ((e.getNodePath().length()
> 1) ? "/" : "") + e.getChildName(),
@@ -176,12 +182,16 @@
                     Path path = Path.create(e.getNodePath(),
                             session.getNamespaceResolver(),
                             true);
-                    modified.add(path);
+                    if (!modified.contains(e.getParentUUID())) {
+                        deleteNode(path, e.getParentUUID());
+                        modified.add(e.getParentUUID());
+                        pendingNodes.add(path);
+                    } else {
+                        // already deleted
+                    }
                 }
             } catch (MalformedPathException e) {
                 log.error("error indexing node.", e);
-            } catch (ItemStateException e) {
-                log.error("error indexing node.", e);
             } catch (RepositoryException e) {
                 log.error("error indexing node.", e);
             } catch (IOException e) {
@@ -189,12 +199,12 @@
             }
         }
 
-        for (Iterator it = modified.iterator(); it.hasNext();) {
+        for (Iterator it = pendingNodes.iterator(); it.hasNext();) {
             try {
                 Path path = (Path) it.next();
                 ItemId id = hmgr.resolvePath(path);
                 path = getIndexlessPath(path);
-                updateNode((NodeState) stateProvider.getItemState(id), path);
+                addNode((NodeState) stateProvider.getItemState(id), path);
             } catch (ItemStateException e) {
                 log.error("error indexing node.", e);
             } catch (RepositoryException e) {
@@ -202,6 +212,11 @@
             } catch (IOException e) {
                 log.error("error indexing node.", e);
             }
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("onEvent: indexing finished in "
+                    + String.valueOf(System.currentTimeMillis() - time) 
+                    + " ms.");
         }
     }
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/BasedFileSystem.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/BasedFileSystem.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/BasedFileSystem.java
Wed Oct  6 06:44:59 2004
@@ -131,6 +131,14 @@
     }
 
     /**
+     * @see FileSystem#getRandomAccessOutputStream
+     */
+    public RandomAccessOutputStream getRandomAccessOutputStream(String filePath)
+            throws FileSystemException {
+        return fsBase.getRandomAccessOutputStream(buildBasePath(filePath));
+    }
+
+    /**
      * @see FileSystem#hasChildren
      */
     public boolean hasChildren(String path) throws FileSystemException {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/FileSystem.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/FileSystem.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/FileSystem.java	Wed
Oct  6 06:44:59 2004
@@ -65,7 +65,7 @@
 
     /**
      * Returns an output stream for writing bytes to the file denoted by this path.
-     * The file will be created if doesn't exist. If the file exists, its contents
+     * The file will be created if it doesn't exist. If the file exists, its contents
      * will be overwritten.
      *
      * @param filePath the path of the file.
@@ -73,6 +73,22 @@
      * @throws FileSystemException
      */
     public OutputStream getOutputStream(String filePath) throws FileSystemException;
+
+    /**
+     * Returns an output stream for writing bytes to the file denoted by this path.
+     * The file will be created if it doesn't exist. The current position of the
+     * file pointer is set to <code>0</code>. See also
+     * {@link RandomAccessOutputStream#seek(long)};
+     *
+     * @param filePath the path of the file.
+     * @return an random access output stream for writing bytes to the file.
+     * @throws FileSystemException if the file could not be created or if the
+     *   output stream cannot be obtained.
+     * @exception UnsupportedOperationException if the implementation does
+     *   not support file access through a {@link RandomAccessOutputStream}.
+     */
+    public RandomAccessOutputStream getRandomAccessOutputStream(String filePath)
+            throws FileSystemException;
 
     /**
      * Creates the folder named by this path, including any necessary but

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/FileSystemResource.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/FileSystemResource.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/FileSystemResource.java
Wed Oct  6 06:44:59 2004
@@ -150,6 +150,14 @@
     }
 
     /**
+     * @see FileSystem#getRandomAccessOutputStream
+     */
+    public RandomAccessOutputStream getRandomAccessOutputStream()
+            throws FileSystemException {
+        return fs.getRandomAccessOutputStream(path);
+    }
+
+    /**
      * @see FileSystem#lastModified
      */
     public long lastModified() throws FileSystemException {

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/RandomAccessOutputStream.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/RandomAccessOutputStream.java
Wed Oct  6 06:44:59 2004
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.fs;
+
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * Extends the regular <code>java.io.OutputStream</code> with a random
+ * access facility. Multiple <code>write()</code> operations can be
+ * positioned off sequence with the {@link #seek} method.
+ */
+public abstract class RandomAccessOutputStream extends OutputStream {
+
+    /**
+     * Sets the current position in the resource where the next write
+     * will occur.
+     * @param position the new position in the resource.
+     * @throws IOException if an error occurs while seeking to the position.
+     */
+    public abstract void seek(long position) throws IOException;
+}

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/FileUtil.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/FileUtil.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/FileUtil.java
Wed Oct  6 06:44:59 2004
@@ -96,6 +96,8 @@
                 delete(children[i]);
             }
         }
-        f.delete();
+        if (!f.delete()) {
+            throw new IOException("Unable to delete " + f.getPath());
+        }
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/LocalFileSystem.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/LocalFileSystem.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/LocalFileSystem.java
Wed Oct  6 06:44:59 2004
@@ -17,9 +17,18 @@
 
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
+import org.apache.jackrabbit.core.fs.RandomAccessOutputStream;
 import org.apache.log4j.Logger;
 
-import java.io.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.OutputStream;
+import java.io.FileOutputStream;
+import java.io.FileFilter;
+import java.io.RandomAccessFile;
 
 /**
  * A <code>LocalFileSystem</code> ...
@@ -138,14 +147,12 @@
         File f = new File(root, osPath(filePath));
         if (!f.isFile()) {
             String msg = f.getPath() + " does not denote an existing file";
-            log.error(msg);
             throw new FileSystemException(msg);
         }
         try {
             FileUtil.delete(f);
         } catch (IOException ioe) {
             String msg = "failed to delete " + f.getPath();
-            log.error(msg, ioe);
             throw new FileSystemException(msg, ioe);
         }
     }
@@ -202,6 +209,21 @@
             String msg = "failed to get output stream for " + f.getPath();
             log.error(msg, fnfe);
             throw new FileSystemException(msg, fnfe);
+        }
+    }
+
+    /**
+     * @see FileSystem#getRandomAccessOutputStream(String)
+     */
+    public RandomAccessOutputStream getRandomAccessOutputStream(String filePath)
+            throws FileSystemException {
+        File f = new File(root, osPath(filePath));
+        try {
+            return new RAFOutputStream(new RandomAccessFile(f, "rw"));
+        } catch (IOException e) {
+            String msg = "failed to get output stream for " + f.getPath();
+            log.error(msg, e);
+            throw new FileSystemException(msg, e);
         }
     }
 

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/RAFOutputStream.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/RAFOutputStream.java
Wed Oct  6 06:44:59 2004
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.fs.local;
+
+import org.apache.jackrabbit.core.fs.RandomAccessOutputStream;
+
+import java.io.RandomAccessFile;
+import java.io.IOException;
+
+/**
+ * Implements a buffered output stream on a random access file.
+ */
+class RAFOutputStream extends RandomAccessOutputStream {
+
+    /**
+     * The default size of the write buffer in bytes.
+     */
+    static final int DEFAULT_BUFFER_SIZE = 1024;
+
+    /**
+     * The write buffer.
+     */
+    private final byte[] buffer;
+
+    /**
+     * The underlying <code>RandomAccessFile</code>.
+     */
+    protected RandomAccessFile raf;
+
+    /**
+     * The starting position of the buffer in the code.
+     */
+    private long bufferStart;
+
+    /**
+     * The end of valid data in the buffer.
+     */
+    private int bufferEnd;
+
+    /**
+     * Dummy buffer for {@link #write(int)}.
+     */
+    private byte[] one = new byte[1];
+
+    /**
+     * Contructs a new output stream with the given buffer size.
+     *
+     * @param raf the underlying <code>RandomAccessFile</code>.
+     * @param size the size of the buffer.
+     */
+    public RAFOutputStream(RandomAccessFile raf, int size) throws IOException {
+        this.raf = raf;
+        this.buffer = new byte[size];
+        bufferStart = raf.getFilePointer();
+    }
+
+    /**
+     * Contructs a new output stream with the default buffer size:
+     * {@link #DEFAULT_BUFFER_SIZE}.
+     *
+     * @param raf the underlying <code>RandomAccessFile</code>.
+     */
+    public RAFOutputStream(RandomAccessFile raf) throws IOException {
+        this(raf, DEFAULT_BUFFER_SIZE);
+    }
+
+    /**
+     * @see java.io.OutputStream#write(int)
+     */
+    public void write(int b) throws IOException {
+        one[0] = (byte) b;
+        write(one, 0, 1);
+    }
+
+    /**
+     * @see java.io.OutputStream#write(byte[])
+     */
+    public void write(byte b[]) throws IOException {
+        write(b, 0, b.length);
+    }
+
+    /**
+     * @see java.io.OutputStream#write(byte[], int, int)
+     */
+    public void write(byte b[], int off, int len) throws IOException {
+        if (len > buffer.length - bufferEnd) {
+            flush();
+            raf.write(b, off, len);
+        } else {
+            System.arraycopy(b, off, buffer, bufferEnd, len);
+            bufferEnd += len;
+        }
+    }
+
+    /**
+     * @see java.io.OutputStream#flush()
+     */
+    public void flush() throws IOException {
+        raf.write(buffer, 0, bufferEnd);
+        bufferEnd = 0;
+        bufferStart = raf.getFilePointer();
+    }
+
+    /**
+     * This method also closes the underlying <code>RandomAccessFile</code>.
+     *
+     * @see java.io.OutputStream#close()
+     */
+    public void close() throws IOException {
+        flush();
+        raf.close();
+        raf = null;
+    }
+
+    /**
+     * @see RandomAccessOutputStream#seek(long)
+     */
+    public void seek(long position) throws IOException {
+        flush();
+        raf.seek(position);
+        bufferStart = position;
+    }
+
+    /**
+     * Returns the current filepointer
+     *
+     * @return the current filepointer
+     */
+    public long getFilePointer() {
+        return bufferStart + bufferEnd;
+    }
+
+}
\ No newline at end of file

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NamespaceMappings.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NamespaceMappings.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NamespaceMappings.java
Wed Oct  6 06:44:59 2004
@@ -19,14 +19,19 @@
 import org.apache.jackrabbit.core.NamespaceResolver;
 import org.apache.jackrabbit.core.NoPrefixDeclaredException;
 import org.apache.jackrabbit.core.Path;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.core.fs.FileSystemException;
 import org.apache.log4j.Logger;
 
 import javax.jcr.NamespaceException;
-import java.io.*;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Properties;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.BufferedOutputStream;
 
 /**
  * The class <code>NamespaceMappings</code> implements a {@link
@@ -48,7 +53,7 @@
     /**
      * Location of the file that persists the uri / prefix mappings
      */
-    private final File storage;
+    private final FileSystemResource storage;
 
     /**
      * Map of uris indexed by prefixes
@@ -73,7 +78,7 @@
      * @throws IOException if an error occurs while reading initial namespace
      *                     mappings from <code>file</code>.
      */
-    public NamespaceMappings(File file) throws IOException {
+    public NamespaceMappings(FileSystemResource file) throws IOException {
         storage = file;
         load();
     }
@@ -151,27 +156,31 @@
      * @throws IOException if an error occurs while reading from the file.
      */
     private void load() throws IOException {
-        if (storage.exists()) {
-            InputStream in = new FileInputStream(storage);
-            try {
-                Properties props = new Properties();
-                log.debug("loading namespace mappings...");
-                props.load(in);
-
-                // read mappings from properties
-                Iterator iter = props.keySet().iterator();
-                while (iter.hasNext()) {
-                    String prefix = (String) iter.next();
-                    String uri = props.getProperty(prefix);
-                    log.debug(prefix + " -> " + uri);
-                    prefixToURI.put(prefix, uri);
-                    uriToPrefix.put(uri, prefix);
+        try {
+            if (storage.exists()) {
+                InputStream in = storage.getInputStream();
+                try {
+                    Properties props = new Properties();
+                    log.debug("loading namespace mappings...");
+                    props.load(in);
+
+                    // read mappings from properties
+                    Iterator iter = props.keySet().iterator();
+                    while (iter.hasNext()) {
+                        String prefix = (String) iter.next();
+                        String uri = props.getProperty(prefix);
+                        log.debug(prefix + " -> " + uri);
+                        prefixToURI.put(prefix, uri);
+                        uriToPrefix.put(uri, prefix);
+                    }
+                    prefixCount = props.size();
+                    log.debug("namespace mappings loaded.");
+                } finally {
+                    in.close();
                 }
-                prefixCount = props.size();
-                log.debug("namespace mappings loaded.");
-            } finally {
-                in.close();
             }
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
         }
     }
 
@@ -191,11 +200,13 @@
             props.setProperty(prefix, uri);
         }
 
-        storage.getParentFile().mkdirs();
-        OutputStream out = new BufferedOutputStream(new FileOutputStream(storage));
-
+        OutputStream out = null;
         try {
+            storage.makeParentDirs();
+            out = new BufferedOutputStream(storage.getOutputStream());
             props.store(out, null);
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
         } finally {
             // make sure stream is closed
             out.close();

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/AbstractIndex.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/AbstractIndex.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/AbstractIndex.java
Wed Oct  6 06:44:59 2004
@@ -26,7 +26,7 @@
 import java.io.IOException;
 
 /**
- *
+ * Implements common functionality for a lucene index.
  */
 abstract class AbstractIndex {
 

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FileSystemDirectory.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FileSystemDirectory.java
Wed Oct  6 06:44:59 2004
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.search.lucene;
+
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.OutputStream;
+import org.apache.lucene.store.InputStream;
+import org.apache.lucene.store.Lock;
+import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.fs.FileSystemException;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.commons.collections.ReferenceMap;
+import org.apache.log4j.Logger;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Implements a lucene Directory based on a
+ * {@link org.apache.jackrabbit.core.fs.FileSystem}.
+ */
+class FileSystemDirectory extends Directory {
+
+    /**
+     * Logger instance for this class.
+     */
+    private static final Logger log = Logger.getLogger(FileSystemDirectory.class);
+
+    /**
+     * Map where the cached CQFSDirectories are stored.<br/>
+     * Key: base path<br/>
+     * Value: FileSystemDirectory
+     */
+    private static final Map directories =
+            new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+
+    /**
+     * The underlying {@link org.apache.jackrabbit.core.fs.FileSystem} that
+     * we use for storing index files.
+     */
+    private final FileSystem fs;
+
+    /**
+     * Returns a lucene <code>Directory</code> which is based on the
+     * {@link org.apache.jackrabbit.core.fs.FileSystem} <code>fs</code>.
+     * <p/>
+     * <code>FileSystemDirectory</code> instances are cached. That is,
+     * subsequent calls to <code>getDirectory()</code> with the same
+     * <code>FileSystem</code> will return the previously returned
+     * <code>FileSystemDirectory</code> instance.
+     *
+     * @param fs the <code>FileSystem</code> where this <code>Directory</code>
+     *   is based on.
+     * @param create if <code>true</code>, an existing index in this
+     *   <code>Directory</code> is deleted.
+     * @return the <code>FileSystemDirectory</code> instance for the
+     *   <code>FileSystem</code> <code>fs</code>.
+     * @throws IOException if the <code>FileSystemDirectory</code> cannot
+     *   be created.
+     */
+    static FileSystemDirectory getDirectory(FileSystem fs,
+                                            boolean create)
+            throws IOException {
+
+        synchronized (directories) {
+            FileSystemDirectory dir = (FileSystemDirectory)directories.get(fs);
+            if (dir == null) {
+                dir = new FileSystemDirectory(fs, create);
+                directories.put(fs, dir);
+            }
+            return dir;
+        }
+    }
+
+    /**
+     * Creates a new <code>FileSystemDirectory</code> based on
+     * <code>FileSystem</code> <code>fs</code>.
+     *
+     * @param fs the <code>FileSystem</code> where this <code>Directory</code>
+     *   is based on.
+     * @param create if <code>true</code>, an existing index in this
+     *   <code>Directory</code> is deleted.
+     * @throws IOException if the <code>FileSystemDirectory</code> cannot
+     *   be created.
+     */
+    private FileSystemDirectory(FileSystem fs,
+                                boolean create) throws IOException {
+        this.fs = fs;
+        if (create) {
+            try {
+                // erase if existing
+                String[] files = fs.list("/");
+                for (int i = 0; i < files.length; i++) {
+                    log.error("deleting " + files[i]);
+                    fs.deleteFile(files[i]);
+                }
+            } catch (FileSystemException e) {
+                throw new IOException(e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * @see Directory#list()
+     */
+    public String[] list() throws IOException {
+        log.debug("list");
+        try {
+            return fs.list("/");
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    /**
+     * @see Directory#fileExists(String)
+     */
+    public boolean fileExists(String name) throws IOException {
+        log.debug("fileExists: " + name);
+        try {
+            return fs.exists(name);
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    /**
+     * @see Directory#fileModified(String)
+     */
+    public long fileModified(String name) throws IOException {
+        log.debug("fileModified: " + name);
+        try {
+            return fs.lastModified(name);
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    /**
+     * @see Directory#touchFile(String)
+     */
+    public void touchFile(String name) throws IOException {
+        log.debug("touchFile: " + name);
+        try {
+            fs.touch(name);
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    /**
+     * @see Directory#deleteFile(String)
+     */
+    public void deleteFile(String name) throws IOException {
+        log.debug("deleteFile: " + name);
+        try {
+            fs.deleteFile(name);
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    /**
+     * @see Directory#renameFile(String, String)
+     */
+    public void renameFile(String from, String to) throws IOException {
+        log.debug("renameFile: from=" + from + " to=" + to);
+        try {
+            fs.move(from, to);
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    /**
+     * @see Directory#fileLength(String)
+     */
+    public long fileLength(String name) throws IOException {
+        log.debug("fileLength: " + name);
+        try {
+            return fs.length(name);
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    /**
+     * @see Directory#createFile(String)
+     */
+    public OutputStream createFile(String name) throws IOException {
+        log.debug("createFile: " + name);
+        return new FileSystemOutputStream(new FileSystemResource(fs, name));
+    }
+
+    /**
+     * @see Directory#openFile(String)
+     */
+    public InputStream openFile(String name) throws IOException {
+        log.debug("openFile: " + name);
+        return new FileSystemInputStream(new FileSystemResource(fs, name));
+    }
+
+    /**
+     * @see Directory#makeLock(String)
+     */
+    public Lock makeLock(String name) {
+        final FileSystemResource lock = new FileSystemResource(fs, name);
+        return new Lock() {
+            public boolean obtain() throws IOException {
+                // FIXME: this is not atomic on the filesystem
+                // find better way.
+                synchronized (FileSystemDirectory.this) {
+                    try {
+                        if (lock.exists()) {
+                            return false;
+                        } else {
+                            // touch the file
+                            lock.getOutputStream().close();
+                            return true;
+                        }
+                    } catch (FileSystemException e) {
+                        throw new IOException(e.getMessage());
+                    }
+                }
+            }
+
+            public void release() {
+                try {
+                    lock.delete();
+                } catch (FileSystemException e) {
+                    log.error("Unable to release lock file " + this + ": " + e);
+                }
+            }
+
+            public boolean isLocked() {
+                try {
+                    boolean locked = lock.exists();
+                    return locked;
+                } catch (FileSystemException e) {
+                    log.error("Unable to determine lock status for file "
+                            + this + ": " + e);
+                    // we're pessimistic
+                    return true;
+                }
+            }
+
+            public String toString() {
+                return "Lock@" + lock.getName();
+            }
+        };
+    }
+
+    /**
+     * @see Directory#close()
+     */
+    public void close() throws IOException {
+        // there is nothing to close here.
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FileSystemInputStream.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FileSystemInputStream.java
Wed Oct  6 06:44:59 2004
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.search.lucene;
+
+import org.apache.lucene.store.InputStream;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.core.fs.FileSystemException;
+
+import java.io.IOException;
+
+/**
+ * Implements a lucene store InputStream that is based on a
+ * {@link org.apache.jackrabbit.core.fs.FileSystemResource}.
+ */
+class FileSystemInputStream extends InputStream {
+
+    private final FileSystemResource res;
+
+    private java.io.InputStream in;
+
+    private long position;
+
+    FileSystemInputStream(FileSystemResource res) throws IOException {
+        this.res = res;
+        try {
+            this.length = res.length();
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    protected void readInternal(byte[] b, int offset, int length) throws IOException {
+        checkOpen();
+        position += in.read(b, offset, length);
+    }
+
+    public void close() throws IOException {
+        if (in != null) {
+            in.close();
+        }
+    }
+
+    protected void seekInternal(long pos) throws IOException {
+        checkOpen();
+        if (pos >= position) {
+            in.skip(pos - position);
+        } else {
+            // seeking backwards
+            in.close();
+            try {
+                in = res.getInputStream();
+            } catch (FileSystemException e) {
+                throw new IOException(e.getMessage());
+            }
+            in.skip(pos);
+        }
+    }
+
+    public Object clone() {
+        FileSystemInputStream clone = (FileSystemInputStream)super.clone();
+        // decouple from this
+        clone.in = null;
+        clone.position = 0;
+        return clone;
+    }
+
+    //----------------------------< internal >----------------------------------
+
+    private void checkOpen() throws IOException {
+        if (in == null) {
+            try {
+                in = res.getInputStream();
+                length = res.length();
+            } catch (FileSystemException e) {
+                throw new IOException(e.getMessage());
+            }
+        }
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FileSystemOutputStream.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FileSystemOutputStream.java
Wed Oct  6 06:44:59 2004
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.search.lucene;
+
+import org.apache.lucene.store.OutputStream;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.core.fs.FileSystemException;
+import org.apache.jackrabbit.core.fs.RandomAccessOutputStream;
+
+import java.io.IOException;
+
+/**
+ * Implements an lucene store OutputStream that is based on a
+ * {@link org.apache.jackrabbit.core.fs.FileSystemResource}.
+ */
+class FileSystemOutputStream extends OutputStream {
+
+    private final FileSystemResource res;
+
+    private final RandomAccessOutputStream out;
+
+    FileSystemOutputStream(FileSystemResource res) throws IOException {
+        this.res = res;
+        try {
+            this.out = res.getRandomAccessOutputStream();
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    protected void flushBuffer(byte[] b, int len) throws IOException {
+        out.write(b, 0, len);
+        out.flush();
+    }
+
+    public long length() throws IOException {
+        try {
+            return res.length();
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
+        }
+    }
+
+    public void close() throws IOException {
+        super.close();
+        out.close();
+    }
+
+    public void seek(long pos) throws IOException {
+        super.seek(pos);
+        out.seek(pos);
+    }
+}

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PersistentIndex.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PersistentIndex.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PersistentIndex.java
Wed Oct  6 06:44:59 2004
@@ -18,24 +18,25 @@
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.store.Directory;
-import org.apache.lucene.store.FSDirectory;
+import org.apache.jackrabbit.core.fs.FileSystem;
 
 import java.io.IOException;
 
 /**
+ * Implements a lucene index which is based on a
+ * {@link org.apache.jackrabbit.core.fs.FileSystem}.
  */
 public class PersistentIndex extends AbstractIndex {
 
-    private String location;
+    private final FileSystem fs;
 
-    PersistentIndex(String location, Analyzer analyzer) throws IOException {
-        super(analyzer,
-                IndexReader.indexExists(location)
-                ? FSDirectory.getDirectory(location, false)
-                : FSDirectory.getDirectory(location, true));
-
-        this.location = location;
+    PersistentIndex(FileSystem fs,
+                    boolean create,
+                    Analyzer analyzer)
+            throws IOException {
 
+        super(analyzer, FileSystemDirectory.getDirectory(fs, create));
+        this.fs = fs;
     }
 
     void mergeIndex(AbstractIndex index) throws IOException {
@@ -45,6 +46,6 @@
     }
 
     Directory getDirectory() throws IOException {
-        return FSDirectory.getDirectory(location, false);
+        return FileSystemDirectory.getDirectory(fs, false);
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java
Wed Oct  6 06:44:59 2004
@@ -22,6 +22,9 @@
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.Hits;
 import org.apache.lucene.search.Query;
+import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.fs.FileSystemException;
+import org.apache.jackrabbit.core.fs.BasedFileSystem;
 
 import java.io.IOException;
 
@@ -48,12 +51,23 @@
 
     private final FIFOReadWriteLock readWriteLock = new FIFOReadWriteLock();
 
-    public SearchIndex(String location, Analyzer analyzer) throws IOException {
+    public SearchIndex(FileSystem fs, String location, Analyzer analyzer)
+            throws IOException {
         //volatileIndex = new VolatileIndex(analyzer);
-        persistentIndex = new PersistentIndex(location, analyzer);
-        persistentIndex.setUseCompoundFile(true);
-        this.location = location;
-        this.analyzer = analyzer;
+        boolean create;
+        try {
+            if (!fs.exists(location)) {
+                fs.createFolder(location);
+            }
+            FileSystem indexFS = new BasedFileSystem(fs, location);
+            create = !indexFS.exists("segments");
+            persistentIndex = new PersistentIndex(indexFS, create, analyzer);
+            persistentIndex.setUseCompoundFile(true);
+            this.location = location;
+            this.analyzer = analyzer;
+        } catch (FileSystemException e) {
+            throw new IOException(e.getMessage());
+        }
     }
 
     public void addDocument(Document doc) throws IOException {

Mime
View raw message