Author: mduerig
Date: Thu Sep  8 12:11:40 2016
New Revision: 1759793

URL: http://svn.apache.org/viewvc?rev=1759793&view=rev
Log:
OAK-4015: Expedite commits from the compactor
Use a fair lock and add an option to expedite set head calls via using the 
write lock instead of the read lock.

Modified:
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStore.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarRevisions.java

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStore.java?rev=1759793&r1=1759792&r2=1759793&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStore.java
 Thu Sep  8 12:11:40 2016
@@ -204,7 +204,6 @@ public class SegmentNodeStore implements
      *          of {@code c.call()} otherwise.
      * @throws Exception
      */
-    // FIXME OAK-4015: Expedite commits from the compactor
     // FIXME OAK-4122: Replace the commit semaphore in the segment node store 
with a scheduler
     // Replace by usage of expeditable lock or commit scheduler
     boolean locked(Callable<Boolean> c, long timeout, TimeUnit unit) throws 
Exception {

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java?rev=1759793&r1=1759792&r2=1759793&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
 Thu Sep  8 12:11:40 2016
@@ -40,6 +40,7 @@ import static org.apache.jackrabbit.oak.
 import static 
org.apache.jackrabbit.oak.segment.SegmentWriterBuilder.segmentWriterBuilder;
 import static org.apache.jackrabbit.oak.segment.file.GCListener.Status.FAILURE;
 import static org.apache.jackrabbit.oak.segment.file.GCListener.Status.SUCCESS;
+import static 
org.apache.jackrabbit.oak.segment.file.TarRevisions.EXPEDITE_OPTION;
 import static org.apache.jackrabbit.oak.segment.file.TarRevisions.timeout;
 
 import java.io.Closeable;
@@ -1011,7 +1012,7 @@ public class FileStore implements Segmen
             int cycles = 0;
             boolean success = false;
             while (cycles < gcOptions.getRetryCount() &&
-                    !(success = revisions.setHead(before.getRecordId(), 
after.getRecordId()))) {
+                    !(success = revisions.setHead(before.getRecordId(), 
after.getRecordId(), EXPEDITE_OPTION))) {
                 // Some other concurrent changes have been made.
                 // Rebase (and compact) those changes on top of the
                 // compacted state before retrying to set the head.

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarRevisions.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarRevisions.java?rev=1759793&r1=1759792&r2=1759793&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarRevisions.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarRevisions.java
 Thu Sep  8 12:11:40 2016
@@ -82,10 +82,8 @@ public class TarRevisions implements Rev
     @Nonnull
     private final AtomicReference<RecordId> persistedHead;
 
-    // FIXME OAK-4015: Expedite commits from the compactor
-    // use a lock that can expedite important commits like compaction and 
checkpoints.
     @Nonnull
-    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
+    private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
 
     private static class TimeOutOption implements Option {
         private final long time;
@@ -109,6 +107,17 @@ public class TarRevisions implements Rev
     }
 
     /**
+     * Option to cause set head calls to be expedited. That is, cause them to 
skip the queue
+     * of any other callers waiting to complete that don't have this option 
specified.
+     */
+    public static final Option EXPEDITE_OPTION = new Option() {
+        @Override
+        public String toString() {
+            return "Expedite Option";
+        }
+    };
+
+    /**
      * Timeout option approximating no time out ({@code Long.MAX_VALUE} days).
      */
     public static final Option INFINITY = new TimeOutOption(MAX_VALUE, DAYS);
@@ -225,8 +234,10 @@ public class TarRevisions implements Rev
      * This implementation blocks if a concurrent call to
      * {@link #setHead(Function, Option...)} is already in
      * progress.
-
-     * @param options   none
+     *
+     * @param options   zero or one expedite option for expediting this call
+     * @throws IllegalArgumentException  on any non recognised {@code option}.
+     * @see #EXPEDITE_OPTION
      */
     @Override
     public boolean setHead(
@@ -234,12 +245,19 @@ public class TarRevisions implements Rev
             @Nonnull RecordId head,
             @Nonnull Option... options) {
         checkBound();
-        rwLock.readLock().lock();
+
+        // If the expedite option was specified we acquire the write lock 
instead of the read lock.
+        // This will cause this thread to get the lock before all threads 
currently waiting to
+        // enter the read lock. See also the class comment of ReadWriteLock.
+        Lock lock = isExpedited(options)
+            ? rwLock.writeLock()
+            : rwLock.readLock();
+        lock.lock();
         try {
             RecordId id = this.head.get();
             return id.equals(expected) && this.head.compareAndSet(id, head);
         } finally {
-            rwLock.readLock().unlock();
+            lock.unlock();
         }
     }
 
@@ -280,6 +298,16 @@ public class TarRevisions implements Rev
         }
     }
 
+    private static boolean isExpedited(Option[] options) {
+        if (options.length == 0) {
+            return false;
+        } else if (options.length == 1) {
+            return options[0] == EXPEDITE_OPTION;
+        } else {
+            throw new IllegalArgumentException("Expected zero or one options, 
got " + options.length);
+        }
+    }
+
     @Nonnull
     private static TimeOutOption getTimeout(@Nonnull Option[] options) {
         if (options.length == 0) {


Reply via email to