lucene-java-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From yo...@apache.org
Subject svn commit: r425538 [2/4] - in /lucene/java/trunk: ./ contrib/gdata-server/ contrib/gdata-server/src/java/org/apache/lucene/gdata/data/ contrib/gdata-server/src/java/org/apache/lucene/gdata/server/ contrib/gdata-server/src/java/org/apache/lucene/gdata/...
Date Tue, 25 Jul 2006 22:23:06 GMT
Modified: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/RequestAuthenticator.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/RequestAuthenticator.java?rev=425538&r1=425537&r2=425538&view=diff
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/RequestAuthenticator.java (original)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/RequestAuthenticator.java Tue Jul 25 15:23:01 2006
@@ -92,6 +92,11 @@
                     + request.getFeedId(), e);
             throw new AuthenticatorException(" Service exception occured", e);
 
+        }finally{
+        
+            if(adminService!=null)
+                adminService.close();
+        
         }
 
         return false;

Modified: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/UpdateFeedHandler.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/UpdateFeedHandler.java?rev=425538&r1=425537&r2=425538&view=diff
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/UpdateFeedHandler.java (original)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/servlet/handler/UpdateFeedHandler.java Tue Jul 25 15:23:01 2006
@@ -28,6 +28,7 @@
 import org.apache.lucene.gdata.data.ServerBaseFeed;
 import org.apache.lucene.gdata.server.ServiceException;
 import org.apache.lucene.gdata.server.ServiceFactory;
+import org.apache.lucene.gdata.server.administration.AdminService;
 import org.apache.lucene.gdata.server.registry.ComponentType;
 import org.apache.lucene.gdata.server.registry.GDataServerRegistry;
 
@@ -48,6 +49,7 @@
             HttpServletResponse response) throws ServletException, IOException {
         super.processRequest(request, response);
         if (this.authenticated) {
+            AdminService service= null;
             try {
                 ServerBaseFeed feed = createFeedFromRequest(request);
                 GDataAccount account = createRequestedAccount(request);
@@ -62,7 +64,8 @@
                     throw new FeedHandlerException(
                             "Can't update feed - ServiceFactory is null");
                 }
-                serviceFactory.getAdminService().updateFeed(feed, account);
+                service = serviceFactory.getAdminService();
+                service.updateFeed(feed, account);
             } catch (ServiceException e) {
                 setError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                         "can not update feed");
@@ -71,10 +74,13 @@
 
                 LOG.error("Can not update feed -- " + e.getMessage(), e);
 
+            }finally{
+                if(service != null)
+                    service.close();
             }
         }
         sendResponse(response);
-
+        
     }
 
 }

Modified: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/IDGenerator.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/IDGenerator.java?rev=425538&r1=425537&r2=425538&view=diff
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/IDGenerator.java (original)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/IDGenerator.java Tue Jul 25 15:23:01 2006
@@ -21,6 +21,7 @@
 import java.security.SecureRandom; 
 import java.util.concurrent.ArrayBlockingQueue; 
 import java.util.concurrent.BlockingQueue; 
+import java.util.concurrent.atomic.AtomicBoolean;
  
 import org.apache.commons.logging.Log; 
 import org.apache.commons.logging.LogFactory; 
@@ -41,6 +42,8 @@
  *  
  */ 
 public class IDGenerator { 
+    final AtomicBoolean stopped = new AtomicBoolean(false);
+    
     private final SecureRandom secureRandom; 
  
     private final MessageDigest mdigest; 
@@ -110,8 +113,10 @@
     /** 
      * Stops the id-producer 
      */ 
-    public void stopIDGenerator() { 
+    public void stopIDGenerator() {
+        this.stopped.set(true);
         this.runner.interrupt(); 
+        
     } 
  
     private class UIDProducer implements Runnable { 
@@ -134,10 +139,10 @@
          */ 
         public void run() { 
  
-            while (true) { 
+            while (!IDGenerator.this.stopped.get()) { 
                 try { 
                     this.queue.put(produce()); 
-                } catch (InterruptedException e) { 
+                } catch (InterruptedException e) {
                     LOGGER 
                             .warn("UIDProducer has been interrupted -- runner is going down"); 
                     return; 
@@ -147,7 +152,7 @@
         } 
  
         private String produce() { 
-            String randomNumber = new Integer(this.random.nextInt()).toString(); 
+            String randomNumber = Integer.toString(this.random.nextInt()); 
             byte[] byteResult = this.digest.digest(randomNumber.getBytes()); 
             return hexEncode(byteResult); 
         } 

Added: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/ModificationConflictException.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/ModificationConflictException.java?rev=425538&view=auto
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/ModificationConflictException.java (added)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/ModificationConflictException.java Tue Jul 25 15:23:01 2006
@@ -0,0 +1,75 @@
+/**
+ * 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.lucene.gdata.storage;
+
+/**
+ * This exception will be thrown if a Version conflict occures while updateing
+ * or deleteing an entry. Or if one entry is modified concurrently.
+ * 
+ * @author Simon Willnauer
+ * 
+ */
+public class ModificationConflictException extends StorageException {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Constructs a new ModificationConflictException
+     */
+    public ModificationConflictException() {
+        super();
+    }
+
+    /**
+     * Constructs a new ModificationConflictException
+     * 
+     * @param message -
+     *            the exception message
+     */
+    public ModificationConflictException(String message) {
+        super(message);
+
+    }
+
+    /**
+     * Constructs a new ModificationConflictException
+     * 
+     * @param message -
+     *            the exception message
+     * @param cause -
+     *            the root cause of this exception
+     */
+    public ModificationConflictException(String message, Throwable cause) {
+        super(message, cause);
+
+    }
+
+    /**
+     * Constructs a new ModificationConflictException
+     * 
+     * @param cause -
+     *            the root cause of this exception
+     */
+    public ModificationConflictException(Throwable cause) {
+        super(cause);
+
+    }
+
+}

Propchange: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/ModificationConflictException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/ModificationConflictException.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/Storage.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/Storage.java?rev=425538&r1=425537&r2=425538&view=diff
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/Storage.java (original)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/Storage.java Tue Jul 25 15:23:01 2006
@@ -212,6 +212,8 @@
             throws StorageException;
 
     /**
+     * 
+     * Retrieves the {@link GDataAccount} for the given account name
      * @param accountName -
      *            the name of the requested account
      * @return - a {@link GDataAccount} instance for the requested account name

Modified: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/StorageController.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/StorageController.java?rev=425538&r1=425537&r2=425538&view=diff
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/StorageController.java (original)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/StorageController.java Tue Jul 25 15:23:01 2006
@@ -58,4 +58,10 @@
      *             if the storage instance can not be created
      */
     public abstract Storage getStorage() throws StorageException;
+    
+    /**
+     * Releases a new unique ID
+     * @return - unique ID
+     */
+    public abstract String releaseId();
 }

Modified: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/StorageException.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/StorageException.java?rev=425538&r1=425537&r2=425538&view=diff
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/StorageException.java (original)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/StorageException.java Tue Jul 25 15:23:01 2006
@@ -23,7 +23,7 @@
  * @author Simon Willnauer 
  *  
  */ 
-public class StorageException extends Exception { 
+public class StorageException extends RuntimeException { 
  
     /** 
      *  

Added: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/ConcurrentStorageLock.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/ConcurrentStorageLock.java?rev=425538&view=auto
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/ConcurrentStorageLock.java (added)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/ConcurrentStorageLock.java Tue Jul 25 15:23:01 2006
@@ -0,0 +1,50 @@
+/**
+ * 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.lucene.gdata.storage.lucenestorage;
+
+/**
+ * 
+ * @author Simon Willnauer
+ *
+ */
+public interface ConcurrentStorageLock {
+    
+    /**
+     * @param key
+     * @return
+     */
+    public abstract boolean setLock(final String key);
+    /**
+     * @param key
+     * @return
+     */
+    public abstract boolean releaseLock(final String key);
+    /**
+     * @return
+     */
+    public abstract boolean releaseThreadLocks();
+    /**
+     * @param key
+     * @return
+     */
+    public abstract boolean isKeyLocked(final String key);
+    /**
+     * 
+     */
+    public abstract void close();
+
+}

Propchange: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/ConcurrentStorageLock.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/ConcurrentStorageLock.java
------------------------------------------------------------------------------
    svn:executable = *

Added: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/SingleHostConcurrentStorageLock.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/SingleHostConcurrentStorageLock.java?rev=425538&view=auto
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/SingleHostConcurrentStorageLock.java (added)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/SingleHostConcurrentStorageLock.java Tue Jul 25 15:23:01 2006
@@ -0,0 +1,175 @@
+/**
+ * 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.lucene.gdata.storage.lucenestorage;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * @author Simon Willnauer
+ *
+ */
+public class SingleHostConcurrentStorageLock implements ConcurrentStorageLock {
+    private volatile static ConcurrentStorageLock INSTANCE = null;
+    private final Map<String,Thread> locks;
+    private final Map<Thread,String> threads;
+    private final ReentrantReadWriteLock synLock = new ReentrantReadWriteLock();
+    private final Lock readLock = this.synLock.readLock();
+    private final Lock writeLock = this.synLock.writeLock();
+    private final AtomicBoolean isClosed = new AtomicBoolean(false);
+    /**
+     * 
+     */
+    private SingleHostConcurrentStorageLock() {
+        super();
+        this.locks = new HashMap<String,Thread>(10);
+        this.threads = new HashMap<Thread,String>(10);
+    }
+    protected static synchronized ConcurrentStorageLock getConcurrentStorageLock(){
+        if(INSTANCE == null)
+            INSTANCE = new SingleHostConcurrentStorageLock();
+        return INSTANCE;
+    }
+    /**
+     * @see org.apache.lucene.gdata.storage.lucenestorage.ConcurrentStorageLock#setLock(java.lang.String)
+     */
+    public boolean setLock(String key) {
+       this.writeLock.lock();
+       try{
+           if(this.isClosed.get())
+               throw new IllegalStateException("Lock has been closed");
+           Thread t = Thread.currentThread();
+           if(this.threads.containsKey(t))
+               throw new ConcurrencyException("one thread must not obtain more than one lock -- single thread can not modify more than one resource");
+           if(this.locks.containsKey(key)){
+               return false;
+           }
+           this.locks.put(key, t);
+           this.threads.put(t,key);
+           return true;
+           
+       }finally{
+           this.writeLock.unlock();
+       }
+        
+    }
+
+    /**
+     * @see org.apache.lucene.gdata.storage.lucenestorage.ConcurrentStorageLock#releaseLock(java.lang.String)
+     */
+    public boolean releaseLock(String key) {
+        this.writeLock.lock();
+        try{
+            if(this.isClosed.get())
+                throw new IllegalStateException("Lock has been closed");
+            Thread t = Thread.currentThread();
+            if(!this.threads.containsKey(t))
+                return false;
+            
+            if(!this.locks.containsKey(key))
+                return false;
+            if(t != this.locks.get(key))
+                throw new ConcurrencyException("Illegal lock access -- current thread is not owner");
+            this.locks.remove(key);
+            this.threads.remove(t);
+            return true;
+            
+        }finally{
+            this.writeLock.unlock();
+        }
+        
+    }
+
+    /**
+     * @see org.apache.lucene.gdata.storage.lucenestorage.ConcurrentStorageLock#releaseThreadLocks()
+     */
+    public boolean releaseThreadLocks() {
+        this.writeLock.lock();
+        try{
+            if(this.isClosed.get())
+                throw new IllegalStateException("Lock has been closed");
+            Thread t = Thread.currentThread();
+            if(!this.threads.containsKey(t))
+                return false;
+            String key = this.threads.get(t);
+            this.threads.remove(t);
+            if(!this.locks.containsKey(key))
+                return false;
+            this.locks.remove(key);
+            return true;
+            
+        }finally{
+            this.writeLock.unlock();
+        }
+    }
+
+    /**
+     * @see org.apache.lucene.gdata.storage.lucenestorage.ConcurrentStorageLock#isKeyLocked(java.lang.String)
+     */
+    public boolean isKeyLocked(String key) {
+        this.readLock.lock();
+        try{
+            if(this.isClosed.get())
+                throw new IllegalStateException("Lock has been closed");
+           return this.locks.containsKey(key);
+        }finally{
+            this.readLock.unlock();
+        }
+    }
+
+    /**
+     * @see org.apache.lucene.gdata.storage.lucenestorage.ConcurrentStorageLock#close()
+     */
+    public void close() {
+        this.writeLock.lock();
+        try{
+            if(this.isClosed.get())
+                throw new IllegalStateException("Lock has been closed");
+            this.isClosed.set(true);
+            this.locks.clear();
+            this.threads.clear();
+            INSTANCE = new SingleHostConcurrentStorageLock();
+        }finally{
+            this.writeLock.unlock();
+        }
+    }
+    
+    
+    protected void forceClear(){
+        this.writeLock.lock();
+        try{
+            if(this.isClosed.get())
+                throw new IllegalStateException("Lock has been closed");
+            this.locks.clear();
+            this.threads.clear();
+            
+        }finally{
+            this.writeLock.unlock();
+        }
+    }
+    static class ConcurrencyException extends RuntimeException{
+      
+        private static final long serialVersionUID = 6388236477729760962L;
+
+        ConcurrencyException(String message){
+            super(message);
+        }
+    }
+}

Propchange: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/SingleHostConcurrentStorageLock.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/SingleHostConcurrentStorageLock.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageBuffer.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageBuffer.java?rev=425538&r1=425537&r2=425538&view=diff
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageBuffer.java (original)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageBuffer.java Tue Jul 25 15:23:01 2006
@@ -52,6 +52,10 @@
  * The read lock may be held simultaneously by multiple reader threads, so long
  * as there are no writers. The write lock is exclusive.
  * </p>
+ * <p>
+ * The entry and feed ID's must not be a composite key. The entry and feed ID
+ * must be unique.
+ * </p>
  * 
  * @see java.util.concurrent.locks.ReentrantReadWriteLock
  * @see org.apache.lucene.gdata.storage.lucenestorage.StorageModifier
@@ -61,255 +65,294 @@
  * 
  */
 public class StorageBuffer {
-	private static final Log LOG = LogFactory.getLog(StorageBuffer.class);
+    private static final Log LOG = LogFactory.getLog(StorageBuffer.class);
 
-	private final Map<String, Map<String, StorageEntryWrapper>> bufferMap;
+    private final Map<String, Map<String, StorageEntryWrapper>> bufferMap;
 
-	private final Map<String, Long> modifiyMap;
+    private final Map<String, Long> modifiyMap;
 
-	private final List<String> excludeList;
+    private final List<String> excludeList;
 
-	private final ReadWriteLock lock = new ReentrantReadWriteLock(true);
-
-	private final Lock readLock = this.lock.readLock();
-
-	private final Lock writeLock = this.lock.writeLock();
-
-	private final static int DEFAULT_BUFFER_COUNT = 10;
-
-	/**
-	 * Constructs a new StorageBuffer.
-	 * <p>
-	 * The expectedBufferCount sould be higher than the maximum of entries added
-	 * to the buffer, resizing the buffer is very efficient. For detailed
-	 * infomation {@link HashMap} as this is used inside the buffer
-	 * </p>
-	 * 
-	 * @param expectedBufferCount -
-	 *            the expected size of the buffer
-	 * 
-	 */
-	protected StorageBuffer(final int expectedBufferCount) {
-		this.bufferMap = new HashMap<String, Map<String, StorageEntryWrapper>>(
-				expectedBufferCount < DEFAULT_BUFFER_COUNT ? DEFAULT_BUFFER_COUNT
-						: expectedBufferCount);
-		this.excludeList = new ArrayList<String>(
-				expectedBufferCount < DEFAULT_BUFFER_COUNT ? DEFAULT_BUFFER_COUNT
-						: expectedBufferCount);
-		this.modifiyMap = new HashMap<String, Long>(
-				expectedBufferCount < DEFAULT_BUFFER_COUNT ? DEFAULT_BUFFER_COUNT
-						: expectedBufferCount);
-	}
-
-	/**
-	 * Adds a {@link StorageEntryWrapper} to the buffer. If a wrapper
-	 * representing the same entry are already in the buffer the wrapper will be
-	 * replaced.
-	 * 
-	 * @param wrapper -
-	 *            the wrapper to buffer
-	 */
-	public void addEntry(final StorageEntryWrapper wrapper) {
-		this.writeLock.lock();
-		try {
-			if (LOG.isInfoEnabled())
-				LOG.info(" Buffering wrapper - " + wrapper.getOperation()
-						+ " ID: " + wrapper.getEntryId() + " FeedID: "
-						+ wrapper.getFeedId());
-			if (wrapper.getOperation().equals(StorageOperation.DELETE))
-				return;
-
-			String feedId = wrapper.getFeedId();
-			if (this.bufferMap.containsKey(feedId))
-				this.bufferMap.get(feedId).put(wrapper.getEntryId(), wrapper);
-			else {
-				Map<String, StorageEntryWrapper> newFeedMap = new HashMap<String, StorageEntryWrapper>(
-						20);
-				newFeedMap.put(wrapper.getEntryId(), wrapper);
-				this.bufferMap.put(feedId, newFeedMap);
-
-			}
-			addLastModified(wrapper.getFeedId(), wrapper.getTimestamp());
-		} finally {
-			/*
-			 * add all to exclude from searches doc will be available via the
-			 * buffer
-			 */
-			this.excludeList.add(wrapper.getEntryId());
-			this.writeLock.unlock();
-		}
-	}
-
-	private void addLastModified(final String feedId, Long timestamp) {
-		if (this.modifiyMap.containsKey(feedId))
-			this.modifiyMap.remove(feedId);
-		this.modifiyMap.put(feedId, timestamp);
-
-	}
-
-	protected Long getFeedLastModified(final String feedId) {
-		return this.modifiyMap.get(feedId);
-	}
-
-	protected Set<Entry<String, Long>> getLastModified() {
-		return this.modifiyMap.entrySet();
-	}
-
-	/**
-	 * Returns all entries for the given feed id sorted by the update timestamp
-	 * desc.
-	 * 
-	 * @param feedId -
-	 *            the feed id
-	 * @return a {@link List} of all {@link StorageEntryWrapper} object buffered
-	 *         in this buffer or an empty list if not entry has been buffered
-	 *         for the given feed
-	 */
-	public List<StorageEntryWrapper> getSortedEntries(String feedId) {
-		this.readLock.lock();
-		try {
-			if (!this.bufferMap.containsKey(feedId))
-				return null;
-			Map<String, StorageEntryWrapper> tempMap = this.bufferMap
-					.get(feedId);
-			if (tempMap == null)
-				return null;
-			Collection<StorageEntryWrapper> col = tempMap.values();
-			List<StorageEntryWrapper> returnList = new ArrayList<StorageEntryWrapper>(
-					col);
-			Collections.sort(returnList);
-			return returnList;
-
-		} finally {
-			this.readLock.unlock();
-		}
-
-	}
-
-	/**
-	 * Adds a deleted entry to the buffer.
-	 * 
-	 * @param entryId -
-	 *            the deleted entry id
-	 * @param feedId -
-	 *            the feed of the entry
-	 */
-	public void addDeleted(final String entryId, final String feedId) {
-		this.writeLock.lock();
-		try {
-			this.excludeList.add(entryId);
-			Map<String, StorageEntryWrapper> tempMap = this.bufferMap
-					.get(feedId);
-			if (tempMap == null)
-				return;
-			tempMap.remove(entryId);
-			this.addLastModified(feedId, new Long(System.currentTimeMillis()));
-		} finally {
-			this.writeLock.unlock();
-
-		}
-
-	}
-
-	/**
-	 * Returns an entry for the given entry id in the feed context spezified by
-	 * the feed id;
-	 * 
-	 * @param entryId -
-	 *            the id of the entry to return
-	 * @param feedId -
-	 *            the feed containing the entry
-	 * @return - the entry or <code>null</code> if the corresponding entry is
-	 *         not in the buffer.
-	 */
-	public StorageEntryWrapper getEntry(final String entryId,
-			final String feedId) {
-		this.readLock.lock();
-		try {
-
-			if (this.bufferMap.containsKey(feedId))
-				return this.bufferMap.get(feedId).get(entryId);
-			return null;
-
-		} finally {
-			this.readLock.unlock();
-		}
-	}
-
-	/**
-	 * The buffer contains updated and delete entries. These entries are already
-	 * available in the lucene index but should not be found during search.
-	 * 
-	 * <p>
-	 * This list contains all entries should not be found by the index searcher.
-	 * This method creates a copy of the current list to prevent concurrent
-	 * modification exceptions while iteration over the collection.
-	 * </p>
-	 * 
-	 * 
-	 * @see ModifiedEntryFilter
-	 * @return - a String array of entries to be omitted from a lucene index
-	 *         search
-	 */
-	public String[] getExculdList() {
-		this.readLock.lock();
-		try {
-			return this.excludeList
-					.toArray(new String[this.excludeList.size()]);
-		} finally {
-			this.readLock.unlock();
-		}
-	}
-
-	// not synchronized
-	private void clearBuffer() {
-		this.bufferMap.clear();
-		this.excludeList.clear();
-		this.modifiyMap.clear();
-
-	}
-
-	/**
-	 * clears the buffer -
-	 */
-	public void close() {
-		this.writeLock.lock();
-		try {
-			clearBuffer();
-		} finally {
-			this.writeLock.unlock();
-		}
-
-	}
-
-	static class BufferableEntry extends BaseEntry {
-
-		/**
-		 * 
-		 */
-		@SuppressWarnings("unchecked")
-		public BufferableEntry() {
-			super();
-			this.links = new LinkedList<Link>();
-		}
-
-		/**
-		 * @param arg0
-		 */
-		@SuppressWarnings("unchecked")
-		public BufferableEntry(BaseEntry arg0) {
-			super(arg0);
-			this.links = new LinkedList<Link>();
-		}
-
-		/**
-		 * @see com.google.gdata.data.BaseEntry#declareExtensions(com.google.gdata.data.ExtensionProfile)
-		 */
-		@Override
-		public void declareExtensions(ExtensionProfile arg0) {
-			//
-		}
-
-	}
+    private final ReadWriteLock lock = new ReentrantReadWriteLock(true);
+
+    private final Lock readLock = this.lock.readLock();
+
+    private final Lock writeLock = this.lock.writeLock();
+
+    private final int bufferSize;
+
+    protected final static int DEFAULT_BUFFER_COUNT = 10;
+
+    /**
+     * Constructs a new StorageBuffer.
+     * <p>
+     * The expectedBufferCount sould be higher than the maximum of entries added
+     * to the buffer, resizing the buffer is very efficient. For detailed
+     * infomation {@link HashMap} as this is used inside the buffer
+     * </p>
+     * 
+     * @param expectedBufferCount -
+     *            the expected size of the buffer
+     * 
+     */
+    protected StorageBuffer(final int expectedBufferCount) {
+        this.bufferSize = expectedBufferCount < DEFAULT_BUFFER_COUNT ? DEFAULT_BUFFER_COUNT
+                : expectedBufferCount;
+        this.bufferMap = new HashMap<String, Map<String, StorageEntryWrapper>>(
+                this.bufferSize);
+        this.excludeList = new ArrayList<String>(this.bufferSize);
+        this.modifiyMap = new HashMap<String, Long>(this.bufferSize);
+    }
+
+    /**
+     * Adds a {@link StorageEntryWrapper} to the buffer. If a wrapper
+     * representing the same entry are already in the buffer the wrapper will be
+     * replaced.
+     * <p>
+     * This method does ignore already delted entries. This should before the
+     * entry is added to the buffer.
+     * </p>
+     * 
+     * @param wrapper -
+     *            the wrapper to buffer
+     */
+    public void addEntry(final StorageEntryWrapper wrapper) {
+        this.writeLock.lock();
+        try {
+            if (LOG.isInfoEnabled())
+                LOG.info(" Buffering wrapper - " + wrapper.getOperation()
+                        + " ID: " + wrapper.getEntryId() + " FeedID: "
+                        + wrapper.getFeedId());
+            if (wrapper.getOperation().equals(StorageOperation.DELETE))
+                return;
+            String feedId = wrapper.getFeedId();
+            if (this.bufferMap.containsKey(feedId))
+                this.bufferMap.get(feedId).put(wrapper.getEntryId(), wrapper);
+            else {
+                Map<String, StorageEntryWrapper> newFeedMap = new HashMap<String, StorageEntryWrapper>(
+                        20);
+                newFeedMap.put(wrapper.getEntryId(), wrapper);
+                this.bufferMap.put(feedId, newFeedMap);
+
+            }
+            addLastModified(wrapper.getFeedId(), wrapper.getTimestamp());
+            /*
+             * add to exclude from searches doc will be available via the buffer
+             * if the entry is not already in the buffer
+             */
+            if (!this.excludeList.contains(wrapper.getEntryId()))
+                this.excludeList.add(wrapper.getEntryId());
+        } finally {
+            this.writeLock.unlock();
+        }
+    }
+
+    private void addLastModified(final String feedId, Long timestamp) {
+        this.writeLock.lock();
+        try {
+            if (this.modifiyMap.containsKey(feedId))
+                this.modifiyMap.remove(feedId);
+            this.modifiyMap.put(feedId, timestamp);
+        } finally {
+            this.writeLock.unlock();
+        }
+
+    }
+
+    /**
+     * the timestamp of the last modification for the given feed id
+     * 
+     * @param feedId -
+     *            feed id
+     * @return timestamp
+     */
+    protected Long getFeedLastModified(final String feedId) {
+        this.readLock.lock();
+        try {
+            return this.modifiyMap.get(feedId);
+        } finally {
+            this.readLock.unlock();
+        }
+    }
+
+    protected Set<Entry<String, Long>> getLastModified() {
+        return this.modifiyMap.entrySet();
+    }
+
+    /**
+     * Returns all entries for the given feed id sorted by the update timestamp
+     * desc.
+     * 
+     * @param feedId -
+     *            the feed id
+     * @return a {@link List} of all {@link StorageEntryWrapper} object buffered
+     *         in this buffer or an empty list if not entry has been buffered
+     *         for the given feed
+     */
+    public List<StorageEntryWrapper> getSortedEntries(String feedId) {
+        this.readLock.lock();
+        try {
+            if (!this.bufferMap.containsKey(feedId))
+                return null;
+            Map<String, StorageEntryWrapper> tempMap = this.bufferMap
+                    .get(feedId);
+            if (tempMap == null)
+                return null;
+            Collection<StorageEntryWrapper> col = tempMap.values();
+            List<StorageEntryWrapper> returnList = new ArrayList<StorageEntryWrapper>(
+                    col);
+            Collections.sort(returnList);
+            return returnList;
+
+        } finally {
+            this.readLock.unlock();
+        }
+
+    }
+
+    /**
+     * Adds a deleted entry to the buffer.
+     * 
+     * @param entryId -
+     *            the deleted entry id
+     * @param feedId -
+     *            the feed of the entry
+     */
+    public void addDeleted(final String entryId, final String feedId) {
+        this.writeLock.lock();
+        try {
+            Map<String, StorageEntryWrapper> tempMap = this.bufferMap
+                    .get(feedId);
+            if (tempMap != null) {
+                tempMap.remove(entryId);
+                this.addLastModified(feedId, new Long(System
+                        .currentTimeMillis()));
+            }
+            /*
+             * add to exclude from searches
+             */
+            if (!this.excludeList.contains(entryId))
+                this.excludeList.add(entryId);
+        } finally {
+
+            this.writeLock.unlock();
+
+        }
+
+    }
+
+    /**
+     * Returns an entry for the given entry id in the feed context spezified by
+     * the feed id;
+     * 
+     * @param entryId -
+     *            the id of the entry to return
+     * @param feedId -
+     *            the feed containing the entry
+     * @return - the entry or <code>null</code> if the corresponding entry is
+     *         not in the buffer.
+     */
+    public StorageEntryWrapper getEntry(final String entryId,
+            final String feedId) {
+        this.readLock.lock();
+        try {
+
+            if (this.bufferMap.containsKey(feedId))
+                return this.bufferMap.get(feedId).get(entryId);
+            return null;
+
+        } finally {
+            this.readLock.unlock();
+        }
+    }
+
+    /**
+     * The buffer contains updated and delete entries. These entries are already
+     * available in the lucene index but should not be found during search.
+     * 
+     * <p>
+     * This list contains all entries should not be found by the index searcher.
+     * This method creates a copy of the current list to prevent concurrent
+     * modification exceptions while iteration over the collection.
+     * </p>
+     * 
+     * 
+     * @see ModifiedEntryFilter
+     * @return - a String array of entries to be omitted from a lucene index
+     *         search
+     */
+    public String[] getExculdList() {
+        this.readLock.lock();
+        try {
+            return this.excludeList
+                    .toArray(new String[this.excludeList.size()]);
+        } finally {
+            this.readLock.unlock();
+        }
+    }
+
+    // not synchronized --> see close()
+    private void clearBuffer() {
+
+        this.bufferMap.clear();
+        this.excludeList.clear();
+        this.modifiyMap.clear();
+
+    }
+
+    /**
+     * clears the buffer -
+     */
+    public void close() {
+        this.writeLock.lock();
+        try {
+            clearBuffer();
+        } finally {
+            this.writeLock.unlock();
+        }
+
+    }
+
+    static class BufferableEntry extends BaseEntry {
+
+        /**
+         * 
+         */
+        @SuppressWarnings("unchecked")
+        public BufferableEntry() {
+            super();
+            this.links = new LinkedList<Link>();
+        }
+
+        /**
+         * @param arg0
+         */
+        @SuppressWarnings("unchecked")
+        public BufferableEntry(BaseEntry arg0) {
+            super(arg0);
+            if (this.links.size() > 0) {
+                LinkedList list = new LinkedList<Link>();
+                list.addAll(this.links);
+                this.links = list;
+            } else
+                this.links = new LinkedList<Link>();
+        }
+
+        /**
+         * @see com.google.gdata.data.BaseEntry#declareExtensions(com.google.gdata.data.ExtensionProfile)
+         */
+        @Override
+        public void declareExtensions(ExtensionProfile arg0) {
+            //
+        }
+
+    }
+
+    /**
+     * @return Returns the bufferSize.
+     */
+    public int getBufferSize() {
+        return this.bufferSize;
+    }
 
 }

Modified: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageCoreController.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageCoreController.java?rev=425538&r1=425537&r2=425538&view=diff
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageCoreController.java (original)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageCoreController.java Tue Jul 25 15:23:01 2006
@@ -12,18 +12,18 @@
 import org.apache.lucene.gdata.data.GDataAccount;
 import org.apache.lucene.gdata.server.registry.Component;
 import org.apache.lucene.gdata.server.registry.ComponentType;
+import org.apache.lucene.gdata.server.registry.configuration.Requiered;
 import org.apache.lucene.gdata.storage.IDGenerator;
 import org.apache.lucene.gdata.storage.Storage;
 import org.apache.lucene.gdata.storage.StorageController;
 import org.apache.lucene.gdata.storage.StorageException;
-import org.apache.lucene.gdata.storage.lucenestorage.configuration.StorageConfigurator;
+import org.apache.lucene.gdata.storage.lucenestorage.recover.RecoverController;
+import org.apache.lucene.gdata.storage.lucenestorage.recover.RecoverException;
 import org.apache.lucene.gdata.storage.lucenestorage.util.ReferenceCounter;
 import org.apache.lucene.index.IndexModifier;
-import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.FSDirectory;
-import org.apache.lucene.store.RAMDirectory;
 
 /**
  *  
@@ -33,14 +33,15 @@
  */
 @Component(componentType = ComponentType.STORAGECONTROLLER)
 public class StorageCoreController implements StorageController {
+    
     protected static final Log LOG = LogFactory
             .getLog(StorageCoreController.class);
 
     private IndexSearcher searcher;
 
-    private final Directory storageDir;
+    private Directory storageDir;
 
-    private final StorageModifier modifier;
+    private StorageModifier modifier;
 
     private ReferenceCounter<StorageQuery> storageQuery;
 
@@ -49,39 +50,39 @@
     private final ReentrantLock storageControllerLock = new ReentrantLock();
     private final Condition closeCondition;
 
-    private static final int DEFAULT_STORAGE_BUFFER_SIZE = 10;
+    private static final int DEFAULT_STORAGE_BUFFER_SIZE = 3;
 
-    private static final int DEFAULT_STORAGE_PERSIST_FACTOR = 10;
+    private static final int DEFAULT_STORAGE_PERSIST_FACTOR = 3;
+    
+    private static final String RECOVERDIRECTORY = "recover";
 
     private static final String STORAGELOG = ".lucenestorage";
 
-    private int storageBufferSize;
-
-    private int storagePersistFactor;
-
-    private StorageConfigurator configurator;
-
     private IDGenerator idGenerator;
 
+    private final ConcurrentStorageLock storageLock;
+    /*
+     *properties set by configuration file e.g. Registry
+     */
     private int indexOptimizeInterval;
     
-//    private RecoverController recoverController;
+    private String storageDirectory; 
+ 
+    private boolean keepRecoveredFiles; 
+ 
+    private boolean recover; 
+    
+    private int storageBufferSize;
 
+    private int storagePersistFactor;
+    
+    private RecoverController recoverController;
     /**
-     * Creates a new <tt>StoragCoreController</tt> and sets up the storage
-     * environment reading the configuration file.
-     * 
-     * 
-     * 
-     * @throws IOException -
-     *             if an IOException occures
-     * @throws StorageException -
-     *             if the storage lock can not be created or the
-     *             {@link IDGenerator} can not be loaded
+     * @see org.apache.lucene.gdata.server.registry.ServerComponent#initialize()
      */
-    public StorageCoreController() throws IOException, StorageException {
+    public void initialize() {
         synchronized (StorageCoreController.class) {
-        	this.closeCondition = this.storageControllerLock.newCondition();
+         
             try {
                 this.idGenerator = new IDGenerator(10);
             } catch (Exception e) {
@@ -89,11 +90,11 @@
             }
 
             boolean createNewStorage = false;
-            this.configurator = StorageConfigurator.getStorageConfigurator();
-            if (!this.configurator.isRamDirectory()) {
+          
+            if (this.storageDir == null) {
 
-                String storageDirPath = this.configurator.getStorageDirectory();
-                File storeDir = new File(storageDirPath);
+                
+                File storeDir = new File(this.storageDirectory);
                 File storageLog = new File(storeDir.getAbsolutePath()
                         + System.getProperty("file.separator") + STORAGELOG);
                 try {
@@ -106,35 +107,83 @@
                         } else
                             throw new StorageException(
                                     "could not create storage lock file in "
-                                            + storageDirPath);
+                                            + this.storageDirectory);
 
                     } else
                         this.storageDir = FSDirectory.getDirectory(storeDir,
                                 false);
                 } catch (IOException e) {
                     storageLog.delete();
-                    throw e;
+                    throw new StorageException(e);
                 }
-                this.indexOptimizeInterval = this.configurator
-                        .getIndexOptimizeInterval();
-                this.storageBufferSize = this.configurator
-                        .getStorageBufferSize() < DEFAULT_STORAGE_BUFFER_SIZE ? DEFAULT_STORAGE_BUFFER_SIZE
-                        : this.configurator.getStorageBufferSize();
-                this.storagePersistFactor = this.configurator
-                        .getStoragepersistFactor() < DEFAULT_STORAGE_PERSIST_FACTOR ? DEFAULT_STORAGE_PERSIST_FACTOR
-                        : this.configurator.getStoragepersistFactor();
-
-            } else
-                this.storageDir = getRamDirectory();
+                
+                this.storageBufferSize = this.storageBufferSize < DEFAULT_STORAGE_BUFFER_SIZE ? DEFAULT_STORAGE_BUFFER_SIZE
+                        : this.storageBufferSize;
+                this.storagePersistFactor = this.storagePersistFactor < DEFAULT_STORAGE_PERSIST_FACTOR ? DEFAULT_STORAGE_PERSIST_FACTOR
+                        : this.storagePersistFactor;
+
+            }else
+                createNewStorage = true;
+               
 
             this.currentBuffer = new StorageBuffer(this.storageBufferSize);
+            try{
             this.modifier = createStorageModifier(createNewStorage);
             this.searcher = new IndexSearcher(this.storageDir);
-//            this.recoverController = new RecoverController(null,this.configurator.isRecover(),this.configurator.isKeepRecoveredFiles());
+            }catch (Exception e) {
+               throw new StorageException("Can not create Searcher/Modifier -- "+e.getMessage(),e);
+            }
+           
+            
             if(createNewStorage)
                 createAdminAccount();
+            if(!this.recover)
+                return;
+            try{
+            tryRecover();
+            }catch (Exception e) {
+                LOG.fatal("Recovering failed",e);
+                throw new StorageException("Recovering failed -- "+e.getMessage(),e); 
+            }
+            
+            this.recoverController = createRecoverController(false,false);
+            try{
+            this.recoverController.initialize();
+            }catch (Exception e) {
+                LOG.fatal("Can not initialize recover controller",e);
+                throw new StorageException("Can not initialize recover controller -- "+e.getMessage(),e);
+            }
 
         }
+    }
+    /*
+     * reads the remaining recover files to store the failed entries
+     */
+    private void tryRecover() throws IOException, RecoverException{
+        if(!this.recover)
+            return;
+        LOG.info("try to recover files if there are any");
+        this.recoverController = createRecoverController(true,false);
+        this.recoverController.initialize();
+        this.recoverController.recoverEntries(this.modifier);
+        this.recoverController.destroy();
+    }
+    
+    private RecoverController createRecoverController(boolean doRecover, boolean keepfiles){
+        String recoverDirectory = null;
+        if(this.storageDirectory.endsWith("/") || this.storageDirectory.endsWith("\\"))
+            recoverDirectory = this.storageDirectory.substring(0,this.storageDirectory.length()-1)+System.getProperty("file.separator")+RECOVERDIRECTORY;
+        else
+            recoverDirectory = this.storageDirectory+System.getProperty("file.separator")+RECOVERDIRECTORY;
+        File recoverDirectoryFile = new File(recoverDirectory);
+       return new RecoverController(recoverDirectoryFile,doRecover,keepfiles);
+    }
+    /**
+     * Creates a new <tt>StoragCoreController</tt>
+     */
+    public StorageCoreController() {
+        this.closeCondition = this.storageControllerLock.newCondition();
+        this.storageLock = SingleHostConcurrentStorageLock.getConcurrentStorageLock();
 
     }
 
@@ -188,7 +237,9 @@
             this.storageQuery.increamentReference();
             return this.storageQuery;
         }finally{
+            try{
         	this.closeCondition.signalAll();
+            }catch (Throwable e) {/**/}
         	this.storageControllerLock.unlock();
         }
     }
@@ -239,7 +290,9 @@
             this.currentBuffer = new StorageBuffer(this.storageBufferSize);
 
         }finally{
-        	this.closeCondition.signalAll();
+            try{
+                this.closeCondition.signalAll();
+                }catch (Throwable e) {/**/}
         	this.storageControllerLock.unlock();
         }
 
@@ -259,7 +312,9 @@
         		throw new IllegalStateException("StorageController is already closed -- server is shutting down");
             return this.currentBuffer;
         }finally{
+            try{
         	this.closeCondition.signalAll();
+            }catch (Throwable e) {/**/}
         	this.storageControllerLock.unlock();
         }
     }
@@ -284,7 +339,9 @@
             return new IndexModifier(this.storageDir, new StandardAnalyzer(),
                     false);
         }finally{
-        	this.closeCondition.signalAll();
+            try{
+                this.closeCondition.signalAll();
+                }catch (Throwable e) {/**/}
         	this.storageControllerLock.unlock();
         }
     }
@@ -308,48 +365,16 @@
                 LOG.info("StorageController has been closed -- server is shutting down -- release all resources");
             if (this.storageQuery != null)
                 this.storageQuery.decrementRef();
+            if(this.recoverController != null)
+                this.recoverController.destroy();
+            this.storageLock.close();
             this.modifier.close();
+            this.idGenerator.stopIDGenerator();
 		}finally{
         	this.storageControllerLock.unlock();
         }
     }
 
-    /**
-     * The size of the <tt>StorageBuffer</tt>.
-     * 
-     * @return - storage buffer size
-     */
-    public int getStorageBufferSize() {
-        return this.storageBufferSize;
-    }
-
-    /**
-     * The size of the <tt>StorageBuffer</tt>. This size should be at least
-     * as big as the persist factor to prevent the <tt>StorageBuffer</tt> from
-     * resizing
-     * 
-     * @param storageBufferSize
-     */
-    public void setStorageBufferSize(int storageBufferSize) {
-        this.storageBufferSize = storageBufferSize;
-    }
-
-    /**
-     * An integer value after how many changes to the StorageModifier the
-     * buffered changes will be persisted / wirtten to the index
-     * 
-     * @return - the persist factor
-     */
-    public int getStoragePersistFactor() {
-        return this.storagePersistFactor;
-    }
-
-    /**
-     * @param storagePersistFactor
-     */
-    public void setStoragePersistFactor(int storagePersistFactor) {
-        this.storagePersistFactor = storagePersistFactor;
-    }
 
     /**
      * Forces the StorageModifier to write all buffered changes.
@@ -364,12 +389,13 @@
         this.modifier.forceWrite();
     }
 
-    private boolean createLuceneStorageLog(File storageDirectory)
+    private boolean createLuceneStorageLog(File directory)
             throws IOException {
-        if (storageDirectory.isDirectory() && !storageDirectory.exists()) {
-            storageDirectory.createNewFile();
+        if (directory.isDirectory() && !directory.exists()) {
+            if(!directory.createNewFile())
+                throw new StorageException("Can not create directory -- "+directory);
         }
-        File file = new File(storageDirectory.getAbsolutePath()
+        File file = new File(directory.getAbsolutePath()
                 + System.getProperty("file.separator") + STORAGELOG);
         return file.createNewFile();
 
@@ -383,7 +409,7 @@
      * @throws StorageException -
      *             if no id can be released
      */
-    public synchronized String releaseID() throws StorageException {
+    public synchronized String releaseId() {
         try {
             return this.idGenerator.getUID();
         } catch (InterruptedException e) {
@@ -427,26 +453,142 @@
         }
     }
 
-    // TODO Try to remove this --> testcases
-    private RAMDirectory getRamDirectory() throws IOException {
-        IndexWriter writer;
-        RAMDirectory retVal = new RAMDirectory();
-        writer = new IndexWriter(retVal, new StandardAnalyzer(), true);
-        writer.close();
-        return retVal;
-    }
 
-    /**
-     * @see org.apache.lucene.gdata.server.registry.ServerComponent#initialize()
-     */
-    public void initialize() {
-        //
-    }
+
+
+    
     
     private void createAdminAccount() throws StorageException{
         GDataAccount adminAccount = GDataAccount.createAdminAccount();
         StorageAccountWrapper wrapper = new StorageAccountWrapper(adminAccount);
         this.getStorageModifier().createAccount(wrapper);
+    }
+    
+    protected ConcurrentStorageLock getLock(){
+        return this.storageLock;
+    }
+
+    
+    /**
+     * The size of the <tt>StorageBuffer</tt>.
+     * 
+     * @return - storage buffer size
+     */
+    public int getBufferSize() {
+        return this.storageBufferSize;
+    }
+
+    /**
+     * The size of the <tt>StorageBuffer</tt>. This size should be at least
+     * as big as the persist factor to prevent the <tt>StorageBuffer</tt> from
+     * resizing
+     * 
+     * @param storageBufferSize
+     */
+    @Requiered
+    public void setBufferSize(int storageBufferSize) {
+        this.storageBufferSize = storageBufferSize;
+    }
+
+    /**
+     * An integer value after how many changes to the StorageModifier the
+     * buffered changes will be persisted / wirtten to the index
+     * 
+     * @return - the persist factor
+     */
+    public int getPersistFactor() {
+        return this.storagePersistFactor;
+    }
+
+    /**
+     * @param storagePersistFactor
+     */
+    @Requiered
+    public void setPersistFactor(int storagePersistFactor) {
+        this.storagePersistFactor = storagePersistFactor;
+    }
+
+
+    /**
+     * @return Returns the indexOptimizeInterval.
+     */
+    public int getIndexOptimizeInterval() {
+        return this.indexOptimizeInterval;
+    }
+
+
+    /**
+     * @param indexOptimizeInterval The indexOptimizeInterval to set.
+     */
+    @Requiered
+    public void setOptimizeInterval(int indexOptimizeInterval) {
+        this.indexOptimizeInterval = indexOptimizeInterval;
+    }
+
+
+    /**
+     * @return Returns the keepRecoveredFiles.
+     */
+    public boolean isKeepRecoveredFiles() {
+        return this.keepRecoveredFiles;
+    }
+
+
+    /**
+     * @param keepRecoveredFiles The keepRecoveredFiles to set.
+     */
+    @Requiered
+    public void setKeepRecoveredFiles(boolean keepRecoveredFiles) {
+        this.keepRecoveredFiles = keepRecoveredFiles;
+    }
+
+
+
+    /**
+     * @return Returns the recover.
+     */
+    public boolean isRecover() {
+        return this.recover;
+    }
+
+
+    /**
+     * @param recover The recover to set.
+     */
+    @Requiered
+    public void setRecover(boolean recover) {
+        this.recover = recover;
+    }
+
+
+    /**
+     * @param storageDir The storageDir to set.
+     */
+   
+    public void setStorageDir(Directory storageDir) {
+        this.storageDir = storageDir;
+    }
+
+
+    /**
+     * @param storageDirectory The storageDirectory to set.
+     */
+    @Requiered
+    public void setDirectory(String storageDirectory) {
+        this.storageDirectory = storageDirectory;
+    }
+    
+    protected void writeRecoverEntry(StorageEntryWrapper wrapper) throws RecoverException{
+        if(this.recoverController!= null &&!this.recoverController.isRecovering() )
+            this.recoverController.storageModified(wrapper);
+    }
+    protected void registerNewRecoverWriter() throws IOException {
+        if(this.recoverController == null || this.recoverController.isRecovering())
+            return;
+        this.recoverController.destroy();
+        this.recoverController = createRecoverController(false,false);
+        this.recoverController.initialize();
+            
     }
 
 }

Modified: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageEntryWrapper.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageEntryWrapper.java?rev=425538&r1=425537&r2=425538&view=diff
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageEntryWrapper.java (original)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageEntryWrapper.java Tue Jul 25 15:23:01 2006
@@ -17,6 +17,7 @@
 package org.apache.lucene.gdata.storage.lucenestorage;
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.io.StringWriter;
 
 import org.apache.lucene.document.Document;
@@ -37,11 +38,13 @@
  * @author Simon Willnauer
  * 
  */
-public class StorageEntryWrapper implements Comparable<StorageEntryWrapper>,
+public class StorageEntryWrapper implements Comparable<StorageEntryWrapper>, Serializable,
         StorageWrapper {
 
     private static final long serialVersionUID = -4619985652059888526L;
-
+    /*
+     * client api uses UTF-8 to encode server requests and entries
+     */
     private static final String INTERNAL_ENCODING = "UTF-8";
 
     /**
@@ -64,21 +67,27 @@
      */
     public final static String FIELD_TIMESTAMP = "timestamp";
 
-    private final String entryId;
+    /**
+     * lucene field name entry version
+     */
+    public final static String FIELD_VERSION = "entryVersion";
+    private  int version;
+
+    private  String entryId;
 
-    private final String feedId;
+    private  String feedId;
 
     private  String content;
 
-    private final ServerBaseEntry entry;
+    private transient ServerBaseEntry entry;
 
     private Long timestamp;
 
-    private transient Document document;
+    private Document document;
 
     private StorageOperation operation;
 
-    private ProvidedService config;
+    private transient ProvidedService config;
 
     /**
      * Creates a new StorageEntryWrapper.
@@ -94,14 +103,15 @@
      */
     public StorageEntryWrapper(final ServerBaseEntry entry,
             StorageOperation operation) throws IOException {
-
         this.entry = entry;
         this.operation = operation;
         this.entryId = entry.getId();
         this.feedId = entry.getFeedId();
+        this.version = entry.getVersion();
         if (operation != StorageOperation.DELETE) {
             this.config = entry.getServiceConfig();
             this.content = buildContent();
+            
          
         }
         this.timestamp = new Long(
@@ -110,7 +120,8 @@
             
 
     }
-
+   
+ 
     private String buildContent() throws IOException {
         StringWriter writer = new StringWriter();
         XmlWriter xmlWriter = new XmlWriter(writer, INTERNAL_ENCODING);
@@ -132,10 +143,12 @@
                 Field.Store.YES, Field.Index.UN_TOKENIZED));
         this.document.add(new Field(FIELD_FEED_REFERENCE, this.feedId,
                 Field.Store.YES, Field.Index.UN_TOKENIZED));
-        this.document.add(new Field(FIELD_CONTENT, this.content,
+        this.document.add(new Field(FIELD_CONTENT,this.content,
                 Field.Store.COMPRESS, Field.Index.NO));
         this.document.add(new Field(FIELD_TIMESTAMP, this.timestamp.toString(),
                 Field.Store.YES, Field.Index.UN_TOKENIZED));
+        this.document.add(new Field(FIELD_VERSION, Integer.toString(this.version),
+                Field.Store.YES, Field.Index.UN_TOKENIZED));
 
         return this.document;
 
@@ -205,7 +218,7 @@
      * 
      */
     public int compareTo(StorageEntryWrapper arg0) {
-        return arg0.timestamp == this.timestamp ? 0
+        return arg0.timestamp.equals(this.timestamp) ? 0
                 : (arg0.timestamp > this.timestamp ? 1 : -1);
     }
 
@@ -222,5 +235,15 @@
     public Long getTimestamp() {
         return this.timestamp;
     }
+
+    /**
+     * @return - the version of the entry
+     */
+    public int getVersion() {
+        
+        return this.version;
+    }
+
+
 
 }

Modified: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageImplementation.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageImplementation.java?rev=425538&r1=425537&r2=425538&view=diff
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageImplementation.java (original)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageImplementation.java Tue Jul 25 15:23:01 2006
@@ -25,6 +25,7 @@
 import org.apache.lucene.gdata.data.ServerBaseFeed;
 import org.apache.lucene.gdata.server.registry.ComponentType;
 import org.apache.lucene.gdata.server.registry.GDataServerRegistry;
+import org.apache.lucene.gdata.storage.ModificationConflictException;
 import org.apache.lucene.gdata.storage.ResourceNotFoundException;
 import org.apache.lucene.gdata.storage.Storage;
 import org.apache.lucene.gdata.storage.StorageController;
@@ -76,11 +77,16 @@
      */
     public BaseEntry storeEntry(final ServerBaseEntry entry)
             throws StorageException {
-
         if (entry == null)
             throw new StorageException("entry is null");
+        if(entry.getFeedId() == null)
+            throw new StorageException("feedid is null");
+        if(entry.getVersion() != 1)
+            throw new StorageException("entry version must be 1");
+        if(entry.getServiceConfig() == null)
+            throw new StorageException("ProvidedService must not be null");
         StorageModifier modifier = this.controller.getStorageModifier();
-        String id = this.controller.releaseID();
+        String id = this.controller.releaseId();
         entry.setId(entry.getFeedId() + id);
         if (LOG.isInfoEnabled())
             LOG.info("Store entry " + id + " -- feed: " + entry.getFeedId());
@@ -108,23 +114,34 @@
 
         if (entry == null)
             throw new StorageException("Entry is null");
-
+        if(entry.getId() == null)
+            throw new StorageException("Entry id is null");
+        if(entry.getFeedId() == null)
+            throw new StorageException("feed id is null");
         if (LOG.isInfoEnabled())
             LOG.info("delete entry " + entry.getId() + " -- feed: "
                     + entry.getFeedId());
         StorageModifier modifier = this.controller.getStorageModifier();
         ReferenceCounter<StorageQuery> query = this.controller.getStorageQuery();
+        // try to set concurrency Lock
+        String key = entry.getId();
+        setLock(key);
         try{
         if(query.get().isEntryStored(entry.getId(),entry.getFeedId())){
-            
-            modifier.deleteEntry(new StorageEntryWrapper(entry,StorageOperation.DELETE));
+            if(query.get().checkEntryVersion(entry.getId(),entry.getFeedId(),entry.getVersion())){
+                modifier.deleteEntry(new StorageEntryWrapper(entry,StorageOperation.DELETE));
+            }else
+                throw new ModificationConflictException("The entry version does not match -- entry "+entry.getId()+" feed:"+entry.getFeedId()+" version: "+entry.getVersion());
         }
         else
             throw new ResourceNotFoundException("Entry for entry id: "+entry.getId()+" is not stored");
         }catch (IOException e) {
             throw new StorageException("Can not access storage");
         }finally{
-            query.decrementRef();
+            if(query != null)
+                query.decrementRef();
+            // release lock for concurrency
+            releaseLock(key);
         }
     }
 
@@ -137,6 +154,8 @@
             throw new StorageException("entry is null");
         if(entry.getId() == null)
             throw new StorageException("entry id is null");
+        if(entry.getServiceConfig() == null)
+            throw new StorageException("service config is not set -- null");
         if(entry.getFeedId() == null)
             throw new StorageException("feed id is null");
         if (LOG.isInfoEnabled())
@@ -144,28 +163,56 @@
                     + entry.getFeedId());
         StorageModifier modifier = this.controller.getStorageModifier();
         ReferenceCounter<StorageQuery> query = this.controller.getStorageQuery();
+        // try to set concurrency Lock
+        String key = entry.getId();
+        setLock(key);
         try {
-            StorageEntryWrapper wrapper = new StorageEntryWrapper(entry,
-                    StorageOperation.UPDATE);
-            if(query.get().isEntryStored(entry.getId(),entry.getFeedId()))
-                modifier.updateEntry(wrapper);
-            else
+            
+            
+            if(query.get().isEntryStored(entry.getId(),entry.getFeedId())){
+                
+                if(query.get().checkEntryVersion(entry.getId(),entry.getFeedId(),entry.getVersion())){
+                    entry.setVersion(entry.getVersion()+1);
+                    StorageEntryWrapper wrapper = new StorageEntryWrapper(entry,
+                            StorageOperation.UPDATE);  
+                    modifier.updateEntry(wrapper);
+                }else
+                    throw new ModificationConflictException("The entry version does not match -- entry "+entry.getId()+" feed:"+entry.getFeedId()+" version: "+entry.getVersion());
+              
+            }else
                 throw new ResourceNotFoundException("Entry for entry id: "+entry.getId()+" is not stored");
             
         } catch (IOException e) {
             LOG.error("Can't update entry for feedID: " + entry.getFeedId()
                     + "; entryId: " + entry.getId() + " -- " + e.getMessage(),
                     e);
-            StorageException ex = new StorageException("Can't create Entry -- "
+            StorageException ex = new StorageException("Can't update Entry -- "
                     + e.getMessage(), e);
             ex.setStackTrace(e.getStackTrace());
             throw ex;
 
         }
 
+        finally{
+            if(query != null)
+                query.decrementRef();
+            // release lock for concurrency
+            releaseLock(key);
+        }
+
         return entry.getEntry();
 
     }
+    private void setLock(String key) throws ModificationConflictException{
+        if(!this.controller.getLock().setLock(key))
+            throw new ModificationConflictException("Can not set lock for entry -- "+key);
+            
+    }
+    
+    private void releaseLock(String key) throws StorageException{
+        if(!this.controller.getLock().releaseLock(key))
+            throw new StorageException("Can not release lock for key: "+key);
+    }
 
     /**
      * @see org.apache.lucene.gdata.storage.Storage#getFeed(org.apache.lucene.gdata.data.ServerBaseFeed)
@@ -382,7 +429,7 @@
             throw ex;
 
         } finally {
-            if (query == null)
+            if (query != null)
                 query.decrementRef();
         }
     }
@@ -415,7 +462,7 @@
             throw ex;
 
         } finally {
-            if (query == null)
+            if (query != null)
                 query.decrementRef();
         }
 

Modified: lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageModifier.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageModifier.java?rev=425538&r1=425537&r2=425538&view=diff
==============================================================================
--- lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageModifier.java (original)
+++ lucene/java/trunk/contrib/gdata-server/src/java/org/apache/lucene/gdata/storage/lucenestorage/StorageModifier.java Tue Jul 25 15:23:01 2006
@@ -1,3 +1,18 @@
+/**
+ * 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.lucene.gdata.storage.lucenestorage;
 
 import java.io.IOException;
@@ -9,7 +24,7 @@
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -67,13 +82,9 @@
 
     private IndexModifier modifier;
 
-    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false);
+    private Lock lock = new ReentrantLock();
     
     private final AtomicBoolean isClosed = new AtomicBoolean(false);
-    
-    private final Lock readLock = this.lock.readLock();
-
-    private final Lock writeLock = this.lock.writeLock();
 
     private final static int DEFAULT_OPTIMIZE_INTERVAL = 10;
 
@@ -130,17 +141,33 @@
             throws StorageException {
         if(wrapper.getOperation() != StorageOperation.UPDATE)
             throw new StorageException("Illegal method call -- updateEntry does not accept other storageOperations than update");
-        this.readLock.lock();
+        this.lock.lock();
         try {
+            
             Term tempTerm = new Term(StorageEntryWrapper.FIELD_ENTRY_ID,
                     wrapper.getEntryId());
             this.documentMap.put(wrapper.getEntryId(), wrapper
                     .getLuceneDocument());
             this.deletedForUpdateDocumentQueue.add(tempTerm);
-            this.buffer.addEntry(wrapper);
             storageModified();
+            /*
+             * If storage not written write entry to recoverfile
+             * and make the entry available via the buffer
+             */
+            if(this.modifiedCounter != 0)
+                try{
+                    this.controller.writeRecoverEntry(wrapper);
+                    this.buffer.addEntry(wrapper);
+                }catch (Exception e) {
+                    /*
+                     * remove from all resources
+                     */
+                    this.documentMap.remove(wrapper.getEntryId());
+                    this.deletedForUpdateDocumentQueue.remove(tempTerm);
+                    
+                }
         } finally {
-            this.readLock.unlock();
+            this.lock.unlock();
         }
     }
 
@@ -156,14 +183,27 @@
             throws StorageException {
         if(wrapper.getOperation() != StorageOperation.INSERT)
             throw new StorageException("Illegal method call -- insertEntry does not accept other storage operations than insert");
-        this.readLock.lock();
+        this.lock.lock();
         try {
             this.documentMap.put(wrapper.getEntryId(), wrapper
                     .getLuceneDocument());
-            this.buffer.addEntry(wrapper);
             storageModified();
+            /*
+             * If storage not written write entry to recoverfile
+             * and make the entry available via the buffer
+             */
+            if(this.modifiedCounter != 0)
+                try{
+                    this.controller.writeRecoverEntry(wrapper);
+                    this.buffer.addEntry(wrapper);
+                }catch (Exception e) {
+                    /*
+                     * remove from all resources
+                     */
+                    this.documentMap.remove(wrapper.getEntryId());
+                }
         } finally {
-            this.readLock.unlock();
+            this.lock.unlock();
         }
     }
 
@@ -179,15 +219,30 @@
             throws StorageException {
         if(wrapper.getOperation() != StorageOperation.DELETE)
             throw new StorageException("Illegal method call -- insertEntry does not accept other storage operations than delete");
-        this.readLock.lock();
+        this.lock.lock();
         try {
+            
             Term tempTerm = new Term(StorageEntryWrapper.FIELD_ENTRY_ID,
                     wrapper.getEntryId());
             this.deletedDocumentQueue.add(tempTerm);
-            this.buffer.addDeleted(wrapper.getEntryId(), wrapper.getFeedId());
             storageModified();
+            /*
+             * If storage not written write entry to recoverfile
+             * and make the entry available via the buffer
+             */
+            if(this.modifiedCounter != 0)
+                try{
+                    this.controller.writeRecoverEntry(wrapper);
+                    this.buffer.addDeleted(wrapper.getEntryId(), wrapper.getFeedId());
+                }catch (Exception e) {
+                    /*
+                     * remove from all resources
+                     */
+                 this.deletedDocumentQueue.remove(tempTerm);
+                    
+                }
         } finally {
-            this.readLock.unlock();
+            this.lock.unlock();
         }
     }
 
@@ -201,12 +256,12 @@
      *             if the feed can not be written
      */
     public void createFeed(StorageFeedWrapper wrapper) throws StorageException {
-        this.readLock.lock();
+        this.lock.lock();
         try {
             this.forceWriteDocuments.add(wrapper.getLuceneDocument());
             storageModified();
         } finally {
-            this.readLock.unlock();
+            this.lock.unlock();
         }
     }
 
@@ -220,12 +275,12 @@
      *             if the user can not be persisted.
      */
     public void createAccount(StorageAccountWrapper account) throws StorageException {
-        this.readLock.lock();
+        this.lock.lock();
         try {
             this.forceWriteDocuments.add(account.getLuceneDocument());
             storageModified();
         } finally {
-            this.readLock.unlock();
+            this.lock.unlock();
         }
     }
 
@@ -239,14 +294,14 @@
      *             If the user could not be deleted
      */
     public void deleteAccount(String accountName) throws StorageException {
-        this.readLock.lock();
+        this.lock.lock();
         try {
             //TODO delete all feeds and entries of this account
             this.forceWriteTerms.add(new Term(
                     StorageAccountWrapper.FIELD_ACCOUNTNAME, accountName));
             storageModified();
         } finally {
-            this.readLock.unlock();
+            this.lock.unlock();
         }
     }
 
@@ -261,7 +316,7 @@
      */
     public void updateAccount(final StorageAccountWrapper user)
             throws StorageException {
-        this.readLock.lock();
+        this.lock.lock();
         try {
             this.forceWriteTerms.add(new Term(
                     StorageAccountWrapper.FIELD_ACCOUNTNAME, user.getUser()
@@ -269,7 +324,7 @@
             this.forceWriteDocuments.add(user.getLuceneDocument());
             storageModified();
         } finally {
-            this.readLock.unlock();
+            this.lock.unlock();
         }
     }
 
@@ -284,14 +339,14 @@
      */
     public void updateFeed(final StorageFeedWrapper wrapper)
             throws StorageException {
-        this.readLock.lock();
+        this.lock.lock();
         try {
             this.forceWriteTerms.add(new Term(StorageFeedWrapper.FIELD_FEED_ID,
                     wrapper.getFeed().getId()));
             this.forceWriteDocuments.add(wrapper.getLuceneDocument());
             storageModified();
         } finally {
-            this.readLock.unlock();
+            this.lock.unlock();
         }
     }
 
@@ -305,7 +360,7 @@
      *             if the feed can not be deleted
      */
     public void deleteFeed(final String feedId) throws StorageException {
-        this.readLock.lock();
+        this.lock.lock();
         try {
             this.deletedDocumentQueue.add(new Term(StorageEntryWrapper.FIELD_FEED_REFERENCE,feedId));
             this.forceWriteTerms.add(new Term(StorageFeedWrapper.FIELD_FEED_ID,
@@ -313,16 +368,14 @@
 
             storageModified();
         } finally {
-            this.readLock.unlock();
+            this.lock.unlock();
         }
     }
 
     private void storageModified() throws StorageException {
     	if(this.isClosed.get())
     		throw new IllegalStateException("StorageModifier is already closed");
-        this.readLock.unlock();
-        this.writeLock.lock();
-
+       
         try {
         	if(this.isClosed.get())
         		throw new IllegalStateException("StorageModifier is already closed");
@@ -343,18 +396,18 @@
 
             LOG.error("Writing persistent index failed - Recovering", e);
             throw new StorageException("could not write to storage index -- "+e.getMessage(),e);
-
-        } finally {
-            this.readLock.lock();
-            this.writeLock.unlock();
         }
-
+       
     }
 
-    protected void forceWrite() throws IOException {
+    /**
+     * Persists all changes imediately
+     * @throws IOException -- if an IO Exception  occures
+     */
+    public void forceWrite() throws IOException {
     	if(this.isClosed.get())
     		throw new IllegalStateException("StorageModifier is already closed");
-        this.writeLock.lock();
+        this.lock.lock();
         try {
             if (LOG.isInfoEnabled())
                 LOG.info("ForceWrite called -- current modifiedCounter: "
@@ -363,12 +416,12 @@
             requestNewIndexModifier();
             this.modifiedCounter = 0;
         } finally {
-            this.writeLock.unlock();
+            this.lock.unlock();
         }
     }
 
     private void requestNewIndexModifier() throws IOException {
-
+        this.controller.registerNewRecoverWriter();
         this.controller.registerNewStorageQuery();
         this.buffer = this.controller.releaseNewStorageBuffer();
         this.modifier = this.controller.createIndexModifier();
@@ -435,7 +488,7 @@
     protected void close() throws IOException {
     	if(this.isClosed.get())
     		throw new IllegalStateException("StorageModifier is already closed");
-        this.writeLock.lock();
+        this.lock.lock();
         try {
         	if(this.isClosed.get())
         		throw new IllegalStateException("StorageModifier is already closed");
@@ -447,7 +500,7 @@
             writePersistentIndex(true);
             this.modifiedCounter = 0;
         } finally {
-            this.writeLock.unlock();
+            this.lock.unlock();
         }
     }
 



Mime
View raw message