This is an automated email from the ASF dual-hosted git repository. domgarguilo pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/main by this push: new 7deced8f5f Remove NanoTime object in favor of new Timer and CountdownTimer object (#4785) 7deced8f5f is described below commit 7deced8f5ff1ac886cbf39a4a242532437676dfc Author: Dom G. <domgargu...@apache.org> AuthorDate: Wed Aug 21 13:28:05 2024 -0400 Remove NanoTime object in favor of new Timer and CountdownTimer object (#4785) * Remove NanoTime object in favor of new Timer and CountdownTimer objects --------- Co-authored-by: Keith Turner <ktur...@apache.org> --- .../apache/accumulo/core/util/time/NanoTime.java | 104 ------------- .../accumulo/core/util/time/NanoTimeTest.java | 162 --------------------- .../accumulo/server/compaction/FileCompactor.java | 14 +- .../org/apache/accumulo/compactor/Compactor.java | 6 +- .../java/org/apache/accumulo/manager/Manager.java | 6 +- .../org/apache/accumulo/tserver/ScanServer.java | 6 +- .../accumulo/tserver/UnloadTabletHandler.java | 6 +- 7 files changed, 20 insertions(+), 284 deletions(-) diff --git a/core/src/main/java/org/apache/accumulo/core/util/time/NanoTime.java b/core/src/main/java/org/apache/accumulo/core/util/time/NanoTime.java deleted file mode 100644 index f081278589..0000000000 --- a/core/src/main/java/org/apache/accumulo/core/util/time/NanoTime.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 - * - * https://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.accumulo.core.util.time; - -import java.time.Duration; - -import com.google.common.annotations.VisibleForTesting; - -/** - * This class implements a strong type for System.nanoTime() that offers the limited operations that - * can be performed on a nanoTime. See the System.nanoTime() javadoc for details - specifically - * these values are meaningful only when the difference between two such values, obtained within the - * same instance of a Java virtual machine, are computed. - */ -public final class NanoTime implements Comparable<NanoTime> { - // In the System.nanoTime javadoc it describes the returned value as the "nanoseconds since some - // fixed but arbitrary origin time (perhaps in the future, so values may be negative)". This - // variable name is derived from that where AO is arbitrary origin. - private final long nanosSinceAO; - - // This method should only be called by test inorder to test edge conditions, that is why it is - // package private. Calling this outside of test makes it hard to reason about the correctness of - // using this class. - @VisibleForTesting - NanoTime(long ntsao) { - this.nanosSinceAO = ntsao; - } - - /** - * @return this.nanoTime - other.nanoTime as a Duration - */ - public Duration subtract(NanoTime other) { - return Duration.ofNanos(nanosSinceAO - other.nanosSinceAO); - } - - /** - * Determines the amount of time that has elapsed since this object was created relative to the - * current nanoTime. - * - * @return System.nanoTime() - this.nanoTime - */ - public Duration elapsed() { - return Duration.ofNanos(System.nanoTime() - nanosSinceAO); - } - - @Override - public boolean equals(Object other) { - if (other instanceof NanoTime) { - return nanosSinceAO == ((NanoTime) other).nanosSinceAO; - } - - return false; - } - - @Override - public int hashCode() { - return Long.hashCode(nanosSinceAO); - } - - @Override - public int compareTo(NanoTime other) { - // All operations w/ nanoTimes must use differences, can not directly compare. This is because a - // nano time of Long.MAX_VALUE -10 is considered less than Long.MAX_VALUE +10 - long diff = nanosSinceAO - other.nanosSinceAO; - - if (diff < 0) { - return -1; - } else if (diff > 0) { - return 1; - } else { - return 0; - } - } - - /** - * @return a NanoTime created using System.nanoTime() - */ - public static NanoTime now() { - return new NanoTime(System.nanoTime()); - } - - /** - * @return a NanoTime created using System.nanoTime() + duration.toNanos() - */ - public static NanoTime nowPlus(Duration duration) { - return new NanoTime(System.nanoTime() + duration.toNanos()); - } -} diff --git a/core/src/test/java/org/apache/accumulo/core/util/time/NanoTimeTest.java b/core/src/test/java/org/apache/accumulo/core/util/time/NanoTimeTest.java deleted file mode 100644 index d306aafc39..0000000000 --- a/core/src/test/java/org/apache/accumulo/core/util/time/NanoTimeTest.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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 - * - * https://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.accumulo.core.util.time; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.time.Duration; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.junit.jupiter.api.Test; - -public class NanoTimeTest { - @Test - public void testMultipleTimes() { - List<NanoTime> ntimes = new ArrayList<>(); - - NanoTime prev = NanoTime.now(); - ntimes.add(prev); - - for (int i = 0; i < 100; i++) { - NanoTime next = NanoTime.now(); - while (prev.equals(next)) { - next = NanoTime.now(); - } - - ntimes.add(next); - prev = next; - } - - long curr = System.nanoTime(); - while (curr == System.nanoTime()) {} - - var start = NanoTime.now(); - - while (start.equals(NanoTime.now())) {} - - for (int i = 1; i < ntimes.size(); i++) { - var last = ntimes.get(i - 1); - var next = ntimes.get(i); - assertTrue(last.compareTo(next) < 0); - assertTrue(next.compareTo(last) > 0); - assertTrue(next.compareTo(next) == 0); - assertTrue(next.elapsed().toNanos() > 0); - assertEquals(next, next); - assertEquals(next.hashCode(), next.hashCode()); - assertNotEquals(last, next); - assertNotEquals(last.hashCode(), next.hashCode()); - - var duration1 = next.elapsed(); - var duration2 = start.subtract(last); - var duration3 = start.subtract(next); - - assertTrue(duration2.compareTo(duration3) > 0); - assertTrue(duration1.compareTo(duration3) > 0); - } - - var copy = List.copyOf(ntimes); - Collections.shuffle(ntimes); - Collections.sort(ntimes); - assertEquals(copy, ntimes); - } - - @Test - public void testBoundry() { - // tests crossing the Long.MAX_VALUE boundry - long origin = Long.MAX_VALUE - 1000; - - List<NanoTime> ntimes = new ArrayList<>(); - - // add times that start positive and then go negative - for (int i = 0; i < 20; i++) { - var nt = i * 100 + origin; - ntimes.add(new NanoTime(nt)); - } - - for (int i = 1; i < ntimes.size(); i++) { - var last = ntimes.get(i - 1); - var next = ntimes.get(i); - assertEquals(100, next.subtract(last).toNanos()); - assertEquals(-100, last.subtract(next).toNanos()); - assertTrue(next.compareTo(last) > 0); - assertTrue(last.compareTo(next) < 0); - assertTrue(next.compareTo(next) == 0); - } - - var copy = List.copyOf(ntimes); - Collections.shuffle(ntimes); - Collections.sort(ntimes); - assertEquals(copy, ntimes); - } - - @Test - public void testNowPlus() { - - List<NanoTime> ntimes = new ArrayList<>(); - for (int i = 0; i < 10; i++) { - ntimes.add(NanoTime.nowPlus(Duration.ofHours(i))); - } - - for (int i = 1; i < ntimes.size(); i++) { - var last = ntimes.get(i - 1); - var next = ntimes.get(i); - - var duration = next.subtract(last); - - assertTrue(duration.compareTo(Duration.ofHours(1)) >= 0); - // This could fail if the test process were paused for more than 3 minutes - assertTrue(duration.compareTo(Duration.ofMinutes(63)) < 0); - assertTrue(next.elapsed().compareTo(Duration.ZERO) < 0); - } - - var copy = List.copyOf(ntimes); - Collections.shuffle(ntimes); - Collections.sort(ntimes); - assertEquals(copy, ntimes); - - ntimes.clear(); - - // nano time can compute elapsed times in a 290 year period which should wrap Long.MAX_VALUE no - // matter where it starts - for (int i = 0; i < 290; i++) { - ntimes.add(NanoTime.nowPlus(Duration.ofDays(365 * i))); - } - - for (int i = 1; i < ntimes.size(); i++) { - var last = ntimes.get(i - 1); - var next = ntimes.get(i); - - var duration = next.subtract(last); - - assertTrue(duration.compareTo(Duration.ofDays(365)) >= 0); - assertTrue(duration.compareTo(Duration.ofDays(366)) < 0); - assertTrue(next.elapsed().compareTo(Duration.ZERO) < 0); - } - - copy = List.copyOf(ntimes); - Collections.shuffle(ntimes); - Collections.sort(ntimes); - assertEquals(copy, ntimes); - } - -} diff --git a/server/base/src/main/java/org/apache/accumulo/server/compaction/FileCompactor.java b/server/base/src/main/java/org/apache/accumulo/server/compaction/FileCompactor.java index b4e53ce2ce..335f583fd6 100644 --- a/server/base/src/main/java/org/apache/accumulo/server/compaction/FileCompactor.java +++ b/server/base/src/main/java/org/apache/accumulo/server/compaction/FileCompactor.java @@ -18,6 +18,8 @@ */ package org.apache.accumulo.server.compaction; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -67,8 +69,8 @@ import org.apache.accumulo.core.tabletserver.thrift.TCompactionReason; import org.apache.accumulo.core.trace.TraceUtil; import org.apache.accumulo.core.util.LocalityGroupUtil; import org.apache.accumulo.core.util.LocalityGroupUtil.LocalityGroupConfigurationError; +import org.apache.accumulo.core.util.Timer; import org.apache.accumulo.core.util.ratelimit.RateLimiter; -import org.apache.accumulo.core.util.time.NanoTime; import org.apache.accumulo.server.ServerContext; import org.apache.accumulo.server.fs.VolumeManager; import org.apache.accumulo.server.iterators.SystemIteratorEnvironment; @@ -125,7 +127,7 @@ public class FileCompactor implements Callable<CompactionStats> { // things to report private String currentLocalityGroup = ""; - private volatile NanoTime startTime; + private volatile Timer startTime; private final AtomicInteger timesPaused = new AtomicInteger(0); @@ -140,7 +142,7 @@ public class FileCompactor implements Callable<CompactionStats> { private static final LongAdder totalEntriesRead = new LongAdder(); private static final LongAdder totalEntriesWritten = new LongAdder(); - private static volatile NanoTime lastUpdateTime = NanoTime.now(); + private static final Timer lastUpdateTime = Timer.startNew(); private final DateFormat dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS"); @@ -217,11 +219,11 @@ public class FileCompactor implements Callable<CompactionStats> { * is rate limited, so it will not cause issues if called too frequently. */ private static void updateTotalEntries() { - if (lastUpdateTime.elapsed().compareTo(Duration.ofMillis(100)) < 0) { + if (!lastUpdateTime.hasElapsed(100, MILLISECONDS)) { return; } runningCompactions.forEach(FileCompactor::updateGlobalEntryCounts); - lastUpdateTime = NanoTime.now(); + lastUpdateTime.restart(); } protected static final Set<FileCompactor> runningCompactions = @@ -284,7 +286,7 @@ public class FileCompactor implements Callable<CompactionStats> { CompactionStats majCStats = new CompactionStats(); - startTime = NanoTime.now(); + startTime = Timer.startNew(); boolean remove = runningCompactions.add(this); diff --git a/server/compactor/src/main/java/org/apache/accumulo/compactor/Compactor.java b/server/compactor/src/main/java/org/apache/accumulo/compactor/Compactor.java index 1af688515c..b7b0470d58 100644 --- a/server/compactor/src/main/java/org/apache/accumulo/compactor/Compactor.java +++ b/server/compactor/src/main/java/org/apache/accumulo/compactor/Compactor.java @@ -94,11 +94,11 @@ import org.apache.accumulo.core.tabletserver.thrift.TCompactionStats; import org.apache.accumulo.core.tabletserver.thrift.TExternalCompactionJob; import org.apache.accumulo.core.trace.TraceUtil; import org.apache.accumulo.core.util.Halt; +import org.apache.accumulo.core.util.Timer; import org.apache.accumulo.core.util.UtilWaitThread; import org.apache.accumulo.core.util.compaction.ExternalCompactionUtil; import org.apache.accumulo.core.util.threads.ThreadPools; import org.apache.accumulo.core.util.threads.Threads; -import org.apache.accumulo.core.util.time.NanoTime; import org.apache.accumulo.server.AbstractServer; import org.apache.accumulo.server.client.ClientServiceHandler; import org.apache.accumulo.server.compaction.CompactionInfo; @@ -500,12 +500,12 @@ public class Compactor extends AbstractServer implements MetricsProducer, Compac return new FileCompactorRunnable() { private final AtomicReference<FileCompactor> compactor = new AtomicReference<>(); - private volatile NanoTime compactionStartTime; + private volatile Timer compactionStartTime; @Override public void initialize() throws RetriesExceededException { LOG.info("Starting up compaction runnable for job: {}", job); - this.compactionStartTime = NanoTime.now(); + this.compactionStartTime = Timer.startNew(); TCompactionStatusUpdate update = new TCompactionStatusUpdate(TCompactionState.STARTED, "Compaction started", -1, -1, -1, getCompactionAge().toNanos()); updateCompactionState(job, update); diff --git a/server/manager/src/main/java/org/apache/accumulo/manager/Manager.java b/server/manager/src/main/java/org/apache/accumulo/manager/Manager.java index 968e5c1c98..96f312d570 100644 --- a/server/manager/src/main/java/org/apache/accumulo/manager/Manager.java +++ b/server/manager/src/main/java/org/apache/accumulo/manager/Manager.java @@ -108,9 +108,9 @@ import org.apache.accumulo.core.tablet.thrift.TUnloadTabletGoal; import org.apache.accumulo.core.trace.TraceUtil; import org.apache.accumulo.core.util.Halt; import org.apache.accumulo.core.util.Retry; +import org.apache.accumulo.core.util.Timer; import org.apache.accumulo.core.util.threads.ThreadPools; import org.apache.accumulo.core.util.threads.Threads; -import org.apache.accumulo.core.util.time.NanoTime; import org.apache.accumulo.core.util.time.SteadyTime; import org.apache.accumulo.manager.metrics.BalancerMetrics; import org.apache.accumulo.manager.metrics.ManagerMetrics; @@ -1179,10 +1179,10 @@ public class Manager extends AbstractServer // wait at least 10 seconds final Duration timeToWait = Comparators.max(Duration.ofSeconds(10), Duration.ofMillis(rpcTimeout / 3)); - final NanoTime startTime = NanoTime.now(); + final Timer startTime = Timer.startNew(); // Wait for all tasks to complete while (!tasks.isEmpty()) { - boolean cancel = (startTime.elapsed().compareTo(timeToWait) > 0); + boolean cancel = (startTime.hasElapsed(timeToWait)); Iterator<Future<?>> iter = tasks.iterator(); while (iter.hasNext()) { Future<?> f = iter.next(); diff --git a/server/tserver/src/main/java/org/apache/accumulo/tserver/ScanServer.java b/server/tserver/src/main/java/org/apache/accumulo/tserver/ScanServer.java index f684b72291..bd5a935b26 100644 --- a/server/tserver/src/main/java/org/apache/accumulo/tserver/ScanServer.java +++ b/server/tserver/src/main/java/org/apache/accumulo/tserver/ScanServer.java @@ -90,9 +90,9 @@ import org.apache.accumulo.core.tabletscan.thrift.TooManyFilesException; import org.apache.accumulo.core.tabletserver.thrift.NoSuchScanIDException; import org.apache.accumulo.core.tabletserver.thrift.NotServingTabletException; import org.apache.accumulo.core.util.Halt; +import org.apache.accumulo.core.util.Timer; import org.apache.accumulo.core.util.UtilWaitThread; import org.apache.accumulo.core.util.threads.ThreadPools; -import org.apache.accumulo.core.util.time.NanoTime; import org.apache.accumulo.server.AbstractServer; import org.apache.accumulo.server.ServerContext; import org.apache.accumulo.server.client.ClientServiceHandler; @@ -703,7 +703,7 @@ public class ScanServer extends AbstractServer @VisibleForTesting ScanReservation reserveFilesInstrumented(Map<KeyExtent,List<TRange>> extents) throws AccumuloException { - NanoTime start = NanoTime.now(); + Timer start = Timer.startNew(); try { return reserveFiles(extents); } finally { @@ -744,7 +744,7 @@ public class ScanServer extends AbstractServer @VisibleForTesting ScanReservation reserveFilesInstrumented(long scanId) throws NoSuchScanIDException { - NanoTime start = NanoTime.now(); + Timer start = Timer.startNew(); try { return reserveFiles(scanId); } finally { diff --git a/server/tserver/src/main/java/org/apache/accumulo/tserver/UnloadTabletHandler.java b/server/tserver/src/main/java/org/apache/accumulo/tserver/UnloadTabletHandler.java index ae67417404..fec30031d0 100644 --- a/server/tserver/src/main/java/org/apache/accumulo/tserver/UnloadTabletHandler.java +++ b/server/tserver/src/main/java/org/apache/accumulo/tserver/UnloadTabletHandler.java @@ -26,7 +26,7 @@ import org.apache.accumulo.core.metadata.TabletLocationState; import org.apache.accumulo.core.metadata.TabletLocationState.BadLocationStateException; import org.apache.accumulo.core.metadata.schema.TabletMetadata.Location; import org.apache.accumulo.core.tablet.thrift.TUnloadTabletGoal; -import org.apache.accumulo.core.util.time.NanoTime; +import org.apache.accumulo.core.util.Timer; import org.apache.accumulo.core.util.time.SteadyTime; import org.apache.accumulo.server.manager.state.DistributedStoreException; import org.apache.accumulo.server.manager.state.TabletStateStore; @@ -40,7 +40,7 @@ class UnloadTabletHandler implements Runnable { private final KeyExtent extent; private final TUnloadTabletGoal goalState; private final SteadyTime requestTime; - private final NanoTime createTime; + private final Timer createTime; private final TabletServer server; public UnloadTabletHandler(TabletServer server, KeyExtent extent, TUnloadTabletGoal goalState, @@ -49,7 +49,7 @@ class UnloadTabletHandler implements Runnable { this.goalState = goalState; this.server = server; this.requestTime = requestTime; - this.createTime = NanoTime.now(); + this.createTime = Timer.startNew(); } @Override