From d8a3bcbc38f10c866bcf795831eb75f2fd71bb08 Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Thu, 27 May 2021 01:34:40 -0600 Subject: [PATCH] Use monotonic clocks for JESpace timeouts. --- .../src/main/java/org/jpos/space/JESpace.java | 37 ++++++++++--------- .../java/org/jpos/space/JESpaceTestCase.java | 5 +-- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/jpos/src/main/java/org/jpos/space/JESpace.java b/jpos/src/main/java/org/jpos/space/JESpace.java index 529552edc0..d904aecc9a 100644 --- a/jpos/src/main/java/org/jpos/space/JESpace.java +++ b/jpos/src/main/java/org/jpos/space/JESpace.java @@ -44,7 +44,6 @@ import org.jpos.iso.ISOUtil; import org.jpos.util.Log; import org.jpos.util.Loggeable; -import org.jpos.util.Profiler; /** * BerkeleyDB Jave Edition based persistent space implementation @@ -175,13 +174,14 @@ public synchronized V in (Object key) { @SuppressWarnings("unchecked") public synchronized V in (Object key, long timeout) { Object obj; - Instant now = Instant.now(); - long duration; + Duration to = Duration.ofMillis(timeout); + Duration now = Duration.ofNanos(System.nanoTime()); + Duration duration; while ((obj = inp (key)) == null && - (duration = Duration.between(now, Instant.now()).toMillis()) < timeout) + to.compareTo(duration = Duration.ofNanos(System.nanoTime()).minus(now)) > 0) { try { - this.wait (timeout - duration); + this.wait (Math.max(to.minus(duration).toMillis(), 1L)); } catch (InterruptedException ignored) { } } return (V) obj; @@ -200,13 +200,14 @@ public synchronized V rd (Object key) { @SuppressWarnings("unchecked") public synchronized V rd (Object key, long timeout) { Object obj; - Instant now = Instant.now(); - long duration; + Duration to = Duration.ofMillis(timeout); + Duration now = Duration.ofNanos(System.nanoTime()); + Duration duration; while ((obj = rdp (key)) == null && - (duration = Duration.between(now, Instant.now()).toMillis()) < timeout) + to.compareTo(duration = Duration.ofNanos(System.nanoTime()).minus(now)) > 0) { try { - this.wait (timeout - duration); + this.wait (Math.max(to.minus(duration).toMillis(), 1L)); } catch (InterruptedException ignored) { } } return (V) obj; @@ -220,13 +221,14 @@ public synchronized void nrd (Object key) { } public synchronized V nrd (Object key, long timeout) { Object obj; - Instant now = Instant.now(); - long duration; + Duration to = Duration.ofMillis(timeout); + Duration now = Duration.ofNanos(System.nanoTime()); + Duration duration; while ((obj = rdp (key)) != null && - (duration = Duration.between(now, Instant.now()).toMillis()) < timeout) + to.compareTo(duration = Duration.ofNanos(System.nanoTime()).minus(now)) > 0) { try { - this.wait (Math.min(NRD_RESOLUTION, timeout - duration)); + this.wait (Math.min(NRD_RESOLUTION, Math.max(to.minus(duration).toMillis(), 1L))); } catch (InterruptedException ignored) { } } return (V) obj; @@ -249,14 +251,15 @@ public boolean existAny (Object[] keys) { return false; } public boolean existAny (Object[] keys, long timeout) { - Instant now = Instant.now(); - long duration; - while ((duration = Duration.between(now, Instant.now()).toMillis()) < timeout) { + Duration to = Duration.ofMillis(timeout); + Duration now = Duration.ofNanos(System.nanoTime()); + Duration duration; + while (to.compareTo(duration = Duration.ofNanos(System.nanoTime()).minus(now)) > 0) { if (existAny (keys)) return true; synchronized (this) { try { - wait (timeout - duration); + wait (Math.max(to.minus(duration).toMillis(), 1L)); } catch (InterruptedException ignored) { } } } diff --git a/jpos/src/test/java/org/jpos/space/JESpaceTestCase.java b/jpos/src/test/java/org/jpos/space/JESpaceTestCase.java index 526715a8ff..1db59daf7d 100644 --- a/jpos/src/test/java/org/jpos/space/JESpaceTestCase.java +++ b/jpos/src/test/java/org/jpos/space/JESpaceTestCase.java @@ -38,7 +38,6 @@ import java.io.IOException; import java.nio.file.Path; import java.time.Duration; -import java.time.Instant; @SuppressWarnings("unchecked") public class JESpaceTestCase { @@ -204,11 +203,11 @@ public void run() { sp.out ("KA", Boolean.TRUE); } }.start(); - Instant now = Instant.now(); + Duration now = Duration.ofNanos(System.nanoTime()); assertTrue( sp.existAny(new String[]{"KA", "KB"}, 2000L), "existAnyWithTimeout ([KA,KB], delay)"); - long elapsed = Duration.between(now, Instant.now()).toMillis(); + long elapsed = Duration.ofNanos(System.nanoTime()).minus(now).toMillis(); assertTrue(elapsed > 900L, "delay was > 1000"); assertNotNull(sp.inp("KA"), "Entry should not be null"); }