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/04/23 11:09:56 UTC

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

Author: dpfister
Date: Mon Apr 23 09:09:55 2012
New Revision: 1329139

URL: http://svn.apache.org/viewvc?rev=1329139&view=rev
Log:
GC for revisions
- fix dangling parent commit

Modified:
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/model/Id.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/test/java/org/apache/jackrabbit/mk/persistence/GCPersistenceTest.java
    jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/store/DefaultRevisionStoreTest.java

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/model/Id.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/model/Id.java?rev=1329139&r1=1329138&r2=1329139&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/model/Id.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/model/Id.java Mon Apr 23 09:09:55 2012
@@ -68,6 +68,22 @@ public class Id implements Comparable<Id
         return new Id(StringUtils.convertHexToBytes(s));
     }
 
+    /**
+     * Creates an {@code Id} instance from a long.
+     *
+     * @param l a long
+     * @return an {@code Id} instance
+     */
+    public static Id fromLong(long value) {
+        byte[] raw = new byte[8];
+        
+        for (int i = raw.length - 1; i >= 0 && value != 0; i--) {
+            raw[i] = (byte) (value & 0xff);
+            value >>>= 8;
+        }
+        return new Id(raw);
+    }
+    
     @Override
     public int hashCode() {
         // the hashCode is intentionally not stored

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=1329139&r1=1329138&r2=1329139&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 Mon Apr 23 09:09:55 2012
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.mk.persistence;
 
+import org.apache.jackrabbit.mk.model.Commit;
 import org.apache.jackrabbit.mk.model.Id;
 
 /**
@@ -45,6 +46,20 @@ public interface GCPersistence extends P
     boolean markCommit(Id id) throws Exception;
     
     /**
+     * Replace a commit. Introduced to replace dangling parent commits where
+     * a parent commit might be collected.
+     * 
+     * @param id
+     *            commit id
+     * @param 
+     * @return {@code true} if the commit was not marked before;
+     *         {@code false} otherwise
+     * 
+     * @throws Exception if an error occurs
+     */
+    void replaceCommit(Id id, Commit commit) throws Exception;
+    
+    /**
      * Mark a node.
      * 
      * @param id

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=1329139&r1=1329138&r2=1329139&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 Mon Apr 23 09:09:55 2012
@@ -261,6 +261,29 @@ public class H2Persistence implements GC
     }
 
     @Override
+    public void replaceCommit(Id id, Commit commit) throws Exception {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        commit.serialize(new BinaryBinding(out));
+        byte[] bytes = out.toByteArray();
+
+        Connection con = cp.getConnection();
+        try {
+            PreparedStatement stmt = con
+                    .prepareStatement(
+                            "update REVS set DATA = ?, TIME = CURRENT_TIMESTAMP() where ID = ?");
+            try {
+                stmt.setBytes(1, bytes);
+                stmt.setBytes(2, id.getBytes());
+                stmt.executeUpdate();
+            } finally {
+                stmt.close();
+            }
+        } finally {
+            con.close();
+        }
+    }
+    
+    @Override
     public boolean markNode(Id id) throws Exception {
         return touch(id, gcStart);
     }

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=1329139&r1=1329138&r2=1329139&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 Mon Apr 23 09:09:55 2012
@@ -155,6 +155,16 @@ public class InMemPersistence implements
         return markObject(id);
     }
     
+    @Override
+    public void replaceCommit(Id id, Commit commit) throws Exception {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        commit.serialize(new BinaryBinding(out));
+        byte[] bytes = out.toByteArray();
+
+        objects.put(id, bytes);
+        marked.put(id, bytes);
+    }
+    
     private boolean markObject(Id id) throws NotFoundException {
         byte[] data = objects.get(id);
         if (data != null) {

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=1329139&r1=1329138&r2=1329139&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 Mon Apr 23 09:09:55 2012
@@ -58,7 +58,7 @@ public class DefaultRevisionStore extend
     private AtomicLong commitCounter;
     private final ReentrantReadWriteLock headLock = new ReentrantReadWriteLock();
     private final Persistence pm;
-    private final GCPersistence gcpm;
+    protected final GCPersistence gcpm;
 
     /* avoid synthetic accessor */ int initialCacheSize;
     /* avoid synthetic accessor */ Map<Id, Object> cache;
@@ -100,7 +100,7 @@ public class DefaultRevisionStore extend
         head = pm.readHead();
         if (head == null || head.getBytes().length == 0) {
             // assume virgin repository
-            byte[] rawHead = longToBytes(commitCounter.incrementAndGet());
+            byte[] rawHead = Id.fromLong(commitCounter.incrementAndGet()).getBytes();
             head = new Id(rawHead);
             
             Id rootNodeId = pm.writeNode(new MutableNode(this, "/"));
@@ -153,22 +153,6 @@ public class DefaultRevisionStore extend
         return (val != null) ? Integer.parseInt(val) : DEFAULT_CACHE_SIZE;
     }
 
-    /**
-     * Convert a long value into a fixed-size byte array of size 8.
-     * 
-     * @param value value
-     * @return byte array
-     */
-    private static byte[] longToBytes(long value) {
-        byte[] result = new byte[8];
-        
-        for (int i = result.length - 1; i >= 0 && value != 0; i--) {
-            result[i] = (byte) (value & 0xff);
-            value >>>= 8;
-        }
-        return result;
-    }
-
     //--------------------------------------------------------< RevisionStore >
 
     public Id putNode(MutableNode node) throws Exception {
@@ -314,7 +298,7 @@ public class DefaultRevisionStore extend
 
         Id id = commit.getId();
         if (id == null) {
-            id = new Id(longToBytes(commitCounter.incrementAndGet()));
+            id = Id.fromLong(commitCounter.incrementAndGet());
         }
         pm.writeCommit(id, commit);
 
@@ -436,10 +420,16 @@ public class DefaultRevisionStore extend
             if (id == null) {
                 break;
             }
-            commit = getCommit(id);
-            if (commit.getCommitTS() < tsLimit) {
+            StoredCommit parentCommit = getCommit(id);
+            if (parentCommit.getCommitTS() < tsLimit) {
                 break;
             }
+            commit = parentCommit;
+        }
+        if (commit.getParentId() != null) {
+            MutableCommit firstCommit = new MutableCommit(commit);
+            firstCommit.setParentId(null);
+            gcpm.replaceCommit(firstCommit.getId(), firstCommit);
         }
     }
 

Modified: jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/persistence/GCPersistenceTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/persistence/GCPersistenceTest.java?rev=1329139&r1=1329138&r2=1329139&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/persistence/GCPersistenceTest.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/persistence/GCPersistenceTest.java Mon Apr 23 09:09:55 2012
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.mk.persistence;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -25,6 +26,7 @@ import java.util.Arrays;
 import java.util.Collection;
 
 import org.apache.jackrabbit.mk.model.Id;
+import org.apache.jackrabbit.mk.model.MutableCommit;
 import org.apache.jackrabbit.mk.model.MutableNode;
 import org.apache.jackrabbit.mk.model.StoredNode;
 import org.apache.jackrabbit.mk.store.NotFoundException;
@@ -121,5 +123,25 @@ public class GCPersistenceTest {
         pm.sweep();
         pm.readNode(new StoredNode(id, null));
     }
+    
+    @Test
+    public void testReplaceCommit() throws Exception {
+        MutableCommit c1 = new MutableCommit();
+        c1.setRootNodeId(Id.fromLong(0));
+        pm.writeCommit(Id.fromLong(1), c1);
+
+        MutableCommit c2 = new MutableCommit();
+        c2.setParentId(c1.getId());
+        c2.setRootNodeId(Id.fromLong(0));
+        pm.writeCommit(Id.fromLong(2), c2);
+
+        pm.start();
+        c2 = new MutableCommit();
+        c2.setRootNodeId(Id.fromLong(0));
+        pm.replaceCommit(Id.fromLong(2), c2);
+        pm.sweep();
+        
+        assertEquals(null, pm.readCommit(Id.fromLong(2)).getParentId());
+    }
 }
 

Modified: jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/store/DefaultRevisionStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/store/DefaultRevisionStoreTest.java?rev=1329139&r1=1329138&r2=1329139&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/store/DefaultRevisionStoreTest.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/store/DefaultRevisionStoreTest.java Mon Apr 23 09:09:55 2012
@@ -22,6 +22,9 @@ import org.apache.jackrabbit.mk.api.Micr
 import org.apache.jackrabbit.mk.blobs.MemoryBlobStore;
 import org.apache.jackrabbit.mk.core.MicroKernelImpl;
 import org.apache.jackrabbit.mk.core.Repository;
+import org.apache.jackrabbit.mk.json.fast.Jsop;
+import org.apache.jackrabbit.mk.json.fast.JsopArray;
+import org.apache.jackrabbit.mk.model.MutableCommit;
 import org.apache.jackrabbit.mk.persistence.InMemPersistence;
 import org.junit.After;
 import org.junit.Before;
@@ -40,7 +43,12 @@ public class DefaultRevisionStoreTest {
         rs = new DefaultRevisionStore(new InMemPersistence()) {
             @Override
             protected void doMark() throws Exception {
+                // Keep head commit only
                 markCommit(getHeadCommit());
+                
+                MutableCommit headCommit = new MutableCommit(getHeadCommit());  
+                headCommit.setParentId(null);
+                gcpm.replaceCommit(headCommit.getId(), headCommit);
             }
         };
         rs.initialize();
@@ -63,10 +71,13 @@ public class DefaultRevisionStoreTest {
         
         String headRevision = mk.getHeadRevision();
         String contents = mk.getNodes("/", headRevision);
-        
+
         rs.gc();
         
         assertEquals(headRevision, mk.getHeadRevision());
         assertEquals(contents, mk.getNodes("/", headRevision));
+        
+        String history = mk.getRevisionHistory(Long.MIN_VALUE, Integer.MIN_VALUE);
+        assertEquals(1, ((JsopArray) Jsop.parse(history)).size());
     }
 }