Author: mreutegg
Date: Tue Jul 12 13:37:01 2016
New Revision: 1752292

URL: http://svn.apache.org/viewvc?rev=1752292&view=rev
Log:
OAK-4553: Retain journal entries for valid checkpoints

Added:
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalGCTest.java
   (with props)
Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java?rev=1752292&r1=1752291&r2=1752292&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalGarbageCollector.java
 Tue Jul 12 13:37:01 2016
@@ -38,12 +38,12 @@ import com.google.common.base.Stopwatch;
  */
 public class JournalGarbageCollector {
 
-    private final DocumentStore ds;
+    private final DocumentNodeStore ns;
 
     private static final Logger log = 
LoggerFactory.getLogger(JournalGarbageCollector.class);
 
     public JournalGarbageCollector(DocumentNodeStore nodeStore) {
-        this.ds = nodeStore.getDocumentStore();
+        this.ns = nodeStore;
     }
 
     /**
@@ -55,7 +55,16 @@ public class JournalGarbageCollector {
      * @return the number of entries that have been removed
      */
     public int gc(long maxRevisionAge, int batchSize, TimeUnit unit) {
+        DocumentStore ds = ns.getDocumentStore();
+        Revision keep = ns.getCheckpoints().getOldestRevisionToKeep();
         long maxRevisionAgeInMillis = unit.toMillis(maxRevisionAge);
+        long now = ns.getClock().getTime();
+        long gcOlderThan = now - maxRevisionAgeInMillis;
+        if (keep != null && keep.getTimestamp() < gcOlderThan) {
+            gcOlderThan = keep.getTimestamp();
+            log.debug("gc: Checkpoint {} is older than maxRevisionAge: {} min",
+                    keep, unit.toMinutes(maxRevisionAge));
+        }
         if (log.isDebugEnabled()) {
             log.debug("gc: Journal garbage collection starts with maxAge: {} 
min., batch size: {}.", 
                     TimeUnit.MILLISECONDS.toMinutes(maxRevisionAgeInMillis), 
batchSize);
@@ -100,7 +109,7 @@ public class JournalGarbageCollector {
             long startPointer = 0;
             while (true) {
                 String fromKey = JournalEntry.asId(new Revision(startPointer, 
0, clusterNodeId, branch));
-                String toKey = JournalEntry.asId(new 
Revision(System.currentTimeMillis() - maxRevisionAgeInMillis, 
Integer.MAX_VALUE, clusterNodeId, branch));
+                String toKey = JournalEntry.asId(new Revision(gcOlderThan, 0, 
clusterNodeId, branch));
                 List<JournalEntry> deletionBatch = 
ds.query(Collection.JOURNAL, fromKey, toKey, batchSize);
                 if (deletionBatch.size() > 0) {
                     ds.remove(Collection.JOURNAL, asKeys(deletionBatch));
@@ -125,7 +134,7 @@ public class JournalGarbageCollector {
 
         if (numDeleted > 0) {
             log.info("gc: Journal garbage collection took {}, deleted {} 
entries that were older than {} min.",
-                    sw, numDeleted, 
TimeUnit.MILLISECONDS.toMinutes(maxRevisionAgeInMillis));
+                    sw, numDeleted, TimeUnit.MILLISECONDS.toMinutes(now - 
gcOlderThan));
         }
         return numDeleted;
     }

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalGCTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalGCTest.java?rev=1752292&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalGCTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalGCTest.java
 Tue Jul 12 13:37:01 2016
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.document;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.stats.Clock;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.apache.jackrabbit.oak.plugins.document.Collection.JOURNAL;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+public class JournalGCTest {
+
+    @Rule
+    public DocumentMKBuilderProvider builderProvider = new 
DocumentMKBuilderProvider();
+
+    @Test
+    public void gcWithCheckpoint() throws Exception {
+        Clock c = new Clock.Virtual();
+        c.waitUntil(System.currentTimeMillis());
+        DocumentNodeStore ns = builderProvider.newBuilder()
+                .clock(c).setAsyncDelay(0).getNodeStore();
+
+        String cp = ns.checkpoint(TimeUnit.DAYS.toMillis(1));
+        // perform some change
+        NodeBuilder builder = ns.getRoot().builder();
+        builder.child("foo");
+        ns.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        Revision head = ns.getHeadRevision().getRevision(ns.getClusterId());
+        assertNotNull(head);
+
+        // trigger creation of journal entry
+        ns.runBackgroundOperations();
+
+        JournalEntry entry = ns.getDocumentStore().find(JOURNAL, 
JournalEntry.asId(head));
+        assertNotNull(entry);
+
+        // wait two hours
+        c.waitUntil(c.getTime() + TimeUnit.HOURS.toMillis(2));
+
+        // instruct journal collector to remove entries older than one hour
+        ns.getJournalGarbageCollector().gc(1, 10, TimeUnit.HOURS);
+
+        // must not remove existing entry, because checkpoint is still valid
+        entry = ns.getDocumentStore().find(JOURNAL, JournalEntry.asId(head));
+        assertNotNull(entry);
+
+        ns.release(cp);
+
+        ns.getJournalGarbageCollector().gc(1, 10, TimeUnit.HOURS);
+        // now journal GC can remove the entry
+        entry = ns.getDocumentStore().find(JOURNAL, JournalEntry.asId(head));
+        assertNull(entry);
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalGCTest.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to