Author: mduerig
Date: Wed Apr 20 10:03:55 2016
New Revision: 1740088

URL: http://svn.apache.org/viewvc?rev=1740088&view=rev
Log:
OAK-3348: Cross gc sessions might introduce references to pre-compacted segments
* SegmentBufferWriter should not throw an IOException in its constructor when 
failing to write the segment info. Instead it should log a warning and continue.
* Make RecordWriters more uniform and introduce WriteOp and WriteOpHandler 
abstractions.
* Determine current generation by looking at the generation of the segment 
containing the current head state instead of by the depth of the compaction map.

Added:
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/WriteOperationHandler.java
Modified:
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Compactor.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/PersistedCompactionMap.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordWriters.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBufferWriter.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBufferWriterPool.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentTracker.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
    
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/PartialCompactionMapTest.java
    
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordUsageAnalyserTest.java
    
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentParserTest.java
    
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStoreIT.java
    
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/TarWriterTest.java

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Compactor.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Compactor.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Compactor.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Compactor.java
 Wed Apr 20 10:03:55 2016
@@ -29,6 +29,8 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import javax.annotation.Nonnull;
+
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.base.Supplier;
@@ -132,8 +134,7 @@ public class Compactor {
 
     public Compactor(SegmentTracker tracker, CompactionStrategy 
compactionStrategy, Supplier<Boolean> cancel) {
         this.tracker = tracker;
-        String wid = "c-" + (tracker.getCompactionMap().getGeneration() + 1);
-        this.writer = tracker.createSegmentWriter(wid);
+        this.writer = createSegmentWriter(tracker);
         if (compactionStrategy.getPersistCompactionMap()) {
             this.map = new PersistedCompactionMap(tracker);
         } else {
@@ -146,6 +147,12 @@ public class Compactor {
         this.cancel = cancel;
     }
 
+    @Nonnull
+    private static SegmentWriter createSegmentWriter(SegmentTracker tracker) {
+        return new SegmentWriter(tracker.getStore(), 
tracker.getSegmentVersion(),
+            new SegmentBufferWriter(tracker.getStore(), 
tracker.getSegmentVersion(), "c", tracker.getGcGen() + 1));
+    }
+
     protected SegmentNodeBuilder process(NodeState before, NodeState after, 
NodeState onto) throws IOException {
         SegmentNodeBuilder builder = new 
SegmentNodeBuilder(writer.writeNode(onto), writer);
         new CompactDiff(builder).diff(before, after);

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/PersistedCompactionMap.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/PersistedCompactionMap.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/PersistedCompactionMap.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/PersistedCompactionMap.java
 Wed Apr 20 10:03:55 2016
@@ -197,7 +197,7 @@ public class PersistedCompactionMap impl
                 base = baseEntry == null ? null : new 
MapRecord(baseEntry.getValue());
 
                 if (writer == null) {
-                    writer = tracker.createSegmentWriter(createWid());
+                    writer = createSegmentWriter();
                 }
 
                 Map<String, RecordId> offsetMap = newHashMap();
@@ -222,7 +222,7 @@ public class PersistedCompactionMap impl
 
             if (!segmentIdMap.isEmpty()) {
                 if (writer == null) {
-                    writer = tracker.createSegmentWriter(createWid());
+                    writer = createSegmentWriter();
                 }
 
                 RecordId previousBaseId = entries == null ? null : 
entries.getRecordId();
@@ -246,8 +246,9 @@ public class PersistedCompactionMap impl
     }
 
     @Nonnull
-    private String createWid() {
-        return "cm-" + (tracker.getCompactionMap().getGeneration() + 1);
+    private SegmentWriter createSegmentWriter() {
+        return new SegmentWriter(tracker.getStore(), 
tracker.getSegmentVersion(),
+            new SegmentBufferWriter(tracker.getStore(), 
tracker.getSegmentVersion(), "cm"));
     }
 
     /**

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordWriters.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordWriters.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordWriters.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordWriters.java
 Wed Apr 20 10:03:55 2016
@@ -43,7 +43,7 @@ final class RecordWriters {
     /**
      * Base class for all record writers
      */
-    public abstract static class RecordWriter<T> {
+    public abstract static class RecordWriter {
         private final RecordType type;
         protected final int size;
         protected final Collection<RecordId> ids;
@@ -63,52 +63,52 @@ final class RecordWriters {
             this(type, size, Collections.<RecordId> emptyList());
         }
 
-        public final T write(SegmentBufferWriter writer) throws IOException {
+        public final RecordId write(SegmentBufferWriter writer) throws 
IOException {
             RecordId id = writer.prepare(type, size, ids);
             return writeRecordContent(id, writer);
         }
 
-        protected abstract T writeRecordContent(RecordId id,
+        protected abstract RecordId writeRecordContent(RecordId id,
                 SegmentBufferWriter writer);
     }
 
-    public static RecordWriter<MapRecord> newMapLeafWriter(int level, 
Collection<MapEntry> entries) {
+    public static RecordWriter newMapLeafWriter(int level, 
Collection<MapEntry> entries) {
         return new MapLeafWriter(level, entries);
     }
 
-    public static RecordWriter<MapRecord> newMapLeafWriter() {
+    public static RecordWriter newMapLeafWriter() {
         return new MapLeafWriter();
     }
 
-    public static RecordWriter<MapRecord> newMapBranchWriter(int level, int 
entryCount, int bitmap, List<RecordId> ids) {
+    public static RecordWriter newMapBranchWriter(int level, int entryCount, 
int bitmap, List<RecordId> ids) {
         return new MapBranchWriter(level, entryCount, bitmap, ids);
     }
 
-    public static RecordWriter<MapRecord> newMapBranchWriter(int bitmap, 
List<RecordId> ids) {
+    public static RecordWriter newMapBranchWriter(int bitmap, List<RecordId> 
ids) {
         return new MapBranchWriter(bitmap, ids);
     }
 
-    public static RecordWriter<RecordId> newListWriter(int count, RecordId 
lid) {
+    public static RecordWriter newListWriter(int count, RecordId lid) {
         return new ListWriter(count, lid);
     }
 
-    public static RecordWriter<RecordId> newListWriter() {
+    public static RecordWriter newListWriter() {
         return new ListWriter();
     }
 
-    public static RecordWriter<RecordId> newListBucketWriter(List<RecordId> 
ids) {
+    public static RecordWriter newListBucketWriter(List<RecordId> ids) {
         return new ListBucketWriter(ids);
     }
 
-    public static RecordWriter<RecordId> newBlockWriter(byte[] bytes, int 
offset, int length) {
+    public static RecordWriter newBlockWriter(byte[] bytes, int offset, int 
length) {
         return new BlockWriter(bytes, offset, length);
     }
 
-    public static RecordWriter<RecordId> newValueWriter(RecordId rid, long 
len) {
+    public static RecordWriter newValueWriter(RecordId rid, long len) {
         return new SingleValueWriter(rid, len);
     }
 
-    public static RecordWriter<RecordId> newValueWriter(int length, byte[] 
data) {
+    public static RecordWriter newValueWriter(int length, byte[] data) {
         return new ArrayValueWriter(length, data);
     }
 
@@ -117,7 +117,7 @@ final class RecordWriters {
      * binary representation is equal to or greater than {@code
      * Segment.BLOB_ID_SMALL_LIMIT}.
      */
-    public static RecordWriter<RecordId> newBlobIdWriter(RecordId rid) {
+    public static RecordWriter newBlobIdWriter(RecordId rid) {
         return new LargeBlobIdWriter(rid);
     }
 
@@ -125,11 +125,11 @@ final class RecordWriters {
      * Write a small blob ID. A blob ID is considered small if the length of 
its
      * binary representation is less than {@code Segment.BLOB_ID_SMALL_LIMIT}.
      */
-    public static RecordWriter<RecordId> newBlobIdWriter(byte[] blobId) {
+    public static RecordWriter newBlobIdWriter(byte[] blobId) {
         return new SmallBlobIdWriter(blobId);
     }
 
-    public static RecordWriter<RecordId> 
newTemplateWriter(Collection<RecordId> ids,
+    public static RecordWriter newTemplateWriter(Collection<RecordId> ids,
             RecordId[] propertyNames, byte[] propertyTypes, int head, RecordId 
primaryId,
             List<RecordId> mixinIds, RecordId childNameId, RecordId 
propNamesId,
             SegmentVersion version) {
@@ -137,7 +137,7 @@ final class RecordWriters {
             childNameId, propNamesId, version);
     }
 
-    public static RecordWriter<SegmentNodeState> 
newNodeStateWriter(List<RecordId> ids) {
+    public static RecordWriter newNodeStateWriter(List<RecordId> ids) {
         return new NodeStateWriter(ids);
     }
 
@@ -145,7 +145,7 @@ final class RecordWriters {
      * Map Leaf record writer.
      * @see RecordType#LEAF
      */
-    private static class MapLeafWriter extends RecordWriter<MapRecord> {
+    private static class MapLeafWriter extends RecordWriter {
         private final int level;
         private final Collection<MapEntry> entries;
 
@@ -171,7 +171,7 @@ final class RecordWriters {
         }
 
         @Override
-        protected MapRecord writeRecordContent(RecordId id,
+        protected RecordId writeRecordContent(RecordId id,
                 SegmentBufferWriter writer) {
             if (entries != null) {
                 int size = entries.size();
@@ -192,7 +192,7 @@ final class RecordWriters {
             } else {
                 writer.writeInt(0);
             }
-            return new MapRecord(id);
+            return id;
         }
     }
 
@@ -200,7 +200,7 @@ final class RecordWriters {
      * Map Branch record writer.
      * @see RecordType#BRANCH
      */
-    private static class MapBranchWriter extends RecordWriter<MapRecord> {
+    private static class MapBranchWriter extends RecordWriter {
         private final int level;
         private final int entryCount;
         private final int bitmap;
@@ -224,14 +224,14 @@ final class RecordWriters {
         }
 
         @Override
-        protected MapRecord writeRecordContent(RecordId id, 
SegmentBufferWriter writer) {
+        protected RecordId writeRecordContent(RecordId id, SegmentBufferWriter 
writer) {
             // -1 to encode a map diff (if level == 0 and entryCount == -1)
             writer.writeInt((level << SIZE_BITS) | entryCount);
             writer.writeInt(bitmap);
             for (RecordId mapId : ids) {
                 writer.writeRecordId(mapId);
             }
-            return new MapRecord(id);
+            return id;
         }
     }
 
@@ -239,7 +239,7 @@ final class RecordWriters {
      * List record writer.
      * @see RecordType#LIST
      */
-    private static class ListWriter extends RecordWriter<RecordId>  {
+    private static class ListWriter extends RecordWriter  {
         private final int count;
         private final RecordId lid;
 
@@ -271,7 +271,7 @@ final class RecordWriters {
      *
      * @see RecordType#BUCKET
      */
-    private static class ListBucketWriter extends RecordWriter<RecordId> {
+    private static class ListBucketWriter extends RecordWriter {
 
         private ListBucketWriter(List<RecordId> ids) {
             super(BUCKET, 0, ids);
@@ -292,7 +292,7 @@ final class RecordWriters {
      * @see SegmentWriter#writeBlock
      * @see RecordType#BLOCK
      */
-    private static class BlockWriter extends RecordWriter<RecordId> {
+    private static class BlockWriter extends RecordWriter {
         private final byte[] bytes;
         private final int offset;
 
@@ -315,7 +315,7 @@ final class RecordWriters {
      * @see SegmentWriter#writeValueRecord
      * @see RecordType#VALUE
      */
-    private static class SingleValueWriter extends RecordWriter<RecordId> {
+    private static class SingleValueWriter extends RecordWriter {
         private final RecordId rid;
         private final long len;
 
@@ -342,7 +342,7 @@ final class RecordWriters {
      * @see Segment#MEDIUM_LIMIT
      * @see RecordType#VALUE
      */
-    private static class ArrayValueWriter extends RecordWriter<RecordId> {
+    private static class ArrayValueWriter extends RecordWriter {
         private final int length;
         private final byte[] data;
 
@@ -384,7 +384,7 @@ final class RecordWriters {
      * @see Segment#BLOB_ID_SMALL_LIMIT
      * @see RecordType#VALUE
      */
-    private static class LargeBlobIdWriter extends RecordWriter<RecordId> {
+    private static class LargeBlobIdWriter extends RecordWriter {
         private final RecordId stringRecord;
 
         private LargeBlobIdWriter(RecordId stringRecord) {
@@ -412,7 +412,7 @@ final class RecordWriters {
      * @see Segment#BLOB_ID_SMALL_LIMIT
      * @see RecordType#VALUE
      */
-    private static class SmallBlobIdWriter extends RecordWriter<RecordId> {
+    private static class SmallBlobIdWriter extends RecordWriter {
         private final byte[] blobId;
 
         private SmallBlobIdWriter(byte[] blobId) {
@@ -436,7 +436,7 @@ final class RecordWriters {
      * Template record writer.
      * @see RecordType#TEMPLATE
      */
-    private static class TemplateWriter extends RecordWriter<RecordId> {
+    private static class TemplateWriter extends RecordWriter {
         private final RecordId[] propertyNames;
         private final byte[] propertyTypes;
         private final int head;
@@ -495,18 +495,18 @@ final class RecordWriters {
      * Node State record writer.
      * @see RecordType#NODE
      */
-    private static class NodeStateWriter extends 
RecordWriter<SegmentNodeState> {
+    private static class NodeStateWriter extends RecordWriter {
         private NodeStateWriter(List<RecordId> ids) {
             super(NODE, 0, ids);
         }
 
         @Override
-        protected SegmentNodeState writeRecordContent(RecordId id,
+        protected RecordId writeRecordContent(RecordId id,
                 SegmentBufferWriter writer) {
             for (RecordId recordId : ids) {
                 writer.writeRecordId(recordId);
             }
-            return new SegmentNodeState(id);
+            return id;
         }
     }
 

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java
 Wed Apr 20 10:03:55 2016
@@ -753,11 +753,7 @@ public class Segment {
                     JsopTokenizer tokenizer = new JsopTokenizer(info);
                     tokenizer.read('{');
                     Map<String, String> properties = 
JsonObject.create(tokenizer).getProperties();
-                    int gen = parseInt(properties.get("gc"));
-                    if (properties.get("wid").contains("c-")) {
-                        gen++;
-                    }
-                    gcGen = gen;
+                    gcGen = parseInt(properties.get("gc"));
                     return gcGen;
                 }
             }

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBufferWriter.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBufferWriter.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBufferWriter.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBufferWriter.java
 Wed Apr 20 10:03:55 2016
@@ -62,7 +62,7 @@ import org.slf4j.LoggerFactory;
  * The behaviour of this class is undefined should the pre-allocated buffer be
  * overrun be calling any of the write methods.
  */
-class SegmentBufferWriter {
+public class SegmentBufferWriter implements WriteOperationHandler {
     private static final Logger LOG = 
LoggerFactory.getLogger(SegmentBufferWriter.class);
 
     /**
@@ -112,7 +112,7 @@ class SegmentBufferWriter {
      */
     private int position;
 
-    public SegmentBufferWriter(SegmentStore store, SegmentVersion version, 
String wid) throws IOException {
+    public SegmentBufferWriter(SegmentStore store, SegmentVersion version, 
String wid, int generation) {
         this.store = store;
         this.version = version;
         this.wid = (wid == null
@@ -120,11 +120,20 @@ class SegmentBufferWriter {
                 : wid);
 
         this.tracker = store.getTracker();
-        this.generation = tracker.getCompactionMap().getGeneration();
+        this.generation = generation;
         this.buffer = createNewBuffer(version);
         newSegment(this.wid);
     }
 
+    public SegmentBufferWriter(SegmentStore store, SegmentVersion version, 
String wid) {
+        this(store, version, wid, store.getTracker().getGcGen());
+    }
+
+    @Override
+    public RecordId execute(WriteOperation writeOperation) throws IOException {
+        return writeOperation.execute(this);
+    }
+
     int getGeneration() {
         return generation;
     }
@@ -144,14 +153,18 @@ class SegmentBufferWriter {
      * The segment meta data is guaranteed to be the first string record in a 
segment.
      * @param wid  the writer id
      */
-    private void newSegment(String wid) throws IOException {
+    private void newSegment(String wid) {
         String metaInfo = "{\"wid\":\"" + wid + '"' +
-                ",\"sno\":" + tracker.getNextSegmentNo() +
-                ",\"gc\":" + generation +
-                ",\"t\":" + currentTimeMillis() + "}";
-        this.segment = new Segment(tracker, buffer, metaInfo);
-        byte[] data = metaInfo.getBytes(UTF_8);
-        newValueWriter(data.length, data).write(this);
+            ",\"sno\":" + tracker.getNextSegmentNo() +
+            ",\"gc\":" + generation +
+            ",\"t\":" + currentTimeMillis() + "}";
+        try {
+            this.segment = new Segment(tracker, buffer, metaInfo);
+            byte[] data = metaInfo.getBytes(UTF_8);
+            newValueWriter(data.length, data).write(this);
+        } catch (IOException e) {
+            LOG.error("Unable to write meta info to segment {} {}", 
segment.getSegmentId(), metaInfo);
+        }
     }
 
     static byte[] createNewBuffer(SegmentVersion v) {
@@ -222,7 +235,7 @@ class SegmentBufferWriter {
 
     private static boolean isCompactionMap(SegmentId id) {
         String info = id.getSegment().getSegmentInfo();
-        return info != null && info.contains("cm-");
+        return info != null && info.contains("cm");
     }
 
     private static String info(Segment segment) {
@@ -268,6 +281,7 @@ class SegmentBufferWriter {
      * store. This is done automatically (called from prepare) when there is 
not
      * enough space for a record. It can also be called explicitly.
      */
+    @Override
     public void flush() throws IOException {
         if (length > 0) {
             int refcount = segment.getRefCount();

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBufferWriterPool.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBufferWriterPool.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBufferWriterPool.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBufferWriterPool.java
 Wed Apr 20 10:03:55 2016
@@ -22,6 +22,7 @@ package org.apache.jackrabbit.oak.plugin
 import static com.google.common.collect.Lists.newArrayList;
 import static com.google.common.collect.Maps.newHashMap;
 import static com.google.common.collect.Sets.newHashSet;
+import static java.lang.Thread.currentThread;
 
 import java.io.IOException;
 import java.util.List;
@@ -31,7 +32,7 @@ import java.util.Set;
 /**
  * FIXME OAK-3348 document
  */
-class SegmentBufferWriterPool {
+class SegmentBufferWriterPool implements WriteOperationHandler {
     private final Map<Object, SegmentBufferWriter> writers = newHashMap();
     private final Set<SegmentBufferWriter> borrowed = newHashSet();
     private final Set<SegmentBufferWriter> disposed = newHashSet();
@@ -47,7 +48,18 @@ class SegmentBufferWriterPool {
         this.wid = wid;
     }
 
-    void flush() throws IOException {
+    @Override
+    public RecordId execute(WriteOperation writeOperation) throws IOException {
+        SegmentBufferWriter writer = borrowWriter(currentThread());
+        try {
+            return writeOperation.execute(writer);
+        } finally {
+            returnWriter(currentThread(), writer);
+        }
+    }
+
+    @Override
+    public void flush() throws IOException {
         List<SegmentBufferWriter> toFlush = newArrayList();
         synchronized (this) {
             toFlush.addAll(writers.values());
@@ -63,11 +75,11 @@ class SegmentBufferWriterPool {
         }
     }
 
-    synchronized SegmentBufferWriter borrowWriter(Object key) throws 
IOException {
+    private synchronized SegmentBufferWriter borrowWriter(Object key) {
         SegmentBufferWriter writer = writers.remove(key);
         if (writer == null) {
             writer = new SegmentBufferWriter(store, version, getWriterId(wid));
-        } else if (writer.getGeneration() != 
store.getTracker().getCompactionMap().getGeneration()) {  // FIXME OAK-3348 
improve generation tracking
+        } else if (writer.getGeneration() != store.getTracker().getGcGen()) {
             disposed.add(writer);
             writer = new SegmentBufferWriter(store, version, getWriterId(wid));
         }
@@ -75,7 +87,7 @@ class SegmentBufferWriterPool {
         return writer;
     }
 
-    synchronized void returnWriter(Object key, SegmentBufferWriter writer) 
throws IOException {
+    private synchronized void returnWriter(Object key, SegmentBufferWriter 
writer) {
         if (borrowed.remove(writer)) {
             writers.put(key, writer);
         } else {
@@ -84,7 +96,7 @@ class SegmentBufferWriterPool {
         }
     }
 
-    private synchronized String getWriterId(String wid) {
+    private String getWriterId(String wid) {
         if (++writerId > 9999) {
             writerId = 0;
         }

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentTracker.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentTracker.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentTracker.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentTracker.java
 Wed Apr 20 10:03:55 2016
@@ -31,16 +31,16 @@ import java.util.concurrent.atomic.Atomi
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 
+import com.google.common.cache.RemovalCause;
 import org.apache.jackrabbit.oak.cache.CacheLIRS;
 import org.apache.jackrabbit.oak.cache.CacheLIRS.EvictionCallback;
 import org.apache.jackrabbit.oak.cache.CacheStats;
 import org.apache.jackrabbit.oak.plugins.blob.ReferenceCollector;
 import org.apache.jackrabbit.oak.plugins.segment.compaction.CompactionStrategy;
+import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.cache.RemovalCause;
-
 /**
  * Tracker of references to segment identifiers and segment instances
  * that are currently kept in memory.
@@ -130,7 +130,8 @@ public class SegmentTracker {
         this.store = store;
         this.compactionMap = new AtomicReference<CompactionMap>(
                 CompactionMap.EMPTY);
-        this.writer = createSegmentWriter("sys");
+        this.writer = new SegmentWriter(store, version,
+                            new SegmentBufferWriterPool(store, version, 
"sys"));
         StringCache c;
         if (DISABLE_STRING_CACHE) {
             c = null;
@@ -170,13 +171,6 @@ public class SegmentTracker {
         return segmentCounter.incrementAndGet();
     }
 
-    /**
-     * @return  a new {@link SegmentWriter} instance for writing to this store.
-     */
-    public final SegmentWriter createSegmentWriter(String wid) {
-        return new SegmentWriter(store, segmentVersion, wid);
-    }
-
     public boolean isTracking(SegmentId segmentId) {
         return this == segmentId.getTracker();
     }
@@ -201,6 +195,10 @@ public class SegmentTracker {
         return store;
     }
 
+    public SegmentVersion getSegmentVersion() {
+        return segmentVersion;
+    }
+
     /**
      * Clear the caches
      */
@@ -267,6 +265,14 @@ public class SegmentTracker {
         return compactionMap.get();
     }
 
+    int getGcGen() {
+        if (store instanceof FileStore) {
+            return ((FileStore) store).getGcGen();
+        } else {
+            return 0;
+        }
+    }
+
     /**
      * Returns all segment identifiers that are currently referenced in memory.
      *

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
 Wed Apr 20 10:03:55 2016
@@ -30,7 +30,6 @@ import static com.google.common.collect.
 import static com.google.common.collect.Lists.partition;
 import static com.google.common.collect.Maps.newHashMap;
 import static com.google.common.io.ByteStreams.read;
-import static java.lang.Thread.currentThread;
 import static java.util.Arrays.asList;
 import static java.util.Collections.emptyMap;
 import static java.util.Collections.nCopies;
@@ -72,6 +71,7 @@ import org.apache.jackrabbit.oak.api.Blo
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.memory.ModifiedNodeState;
+import 
org.apache.jackrabbit.oak.plugins.segment.WriteOperationHandler.WriteOperation;
 import org.apache.jackrabbit.oak.spi.blob.BlobStore;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff;
@@ -117,57 +117,58 @@ public class SegmentWriter {
      */
     private final SegmentVersion version;
 
-    private final SegmentBufferWriterPool segmentBufferWriterPool;
+    private final WriteOperationHandler writeOperationHandler;
 
     /**
      * @param store     store to write to
      * @param version   segment version to write
-     * @param wid       id of this writer
      */
-    public SegmentWriter(SegmentStore store, SegmentVersion version, String 
wid) {
+    public SegmentWriter(SegmentStore store, SegmentVersion version, 
WriteOperationHandler writeOperationHandler) {
         this.store = store;
         this.version = version;
-        this.segmentBufferWriterPool = new SegmentBufferWriterPool(store, 
version, wid);
+        this.writeOperationHandler = writeOperationHandler;
     }
 
     public void flush() throws IOException {
-        segmentBufferWriterPool.flush();
+        writeOperationHandler.flush();
     }
 
-    MapRecord writeMap(MapRecord base, Map<String, RecordId> changes) throws 
IOException {
-        Writer writer = new Writer();
-        try {
-            return writer.writeMap(base, changes);
-        } finally {
-            writer.close();
-        }
+    MapRecord writeMap(final MapRecord base, final Map<String, RecordId> 
changes) throws IOException {
+        return new MapRecord(
+            writeOperationHandler.execute(new SegmentWriteOperation() {
+                @Override
+                public RecordId execute(SegmentBufferWriter writer) throws 
IOException {
+                    return with(writer).writeMap(base, changes);
+                }
+            }));
     }
 
-    public RecordId writeList(List<RecordId> list) throws IOException {
-        Writer writer = new Writer();
-        try {
-            return writer.writeList(list);
-        } finally {
-            writer.close();
-        }
+    public RecordId writeList(final List<RecordId> list) throws IOException {
+        return writeOperationHandler.execute(new SegmentWriteOperation() {
+            @Override
+            public RecordId execute(SegmentBufferWriter writer) throws 
IOException {
+                return with(writer).writeList(list);
+            }
+        });
     }
 
-    public RecordId writeString(String string) throws IOException {
-        Writer writer = new Writer();
-        try {
-            return writer.writeString(string);
-        } finally {
-            writer.close();
-        }
+    public RecordId writeString(final String string) throws IOException {
+        return writeOperationHandler.execute(new SegmentWriteOperation() {
+            @Override
+            public RecordId execute(SegmentBufferWriter writer) throws 
IOException {
+                return with(writer).writeString(string);
+            }
+        });
     }
 
-    SegmentBlob writeBlob(Blob blob) throws IOException {
-        Writer writer = new Writer();
-        try {
-            return writer.writeBlob(blob);
-        } finally {
-            writer.close();
-        }
+    SegmentBlob writeBlob(final Blob blob) throws IOException {
+        return new SegmentBlob(
+            writeOperationHandler.execute(new SegmentWriteOperation() {
+                @Override
+                public RecordId execute(SegmentBufferWriter writer) throws 
IOException {
+                    return with(writer).writeBlob(blob);
+                }
+            }));
     }
 
     /**
@@ -178,31 +179,33 @@ public class SegmentWriter {
      * @param length number of bytes to write
      * @return block record identifier
      */
-    RecordId writeBlock(byte[] bytes, int offset, int length) throws 
IOException {
-        Writer writer = new Writer();
-        try {
-            return writer.writeBlock(bytes, offset, length);
-        } finally {
-            writer.close();
-        }
+    RecordId writeBlock(final byte[] bytes, final int offset, final int 
length) throws IOException {
+        return writeOperationHandler.execute(new SegmentWriteOperation() {
+            @Override
+            public RecordId execute(SegmentBufferWriter writer) throws 
IOException {
+                return with(writer).writeBlock(bytes, offset, length);
+            }
+        });
     }
 
-    SegmentBlob writeExternalBlob(String blobId) throws IOException {
-        Writer writer = new Writer();
-        try {
-            return writer.writeExternalBlob(blobId);
-        } finally {
-            writer.close();
-        }
+    SegmentBlob writeExternalBlob(final String blobId) throws IOException {
+        return new SegmentBlob(
+            writeOperationHandler.execute(new SegmentWriteOperation() {
+                @Override
+                public RecordId execute(SegmentBufferWriter writer) throws 
IOException {
+                    return with(writer).writeExternalBlob(blobId);
+                }
+            }));
     }
 
-    SegmentBlob writeLargeBlob(long length, List<RecordId> list) throws 
IOException {
-        Writer writer = new Writer();
-        try {
-            return writer.writeLargeBlob(length, list);
-        } finally {
-            writer.close();
-        }
+    SegmentBlob writeLargeBlob(final long length, final List<RecordId> list) 
throws IOException {
+        return new SegmentBlob(
+            writeOperationHandler.execute(new SegmentWriteOperation() {
+                @Override
+                public RecordId execute(SegmentBufferWriter writer) throws 
IOException {
+                    return with(writer).writeLargeBlob(length, list);
+                }
+            }));
     }
 
     /**
@@ -213,39 +216,40 @@ public class SegmentWriter {
      * @return blob for the passed {@code stream}
      * @throws IOException if the input stream could not be read or the output 
could not be written
      */
-    public SegmentBlob writeStream(InputStream stream) throws IOException {
-        Writer writer = new Writer();
-        try {
-            return writer.writeStream(stream);
-        } finally {
-            writer.close();
-        }
-    }
-
-    public SegmentNodeState writeNode(NodeState state) throws IOException {
-        Writer writer = new Writer();
-        try {
-            return writer.writeNode(state);
-        } finally {
-            writer.close();
-        }
+    public SegmentBlob writeStream(final InputStream stream) throws 
IOException {
+        return new SegmentBlob(
+            writeOperationHandler.execute(new SegmentWriteOperation() {
+                @Override
+                public RecordId execute(SegmentBufferWriter writer) throws 
IOException {
+                    return with(writer).writeStream(stream);
+                }
+            }));
+    }
+
+    public SegmentNodeState writeNode(final NodeState state) throws 
IOException {
+        return new SegmentNodeState(
+            writeOperationHandler.execute(new SegmentWriteOperation() {
+                @Override
+                public RecordId execute(SegmentBufferWriter writer) throws 
IOException {
+                    return with(writer).writeNode(state);
+                }
+            }));
     }
 
     // FIXME OAK-3348 document: not thread safe
-    private final class Writer {
-        private final SegmentBufferWriter writer;
-        private final int key = currentThread().hashCode();
+    private abstract class SegmentWriteOperation implements WriteOperation {
+        private SegmentBufferWriter writer;
 
-        private Writer() throws IOException {
-            writer = segmentBufferWriterPool.borrowWriter(key);
-        }
+        @Override
+        public abstract RecordId execute(SegmentBufferWriter writer) throws 
IOException;
 
-        private void close() throws IOException {
-            // Not implementing Closeable because we are not idempotent
-            segmentBufferWriterPool.returnWriter(key, writer);
+        SegmentWriteOperation with(SegmentBufferWriter writer) {
+            checkState(this.writer == null);
+            this.writer = writer;
+            return this;
         }
 
-        private MapRecord writeMap(MapRecord base, Map<String, RecordId> 
changes) throws IOException {
+        private RecordId writeMap(MapRecord base, Map<String, RecordId> 
changes) throws IOException {
             if (base != null && base.isDiff()) {
                 Segment segment = base.getSegment();
                 RecordId key = segment.readRecordId(base.getOffset(8));
@@ -264,7 +268,7 @@ public class SegmentWriter {
                     MapEntry entry = base.getEntry(change.getKey());
                     if (entry != null) {
                         if (value.equals(entry.getValue())) {
-                            return base;
+                            return base.getRecordId();
                         } else {
                             return newMapBranchWriter(entry.getHash(), 
asList(entry.getKey(),
                                 value, base.getRecordId())).write(writer);
@@ -295,7 +299,7 @@ public class SegmentWriter {
             return writeMapBucket(base, entries, 0);
         }
 
-        private MapRecord writeMapLeaf(int level, Collection<MapEntry> 
entries) throws IOException {
+        private RecordId writeMapLeaf(int level, Collection<MapEntry> entries) 
throws IOException {
             checkNotNull(entries);
             int size = entries.size();
             checkElementIndex(size, MapRecord.MAX_SIZE);
@@ -304,7 +308,7 @@ public class SegmentWriter {
             return newMapLeafWriter(level, entries).write(writer);
         }
 
-        private MapRecord writeMapBranch(int level, int size, MapRecord... 
buckets) throws IOException {
+        private RecordId writeMapBranch(int level, int size, MapRecord... 
buckets) throws IOException {
             int bitmap = 0;
             List<RecordId> bucketIds = 
newArrayListWithCapacity(buckets.length);
             for (int i = 0; i < buckets.length; i++) {
@@ -316,12 +320,12 @@ public class SegmentWriter {
             return newMapBranchWriter(level, size, bitmap, 
bucketIds).write(writer);
         }
 
-        private MapRecord writeMapBucket(MapRecord base, Collection<MapEntry> 
entries, int level)
+        private RecordId writeMapBucket(MapRecord base, Collection<MapEntry> 
entries, int level)
                 throws IOException {
             // when no changed entries, return the base map (if any) as-is
             if (entries == null || entries.isEmpty()) {
                 if (base != null) {
-                    return base;
+                    return base.getRecordId();
                 } else if (level == 0) {
                     return newMapLeafWriter().write(writer);
                 } else {
@@ -341,7 +345,7 @@ public class SegmentWriter {
                 MapRecord[] buckets = new MapRecord[BUCKETS_PER_LEVEL];
                 List<List<MapEntry>> changes = splitToBuckets(entries, level);
                 for (int i = 0; i < BUCKETS_PER_LEVEL; i++) {
-                    buckets[i] = writeMapBucket(null, changes.get(i), level + 
1);
+                    buckets[i] = mapRecordOrNull(writeMapBucket(null, 
changes.get(i), level + 1));
                 }
 
                 // combine the buckets into one big map
@@ -370,7 +374,7 @@ public class SegmentWriter {
             MapRecord[] buckets = base.getBuckets();
             List<List<MapEntry>> changes = splitToBuckets(entries, level);
             for (int i = 0; i < BUCKETS_PER_LEVEL; i++) {
-                buckets[i] = writeMapBucket(buckets[i], changes.get(i), level 
+ 1);
+                buckets[i] = mapRecordOrNull(writeMapBucket(buckets[i], 
changes.get(i), level + 1));
                 if (buckets[i] != null) {
                     newSize += buckets[i].size();
                     newCount++;
@@ -384,7 +388,7 @@ public class SegmentWriter {
                 // up to one bucket contains entries, so return that as the 
new map
                 for (MapRecord bucket : buckets) {
                     if (bucket != null) {
-                        return bucket;
+                        return bucket.getRecordId();
                     }
                 }
                 // no buckets remaining, return empty map
@@ -401,6 +405,10 @@ public class SegmentWriter {
             }
         }
 
+        private MapRecord mapRecordOrNull(RecordId id) {
+            return id == null ? null : new MapRecord(id);
+        }
+
         /**
          * Writes a list record containing the given list of record 
identifiers.
          *
@@ -509,11 +517,11 @@ public class SegmentWriter {
                     && (getTracker().isTracking(((Record) 
blob).getRecordId().getSegmentId()));
         }
 
-        private SegmentBlob writeBlob(Blob blob) throws IOException {
+        private RecordId writeBlob(Blob blob) throws IOException {
             if (hasSegment(blob)) {
                 SegmentBlob segmentBlob = (SegmentBlob) blob;
                 if (!isOldGen(segmentBlob.getRecordId())) {
-                    return segmentBlob;
+                    return segmentBlob.getRecordId();
                 }
             }
 
@@ -521,8 +529,7 @@ public class SegmentWriter {
             if (reference != null && store.getBlobStore() != null) {
                 String blobId = store.getBlobStore().getBlobId(reference);
                 if (blobId != null) {
-                    RecordId id = writeBlobId(blobId);
-                    return new SegmentBlob(id);
+                    return writeBlobId(blobId);
                 } else {
                     LOG.debug("No blob found for reference {}, inlining...", 
reference);
                 }
@@ -554,17 +561,15 @@ public class SegmentWriter {
             return newBlockWriter(bytes, offset, length).write(writer);
         }
 
-        private SegmentBlob writeExternalBlob(String blobId) throws 
IOException {
-            RecordId id = writeBlobId(blobId);
-            return new SegmentBlob(id);
+        private RecordId writeExternalBlob(String blobId) throws IOException {
+            return writeBlobId(blobId);
         }
 
-        private SegmentBlob writeLargeBlob(long length, List<RecordId> list) 
throws IOException {
-            RecordId id = writeValueRecord(length, writeList(list));
-            return new SegmentBlob(id);
+        private RecordId writeLargeBlob(long length, List<RecordId> list) 
throws IOException {
+            return writeValueRecord(length, writeList(list));
         }
 
-        private SegmentBlob writeStream(InputStream stream) throws IOException 
{
+        private RecordId writeStream(InputStream stream) throws IOException {
             boolean threw = true;
             try {
                 RecordId id = SegmentStream.getRecordIdIfAvailable(stream, 
store);
@@ -572,7 +577,7 @@ public class SegmentWriter {
                     id = internalWriteStream(stream);
                 }
                 threw = false;
-                return new SegmentBlob(id);
+                return id;
             } finally {
                 Closeables.close(stream, threw);
             }
@@ -632,9 +637,7 @@ public class SegmentWriter {
             for (int i = 0; i < count; i++) {
                 if (type.tag() == PropertyType.BINARY) {
                     try {
-                        SegmentBlob blob =
-                            writeBlob(state.getValue(BINARY, i));
-                        valueIds.add(blob.getRecordId());
+                        valueIds.add(writeBlob(state.getValue(BINARY, i)));
                     } catch (IOException e) {
                         throw new IllegalStateException("Unexpected 
IOException", e);
                     }
@@ -737,12 +740,12 @@ public class SegmentWriter {
 
         // FIXME OAK-3348 defer compacted items are not in the compaction map 
-> performance regression
         //        split compaction map into 1) id based equality and 2) cache 
(like string and template) for nodes
-        private SegmentNodeState writeNode(NodeState state) throws IOException 
{
+        private RecordId writeNode(NodeState state) throws IOException {
             if (state instanceof SegmentNodeState) {
                 SegmentNodeState sns = uncompact((SegmentNodeState) state);
                 if (sns != state || hasSegment(sns)) {
                     if (!isOldGen(sns.getRecordId())) {
-                        return sns;
+                        return sns.getRecordId();
                     }
                 }
             }
@@ -790,12 +793,12 @@ public class SegmentWriter {
                     for (ChildNodeEntry entry : state.getChildNodeEntries()) {
                         childNodes.put(
                             entry.getName(),
-                            writeNode(entry.getNodeState()).getRecordId());
+                            writeNode(entry.getNodeState()));
                     }
                 }
-                ids.add(writeMap(base, childNodes).getRecordId());
+                ids.add(writeMap(base, childNodes));
             } else if (childName != Template.ZERO_CHILD_NODES) {
-                
ids.add(writeNode(state.getChildNode(template.getChildName())).getRecordId());
+                
ids.add(writeNode(state.getChildNode(template.getChildName())));
             }
 
             List<RecordId> pIds = newArrayList();
@@ -893,7 +896,7 @@ public class SegmentWriter {
             @Override
             public boolean childNodeAdded(String name, NodeState after) {
                 try {
-                    childNodes.put(name, writeNode(after).getRecordId());
+                    childNodes.put(name, writeNode(after));
                 } catch (IOException e) {
                     exception = e;
                     return false;
@@ -905,7 +908,7 @@ public class SegmentWriter {
             public boolean childNodeChanged(
                 String name, NodeState before, NodeState after) {
                 try {
-                    childNodes.put(name, writeNode(after).getRecordId());
+                    childNodes.put(name, writeNode(after));
                 } catch (IOException e) {
                     exception = e;
                     return false;

Added: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/WriteOperationHandler.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/WriteOperationHandler.java?rev=1740088&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/WriteOperationHandler.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/WriteOperationHandler.java
 Wed Apr 20 10:03:55 2016
@@ -0,0 +1,33 @@
+/*
+ * 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.segment;
+
+import java.io.IOException;
+
+/**
+ */
+interface WriteOperationHandler {
+    interface WriteOperation {
+        RecordId execute(SegmentBufferWriter writer) throws IOException;
+    }
+
+    RecordId execute(WriteOperation writeOperation) throws IOException;
+    void flush() throws IOException;
+}

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
 Wed Apr 20 10:03:55 2016
@@ -539,6 +539,17 @@ public class FileStore implements Segmen
         log.debug("TarMK readers {}", this.readers);
     }
 
+    public int getGcGen() {
+        if (head == null) {
+            return 0;  // not fully initialised
+        }
+        RecordId headId = head.get();
+        if (headId == null) {
+            return 0;  // not fully initialised
+        }
+        return headId.getSegment().getGcGen();
+    }
+
     public boolean maybeCompact(boolean cleanup) throws IOException {
         gcMonitor.info("TarMK GC #{}: started", gcCount.incrementAndGet());
 

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/PartialCompactionMapTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/PartialCompactionMapTest.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/PartialCompactionMapTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/PartialCompactionMapTest.java
 Wed Apr 20 10:03:55 2016
@@ -27,7 +27,6 @@ import static junit.framework.Assert.ass
 import static org.apache.jackrabbit.oak.commons.IOUtils.humanReadableByteCount;
 import static org.apache.jackrabbit.oak.commons.benchmark.MicroBenchmark.run;
 import static 
org.apache.jackrabbit.oak.plugins.segment.Segment.MAX_SEGMENT_SIZE;
-import static org.apache.jackrabbit.oak.plugins.segment.SegmentVersion.V_11;
 import static 
org.apache.jackrabbit.oak.plugins.segment.TestUtils.newValidOffset;
 import static 
org.apache.jackrabbit.oak.plugins.segment.TestUtils.randomRecordIdMap;
 import static org.junit.Assert.assertEquals;
@@ -110,7 +109,6 @@ public class PartialCompactionMapTest {
     }
 
     private PartialCompactionMap createCompactionMap() {
-        SegmentWriter writer = new SegmentWriter(segmentStore, V_11, "");
         if (usePersistedMap) {
             return new PersistedCompactionMap(segmentStore.getTracker());
         } else {

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordUsageAnalyserTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordUsageAnalyserTest.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordUsageAnalyserTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordUsageAnalyserTest.java
 Wed Apr 20 10:03:55 2016
@@ -70,7 +70,8 @@ public class RecordUsageAnalyserTest {
         store = mock(SegmentStore.class);
         SegmentTracker tracker = new SegmentTracker(store);
         when(store.getTracker()).thenReturn(tracker);
-        writer = new SegmentWriter(store, segmentVersion, "");
+        writer = new SegmentWriter(store, segmentVersion,
+            new SegmentBufferWriter(store, segmentVersion, ""));
         analyser = new RecordUsageAnalyser();
     }
 

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentParserTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentParserTest.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentParserTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentParserTest.java
 Wed Apr 20 10:03:55 2016
@@ -160,7 +160,8 @@ public class SegmentParserTest {
         directory.mkdir();
 
         store = FileStore.builder(directory).build();
-        writer = new SegmentWriter(store, segmentVersion, "");
+        writer = new SegmentWriter(store, segmentVersion,
+            new SegmentBufferWriter(store, segmentVersion, ""));
     }
 
     @After

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStoreIT.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStoreIT.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStoreIT.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStoreIT.java
 Wed Apr 20 10:03:55 2016
@@ -21,7 +21,6 @@ import static com.google.common.collect.
 import static 
org.apache.jackrabbit.oak.commons.FixturesHelper.Fixture.SEGMENT_MK;
 import static org.apache.jackrabbit.oak.commons.FixturesHelper.getFixtures;
 import static 
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
-import static org.apache.jackrabbit.oak.plugins.segment.SegmentVersion.V_11;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -43,6 +42,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.segment.RecordId;
 import org.apache.jackrabbit.oak.plugins.segment.Segment;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentBlob;
+import org.apache.jackrabbit.oak.plugins.segment.SegmentBufferWriter;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeBuilder;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentWriter;
@@ -148,7 +148,8 @@ public class FileStoreIT {
         store = 
FileStore.builder(getFileStoreFolder()).withMaxFileSize(1).withMemoryMapping(false).build();
         head = store.getHead();
         assertTrue(store.size() > largeBinarySize);
-        writer = new SegmentWriter(store, V_11, "");
+        writer = new SegmentWriter(store, 
store.getTracker().getSegmentVersion(),
+            new SegmentBufferWriter(store, 
store.getTracker().getSegmentVersion(), ""));
         compactor = new Compactor(store.getTracker());
         compacted = compactor.compact(EMPTY_NODE, head, EMPTY_NODE);
         builder = head.builder();

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/TarWriterTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/TarWriterTest.java?rev=1740088&r1=1740087&r2=1740088&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/TarWriterTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/plugins/segment/file/TarWriterTest.java
 Wed Apr 20 10:03:55 2016
@@ -23,7 +23,6 @@ import static com.google.common.collect.
 import static com.google.common.collect.Sets.newHashSet;
 import static java.nio.ByteBuffer.allocate;
 import static java.util.Collections.singleton;
-import static org.apache.jackrabbit.oak.plugins.segment.SegmentVersion.V_11;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -37,6 +36,7 @@ import java.util.UUID;
 import com.google.common.collect.ImmutableList;
 import org.apache.jackrabbit.oak.plugins.segment.RecordId;
 import org.apache.jackrabbit.oak.plugins.segment.Segment;
+import org.apache.jackrabbit.oak.plugins.segment.SegmentBufferWriter;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentId;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentStore;
 import org.apache.jackrabbit.oak.plugins.segment.SegmentWriter;
@@ -166,7 +166,8 @@ public class TarWriterTest {
                     segments.put(id, buffer);
                 }
             };
-            writer = new SegmentWriter(store, V_11, "");
+            writer = new SegmentWriter(store, 
store.getTracker().getSegmentVersion(),
+                new SegmentBufferWriter(store, 
store.getTracker().getSegmentVersion(), ""));
         }
 
         public class Node {


Reply via email to