You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2012/02/06 14:51:10 UTC

svn commit: r1241011 - in /jackrabbit/sandbox/microkernel/src: main/java/org/apache/jackrabbit/mk/mem/ main/java/org/apache/jackrabbit/mk/util/ test/java/org/apache/jackrabbit/mk/util/

Author: thomasm
Date: Mon Feb  6 13:51:10 2012
New Revision: 1241011

URL: http://svn.apache.org/viewvc?rev=1241011&view=rev
Log:
Use nanoseconds resolution internally

Removed:
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/util/NonDescendingClock.java
    jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/util/NonDescendingClockTest.java
Modified:
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/util/AscendingClock.java
    jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/util/AscendingClockTest.java

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java?rev=1241011&r1=1241010&r2=1241011&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java Mon Feb  6 13:51:10 2012
@@ -26,10 +26,10 @@ import org.apache.jackrabbit.mk.json.Jso
 import org.apache.jackrabbit.mk.json.JsopTokenizer;
 import org.apache.jackrabbit.mk.json.JsopWriter;
 import org.apache.jackrabbit.mk.server.Server;
+import org.apache.jackrabbit.mk.util.AscendingClock;
 import org.apache.jackrabbit.mk.util.Cache;
 import org.apache.jackrabbit.mk.util.CommitGate;
 import org.apache.jackrabbit.mk.util.ExceptionFactory;
-import org.apache.jackrabbit.mk.util.NonDescendingClock;
 import org.apache.jackrabbit.mk.util.PathUtils;
 import org.apache.jackrabbit.mk.wrapper.WrapperBase;
 
@@ -44,12 +44,12 @@ import java.util.HashMap;
 Node structure:
 
 /head/rev = 100
-/head/time = millis
+/head/nanos = nanos
 /head/commit/diff = [+ "/test"{}]
 /head/commit/msg = "hello ..."
 /head/config/ (optional)
 /head/data/
-/99/head/time = millis
+/99/head/nanos = nanos
 /99/98/head
 /99/98/97/head
 /99/90/head
@@ -69,7 +69,7 @@ public class MemoryKernelImpl extends Wr
 
     private final String name;
     private final AbstractBlobStore ds;
-    private final NonDescendingClock clock = new NonDescendingClock(System.currentTimeMillis());
+    private final AscendingClock clock = new AscendingClock(System.currentTimeMillis());
     private final CommitGate gate = new CommitGate();
     private final Cache<Long, Revision> revisionCache = Cache.newInstance(null, 1024 * 1024);
 
@@ -340,7 +340,7 @@ public class MemoryKernelImpl extends Wr
             }
         }
         head = head.setChild("data", data, rev);
-        Revision revNode = new Revision(rev, clock.time(), diff.toString(), message);
+        Revision revNode = new Revision(rev, clock.nanoTime(), diff.toString(), message);
         revisionCache.put(rev, revNode);
         head = revNode.store(head, new NodeImpl(nodeMap, rev));
         root = root.setChild("head", head, rev);
@@ -379,9 +379,10 @@ public class MemoryKernelImpl extends Wr
 
     public JsopReader getRevisionsStream(long since, int maxEntries) {
         NodeImpl node = getRoot();
+        long sinceNanos = since * 1000000;
         ArrayList<Revision> revisions = new ArrayList<Revision>();
         Revision r = Revision.get(node.getNode("head"));
-        if (since < r.getTime() && maxEntries > 0) {
+        if (sinceNanos < r.getNanos() && maxEntries > 0) {
             revisions.add(r);
             while (revisions.size() < maxEntries) {
                 String newest = null;
@@ -407,7 +408,7 @@ public class MemoryKernelImpl extends Wr
         JsopStream buff = new JsopStream().array();
         Collections.sort(revisions);
         for (Revision rev : revisions) {
-            if (rev.getTime() > since) {
+            if (rev.getNanos() > sinceNanos) {
                 buff.encodedValue(rev.toString());
             }
         }

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java?rev=1241011&r1=1241010&r2=1241011&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java Mon Feb  6 13:51:10 2012
@@ -28,20 +28,20 @@ public class Revision implements Compara
 
     private NodeImpl node;
     private final long id;
-    private final long time;
+    private final long nanos;
     private String diff;
     private String msg;
 
-    Revision(long id, long time, String diff, String msg) {
+    Revision(long id, long nanos, String diff, String msg) {
         this.id = id;
-        this.time = time;
+        this.nanos = nanos;
         this.diff = diff;
         this.msg = msg == null ? "" : msg;
     }
 
-    Revision(long id, long time, NodeImpl node) {
+    private Revision(long id, long nanos, NodeImpl node) {
         this.id = id;
-        this.time = time;
+        this.nanos = nanos;
         this.node = node;
     }
 
@@ -51,16 +51,16 @@ public class Revision implements Compara
             return null;
         }
         long id = parseId(JsopTokenizer.decodeQuoted(rev));
-        long time = Long.parseLong(node.getProperty("time"));
-        return new Revision(id, time, node);
+        long nanos = Long.parseLong(node.getProperty("nanos"));
+        return new Revision(id, nanos, node);
     }
 
     long getId() {
         return id;
     }
 
-    long getTime() {
-        return time;
+    long getNanos() {
+        return nanos;
     }
 
     private String getDiff() {
@@ -104,7 +104,7 @@ public class Revision implements Compara
     public String toString() {
         return new JsopBuilder().object().
             key("id").value(formatId(id)).
-            key("ts").value(time).
+            key("ts").value(nanos / 1000000).
         endObject().toString();
     }
 
@@ -118,7 +118,7 @@ public class Revision implements Compara
 
     NodeImpl store(NodeImpl head, NodeImpl commit) {
         head = head.cloneAndSetProperty("rev", JsopBuilder.encode(formatId(id)), id);
-        head = head.cloneAndSetProperty("time", Long.toString(time), id);
+        head = head.cloneAndSetProperty("nanos", Long.toString(nanos), id);
         if (diff.indexOf(";\n") >= 0) {
             commit.setProperty("diff", JsopBuilder.encode(diff));
         } else {
@@ -133,7 +133,7 @@ public class Revision implements Compara
     void appendJournal(JsopWriter buff) {
         buff.object().
             key("id").value(Revision.formatId(id)).
-            key("ts").value(time).
+            key("ts").value(nanos / 1000000).
             key("msg").value(getMsg()).
             key("changes").value(getDiff()).
         endObject().newline();

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/util/AscendingClock.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/util/AscendingClock.java?rev=1241011&r1=1241010&r2=1241011&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/util/AscendingClock.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/util/AscendingClock.java Mon Feb  6 13:51:10 2012
@@ -17,13 +17,30 @@
 package org.apache.jackrabbit.mk.util;
 
 /**
- * A clock that normally returns the current system time, but is guaranteed to
- * return ascending values (even if the system time is changed), and never the
- * same value twice. Worst case, it returns incrementing values.
+ * A clock that normally returns the current system time since 1970, and is
+ * guaranteed to return ascending values. It returns ascending values even if
+ * the system time is changed, and never the same value twice. Worst case, it
+ * returns incrementing values. Unique nanosecond values are returned for system
+ * times between the years 1970 and 2554.
  */
 public class AscendingClock {
 
-    private long last;
+    /**
+     * The offset between System.nanoTime() (which returns elapsed time) and the
+     * absolute current system time in nanoseconds since 1970 UTC.
+     */
+    private long nanoOffset;
+
+    /**
+     * The last millisecond value returned.
+     */
+    private long lastMillis;
+
+    /**
+     * The last nanosecond value returned.
+     */
+    private long lastNanos;
+
 
     /**
      * Create a new clock.
@@ -31,8 +48,38 @@ public class AscendingClock {
      * @param last the time (the next returned value will be at least one
      *            bigger)
      */
-    public AscendingClock(long last) {
-        this.last = last;
+    public AscendingClock(long lastMillis) {
+        this.lastMillis = lastMillis;
+        this.lastNanos = lastMillis * 1000000;
+        resetNanoOffset();
+    }
+
+    /**
+     * Get the current time, ensuring that the value is always larger than the
+     * last returned time, even if the system time was changed. Worst case, this
+     * method will return the last returned value plus one.
+     *
+     * @return the time in nanoseconds since 1970-01-01 (UTC)
+     */
+    public synchronized long nanoTime() {
+        long nanos = System.nanoTime();
+        long now = nanoOffset + nanos;
+        if (nanos > lastNanos + 1000000000) {
+            // re-sync every second, in case
+            // the system time was changed
+            resetNanoOffset();
+            now = nanoOffset + nanos;
+        }
+        if (now > lastNanos) {
+            lastNanos = now;
+        } else {
+            now = ++lastNanos;
+        }
+        return now;
+    }
+
+    private void resetNanoOffset() {
+        nanoOffset = System.currentTimeMillis() * 1000000 - System.nanoTime();
     }
 
     /**
@@ -44,12 +91,12 @@ public class AscendingClock {
      */
     public synchronized long time() {
         long now = System.currentTimeMillis();
-        if (now > last) {
-            last = now;
+        if (now > lastMillis) {
+            lastMillis = now;
         } else {
-            last++;
+            now = ++lastMillis;
         }
-        return last;
+        return now;
     }
 
 }

Modified: jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/util/AscendingClockTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/util/AscendingClockTest.java?rev=1241011&r1=1241010&r2=1241011&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/util/AscendingClockTest.java (original)
+++ jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/util/AscendingClockTest.java Mon Feb  6 13:51:10 2012
@@ -20,7 +20,7 @@ import junit.framework.TestCase;
 
 public class AscendingClockTest extends TestCase {
 
-    public void test() throws InterruptedException {
+    public void testMillis() throws InterruptedException {
         long start, last;
         last = start = System.currentTimeMillis() + 10000;
         AscendingClock c = new AscendingClock(start);
@@ -31,4 +31,16 @@ public class AscendingClockTest extends 
         }
     }
 
+    public void testNanos() throws InterruptedException {
+        long start, last;
+        last = start = System.currentTimeMillis() + 10000;
+        AscendingClock c = new AscendingClock(start);
+        assertTrue(c.nanoTime() > last * 1000000);
+        for (int i = 0; i < 10000; i++) {
+            long t = c.nanoTime();
+            assertTrue(t > last);
+            last = t;
+        }
+    }
+
 }