From d607d8db9afddff03224198cd10e64fc6d506380 Mon Sep 17 00:00:00 2001 From: Devin Smith Date: Mon, 5 Jun 2023 09:19:45 -0700 Subject: [PATCH 1/6] Post release bump to 0.26.0 (#3926) --- authorization-codegen/protoc-gen-contextual-auth-wiring | 2 +- authorization-codegen/protoc-gen-service-auth-wiring | 2 +- buildSrc/src/main/groovy/io.deephaven.common-conventions.gradle | 2 +- py/client/README.md | 2 +- py/client/pydeephaven/__init__.py | 2 +- py/client/setup.py | 2 +- py/embedded-server/deephaven_server/__init__.py | 2 +- py/server/deephaven/__init__.py | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/authorization-codegen/protoc-gen-contextual-auth-wiring b/authorization-codegen/protoc-gen-contextual-auth-wiring index e6ef7a35bda..931f969cef1 100755 --- a/authorization-codegen/protoc-gen-contextual-auth-wiring +++ b/authorization-codegen/protoc-gen-contextual-auth-wiring @@ -1,2 +1,2 @@ # protoc-gen-contextual-auth-wiring -java -cp authorization-codegen/build/libs/deephaven-authorization-codegen-0.25.0-all.jar io.deephaven.auth.codegen.GenerateContextualAuthWiring +java -cp authorization-codegen/build/libs/deephaven-authorization-codegen-0.26.0-all.jar io.deephaven.auth.codegen.GenerateContextualAuthWiring diff --git a/authorization-codegen/protoc-gen-service-auth-wiring b/authorization-codegen/protoc-gen-service-auth-wiring index 824168491cc..a05903eaaee 100755 --- a/authorization-codegen/protoc-gen-service-auth-wiring +++ b/authorization-codegen/protoc-gen-service-auth-wiring @@ -1,2 +1,2 @@ # protoc-gen-service-auth-wiring -java -cp authorization-codegen/build/libs/deephaven-authorization-codegen-0.25.0-all.jar io.deephaven.auth.codegen.GenerateServiceAuthWiring +java -cp authorization-codegen/build/libs/deephaven-authorization-codegen-0.26.0-all.jar io.deephaven.auth.codegen.GenerateServiceAuthWiring diff --git a/buildSrc/src/main/groovy/io.deephaven.common-conventions.gradle b/buildSrc/src/main/groovy/io.deephaven.common-conventions.gradle index 2b447322f4b..067ad40949d 100644 --- a/buildSrc/src/main/groovy/io.deephaven.common-conventions.gradle +++ b/buildSrc/src/main/groovy/io.deephaven.common-conventions.gradle @@ -5,7 +5,7 @@ plugins { } group = 'io.deephaven' -version = '0.25.0' +version = '0.26.0' if (!name.startsWith('deephaven-')) { archivesBaseName = "deephaven-${name}" diff --git a/py/client/README.md b/py/client/README.md index a934b163c0f..59bda886e7e 100644 --- a/py/client/README.md +++ b/py/client/README.md @@ -35,7 +35,7 @@ $ python3 -m examples.demo_asof_join ``` ## Install ``` shell -$ pip3 install dist/pydeephaven-0.25.0-py3-none-any.whl +$ pip3 install dist/pydeephaven-0.26.0-py3-none-any.whl ``` ## Quick start diff --git a/py/client/pydeephaven/__init__.py b/py/client/pydeephaven/__init__.py index ff730641a1e..a7eca2075c5 100644 --- a/py/client/pydeephaven/__init__.py +++ b/py/client/pydeephaven/__init__.py @@ -29,4 +29,4 @@ from .query import Query __all__ = ["Session", "DHError", "SortDirection"] -__version__ = "0.25.0" +__version__ = "0.26.0" diff --git a/py/client/setup.py b/py/client/setup.py index febbfa696ed..e60ba4638a0 100644 --- a/py/client/setup.py +++ b/py/client/setup.py @@ -12,7 +12,7 @@ setup( name='pydeephaven', - version='0.25.0', + version='0.26.0', description='The Deephaven Python Client', long_description=README, long_description_content_type="text/markdown", diff --git a/py/embedded-server/deephaven_server/__init__.py b/py/embedded-server/deephaven_server/__init__.py index fdbeaed6da4..6838ef173c5 100644 --- a/py/embedded-server/deephaven_server/__init__.py +++ b/py/embedded-server/deephaven_server/__init__.py @@ -1,7 +1,7 @@ # # Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending # -__version__ = "0.25.0" +__version__ = "0.26.0" from .start_jvm import DEFAULT_JVM_PROPERTIES, DEFAULT_JVM_ARGS, start_jvm from .server import Server diff --git a/py/server/deephaven/__init__.py b/py/server/deephaven/__init__.py index 2d8d7da51d5..b863efb4cea 100644 --- a/py/server/deephaven/__init__.py +++ b/py/server/deephaven/__init__.py @@ -7,7 +7,7 @@ """ -__version__ = "0.25.0" +__version__ = "0.26.0" from deephaven_internal import jvm From d18570a96239f1b9f91c8268dc6917a016f10505 Mon Sep 17 00:00:00 2001 From: Devin Smith Date: Mon, 5 Jun 2023 11:43:13 -0700 Subject: [PATCH 2/6] Improve CI uploaded artifacts (#3929) The binary logs may provide useful debugging information when CI appears to fail for no other apparent reason. * Upload binary test-results as artifact for check-ci and nightly-check-ci * Combines test-results and reports for check-ci (matches nightly-check-ci behavior) * Adds core as artifact for check-ci-jvm-err (matches nightly-check-ci behavior) --- .github/workflows/check-ci.yml | 13 ++++--------- .github/workflows/nightly-check-ci.yml | 1 - 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/check-ci.yml b/.github/workflows/check-ci.yml index dda41d965e5..1a1e09d5a9e 100644 --- a/.github/workflows/check-ci.yml +++ b/.github/workflows/check-ci.yml @@ -51,19 +51,14 @@ jobs: name: check-ci-results path: | **/build/test-results/** - !**/build/test-results/**/binary/** - - - name: Upload Test Reports - uses: actions/upload-artifact@v3 - if: always() - with: - name: check-ci-reports - path: '**/build/reports/tests/**' + **/build/reports/tests/** - name: Upload JVM Error Logs uses: actions/upload-artifact@v3 if: failure() with: name: check-ci-jvm-err - path: '**/*_pid*.log' + path: | + **/*_pid*.log + **/core.* if-no-files-found: ignore diff --git a/.github/workflows/nightly-check-ci.yml b/.github/workflows/nightly-check-ci.yml index 9adefe1d42a..60b3d0f7873 100644 --- a/.github/workflows/nightly-check-ci.yml +++ b/.github/workflows/nightly-check-ci.yml @@ -68,7 +68,6 @@ jobs: path: | **/build/test-results/** **/build/reports/tests/** - !**/build/test-results/**/binary/** - name: Upload JVM Error Logs uses: actions/upload-artifact@v3 From 501d4d6b973f9af15d1c358c434bef91ce23ecf7 Mon Sep 17 00:00:00 2001 From: Andrew <3199649+abaranec@users.noreply.github.com> Date: Mon, 5 Jun 2023 15:36:16 -0400 Subject: [PATCH 3/6] Fix UpdateGraph not always available to performance trackers (#3932) --- .../impl/perf/UpdatePerformanceTracker.java | 23 +++++++++++++++---- .../table/impl/util/ServerStateTracker.java | 17 ++++++++++---- .../impl/memory/MemoryTableLogger.java | 2 ++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/perf/UpdatePerformanceTracker.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/perf/UpdatePerformanceTracker.java index d39c8ac66db..ed556fcebf7 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/perf/UpdatePerformanceTracker.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/perf/UpdatePerformanceTracker.java @@ -4,12 +4,18 @@ package io.deephaven.engine.table.impl.perf; import io.deephaven.configuration.Configuration; -import io.deephaven.engine.table.*; +import io.deephaven.engine.context.ExecutionContext; +import io.deephaven.engine.table.ShiftObliviousListener; +import io.deephaven.engine.table.Table; +import io.deephaven.engine.table.TableUpdateListener; +import io.deephaven.engine.table.impl.InstrumentedTableUpdateListener; +import io.deephaven.engine.table.impl.QueryTable; +import io.deephaven.engine.table.impl.ShiftObliviousInstrumentedListener; import io.deephaven.engine.tablelogger.EngineTableLoggers; import io.deephaven.engine.tablelogger.UpdatePerformanceLogLogger; import io.deephaven.engine.tablelogger.impl.memory.MemoryTableLogger; +import io.deephaven.engine.updategraph.UpdateGraph; import io.deephaven.engine.updategraph.impl.PeriodicUpdateGraph; -import io.deephaven.engine.table.impl.*; import io.deephaven.internal.log.LoggerFactory; import io.deephaven.io.logger.Logger; import io.deephaven.util.QueryConstants; @@ -76,7 +82,8 @@ private UpdatePerformanceTracker(@NotNull final Logger logger) { } private void startThread() { - Thread driverThread = new Thread(new Driver(), "UpdatePerformanceTracker.Driver"); + final UpdateGraph updateGraph = ExecutionContext.getContext().getUpdateGraph(); + Thread driverThread = new Thread(new Driver(updateGraph), "UpdatePerformanceTracker.Driver"); driverThread.setDaemon(true); driverThread.start(); } @@ -90,6 +97,13 @@ public static synchronized void start() { } private class Driver implements Runnable { + + private final UpdateGraph updateGraph; + + public Driver(@NotNull final UpdateGraph updateGraph) { + this.updateGraph = updateGraph; + } + @Override public void run() { // noinspection InfiniteLoopStatement @@ -102,7 +116,7 @@ public void run() { // should log, but no logger handy // ignore } - getQueryTable().getUpdateGraph().sharedLock().doLocked( + updateGraph.sharedLock().doLocked( () -> finishInterval(intervalStartTimeMillis, System.currentTimeMillis(), System.nanoTime() - intervalStartTimeNanos)); } @@ -232,6 +246,7 @@ public long getIntervalDurationNanos() { } } + @NotNull public QueryTable getQueryTable() { return MemoryTableLogger.maybeGetQueryTable(tableLogger); } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/util/ServerStateTracker.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/util/ServerStateTracker.java index 9a6b53c07ac..ed7ed51a58c 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/util/ServerStateTracker.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/util/ServerStateTracker.java @@ -4,13 +4,16 @@ package io.deephaven.engine.table.impl.util; import io.deephaven.configuration.Configuration; +import io.deephaven.engine.context.ExecutionContext; +import io.deephaven.engine.table.impl.QueryTable; import io.deephaven.engine.tablelogger.EngineTableLoggers; import io.deephaven.engine.tablelogger.ServerStateLogLogger; -import io.deephaven.engine.table.impl.QueryTable; import io.deephaven.engine.tablelogger.impl.memory.MemoryTableLogger; +import io.deephaven.engine.updategraph.UpdateGraph; import io.deephaven.engine.updategraph.impl.PeriodicUpdateGraph; -import io.deephaven.io.logger.Logger; import io.deephaven.internal.log.LoggerFactory; +import io.deephaven.io.logger.Logger; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.util.Arrays; @@ -47,8 +50,9 @@ private ServerStateTracker() { } private void startThread() { + final UpdateGraph updateGraph = ExecutionContext.getContext().getUpdateGraph(); Thread driverThread = new Thread( - new ServerStateTracker.Driver(), + new ServerStateTracker.Driver(updateGraph), ServerStateTracker.class.getSimpleName() + ".Driver"); driverThread.setDaemon(true); driverThread.start(); @@ -110,6 +114,12 @@ static void calcStats(final Stats out, final long[] values, final int nValues) { } private class Driver implements Runnable { + private final PeriodicUpdateGraph updateGraph; + + public Driver(@NotNull final UpdateGraph updateGraph) { + this.updateGraph = updateGraph.cast(); + } + @Override public void run() { final RuntimeMemory.Sample memSample = new RuntimeMemory.Sample(); @@ -126,7 +136,6 @@ public void run() { final long prevTotalCollections = memSample.totalCollections; final long prevTotalCollectionTimeMs = memSample.totalCollectionTimeMs; RuntimeMemory.getInstance().read(memSample); - PeriodicUpdateGraph updateGraph = getQueryTable().getUpdateGraph().cast(); updateGraph.takeAccumulatedCycleStats(ugpAccumCycleStats); final long endTimeMillis = System.currentTimeMillis(); logProcessMem( diff --git a/engine/table/src/main/java/io/deephaven/engine/tablelogger/impl/memory/MemoryTableLogger.java b/engine/table/src/main/java/io/deephaven/engine/tablelogger/impl/memory/MemoryTableLogger.java index 60205c6749e..0b1c8394b85 100644 --- a/engine/table/src/main/java/io/deephaven/engine/tablelogger/impl/memory/MemoryTableLogger.java +++ b/engine/table/src/main/java/io/deephaven/engine/tablelogger/impl/memory/MemoryTableLogger.java @@ -8,6 +8,7 @@ import io.deephaven.io.logger.Logger; import io.deephaven.tablelogger.TableLoggerImpl2; import io.deephaven.tablelogger.WritableRowContainer; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.io.UncheckedIOException; @@ -16,6 +17,7 @@ * Base class for memory table loggers that create and initialize a {@link DynamicTableWriter}. */ public abstract class MemoryTableLogger extends TableLoggerImpl2 { + @NotNull public static QueryTable maybeGetQueryTable(final Object maybeMemoryTableLogger) { if (maybeMemoryTableLogger instanceof MemoryTableLogger) { return ((MemoryTableLogger) maybeMemoryTableLogger).getQueryTable(); From 8c6b199a06fb294ebadfa4739342672f3854d020 Mon Sep 17 00:00:00 2001 From: Nate Bauernfeind Date: Mon, 5 Jun 2023 13:49:15 -0600 Subject: [PATCH 4/6] Fix RowRedirectionLockFreeTest: Prevent Succeeding If Thread Fails (#3928) --- .../impl/util/RowRedirectionLockFreeTest.java | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/engine/table/src/test/java/io/deephaven/engine/table/impl/util/RowRedirectionLockFreeTest.java b/engine/table/src/test/java/io/deephaven/engine/table/impl/util/RowRedirectionLockFreeTest.java index 82791bbcb64..767836b0ee5 100644 --- a/engine/table/src/test/java/io/deephaven/engine/table/impl/util/RowRedirectionLockFreeTest.java +++ b/engine/table/src/test/java/io/deephaven/engine/table/impl/util/RowRedirectionLockFreeTest.java @@ -5,23 +5,32 @@ import io.deephaven.engine.context.ExecutionContext; import io.deephaven.engine.testutil.ControlledUpdateGraph; -import io.deephaven.engine.testutil.testcase.RefreshingTableTestCase; +import io.deephaven.engine.testutil.junit4.EngineCleanup; import io.deephaven.engine.updategraph.LogicalClock; import gnu.trove.list.array.TLongArrayList; import io.deephaven.test.types.OutOfBandTest; +import junit.framework.TestCase; import org.apache.commons.lang3.mutable.MutableInt; import java.util.Arrays; import java.util.Random; + +import org.junit.Rule; +import org.junit.Test; import org.junit.experimental.categories.Category; import static io.deephaven.base.ArrayUtil.swap; @Category(OutOfBandTest.class) -public class RowRedirectionLockFreeTest extends RefreshingTableTestCase { +public class RowRedirectionLockFreeTest { + + @Rule + public final EngineCleanup framework = new EngineCleanup(); + private static final long oneBillion = 1000000000L; private static final int testDurationInSeconds = 15; + @Test public void testRowRedirection() throws InterruptedException { final WritableRowRedirectionLockFree index = new RowRedirectionLockFreeFactory().createRowRedirection(10); index.startTrackingPrevValues(); @@ -44,8 +53,11 @@ public void testRowRedirection() throws InterruptedException { for (RWBase rwb : participants) { rwb.cancel(); } - for (Thread thread : threads) { - thread.join(); + for (int ii = 0; ii < threads.length; ++ii) { + threads[ii].join(); + if (participants[ii].caughtException != null) { + throw participants[ii].caughtException; + } } boolean failed = false; for (RWBase rwb : participants) { @@ -53,7 +65,7 @@ public void testRowRedirection() throws InterruptedException { failed |= rwb.hasFailed(); } if (failed) { - fail("WritableRowRedirection had some corrupt values"); + TestCase.fail("WritableRowRedirection had some corrupt values"); } } @@ -67,6 +79,7 @@ private static abstract class RWBase implements Runnable, Cancellable { protected final WritableRowRedirectionLockFree index; protected int numIterations; protected volatile boolean cancelled; + protected volatile RuntimeException caughtException; protected RWBase(String name, long initialStep, WritableRowRedirectionLockFree index) { this.name = name; @@ -77,9 +90,13 @@ protected RWBase(String name, long initialStep, WritableRowRedirectionLockFree i } public final void run() { - while (!cancelled) { - doOneIteration(); - ++numIterations; + try { + while (!cancelled) { + doOneIteration(); + ++numIterations; + } + } catch (RuntimeException e) { + caughtException = e; } } @@ -100,6 +117,8 @@ private static class Reader extends RWBase { private int badUpdateCycles; private int incoherentCycles; + protected final ControlledUpdateGraph updateGraph = ExecutionContext.getContext().getUpdateGraph().cast(); + Reader(String name, long initialStep, WritableRowRedirectionLockFree index) { super(name, initialStep, index); goodIdleCycles = 0; @@ -112,7 +131,7 @@ private static class Reader extends RWBase { @Override protected final void doOneIteration() { // Figure out what step we're in and what step to read from (current or prev). - final long logicalClockStartValue = ExecutionContext.getContext().getUpdateGraph().clock().currentValue(); + final long logicalClockStartValue = updateGraph.clock().currentValue(); final long stepFromCycle = LogicalClock.getStep(logicalClockStartValue); final LogicalClock.State state = LogicalClock.getState(logicalClockStartValue); final long step = state == LogicalClock.State.Updating ? stepFromCycle - 1 : stepFromCycle; @@ -153,7 +172,7 @@ protected final void doOneIteration() { } - final long logicalClockEndValue = ExecutionContext.getContext().getUpdateGraph().clock().currentValue(); + final long logicalClockEndValue = updateGraph.clock().currentValue(); if (logicalClockStartValue != logicalClockEndValue) { ++incoherentCycles; return; @@ -188,6 +207,8 @@ public String toString() { } private static class Writer extends RWBase { + final ControlledUpdateGraph updateGraph = ExecutionContext.getContext().getUpdateGraph().cast(); + Writer(String name, long initialStep, WritableRowRedirectionLockFree index) { super(name, initialStep, index); } @@ -196,7 +217,6 @@ private static class Writer extends RWBase { protected final void doOneIteration() { final MutableInt keysInThisGeneration = new MutableInt(); // A bit of a waste because we only look at the first 'numKeysToInsert' keys, but that's ok. - final ControlledUpdateGraph updateGraph = ExecutionContext.getContext().getUpdateGraph().cast(); updateGraph.runWithinUnitTestCycle(() -> { final long step = updateGraph.clock().currentStep(); keysInThisGeneration.setValue((int) ((step - initialStep) * 1000 + 1000)); From ca7daa7ec03d8ad2901e6f95d744051b9979f16b Mon Sep 17 00:00:00 2001 From: Nate Bauernfeind Date: Mon, 5 Jun 2023 14:25:44 -0600 Subject: [PATCH 5/6] Fix TestTableTools: wrong junit version (#3933) --- .../deephaven/engine/util/TestTableTools.java | 172 ++++++++++-------- 1 file changed, 96 insertions(+), 76 deletions(-) diff --git a/engine/table/src/test/java/io/deephaven/engine/util/TestTableTools.java b/engine/table/src/test/java/io/deephaven/engine/util/TestTableTools.java index adfcd00bd79..dd76fb10aa3 100644 --- a/engine/table/src/test/java/io/deephaven/engine/util/TestTableTools.java +++ b/engine/table/src/test/java/io/deephaven/engine/util/TestTableTools.java @@ -15,7 +15,6 @@ import io.deephaven.engine.table.impl.QueryTable; import io.deephaven.engine.table.impl.DataAccessHelpers; import io.deephaven.engine.table.impl.TableUpdateImpl; -import io.deephaven.engine.table.impl.UpdateErrorReporter; import io.deephaven.engine.table.impl.sources.UnionRedirection; import io.deephaven.engine.table.impl.util.ColumnHolder; import io.deephaven.engine.testutil.*; @@ -28,12 +27,12 @@ import io.deephaven.engine.updategraph.LogicalClockImpl; import io.deephaven.test.types.OutOfBandTest; import io.deephaven.time.DateTimeUtils; -import io.deephaven.util.ExceptionDetails; import io.deephaven.util.QueryConstants; import junit.framework.TestCase; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; +import org.junit.Test; import org.junit.experimental.categories.Category; import java.time.Instant; @@ -50,7 +49,7 @@ * Unit tests for {@link TableTools}. */ @Category(OutOfBandTest.class) -public class TestTableTools extends TestCase implements UpdateErrorReporter { +public class TestTableTools { @Rule public final EngineCleanup framework = new EngineCleanup(); @@ -61,8 +60,6 @@ public class TestTableTools extends TestCase implements UpdateErrorReporter { @Before public void setUp() throws Exception { - super.setUp(); - table1 = testRefreshingTable(TstUtils.i(2, 3, 6, 7, 8, 10, 12, 15, 16).toTracking(), col("StringKeys", "key1", "key1", "key1", "key1", "key2", "key2", "key2", "key2", "key2"), col("GroupedInts", 1, 1, 2, 2, 2, 3, 3, 3, 3)); @@ -71,15 +68,9 @@ public void setUp() throws Exception { col("GroupedInts1", 1, 1, 2, 2, 2, 3, 3, 3, 3)); emptyTable = testRefreshingTable(col("StringKeys", (Object) CollectionUtil.ZERO_LENGTH_STRING_ARRAY), col("GroupedInts", (Object) CollectionUtil.ZERO_LENGTH_BYTE_ARRAY)); - - } - - @Override - public void reportUpdateError(Throwable t) { - System.err.println("Received error notification: " + new ExceptionDetails(t).getFullStackTrace()); - TestCase.fail(t.getMessage()); } + @Test public void testMerge() { final Table result = TableTools.merge(table1, table1, table1); tableRangesAreEqual(table1, result, 0, 0, table1.size()); @@ -87,6 +78,7 @@ public void testMerge() { tableRangesAreEqual(table1, result, 0, table1.size() * 2, table1.size()); } + @Test public void testMergeWithNullTables() { assertThrows(TableTools::merge); assertThrows(() -> TableTools.merge(null, null)); @@ -102,6 +94,7 @@ public void testMergeWithNullTables() { tableRangesAreEqual(table2, result, 0, 0, table2.size()); } + @Test public void testMergeOfMismatchedTables() { try { TableTools.merge(table1, table2); @@ -134,6 +127,7 @@ public void testMergeOfMismatchedTables() { } } + @Test public void testMergeWithWhere() { Table t1 = TableTools.emptyTable(1).update("Col=`A`"); Table t2 = TableTools.emptyTable(1).update("Col=`B`"); @@ -158,74 +152,76 @@ public void testMergeWithWhere() { TableTools.show(t_3_4_filtered); TableTools.show(t_all); - assertEquals(t_all.size(), 3); + Assert.assertEquals(t_all.size(), 3); assertArrayEquals((Object[]) DataAccessHelpers.getColumn(t_all, "Col").getDirect(), new String[] {"A", "B", "D"}); } + @Test public void testDiff() { - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 1 encountered 2 expected null\n", TableTools.diff(TableTools.newTable(intCol("x", 1, 2, 3)), TableTools.newTable(intCol("x", 1, NULL_INT, NULL_INT)), 10)); - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 1 encountered null expected 2\n", TableTools.diff(TableTools.newTable(intCol("x", 1, NULL_INT, NULL_INT)), TableTools.newTable(intCol("x", 1, 2, 3)), 10)); - assertEquals("", + Assert.assertEquals("", TableTools.diff(TableTools.newTable(col("x", 1, 2, 3)), TableTools.newTable(col("x", 1, 2, 3)), 10)); - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 1 encountered 2.0 expected null\n", TableTools.diff(TableTools.newTable(col("x", 1.0, 2.0, 3.0)), TableTools.newTable(col("x", 1.0, null, null)), 10)); - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 1 encountered null expected 2.0\n", TableTools.diff(TableTools.newTable(col("x", 1.0, null, null)), TableTools.newTable(col("x", 1.0, 2.0, 3.0)), 10)); - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 1 encountered 2.0E-12 expected null\n", TableTools.diff(TableTools.newTable(col("x", 0.000000000001, 0.000000000002, 0.000000000003)), TableTools.newTable(col("x", 0.000000000001, null, null)), 10)); - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 1 encountered 2.0E-12 expected null\n", TableTools.diff(TableTools.newTable(col("x", 0.000000000001, 0.000000000002, 0.000000000003)), TableTools.newTable(col("x", 0.000000000002, null, null)), 10, EnumSet.of(TableDiff.DiffItems.DoublesExact))); - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 0 encountered 1.0E-12 expected 2.0E-12 (difference = 1.0E-12)\n", TableTools.diff(TableTools.newTable(col("x", 0.000000000001, 0.000000000002, 0.000000000003)), TableTools.newTable(col("x", 0.000000000002, null, null)), 10)); - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 1 encountered null expected 2.0\n", TableTools.diff(TableTools.newTable(floatCol("x", 1.0f, NULL_FLOAT, NULL_FLOAT)), TableTools.newTable(floatCol("x", 1.0f, 2.0f, 3.0f)), 10)); - assertEquals("", TableTools.diff(TableTools.newTable(floatCol("x", 1, 2, 3)), + Assert.assertEquals("", TableTools.diff(TableTools.newTable(floatCol("x", 1, 2, 3)), TableTools.newTable(floatCol("x", 1.0f, 2.0f, 3.0f)), 10)); - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 1 encountered 2.0 expected null\n", TableTools.diff(TableTools.newTable(floatCol("x", 1.0f, 2.0f, 3.0f)), TableTools.newTable(floatCol("x", 1.0f, NULL_FLOAT, NULL_FLOAT)), 10)); - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 1 encountered null expected 2.0\n", TableTools.diff(TableTools.newTable(floatCol("x", 1.0f, NULL_FLOAT, NULL_FLOAT)), TableTools.newTable(floatCol("x", 1.0f, 2.0f, 3.0f)), 10)); - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 1 encountered 2.0E-12 expected null\n", TableTools.diff(TableTools.newTable(floatCol("x", 0.000000000001f, 0.000000000002f, 0.000000000003f)), TableTools.newTable(floatCol("x", 0.000000000001f, NULL_FLOAT, NULL_FLOAT)), 10)); - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 1 encountered 2.0E-12 expected null\n", TableTools.diff(TableTools.newTable(floatCol("x", 0.000000000001f, 0.000000000002f, 0.000000000003f)), TableTools.newTable(floatCol("x", 0.000000000002f, NULL_FLOAT, NULL_FLOAT)), 10, EnumSet.of(TableDiff.DiffItems.DoublesExact))); - assertEquals( + Assert.assertEquals( "Column x different from the expected set, first difference at row 0 encountered 1.0E-12 expected 2.0E-12 (difference = 1.0E-12)\n", TableTools.diff(TableTools.newTable(floatCol("x", 0.000000000001f, 0.000000000002f, 0.000000000003f)), TableTools.newTable(floatCol("x", 0.000000000002f, NULL_FLOAT, NULL_FLOAT)), 10)); } + @Test public void testRoundDecimalColumns() { Table table = newTable( col("String", "c", "e", "g"), @@ -236,54 +232,55 @@ public void testRoundDecimalColumns() { // Test whether we're rounding all columns properly Table roundedColumns = TableTools.roundDecimalColumns(table); - assertArrayEquals((String[]) DataAccessHelpers.getColumn(roundedColumns, "String").getDirect(), + Assert.assertArrayEquals((String[]) DataAccessHelpers.getColumn(roundedColumns, "String").getDirect(), (String[]) DataAccessHelpers.getColumn(table, "String").getDirect()); - assertArrayEquals((int[]) DataAccessHelpers.getColumn(roundedColumns, "Int").getDirect(), + Assert.assertArrayEquals((int[]) DataAccessHelpers.getColumn(roundedColumns, "Int").getDirect(), (int[]) DataAccessHelpers.getColumn(table, "Int").getDirect()); - assertEquals(Math.round((double) DataAccessHelpers.getColumn(table, "Double").get(0)), + Assert.assertEquals(Math.round((double) DataAccessHelpers.getColumn(table, "Double").get(0)), DataAccessHelpers.getColumn(roundedColumns, "Double").get(0)); - assertEquals(Math.round((double) DataAccessHelpers.getColumn(table, "Double").get(1)), + Assert.assertEquals(Math.round((double) DataAccessHelpers.getColumn(table, "Double").get(1)), DataAccessHelpers.getColumn(roundedColumns, "Double").get(1)); - assertEquals(Math.round((double) DataAccessHelpers.getColumn(table, "Double").get(2)), + Assert.assertEquals(Math.round((double) DataAccessHelpers.getColumn(table, "Double").get(2)), DataAccessHelpers.getColumn(roundedColumns, "Double").get(2)); // Cast these cause the DB rounds floats to longs - assertEquals((long) Math.round((float) DataAccessHelpers.getColumn(table, "Float").get(0)), + Assert.assertEquals((long) Math.round((float) DataAccessHelpers.getColumn(table, "Float").get(0)), DataAccessHelpers.getColumn(roundedColumns, "Float").get(0)); - assertEquals((long) Math.round((float) DataAccessHelpers.getColumn(table, "Float").get(1)), + Assert.assertEquals((long) Math.round((float) DataAccessHelpers.getColumn(table, "Float").get(1)), DataAccessHelpers.getColumn(roundedColumns, "Float").get(1)); - assertEquals((long) Math.round((float) DataAccessHelpers.getColumn(table, "Float").get(2)), + Assert.assertEquals((long) Math.round((float) DataAccessHelpers.getColumn(table, "Float").get(2)), DataAccessHelpers.getColumn(roundedColumns, "Float").get(2)); // Test whether it works when we specify the columns, by comparing to the validated results from before Table specificRoundedColums = TableTools.roundDecimalColumns(table, "Double", "Float"); - assertArrayEquals((String[]) DataAccessHelpers.getColumn(roundedColumns, "String").getDirect(), + Assert.assertArrayEquals((String[]) DataAccessHelpers.getColumn(roundedColumns, "String").getDirect(), (String[]) DataAccessHelpers.getColumn(specificRoundedColums, "String").getDirect()); - assertArrayEquals((int[]) DataAccessHelpers.getColumn(roundedColumns, "Int").getDirect(), + Assert.assertArrayEquals((int[]) DataAccessHelpers.getColumn(roundedColumns, "Int").getDirect(), (int[]) DataAccessHelpers.getColumn(specificRoundedColums, "Int").getDirect()); - assertArrayEquals((long[]) DataAccessHelpers.getColumn(roundedColumns, "Double").getDirect(), + Assert.assertArrayEquals((long[]) DataAccessHelpers.getColumn(roundedColumns, "Double").getDirect(), (long[]) DataAccessHelpers.getColumn(specificRoundedColums, "Double").getDirect()); - assertArrayEquals((long[]) DataAccessHelpers.getColumn(roundedColumns, "Float").getDirect(), + Assert.assertArrayEquals((long[]) DataAccessHelpers.getColumn(roundedColumns, "Float").getDirect(), (long[]) DataAccessHelpers.getColumn(specificRoundedColums, "Float").getDirect()); // Test whether it works properly when we specify what NOT to round Table onlyOneRoundedColumn = TableTools.roundDecimalColumnsExcept(table, "Float"); - assertArrayEquals((String[]) DataAccessHelpers.getColumn(roundedColumns, "String").getDirect(), + Assert.assertArrayEquals((String[]) DataAccessHelpers.getColumn(roundedColumns, "String").getDirect(), (String[]) DataAccessHelpers.getColumn(onlyOneRoundedColumn, "String").getDirect()); - assertArrayEquals((int[]) DataAccessHelpers.getColumn(table, "Int").getDirect(), + Assert.assertArrayEquals((int[]) DataAccessHelpers.getColumn(table, "Int").getDirect(), (int[]) DataAccessHelpers.getColumn(onlyOneRoundedColumn, "Int").getDirect()); - assertArrayEquals((long[]) DataAccessHelpers.getColumn(roundedColumns, "Double").getDirect(), + Assert.assertArrayEquals((long[]) DataAccessHelpers.getColumn(roundedColumns, "Double").getDirect(), (long[]) DataAccessHelpers.getColumn(onlyOneRoundedColumn, "Double").getDirect()); - assertArrayEquals((float[]) DataAccessHelpers.getColumn(table, "Float").getDirect(), + Assert.assertArrayEquals((float[]) DataAccessHelpers.getColumn(table, "Float").getDirect(), (float[]) DataAccessHelpers.getColumn(onlyOneRoundedColumn, "Float").getDirect(), 0.0f); try { // Make sure we complain if you try to round the unroundable TableTools.roundDecimalColumns(table, "String"); - fail("Expected exception: trying to round a String column"); + Assert.fail("Expected exception: trying to round a String column"); } catch (Exception ignored) { } } + @Test public void testInstantColumnHolder() { // create two columns with the same data @@ -320,6 +317,7 @@ public void testInstantColumnHolder() { Assert.assertEquals(longData[2], DataAccessHelpers.getColumn(table, 1).getLong(2)); } + @Test public void testSimpleDiffRegression() { final Table expected = emptyTable(1).update("Sym=`AXP`"); final Table result = emptyTable(1).update("Sym=`BAC`"); @@ -329,6 +327,7 @@ public void testSimpleDiffRegression() { Assert.assertNotEquals(0, diffInfo.length()); } + @Test public void testMerge2() { Random random = new Random(0); int size = random.nextInt(10); @@ -357,6 +356,7 @@ public void testMerge2() { tableRangesAreEqual(table3, result, 0, table1.size() + table2.size(), table3.size()); } + @Test public void testMergeIterative() { Random random = new Random(0); int size = 3; @@ -447,6 +447,7 @@ protected Table e() { } } + @Test public void testMergeIterative2() { LogicalClockImpl clock = (LogicalClockImpl) ExecutionContext.getContext().getUpdateGraph().clock(); Random random = new Random(0); @@ -552,6 +553,7 @@ protected Table e() { // This merge should work out nicely, we'll end up collapsing it into a single broad merge. + @Test public void testMergeRecursive() { Table result = null; @@ -571,6 +573,7 @@ public void testMergeRecursive() { } // This test does a merge, followed by a view, then another merge. + @Test public void testMergeRecursive2() { Table merge1 = TableTools.merge(table1, table2.renameColumns("GroupedInts=GroupedInts1", "StringKeys=StringKeys1")) @@ -588,6 +591,7 @@ public void testMergeRecursive2() { tableRangesAreEqual(table1.view("StringKeys"), merge2, 0, table1.size() + table2.size(), table1.size()); } + @Test public void testUncollapsableMerge() { final int numRecursions = 128; @@ -609,6 +613,7 @@ public void testUncollapsableMerge() { } } + @Test public void testMergeWithNestedShift() { // Test that an outer shift properly shifts RowSet when inner shifts are also propagated to the RowSet. final QueryTable table = testRefreshingTable(i(1).toTracking(), col("Sentinel", 1)); @@ -632,6 +637,7 @@ public void testMergeWithNestedShift() { TableTools.show(result, 100); } + @Test public void testMergeWithShiftBoundary() { // Test that an outer shift properly shifts RowSet when inner shifts are also propagated to the RowSet. final int ONE_MILLION = 1024 * 1024; @@ -659,6 +665,7 @@ public void testMergeWithShiftBoundary() { showWithRowSet(result); } + @Test public void testMergeShiftsEmptyTable() { // Test that an outer shift properly shifts RowSet when inner shifts are also propagated to the RowSet. final QueryTable table = testRefreshingTable(i(1).toTracking(), col("Sentinel", 1)); @@ -696,6 +703,7 @@ public void testMergeShiftsEmptyTable() { } } + @Test public void testMergeShiftBoundary() { // DH-11032 // Test that when our inner table has a shift that is begins beyond the last key for our subtable (because @@ -732,6 +740,7 @@ public void testMergeShiftBoundary() { assertTableEquals(expected, m2); } + @Test public void testMergeDeepShifts() { // Test that an outer shift properly shifts RowSet when inner shifts are also propagated to the RowSet. final QueryTable table = testRefreshingTable(i(1).toTracking(), col("Sentinel", 1)); @@ -786,6 +795,7 @@ private void addRows(Random random, QueryTable table1) { table1.notifyListeners(newRowSet, TstUtils.i(), TstUtils.i()); } + @Test public void testMergeWithEmptyTables() { Table emptyLikeTable1 = TableTools.newTable(table1.getDefinition()); Table result = TableTools.merge(table1, emptyLikeTable1); @@ -796,6 +806,7 @@ public void testMergeWithEmptyTables() { TestCase.assertEquals(0, result.size()); } + @Test public void testMergeSorted() { Table table1 = testTable(i(1, 3, 5, 6, 7).toTracking(), col("Key", "a", "c", "d", "e", "f")) .updateView("Sentinel=k"); @@ -809,6 +820,7 @@ public void testMergeSorted() { assertTableEquals(merged, standardWay); } + @Test public void testMergeSorted2() { Random random = new Random(42); List tables = new ArrayList<>(); @@ -830,6 +842,7 @@ public void testMergeSorted2() { assertTableEquals(merged, standardWay); } + @Test public void testMergeGetChunk() { final QueryTable table = testRefreshingTable(i(1).toTracking(), col("Sentinel", 1)); final Table m2 = TableTools.merge(table, table).updateView("Sentinel=Sentinel+1"); @@ -845,24 +858,26 @@ public void testMergeGetChunk() { final int numElements = origRowSet.intSize(); final ColumnSource origCol = table.getColumnSource("Sentinel"); - final ColumnSource.GetContext origContext = origCol.makeGetContext(numElements); - final IntChunk origContent = usePrev - ? origCol.getPrevChunk(origContext, origRowSet).asIntChunk() - : origCol.getChunk(origContext, origRowSet).asIntChunk(); - - final ColumnSource resCol = result.getColumnSource("Sentinel"); - final ColumnSource.GetContext resContext = resCol.makeGetContext(numElements * 3); - final IntChunk resContent = usePrev - ? resCol.getPrevChunk(resContext, resRowSet).asIntChunk() - : resCol.getChunk(resContext, resRowSet).asIntChunk(); - - Assert.assertEquals(numElements, origContent.size()); - Assert.assertEquals(3 * numElements, resContent.size()); - - for (int ii = 0; ii < numElements; ++ii) { - Assert.assertEquals(origContent.get(ii), resContent.get(ii)); - Assert.assertEquals(origContent.get(ii), resContent.get(ii + numElements) - 1); - Assert.assertEquals(origContent.get(ii), resContent.get(ii + 2 * numElements) - 1); + try (final ColumnSource.GetContext origContext = origCol.makeGetContext(numElements)) { + final IntChunk origContent = usePrev + ? origCol.getPrevChunk(origContext, origRowSet).asIntChunk() + : origCol.getChunk(origContext, origRowSet).asIntChunk(); + + final ColumnSource resCol = result.getColumnSource("Sentinel"); + try (final ColumnSource.GetContext resContext = resCol.makeGetContext(numElements * 3)) { + final IntChunk resContent = usePrev + ? resCol.getPrevChunk(resContext, resRowSet).asIntChunk() + : resCol.getChunk(resContext, resRowSet).asIntChunk(); + + Assert.assertEquals(numElements, origContent.size()); + Assert.assertEquals(3 * numElements, resContent.size()); + + for (int ii = 0; ii < numElements; ++ii) { + Assert.assertEquals(origContent.get(ii), resContent.get(ii)); + Assert.assertEquals(origContent.get(ii), resContent.get(ii + numElements) - 1); + Assert.assertEquals(origContent.get(ii), resContent.get(ii + 2 * numElements) - 1); + } + } } }; @@ -888,6 +903,7 @@ protected void onFailureInternal(Throwable originalException, Entry sourceEntry) } } + @Test public void testMergeGetChunkEmpty() { final QueryTable table = testRefreshingTable(i(1).toTracking(), col("Sentinel", 1)); final Table m2 = TableTools.merge(table, table).updateView("Sentinel=Sentinel+1"); @@ -898,25 +914,28 @@ public void testMergeGetChunkEmpty() { final int numElements = 1024; final ColumnSource origCol = table.getColumnSource("Sentinel"); - final ColumnSource.GetContext origContext = origCol.makeGetContext(numElements); - final IntChunk origContent = usePrev - ? origCol.getPrevChunk(origContext, rowSet).asIntChunk() - : origCol.getChunk(origContext, rowSet).asIntChunk(); - - final ColumnSource resCol = result.getColumnSource("Sentinel"); - final ColumnSource.GetContext resContext = resCol.makeGetContext(numElements * 3); - final IntChunk resContent = usePrev - ? resCol.getPrevChunk(resContext, rowSet).asIntChunk() - : resCol.getChunk(resContext, rowSet).asIntChunk(); - - Assert.assertEquals(0, origContent.size()); - Assert.assertEquals(0, resContent.size()); + try (final ColumnSource.GetContext origContext = origCol.makeGetContext(numElements)) { + final IntChunk origContent = usePrev + ? origCol.getPrevChunk(origContext, rowSet).asIntChunk() + : origCol.getChunk(origContext, rowSet).asIntChunk(); + + final ColumnSource resCol = result.getColumnSource("Sentinel"); + try (final ColumnSource.GetContext resContext = resCol.makeGetContext(numElements * 3)) { + final IntChunk resContent = usePrev + ? resCol.getPrevChunk(resContext, rowSet).asIntChunk() + : resCol.getChunk(resContext, rowSet).asIntChunk(); + + Assert.assertEquals(0, origContent.size()); + Assert.assertEquals(0, resContent.size()); + } + } }; validate.accept(false); validate.accept(true); } + @Test public void testEmptyTable() { Table emptyTable = TableTools.emptyTable(2); TestCase.assertEquals(2, emptyTable.size()); @@ -940,6 +959,7 @@ public void testEmptyTable() { TableTools.show(emptyTable3); } + @Test public void testMergeIndexShiftingPerformance() { final QueryTable testRefreshingTable = TstUtils.testRefreshingTable(i(0).toTracking(), intCol("IntCol", 0), charCol("CharCol", 'a')); From 061d42f270317e2ef6e5a53624229e927e31d94d Mon Sep 17 00:00:00 2001 From: Nate Bauernfeind Date: Mon, 5 Jun 2023 15:03:14 -0600 Subject: [PATCH 6/6] SessionState: Hold Open ExecutionContext During Perf-log Invocations (#3935) --- .../server/session/SessionState.java | 102 +++++++++--------- 1 file changed, 52 insertions(+), 50 deletions(-) diff --git a/server/src/main/java/io/deephaven/server/session/SessionState.java b/server/src/main/java/io/deephaven/server/session/SessionState.java index b2e254ea20d..2dafcb236ed 100644 --- a/server/src/main/java/io/deephaven/server/session/SessionState.java +++ b/server/src/main/java/io/deephaven/server/session/SessionState.java @@ -885,61 +885,63 @@ private void doExport() { boolean shouldLog = false; int evaluationNumber = -1; QueryProcessingResults queryProcessingResults = null; - try (final SafeCloseable ignored1 = LivenessScopeStack.open(); - final SafeCloseable ignored2 = session.executionContext.open()) { - queryProcessingResults = new QueryProcessingResults( - QueryPerformanceRecorder.getInstance()); - - evaluationNumber = QueryPerformanceRecorder.getInstance() - .startQuery("session=" + session.sessionId + ",exportId=" + logIdentity); - try { - setResult(capturedExport.call()); - } finally { - shouldLog = QueryPerformanceRecorder.getInstance().endQuery(); - } - } catch (final Exception err) { - caughtException = err; - synchronized (this) { - if (!isExportStateTerminal(state)) { - assignErrorId(); - if (!(caughtException instanceof StatusRuntimeException)) { - log.error().append("Internal Error '").append(errorId).append("' ").append(err).endl(); + try (final SafeCloseable ignored1 = session.executionContext.open()) { + try (final SafeCloseable ignored2 = LivenessScopeStack.open()) { + queryProcessingResults = new QueryProcessingResults( + QueryPerformanceRecorder.getInstance()); + + evaluationNumber = QueryPerformanceRecorder.getInstance() + .startQuery("session=" + session.sessionId + ",exportId=" + logIdentity); + + try { + setResult(capturedExport.call()); + } finally { + shouldLog = QueryPerformanceRecorder.getInstance().endQuery(); + } + } catch (final Exception err) { + caughtException = err; + synchronized (this) { + if (!isExportStateTerminal(state)) { + assignErrorId(); + if (!(caughtException instanceof StatusRuntimeException)) { + log.error().append("Internal Error '").append(errorId).append("' ").append(err).endl(); + } + setState(ExportNotification.State.FAILED); } - setState(ExportNotification.State.FAILED); } - } - } finally { - if (caughtException != null && queryProcessingResults != null) { - queryProcessingResults.setException(caughtException.toString()); - } - QueryPerformanceRecorder.resetInstance(); - } - if ((shouldLog || caughtException != null) && queryProcessingResults != null) { - final EngineMetrics memLoggers = EngineMetrics.getInstance(); - final QueryPerformanceLogLogger qplLogger = memLoggers.getQplLogger(); - final QueryOperationPerformanceLogLogger qoplLogger = memLoggers.getQoplLogger(); - try { - final QueryPerformanceNugget nugget = Require.neqNull( - queryProcessingResults.getRecorder().getQueryLevelPerformanceData(), - "queryProcessingResults.getRecorder().getQueryLevelPerformanceData()"); - - // noinspection SynchronizationOnLocalVariableOrMethodParameter - synchronized (qplLogger) { - qplLogger.log(evaluationNumber, - queryProcessingResults, - nugget); + } finally { + if (caughtException != null && queryProcessingResults != null) { + queryProcessingResults.setException(caughtException.toString()); } - final List nuggets = - queryProcessingResults.getRecorder().getOperationLevelPerformanceData(); - // noinspection SynchronizationOnLocalVariableOrMethodParameter - synchronized (qoplLogger) { - int opNo = 0; - for (QueryPerformanceNugget n : nuggets) { - qoplLogger.log(opNo++, n); + QueryPerformanceRecorder.resetInstance(); + } + if ((shouldLog || caughtException != null) && queryProcessingResults != null) { + final EngineMetrics memLoggers = EngineMetrics.getInstance(); + final QueryPerformanceLogLogger qplLogger = memLoggers.getQplLogger(); + final QueryOperationPerformanceLogLogger qoplLogger = memLoggers.getQoplLogger(); + try { + final QueryPerformanceNugget nugget = Require.neqNull( + queryProcessingResults.getRecorder().getQueryLevelPerformanceData(), + "queryProcessingResults.getRecorder().getQueryLevelPerformanceData()"); + + // noinspection SynchronizationOnLocalVariableOrMethodParameter + synchronized (qplLogger) { + qplLogger.log(evaluationNumber, + queryProcessingResults, + nugget); + } + final List nuggets = + queryProcessingResults.getRecorder().getOperationLevelPerformanceData(); + // noinspection SynchronizationOnLocalVariableOrMethodParameter + synchronized (qoplLogger) { + int opNo = 0; + for (QueryPerformanceNugget n : nuggets) { + qoplLogger.log(opNo++, n); + } } + } catch (final Exception e) { + log.error().append("Failed to log query performance data: ").append(e).endl(); } - } catch (final Exception e) { - log.error().append("Failed to log query performance data: ").append(e).endl(); } } }