You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by dp...@apache.org on 2012/08/22 16:53:18 UTC

svn commit: r1376084 - in /jackrabbit/oak/trunk/oak-mk: ./ src/main/java/org/apache/jackrabbit/mk/model/ src/main/java/org/apache/jackrabbit/mk/persistence/ src/main/java/org/apache/jackrabbit/mk/store/

Author: dpfister
Date: Wed Aug 22 14:53:18 2012
New Revision: 1376084

URL: http://svn.apache.org/viewvc?rev=1376084&view=rev
Log:
OAK-216 - Occasional org.apache.jackrabbit.mk.store.NotFoundExceptions
- add logging support to oak-mk

Modified:
    jackrabbit/oak/trunk/oak-mk/pom.xml
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/model/CommitBuilder.java
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/GCPersistence.java
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/H2Persistence.java
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/InMemPersistence.java
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/store/DefaultRevisionStore.java
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/store/RevisionStore.java

Modified: jackrabbit/oak/trunk/oak-mk/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/pom.xml?rev=1376084&r1=1376083&r2=1376084&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-mk/pom.xml Wed Aug 22 14:53:18 2012
@@ -93,6 +93,13 @@
       <version>${project.version}</version>
     </dependency>
 
+    <!-- Logging -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <version>1.6.4</version>
+    </dependency>
+
     <!-- default persistence backend -->
     <dependency>
       <groupId>com.h2database</groupId>
@@ -121,6 +128,12 @@
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <version>1.0.1</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
 

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/model/CommitBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/model/CommitBuilder.java?rev=1376084&r1=1376083&r2=1376084&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/model/CommitBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/model/CommitBuilder.java Wed Aug 22 14:53:18 2012
@@ -156,7 +156,7 @@ public class CommitBuilder {
                 newCommit.setChanges(diff.toString());
                 newCommit.setRootNodeId(rootNodeId);
                 newCommit.setBranchRootId(null);
-                newRevId = store.putHeadCommit(token, newCommit, null);
+                newRevId = store.putHeadCommit(token, newCommit, null, null);
             } finally {
                 store.unlockHead();
             }
@@ -228,7 +228,7 @@ public class CommitBuilder {
             newCommit.setChanges(diff);
             newCommit.setRootNodeId(rootNodeId);
             newCommit.setBranchRootId(null);
-            newRevId = store.putHeadCommit(token, newCommit, branchRootId);
+            newRevId = store.putHeadCommit(token, newCommit, branchRootId, baseRevId);
         } finally {
             store.unlockHead();
         }

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/GCPersistence.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/GCPersistence.java?rev=1376084&r1=1376083&r2=1376084&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/GCPersistence.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/GCPersistence.java Wed Aug 22 14:53:18 2012
@@ -86,7 +86,8 @@ public interface GCPersistence extends P
     /**
      * Sweep all objects that are not marked and were written before the GC started.
      * 
+     * @return number of swept items or <code>-1</code> if number is unknown
      * @throws Exception if an error occurs
      */
-    void sweep() throws Exception;
+    int sweep() throws Exception;
 }

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/H2Persistence.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/H2Persistence.java?rev=1376084&r1=1376083&r2=1376084&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/H2Persistence.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/H2Persistence.java Wed Aug 22 14:53:18 2012
@@ -141,17 +141,19 @@ public class H2Persistence implements GC
         node.serialize(new BinaryBinding(out));
         byte[] bytes = out.toByteArray();
         byte[] rawId = idFactory.createContentId(bytes);
+        Timestamp ts = new Timestamp(System.currentTimeMillis());
         //String id = StringUtils.convertBytesToHex(rawId);
 
         Connection con = cp.getConnection();
         try {
             PreparedStatement stmt = con
                     .prepareStatement(
-                            "insert into REVS (ID, DATA, TIME) select ?, ?, CURRENT_TIMESTAMP() where not exists (select 1 from REVS where ID = ?)");
+                            "insert into REVS (ID, DATA, TIME) select ?, ?, ? where not exists (select 1 from REVS where ID = ?)");
             try {
                 stmt.setBytes(1, rawId);
                 stmt.setBytes(2, bytes);
-                stmt.setBytes(3, rawId);
+                stmt.setTimestamp(3, ts);
+                stmt.setBytes(4, rawId);
                 stmt.executeUpdate();
             } finally {
                 stmt.close();
@@ -187,16 +189,18 @@ public class H2Persistence implements GC
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         commit.serialize(new BinaryBinding(out));
         byte[] bytes = out.toByteArray();
+        Timestamp ts = new Timestamp(System.currentTimeMillis());
 
         Connection con = cp.getConnection();
         try {
             PreparedStatement stmt = con
                     .prepareStatement(
-                            "insert into REVS (ID, DATA, TIME) select ?, ?, CURRENT_TIMESTAMP() where not exists (select 1 from REVS where ID = ?)");
+                            "insert into REVS (ID, DATA, TIME) select ?, ?, ? where not exists (select 1 from REVS where ID = ?)");
             try {
                 stmt.setBytes(1, id.getBytes());
                 stmt.setBytes(2, bytes);
-                stmt.setBytes(3, id.getBytes());
+                stmt.setTimestamp(3, ts);
+                stmt.setBytes(4, id.getBytes());
                 stmt.executeUpdate();
             } finally {
                 stmt.close();
@@ -232,16 +236,18 @@ public class H2Persistence implements GC
         map.serialize(new BinaryBinding(out));
         byte[] bytes = out.toByteArray();
         byte[] rawId = idFactory.createContentId(bytes);
+        Timestamp ts = new Timestamp(System.currentTimeMillis());
 
         Connection con = cp.getConnection();
         try {
             PreparedStatement stmt = con
                     .prepareStatement(
-                            "insert into REVS (ID, DATA, TIME) select ?, ?, CURRENT_TIMESTAMP() where not exists (select 1 from REVS where ID = ?)");
+                            "insert into REVS (ID, DATA, TIME) select ?, ?, ? where not exists (select 1 from REVS where ID = ?)");
             try {
                 stmt.setBytes(1, rawId);
                 stmt.setBytes(2, bytes);
-                stmt.setBytes(3, rawId);
+                stmt.setTimestamp(3, ts);
+                stmt.setBytes(4, rawId);
                 stmt.executeUpdate();
             } finally {
                 stmt.close();
@@ -317,7 +323,7 @@ public class H2Persistence implements GC
     }
     
     @Override
-    public void sweep() throws Exception {
+    public int sweep() throws Exception {
         Timestamp ts = new Timestamp(gcStart);
 
         Connection con = cp.getConnection();
@@ -327,7 +333,7 @@ public class H2Persistence implements GC
                             "delete REVS where TIME < ?");
             try {
                 stmt.setTimestamp(1, ts);
-                stmt.executeUpdate();
+                return stmt.executeUpdate();
             } finally {
                 stmt.close();
             }

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/InMemPersistence.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/InMemPersistence.java?rev=1376084&r1=1376083&r2=1376084&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/InMemPersistence.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/persistence/InMemPersistence.java Wed Aug 22 14:53:18 2012
@@ -175,10 +175,13 @@ public class InMemPersistence implements
     }
 
     @Override
-    public void sweep() {
+    public int sweep() {
+        int count = objects.size();
+        
         objects.clear();
         objects.putAll(marked);
         
         gcStart = 0;
+        return count;
     }
 }

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/store/DefaultRevisionStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/store/DefaultRevisionStore.java?rev=1376084&r1=1376083&r2=1376084&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/store/DefaultRevisionStore.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/store/DefaultRevisionStore.java Wed Aug 22 14:53:18 2012
@@ -32,6 +32,8 @@ import org.apache.jackrabbit.mk.persiste
 import org.apache.jackrabbit.mk.persistence.Persistence;
 import org.apache.jackrabbit.mk.util.IOUtils;
 import org.apache.jackrabbit.mk.util.SimpleLRUCache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.Closeable;
 import java.util.Collections;
@@ -55,6 +57,8 @@ import java.util.concurrent.locks.Reentr
 public class DefaultRevisionStore extends AbstractRevisionStore implements
         Closeable {
 
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultRevisionStore.class);
+    
     public static final String CACHE_SIZE = "mk.cacheSize";
     public static final int DEFAULT_CACHE_SIZE = 10000;
 
@@ -82,6 +86,8 @@ public class DefaultRevisionStore extend
      * GC run state.
      */
     private final AtomicInteger gcState = new AtomicInteger();
+    
+    private int markedNodes, markedCommits;
 
     /**
      * GC executor.
@@ -99,7 +105,7 @@ public class DefaultRevisionStore extend
     private final ReentrantReadWriteLock tokensLock = new ReentrantReadWriteLock();
 
     /**
-     * Active branches (Key: branch root id, Value: branch head).
+     * Active branches (Key: current branch head, Value: branch root id).
      */
     private final TreeMap<Id,Id> branches = new TreeMap<Id, Id>();
 
@@ -160,7 +166,7 @@ public class DefaultRevisionStore extend
                         gc();
                     }
                 }
-            }, 60, 1, TimeUnit.MINUTES); // FIXME, see OAK-216
+            }, 10, 1, TimeUnit.MINUTES);
         }
 
         initialized = true;
@@ -292,7 +298,7 @@ public class DefaultRevisionStore extend
         headLock.writeLock().lock();
     }
 
-    public Id putHeadCommit(PutToken token, MutableCommit commit, Id branchRootId)
+    public Id putHeadCommit(PutToken token, MutableCommit commit, Id branchRootId, Id branchRevId)
             throws Exception {
         verifyInitialized();
         if (!headLock.writeLock().isHeldByCurrentThread()) {
@@ -304,9 +310,9 @@ public class DefaultRevisionStore extend
         setHeadCommitId(id);
         
         putTokens.remove(token);
-        if (branchRootId != null) {
+        if (branchRevId != null) {
             synchronized (branches) {
-                branches.remove(branchRootId);
+                branches.remove(branchRevId);
             }
         }
         return id;
@@ -321,10 +327,14 @@ public class DefaultRevisionStore extend
         Id branchRootId = commit.getBranchRootId();
         if (branchRootId != null) {
             synchronized (branches) {
-                branches.put(branchRootId, commitId);
+                Id parentId = commit.getParentId();
+                if (!parentId.equals(branchRootId)) {
+                    /* not the first branch commit, replace its head */
+                    branches.remove(parentId);
+                }
+                branches.put(commitId, branchRootId);
             }
         }
-        
         return commitId;
     }
 
@@ -496,11 +506,20 @@ public class DefaultRevisionStore extend
             // already running
             return;
         }
+        
+        LOG.debug("GC started.");
+        markedCommits = markedNodes = 0;
 
         try {
             markUncommittedNodes();
             Id firstBranchRootId = markBranches();
+            if (firstBranchRootId != null) {
+                LOG.debug("First branch root to be preserved: {}", firstBranchRootId);
+            }
             Id firstCommitId = markCommits();
+            LOG.debug("First commit to be preserved: {}", firstCommitId);
+
+            LOG.debug("Marked {} commits, {} nodes.", markedCommits, markedNodes);
 
             if (firstBranchRootId != null && firstBranchRootId.compareTo(firstCommitId) < 0) {
                 firstCommitId = firstBranchRootId;
@@ -515,21 +534,24 @@ public class DefaultRevisionStore extend
             
         } catch (Exception e) {
             /* unable to perform GC */
+            LOG.error("Exception occurred in GC cycle", e);
             gcState.set(NOT_ACTIVE);
-            e.printStackTrace();
             return;
         }
         
         gcState.set(SWEEPING);
 
         try {
-            gcpm.sweep();
+            int swept = gcpm.sweep();
+            LOG.debug("GC cycle swept {} items", swept);
             cache.clear();
         } catch (Exception e) {
-            e.printStackTrace();
+            LOG.error("Exception occurred in GC cycle", e);
         } finally {
             gcState.set(NOT_ACTIVE);
         }
+        
+        LOG.debug("GC stopped.");
     }
     
     /**
@@ -569,19 +591,23 @@ public class DefaultRevisionStore extend
             tmpBranches = (Map<Id,Id>) branches.clone();
         }
         
+        Id firstBranchRootId = null;
+        
         /* Mark all branch commits */
         for (Entry<Id, Id> entry : tmpBranches.entrySet()) {
-            Id branchRootId = entry.getKey();
-            Id branchHeadId = entry.getValue();
-            while (!branchHeadId.equals(branchRootId)) {
-                StoredCommit commit = getCommit(branchHeadId);
+            Id branchRevId = entry.getKey();
+            Id branchRootId = entry.getValue();
+            while (!branchRevId.equals(branchRootId)) {
+                StoredCommit commit = getCommit(branchRevId);
                 markCommit(commit);
-                branchHeadId = commit.getParentId();
+                branchRevId = commit.getParentId();
+            }
+            if (firstBranchRootId == null || firstBranchRootId.compareTo(branchRootId) > 0) {
+                firstBranchRootId = branchRootId;
             }
         }
         /* Mark all master commits till the first branch root id */
-        if (!tmpBranches.isEmpty()) {
-            Id firstBranchRootId = tmpBranches.keySet().iterator().next();
+        if (firstBranchRootId != null) {
             StoredCommit commit = getHeadCommit();
 
             for (;;) {
@@ -637,6 +663,8 @@ public class DefaultRevisionStore extend
         if (!gcpm.markCommit(commit.getId())) {
             return;
         }
+        markedCommits++;
+
         markNode(getNode(commit.getRootNodeId()));
     }
 
@@ -650,6 +678,8 @@ public class DefaultRevisionStore extend
         if (!gcpm.markNode(node.getId())) {
             return;
         }
+        markedNodes++;
+        
         Iterator<ChildNodeEntry> iter = node.getChildNodeEntries(0, -1);
         while (iter.hasNext()) {
             ChildNodeEntry c = iter.next();

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/store/RevisionStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/store/RevisionStore.java?rev=1376084&r1=1376083&r2=1376084&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/store/RevisionStore.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/store/RevisionStore.java Wed Aug 22 14:53:18 2012
@@ -64,12 +64,15 @@ public interface RevisionStore extends R
      * @param branchRootId
      *            former branch root id, if this is a merge; otherwise
      *            {@code null}
+     * @return branchRevId
+     *            current branch head, i.e. last commit on this branch, 
+     *            if this is a merge; otherwise {@code null}
      * @return head commit id
      * @throws Exception
      *             if an error occurs
      * @see #lockHead()
      */
-    Id /*id*/ putHeadCommit(PutToken token, MutableCommit commit, Id branchRootId) throws Exception;
+    Id /*id*/ putHeadCommit(PutToken token, MutableCommit commit, Id branchRootId, Id branchRevId) throws Exception;
     
     /**
      * Unlock the head.