You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2013/05/15 11:08:54 UTC

svn commit: r1482732 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/ main/java/org/apache/jackrabbit/core/data/ test/java/org/apache/jackrabbit/core/data/

Author: thomasm
Date: Wed May 15 09:08:53 2013
New Revision: 1482732

URL: http://svn.apache.org/r1482732
Log:
JCR-3547 Datastore GC doesn't reset updateModifiedDateOnAccess on datastore

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryContext.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryContext.java?rev=1482732&r1=1482731&r2=1482732&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryContext.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryContext.java Wed May 15 09:08:53 2013
@@ -124,6 +124,12 @@ public class RepositoryContext {
      * The Statistics manager, handles statistics
      */
     private StatManager statManager;
+    
+    /**
+     *  flag to indicate if GC is running
+     */
+    
+    private boolean gcRunning;
 
     /**
      * Creates a component context for the given repository.
@@ -450,4 +456,22 @@ public class RepositoryContext {
         return statManager;
     }
 
+    /**
+     * 
+     * @return gcRunning status
+     */
+    public boolean isGcRunning() {
+        return gcRunning;
+    }
+
+    /**
+     * set gcRunnign status
+     * @param gcRunning
+     */
+    public synchronized void setGcRunning(boolean gcRunning) {
+        this.gcRunning = gcRunning;
+    }
+    
+    
+
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=1482732&r1=1482731&r2=1482732&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Wed May 15 09:08:53 2013
@@ -1423,7 +1423,14 @@ public class RepositoryImpl extends Abst
             }
             ipmList[i] = (IterablePersistenceManager) pm;
         }
-        return new GarbageCollector(context.getDataStore(), ipmList, sessions);
+        GarbageCollector gc = new GarbageCollector(context, context.getDataStore(), ipmList, sessions);
+        synchronized (this) {
+            if (context.isGcRunning()) {
+                throw new RepositoryException("Cannot create GC. GC already running");
+            }
+            context.setGcRunning(true);
+        }
+        return gc;
     }
 
     //-----------------------------------------------------------< Repository >

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java?rev=1482732&r1=1482731&r2=1482732&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java Wed May 15 09:08:53 2013
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.core.data;
 
 import org.apache.jackrabbit.api.management.DataStoreGarbageCollector;
 import org.apache.jackrabbit.api.management.MarkEventListener;
+import org.apache.jackrabbit.core.RepositoryContext;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.id.PropertyId;
@@ -103,6 +104,8 @@ public class GarbageCollector implements
     private final SessionImpl[] sessionList;
 
     private final AtomicBoolean closed = new AtomicBoolean();
+    
+    private final RepositoryContext context;
 
     private boolean persistenceManagerScan;
 
@@ -112,14 +115,17 @@ public class GarbageCollector implements
      * Create a new garbage collector.
      * This method is usually not called by the application, it is called
      * by SessionImpl.createDataStoreGarbageCollector().
-     *
+     * 
+     * @param context repository context
      * @param dataStore the data store to be garbage-collected
      * @param list the persistence managers
      * @param sessionList the sessions to access the workspaces
      */
-    public GarbageCollector(
+    
+    public GarbageCollector(RepositoryContext context, 
             DataStore dataStore, IterablePersistenceManager[] list,
             SessionImpl[] sessionList) {
+        this.context = context;
         this.store = dataStore;
         this.pmList = list;
         this.persistenceManagerScan = list != null;
@@ -226,9 +232,13 @@ public class GarbageCollector implements
     }
 
     /**
-     * Stop the observation listener if any are installed.
+     * Reset modifiedDateOnAccess to 0 and stop the observation 
+     * listener if any are installed.
      */
     public void stopScan() throws RepositoryException {
+         // reset updateModifiedDateOnAccess to OL
+        store.updateModifiedDateOnAccess(0L);
+        
         if (listeners.size() > 0) {
             for (Listener listener : listeners) {
                 listener.stop();
@@ -236,6 +246,7 @@ public class GarbageCollector implements
             listeners.clear();
         }
         checkObservationException();
+        context.setGcRunning(false);
     }
 
     public int sweep() throws RepositoryException {
@@ -335,7 +346,7 @@ public class GarbageCollector implements
          */
     }
 
-    private void checkLengths(long... lengths) throws RepositoryException {
+    private static void checkLengths(long... lengths) throws RepositoryException {
         for (long length : lengths) {
             if (length == -1) {
                 throw new RepositoryException("mark failed to access a property");

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java?rev=1482732&r1=1482731&r2=1482732&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java Wed May 15 09:08:53 2013
@@ -56,7 +56,7 @@ public class GarbageCollectorTest extend
                 closeTest();
             }
 
-            private void closeTest() throws RepositoryException {
+            private void closeTest() {
                 if (closed) {
                     ex[0] = new Exception("Scanning after the session is closed");
                 }
@@ -183,6 +183,35 @@ public class GarbageCollectorTest extend
 
         gc.close();
     }
+    
+    /**
+     *  Test to validate that two  GC cannot run simulatenously. one 
+     *  exits throwing exception  
+     */
+    public void testSimulatenousRunGC() throws Exception {
+        Node root = testRootNode;
+        Session session = root.getSession();
+
+        GCThread gct1 = new GCThread(session);
+        GCThread gct2 = new GCThread(session);
+        Thread gcThread1 = new Thread(gct1, "Datastore Garbage Collector 1");
+        Thread gcThread2 = new Thread(gct2, "Datastore Garbage Collector 2");
+        // run simulatensou gc
+        gcThread1.start();
+        gcThread2.start();
+        Thread.sleep(100);
+        
+        gct1.setStop(true);
+        gct2.setStop(true);
+        
+        // allow them to complete
+        gcThread1.join();
+        gcThread2.join();
+
+        // only one should throw error
+        int count = (gct1.getException() == null ? 0 : 1) + (gct2.getException() == null ? 0 : 1);
+        assertEquals("only one gc should throw exception ", 1, count);
+    }
 
     private void runGC(Session session, boolean all) throws Exception {
         GarbageCollector gc = ((SessionImpl)session).createDataStoreGarbageCollector();
@@ -202,7 +231,7 @@ public class GarbageCollectorTest extend
         gc.close();
     }
 
-    private int listIdentifiers(GarbageCollector gc) throws DataStoreException {
+    private static int listIdentifiers(GarbageCollector gc) throws DataStoreException {
         LOG.debug("identifiers:");
         int count = 0;
         Iterator<DataIdentifier> it = gc.getDataStore().getAllIdentifiers();
@@ -242,7 +271,7 @@ public class GarbageCollectorTest extend
         s2.logout();
     }
 
-    private void verifyInputStream(InputStream in, InputStream in2) throws IOException {
+    private static void verifyInputStream(InputStream in, InputStream in2) throws IOException {
         while (true) {
             int a = in.read();
             int b = in2.read();