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 md...@apache.org on 2014/07/08 16:20:06 UTC

svn commit: r1608797 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/management/ main/java/org/apache/jackrabbit/oak/plugins/backup/ main/java/org/apache/jackrabbit/oak/plugins/blob/ main/java/org/apache/jackrabbit/oak/plug...

Author: mduerig
Date: Tue Jul  8 14:20:06 2014
New Revision: 1608797

URL: http://svn.apache.org/r1608797
Log:
OAK-1863: Generic operation tasks should be able to return specific results
Parametrise ManagementOperation on the return type of the passed task

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/management/ManagementOperation.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackupRestore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/BlobGC.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexAsyncReindex.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/RevisionGC.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/management/ManagementOperationTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/management/ManagementOperation.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/management/ManagementOperation.java?rev=1608797&r1=1608796&r2=1608797&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/management/ManagementOperation.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/management/ManagementOperation.java Tue Jul  8 14:20:06 2014
@@ -21,8 +21,13 @@ package org.apache.jackrabbit.oak.manage
 
 import static com.google.common.base.Objects.toStringHelper;
 import static java.lang.Thread.currentThread;
-import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.concurrent.TimeUnit.DAYS;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static java.util.concurrent.TimeUnit.HOURS;
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.MICROSECONDS;
 import static javax.management.openmbean.SimpleType.INTEGER;
 import static javax.management.openmbean.SimpleType.STRING;
 import static org.apache.jackrabbit.oak.api.jmx.RepositoryManagementMBean.StatusCode;
@@ -40,6 +45,7 @@ import static org.apache.jackrabbit.oak.
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.management.openmbean.CompositeData;
@@ -59,7 +65,7 @@ import org.slf4j.LoggerFactory;
  *
  * @see org.apache.jackrabbit.oak.api.jmx.RepositoryManagementMBean
  */
-public class ManagementOperation extends FutureTask<Long> {
+public class ManagementOperation<R> extends FutureTask<R> {
     private static final Logger LOG = LoggerFactory.getLogger(ManagementOperation.class);
     private static final AtomicInteger idGen = new AtomicInteger();
 
@@ -73,55 +79,32 @@ public class ManagementOperation extends
      * @param name  informal name
      * @param task  task to execute for this operation
      */
-    public ManagementOperation(String name, Callable<Long> task) {
-        super(task);
-        this.id = idGen.incrementAndGet();
-        this.name = name;
-    }
-
-    private static final Callable<Long> NOP = new Callable<Long>() {
-        @Override
-        public Long call() throws Exception {
-            return 0L;
-        }
-    };
-
-    /**
-     * Each instance of a {@code ManagementOperation} has an unique id
-     * associated with it. This id is returned as a part of its
-     * {@link #getStatus() status}
-     *
-     * @return  id of this operation
-     */
-    public int getId() {
-        return id;
-    }
-
-    /**
-     * Informal name
-     * @return  name of this operation
-     */
-    public String getName() {
-        return name;
+    public static <R> ManagementOperation<R> newManagementOperation(String name, Callable<R> task) {
+        return new ManagementOperation<R>(name, task);
     }
 
     /**
      * An operation that is already done with the given {@code value}.
      *
-     * @param name  name of the operation
-     * @param value value returned by the operation
+     * @param name   name of the operation
+     * @param result result returned by the operation
      * @return  a {@code ManagementOperation} instance that is already done.
      */
-    public static ManagementOperation done(String name, final long value) {
-        return new ManagementOperation("not started", NOP) {
+    public static <R> ManagementOperation<R> done(String name, final R result) {
+        return new ManagementOperation<R>("not started", new Callable<R>() {
+            @Override
+            public R call() throws Exception {
+                return result;
+            }
+        }) {
             @Override
             public boolean isDone() {
                 return true;
             }
 
             @Override
-            public Long get() {
-                return value;
+            public R get() {
+                return result;
             }
 
             @Override
@@ -137,6 +120,38 @@ public class ManagementOperation extends
     }
 
     /**
+     * Create a new {@code ManagementOperation} of the given name. The name
+     * is an informal value attached to this instance.
+     *
+     * @param name  informal name
+     * @param task  task to execute for this operation
+     */
+    private ManagementOperation(String name, Callable<R> task) {
+        super(task);
+        this.id = idGen.incrementAndGet();
+        this.name = name;
+    }
+
+    /**
+     * Each instance of a {@code ManagementOperation} has an unique id
+     * associated with it. This id is returned as a part of its
+     * {@link #getStatus() status}
+     *
+     * @return  id of this operation
+     */
+    public int getId() {
+        return id;
+    }
+
+    /**
+     * Informal name
+     * @return  name of this operation
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
      * The {@link ManagementOperation.Status status} of this operation:
      * <ul>
      *     <li>{@link Status#running(String) running} if the operation is currently
@@ -155,7 +170,7 @@ public class ManagementOperation extends
             return failed(id, name + " cancelled");
         } else if (isDone()) {
             try {
-                return succeeded(id, name + " completed in " + formatTime(get()));
+                return succeeded(id, name + " succeeded: " + get());
             } catch (InterruptedException e) {
                 currentThread().interrupt();
                 return failed(id, name + " status unknown: " + e.getMessage());
@@ -168,10 +183,6 @@ public class ManagementOperation extends
         }
     }
 
-    private static String formatTime(long nanos) {
-        return MINUTES.convert(nanos, NANOSECONDS) + " minutes";
-    }
-
     @Override
     public String toString() {
         return toStringHelper(this)
@@ -265,6 +276,61 @@ public class ManagementOperation extends
         }
 
         /**
+         * Utility method for formatting a duration in nano seconds
+         * into a human readable string.
+         * @param nanos  number of nano seconds
+         * @return human readable string
+         */
+        public static String formatTime(long nanos) {
+            TimeUnit unit = chooseUnit(nanos);
+            double value = (double) nanos / NANOSECONDS.convert(1, unit);
+            return String.format("%.4g %s", value, abbreviate(unit));
+        }
+
+        private static TimeUnit chooseUnit(long nanos) {
+            if (DAYS.convert(nanos, NANOSECONDS) > 0) {
+                return DAYS;
+            }
+            if (HOURS.convert(nanos, NANOSECONDS) > 0) {
+                return HOURS;
+            }
+            if (MINUTES.convert(nanos, NANOSECONDS) > 0) {
+                return MINUTES;
+            }
+            if (SECONDS.convert(nanos, NANOSECONDS) > 0) {
+                return SECONDS;
+            }
+            if (MILLISECONDS.convert(nanos, NANOSECONDS) > 0) {
+                return MILLISECONDS;
+            }
+            if (MICROSECONDS.convert(nanos, NANOSECONDS) > 0) {
+                return MICROSECONDS;
+            }
+            return NANOSECONDS;
+        }
+
+        private static String abbreviate(TimeUnit unit) {
+            switch (unit) {
+                case NANOSECONDS:
+                    return "ns";
+                case MICROSECONDS:
+                    return "\u03bcs"; // μs
+                case MILLISECONDS:
+                    return "ms";
+                case SECONDS:
+                    return "s";
+                case MINUTES:
+                    return "min";
+                case HOURS:
+                    return "h";
+                case DAYS:
+                    return "d";
+                default:
+                    throw new IllegalArgumentException(String.valueOf(unit));
+            }
+        }
+
+        /**
          * Utility method for converting a {@code CompositeData} encoding
          * of a status to a {@code Status} instance.
          *
@@ -367,4 +433,5 @@ public class ManagementOperation extends
             return result;
         }
     }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackupRestore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackupRestore.java?rev=1608797&r1=1608796&r2=1608797&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackupRestore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/backup/FileStoreBackupRestore.java Tue Jul  8 14:20:06 2014
@@ -21,7 +21,9 @@ package org.apache.jackrabbit.oak.plugin
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static java.lang.System.nanoTime;
+import static org.apache.jackrabbit.oak.management.ManagementOperation.Status.formatTime;
 import static org.apache.jackrabbit.oak.management.ManagementOperation.done;
+import static org.apache.jackrabbit.oak.management.ManagementOperation.newManagementOperation;
 import static org.apache.jackrabbit.oak.plugins.backup.FileStoreBackup.backup;
 import static org.apache.jackrabbit.oak.plugins.backup.FileStoreRestore.restore;
 
@@ -50,8 +52,8 @@ public class FileStoreBackupRestore impl
     private final File file;
     private final Executor executor;
 
-    private ManagementOperation backupOp = done(BACKUP_OP_NAME, 0);
-    private ManagementOperation restoreOp = done(RESTORE_OP_NAME, 0);
+    private ManagementOperation<String> backupOp = done(BACKUP_OP_NAME, "");
+    private ManagementOperation<String> restoreOp = done(RESTORE_OP_NAME, "");
 
     /**
      * @param store  store to back up from or restore to
@@ -70,12 +72,12 @@ public class FileStoreBackupRestore impl
     @Override
     public synchronized CompositeData startBackup() {
         if (backupOp.isDone()) {
-            backupOp = new ManagementOperation("Backup", new Callable<Long>() {
+            backupOp = newManagementOperation("Backup", new Callable<String>() {
                 @Override
-                public Long call() throws Exception {
+                public String call() throws Exception {
                     long t0 = nanoTime();
                     backup(store, file);
-                    return nanoTime() - t0;
+                    return "Backup completed in " + formatTime(nanoTime() - t0);
                 }
             });
             executor.execute(backupOp);
@@ -91,12 +93,12 @@ public class FileStoreBackupRestore impl
     @Override
     public synchronized CompositeData startRestore() {
         if (restoreOp.isDone()) {
-            restoreOp = new ManagementOperation("Restore", new Callable<Long>() {
+            restoreOp = newManagementOperation("Restore", new Callable<String>() {
                 @Override
-                public Long call() throws Exception {
+                public String call() throws Exception {
                     long t0 = nanoTime();
                     restore(file, store);
-                    return nanoTime() - t0;
+                    return "Restore completed in " + formatTime(nanoTime() - t0);
                 }
             });
             executor.execute(restoreOp);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/BlobGC.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/BlobGC.java?rev=1608797&r1=1608796&r2=1608797&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/BlobGC.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/BlobGC.java Tue Jul  8 14:20:06 2014
@@ -21,7 +21,9 @@ package org.apache.jackrabbit.oak.plugin
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static java.lang.System.nanoTime;
+import static org.apache.jackrabbit.oak.management.ManagementOperation.Status.formatTime;
 import static org.apache.jackrabbit.oak.management.ManagementOperation.done;
+import static org.apache.jackrabbit.oak.management.ManagementOperation.newManagementOperation;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.Executor;
@@ -44,7 +46,7 @@ public class BlobGC implements BlobGCMBe
     private final BlobGarbageCollector blobGarbageCollector;
     private final Executor executor;
 
-    private ManagementOperation gcOp = done(OP_NAME, 0);
+    private ManagementOperation<String> gcOp = done(OP_NAME, "");
 
     /**
      * @param blobGarbageCollector  Blob garbage collector
@@ -61,12 +63,12 @@ public class BlobGC implements BlobGCMBe
     @Override
     public CompositeData startBlobGC() {
         if (gcOp.isDone()) {
-            gcOp = new ManagementOperation(OP_NAME, new Callable<Long>() {
+            gcOp = newManagementOperation(OP_NAME, new Callable<String>() {
                 @Override
-                public Long call() throws Exception {
+                public String call() throws Exception {
                     long t0 = nanoTime();
                     blobGarbageCollector.collectGarbage();
-                    return nanoTime() - t0;
+                    return "Blob gc completed in " + formatTime(nanoTime() - t0);
                 }
             });
             executor.execute(gcOp);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexAsyncReindex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexAsyncReindex.java?rev=1608797&r1=1608796&r2=1608797&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexAsyncReindex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/jmx/PropertyIndexAsyncReindex.java Tue Jul  8 14:20:06 2014
@@ -19,7 +19,9 @@ package org.apache.jackrabbit.oak.plugin
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static java.lang.System.nanoTime;
+import static org.apache.jackrabbit.oak.management.ManagementOperation.Status.formatTime;
 import static org.apache.jackrabbit.oak.management.ManagementOperation.done;
+import static org.apache.jackrabbit.oak.management.ManagementOperation.newManagementOperation;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.Executor;
@@ -42,11 +44,10 @@ public class PropertyIndexAsyncReindex i
     private final AsyncIndexUpdate async;
     private final Executor executor;
 
-    private ManagementOperation arOp = done(OP_NAME, 0);
+    private ManagementOperation<String> arOp = done(OP_NAME, "");
 
     /**
-     * @param gc
-     *            Revision garbage collector
+     * @param async
      * @param executor
      *            executor for running the garbage collection task
      */
@@ -60,16 +61,16 @@ public class PropertyIndexAsyncReindex i
     @Override
     public CompositeData startPropertyIndexAsyncReindex() {
         if (arOp.isDone()) {
-            arOp = new ManagementOperation(OP_NAME, new Callable<Long>() {
+            arOp = newManagementOperation(OP_NAME, new Callable<String>() {
                 @Override
-                public Long call() throws Exception {
+                public String call() throws Exception {
                     long t0 = nanoTime();
                     boolean done = false;
                     while (!done) {
                         async.run();
                         done = async.isFinished();
                     }
-                    return nanoTime() - t0;
+                    return "Reindex completed in " + formatTime(nanoTime() - t0);
                 }
             });
             executor.execute(arOp);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/RevisionGC.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/RevisionGC.java?rev=1608797&r1=1608796&r2=1608797&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/RevisionGC.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/RevisionGC.java Tue Jul  8 14:20:06 2014
@@ -20,8 +20,8 @@
 package org.apache.jackrabbit.oak.spi.state;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static java.lang.System.nanoTime;
 import static org.apache.jackrabbit.oak.management.ManagementOperation.done;
+import static org.apache.jackrabbit.oak.management.ManagementOperation.newManagementOperation;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.Executor;
@@ -44,7 +44,7 @@ public class RevisionGC implements Revis
     private final Runnable gc;
     private final Executor executor;
 
-    private ManagementOperation gcOp = done(OP_NAME, 0);
+    private ManagementOperation<String> gcOp = done(OP_NAME, "");
 
     /**
      * @param gc               Revision garbage collector
@@ -61,12 +61,11 @@ public class RevisionGC implements Revis
     @Override
     public CompositeData startRevisionGC() {
         if (gcOp.isDone()) {
-            gcOp = new ManagementOperation(OP_NAME, new Callable<Long>() {
+            gcOp = newManagementOperation(OP_NAME, new Callable<String>() {
                 @Override
-                public Long call() throws Exception {
-                    long t0 = nanoTime();
+                public String call() throws Exception {
                     gc.run();
-                    return nanoTime() - t0;
+                    return "Revision GC initiated";
                 }
             });
             executor.execute(gcOp);

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/management/ManagementOperationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/management/ManagementOperationTest.java?rev=1608797&r1=1608796&r2=1608797&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/management/ManagementOperationTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/management/ManagementOperationTest.java Tue Jul  8 14:20:06 2014
@@ -28,6 +28,7 @@ import static java.util.concurrent.TimeU
 import static org.apache.jackrabbit.oak.api.jmx.RepositoryManagementMBean.StatusCode.FAILED;
 import static org.apache.jackrabbit.oak.api.jmx.RepositoryManagementMBean.StatusCode.RUNNING;
 import static org.apache.jackrabbit.oak.api.jmx.RepositoryManagementMBean.StatusCode.SUCCEEDED;
+import static org.apache.jackrabbit.oak.management.ManagementOperation.newManagementOperation;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -60,15 +61,15 @@ public class ManagementOperationTest {
 
     @Test(expected = IllegalStateException.class)
     public void notStarted() throws ExecutionException, InterruptedException {
-        ManagementOperation op = ManagementOperation.done("test", 42);
+        ManagementOperation<Integer> op = ManagementOperation.done("test", 42);
         assertTrue(op.isDone());
-        assertEquals(42, (long) op.get());
+        assertEquals(42, (int) op.get());
         sameThreadExecutor().execute(op);
     }
 
     @Test
     public void succeeded() throws InterruptedException, ExecutionException, TimeoutException {
-        ManagementOperation op = new ManagementOperation("test", new Callable<Long>() {
+        ManagementOperation<Long> op = newManagementOperation("test", new Callable<Long>() {
             @Override
             public Long call() throws Exception {
                 return 42L;
@@ -76,27 +77,26 @@ public class ManagementOperationTest {
         });
 
         executor.execute(op);
-        assertEquals(42, (long) op.get(5, SECONDS));
+        assertEquals(42L, (long) op.get(5, SECONDS));
         assertTrue(op.isDone());
         Status status = op.getStatus();
         assertEquals(op.getId(), status.getId());
         assertEquals(SUCCEEDED, status.getCode());
-        assertTrue(status.getMessage().contains("test completed in"));
     }
 
     @Test
     public void failed() throws InterruptedException, TimeoutException {
         final Exception failure = new Exception("fail");
-        ManagementOperation op = new ManagementOperation("test", new Callable<Long>() {
+        ManagementOperation<Void> op = newManagementOperation("test", new Callable<Void>() {
             @Override
-            public Long call() throws Exception {
+            public Void call() throws Exception {
                 throw failure;
             }
         });
 
         executor.execute(op);
         try {
-            assertEquals(42, (long) op.get(5, SECONDS));
+            assertEquals(null, op.get(5, SECONDS));
             fail("Expected " + failure);
         } catch (ExecutionException e) {
             assertEquals(failure, e.getCause());
@@ -112,12 +112,12 @@ public class ManagementOperationTest {
     public void running() throws InterruptedException {
         final LinkedBlockingDeque<Thread> thread = new LinkedBlockingDeque<Thread>(1);
 
-        ManagementOperation op = new ManagementOperation("test", new Callable<Long>() {
+        ManagementOperation<Void> op = newManagementOperation("test", new Callable<Void>() {
             @Override
-            public Long call() throws Exception {
+            public Void call() throws Exception {
                 thread.add(currentThread());
                 sleep(100000);
-                return 0L;
+                return null;
             }
         });
 
@@ -142,10 +142,10 @@ public class ManagementOperationTest {
 
     @Test
     public void cancelled() {
-        ManagementOperation op = new ManagementOperation("test", new Callable<Long>() {
+        ManagementOperation<Void> op = newManagementOperation("test", new Callable<Void>() {
             @Override
-            public Long call() throws Exception {
-                return 0L;
+            public Void call() throws Exception {
+                return null;
             }
         });