Author: jukka
Date: Thu Jul  3 04:18:56 2014
New Revision: 1607526

URL: http://svn.apache.org/r1607526
Log:
OAK-1932: TarMK compaction can create mixed segments

Use a separate writer in the compaction code

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/CompactionMap.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Compactor.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeBuilder.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStoreTest.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/CompactionMap.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/CompactionMap.java?rev=1607526&r1=1607525&r2=1607526&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/CompactionMap.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/CompactionMap.java
 Thu Jul  3 04:18:56 2014
@@ -93,6 +93,19 @@ public class CompactionMap {
         return after.equals(get(before));
     }
 
+    /**
+     * Checks whether content in the segment with the given identifier was
+     * compacted to new segments.
+     *
+     * @param id segment identifier
+     * @return whether the identified segment was compacted
+     */
+    boolean wasCompacted(SegmentId id) {
+        long msb = id.getMostSignificantBits();
+        long lsb = id.getLeastSignificantBits();
+        return findEntry(msb, lsb) != -1;
+    }
+
     public RecordId get(RecordId before) {
         RecordId after = recent.get(before);
         if (after != null) {

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Compactor.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Compactor.java?rev=1607526&r1=1607525&r2=1607526&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Compactor.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Compactor.java
 Thu Jul  3 04:18:56 2014
@@ -75,7 +75,8 @@ public class Compactor {
 
     public Compactor(SegmentWriter writer) {
         this.writer = writer;
-        this.builder = writer.writeNode(EMPTY_NODE).builder();
+        this.builder =
+                new SegmentNodeBuilder(writer.writeNode(EMPTY_NODE), writer);
     }
 
     public SegmentNodeState compact(NodeState before, NodeState after) {

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java?rev=1607526&r1=1607525&r2=1607526&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java
 Thu Jul  3 04:18:56 2014
@@ -65,6 +65,15 @@ class Record {
     }
 
     /**
+     * Returns the tracker of the segment that contains this record.
+     *
+     * @return segment tracker
+     */
+    protected SegmentTracker getTracker() {
+        return segmentId.getTracker();
+    }
+
+    /**
      * Returns the segment that contains this record.
      *
      * @return segment that contains this record

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeBuilder.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeBuilder.java?rev=1607526&r1=1607525&r2=1607526&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeBuilder.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeBuilder.java
 Thu Jul  3 04:18:56 2014
@@ -33,8 +33,12 @@ public class SegmentNodeBuilder extends 
     private long updateCount = 0;
 
     SegmentNodeBuilder(SegmentNodeState base) {
+        this(base, base.getTracker().getWriter());
+    }
+
+    SegmentNodeBuilder(SegmentNodeState base, SegmentWriter writer) {
         super(base);
-        this.writer = 
base.getRecordId().getSegmentId().getTracker().getWriter();
+        this.writer = writer;
     }
 
     //-------------------------------------------------< MemoryNodeBuilder >--

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java?rev=1607526&r1=1607525&r2=1607526&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
 Thu Jul  3 04:18:56 2014
@@ -940,10 +940,22 @@ public class SegmentWriter {
         return id;
     }
 
+    private SegmentNodeState uncompact(SegmentNodeState state) {
+        RecordId id = tracker.getCompactionMap().get(state.getRecordId());
+        if (id != null) {
+            return new SegmentNodeState(id);
+        } else {
+            return state;
+        }
+    }
+
     public SegmentNodeState writeNode(NodeState state) {
-        if (state instanceof SegmentNodeState
-                && store.containsSegment(((SegmentNodeState) 
state).getRecordId().getSegmentId())) {
-            return (SegmentNodeState) state;
+        if (state instanceof SegmentNodeState) {
+            SegmentNodeState sns = uncompact((SegmentNodeState) state);
+            if (sns != state || store.containsSegment(
+                    sns.getRecordId().getSegmentId())) {
+                return sns;
+            }
         }
 
         SegmentNodeState before = null;
@@ -952,10 +964,13 @@ public class SegmentWriter {
         if (state instanceof ModifiedNodeState) {
             after = (ModifiedNodeState) state;
             NodeState base = after.getBaseState();
-            if (base instanceof SegmentNodeState
-                    && store.containsSegment(((SegmentNodeState) 
base).getRecordId().getSegmentId())) {
-                before = (SegmentNodeState) base;
-                beforeTemplate = before.getTemplate();
+            if (base instanceof SegmentNodeState) {
+                SegmentNodeState sns = uncompact((SegmentNodeState) base);
+                if (sns != base || store.containsSegment(
+                        sns.getRecordId().getSegmentId())) {
+                    before = sns;
+                    beforeTemplate = before.getTemplate();
+                }
             }
         }
 

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java?rev=1607526&r1=1607525&r2=1607526&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
 Thu Jul  3 04:18:56 2014
@@ -415,6 +415,7 @@ public class FileStore implements Segmen
 
         SegmentNodeState before = getHead();
         SegmentNodeState after = compactor.compact(EMPTY_NODE, before);
+        writer.flush();
         while (!setHead(before, after)) {
             // Some other concurrent changes have been made.
             // Rebase (and compact) those changes on top of the
@@ -422,9 +423,16 @@ public class FileStore implements Segmen
             SegmentNodeState head = getHead();
             after = compactor.compact(before, head);
             before = head;
+            writer.flush();
         }
         tracker.setCompactionMap(compactor.getCompactionMap());
 
+        // Drop the SegmentWriter caches and flush any existing state
+        // in an attempt to prevent new references to old pre-compacted
+        // content. TODO: There should be a cleaner way to do this.
+        tracker.getWriter().dropCache();
+        tracker.getWriter().flush();
+
         log.info("TarMK compaction completed in {}ms", MILLISECONDS
                 .convert(System.nanoTime() - start, NANOSECONDS));
         cleanupNeeded.set(true);

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStoreTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStoreTest.java?rev=1607526&r1=1607525&r2=1607526&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStoreTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStoreTest.java
 Thu Jul  3 04:18:56 2014
@@ -143,25 +143,7 @@ public class FileStoreTest {
         assertTrue(store.setHead(head, compacted));
         store.close();
 
-        // Revision cleanup is still unable to reclaim extra space (OAK-1932)
-        store = new FileStore(directory, 1, false);
-        assertTrue(store.size() > largeBinarySize);
-        store.cleanup();
-        assertTrue(store.size() > largeBinarySize); // FIXME: should be <
-        store.close();
-
-        // Finally do the compaction without concurrent writes
-        store = new FileStore(directory, 1, false);
-        head = store.getHead();
-        assertTrue(store.size() > largeBinarySize);
-        writer = new SegmentWriter(store, store.getTracker());
-        compactor = new Compactor(writer);
-        compacted = compactor.compact(EmptyNodeState.EMPTY_NODE, head);
-        writer.flush();
-        assertTrue(store.setHead(head, compacted));
-        store.close();
-
-        // Now the revision cleanup is able to reclaim the extra space
+        // Revision cleanup is now able to reclaim the extra space (OAK-1932)
         store = new FileStore(directory, 1, false);
         assertTrue(store.size() > largeBinarySize);
         store.cleanup();


Reply via email to