diff --git a/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java b/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java index c0dd642a4432b..76e58a5c6e801 100644 --- a/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java +++ b/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java @@ -299,8 +299,11 @@ public class GraphDatabaseSettings implements LoadableConfig Boolean.toString( Configuration.DEFAULT_LEGACY_STYLE_QUOTING ) ); @Description( "Enables or disables tracking of how much time a query spends actively executing on the CPU." ) + @Dynamic public static Setting track_query_cpu_time = setting( "dbms.track_query_cpu_time", BOOLEAN, TRUE ); + @Description( "Enables or disables tracking of how many bytes are allocated by the execution of a query." ) + @Dynamic public static Setting track_query_allocation = setting( "dbms.track_query_allocation", BOOLEAN, TRUE ); @Description( "The size of the morsels" ) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/NeoStoreDataSource.java b/community/kernel/src/main/java/org/neo4j/kernel/NeoStoreDataSource.java index 2f79ca6d51bfa..a2cfd267198fd 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/NeoStoreDataSource.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/NeoStoreDataSource.java @@ -25,7 +25,9 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.LockSupport; +import java.util.function.BiConsumer; import java.util.function.Supplier; import org.neo4j.graphdb.DependencyResolver; @@ -33,6 +35,7 @@ import org.neo4j.graphdb.config.Setting; import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.helpers.Exceptions; +import org.neo4j.helpers.Reference; import org.neo4j.index.internal.gbptree.RecoveryCleanupWorkCollector; import org.neo4j.internal.kernel.api.TokenNameLookup; import org.neo4j.internal.kernel.api.exceptions.KernelException; @@ -643,16 +646,8 @@ private NeoStoreKernelModule buildKernel( LogFiles logFiles, TransactionAppender StorageEngine storageEngine, IndexConfigStore indexConfigStore, TransactionIdStore transactionIdStore, AvailabilityGuard availabilityGuard, SystemNanoClock clock, PropertyAccessor propertyAccessor ) throws KernelException, IOException { - CpuClock cpuClock = CpuClock.NOT_AVAILABLE; - if ( config.get( GraphDatabaseSettings.track_query_cpu_time ) ) - { - cpuClock = CpuClock.CPU_CLOCK; - } - HeapAllocation heapAllocation = HeapAllocation.NOT_AVAILABLE; - if ( config.get( GraphDatabaseSettings.track_query_allocation ) ) - { - heapAllocation = HeapAllocation.HEAP_ALLOCATION; - } + AtomicReference cpuClockRef = setupCpuClockAtomicReference(); + AtomicReference heapAllocationRef = setupHeapAllocationAtomicReference(); TransactionCommitProcess transactionCommitProcess = commitProcessFactory.create( appender, storageEngine, config ); @@ -671,14 +666,14 @@ private NeoStoreKernelModule buildKernel( LogFiles logFiles, TransactionAppender StatementOperationParts statementOperationParts = dependencies.satisfyDependency( buildStatementOperations( storeLayer, autoIndexing, - constraintIndexCreator, databaseSchemaState, explicitIndexStore, cpuClock, heapAllocation ) ); + constraintIndexCreator, databaseSchemaState, explicitIndexStore, cpuClockRef, heapAllocationRef ) ); TransactionHooks hooks = new TransactionHooks(); KernelTransactions kernelTransactions = life.add( new KernelTransactions( statementLocksFactory, constraintIndexCreator, statementOperationParts, schemaWriteGuard, transactionHeaderInformationFactory, transactionCommitProcess, indexConfigStore, explicitIndexProviderLookup, hooks, transactionMonitor, availabilityGuard, tracers, storageEngine, procedures, transactionIdStore, clock, - cpuClock, heapAllocation, accessCapability, new Cursors(), autoIndexing, explicitIndexStore ) ); + cpuClockRef, heapAllocationRef, accessCapability, new Cursors(), autoIndexing, explicitIndexStore ) ); buildTransactionMonitor( kernelTransactions, clock, config ); @@ -694,6 +689,50 @@ private NeoStoreKernelModule buildKernel( LogFiles logFiles, TransactionAppender return new NeoStoreKernelModule( transactionCommitProcess, kernel, kernelTransactions, fileListing ); } + private AtomicReference setupCpuClockAtomicReference() + { + AtomicReference cpuClock = new AtomicReference<>( CpuClock.NOT_AVAILABLE ); + if ( config.get( GraphDatabaseSettings.track_query_cpu_time ) ) + { + cpuClock.set( CpuClock.CPU_CLOCK ); + } + BiConsumer cpuClockUpdater = ( before, after ) -> + { + if ( after ) + { + cpuClock.set( CpuClock.CPU_CLOCK ); + } + else + { + cpuClock.set( CpuClock.NOT_AVAILABLE ); + } + }; + config.registerDynamicUpdateListener( GraphDatabaseSettings.track_query_cpu_time, cpuClockUpdater ); + return cpuClock; + } + + private AtomicReference setupHeapAllocationAtomicReference() + { + AtomicReference heapAllocation = new AtomicReference<>( HeapAllocation.NOT_AVAILABLE ); + if ( config.get( GraphDatabaseSettings.track_query_allocation ) ) + { + heapAllocation.set( HeapAllocation.HEAP_ALLOCATION ); + } + BiConsumer heapAllocationUpdater = ( before, after ) -> + { + if ( after ) + { + heapAllocation.set( HeapAllocation.HEAP_ALLOCATION ); + } + else + { + heapAllocation.set( HeapAllocation.NOT_AVAILABLE ); + } + }; + config.registerDynamicUpdateListener( GraphDatabaseSettings.track_query_allocation, heapAllocationUpdater ); + return heapAllocation; + } + private void buildTransactionMonitor( KernelTransactions kernelTransactions, Clock clock, Config config ) { KernelTransactionTimeoutMonitor kernelTransactionTimeoutMonitor = @@ -801,7 +840,7 @@ public DependencyResolver getDependencyResolver() private StatementOperationParts buildStatementOperations( StoreReadLayer storeReadLayer, AutoIndexing autoIndexing, ConstraintIndexCreator constraintIndexCreator, DatabaseSchemaState databaseSchemaState, - ExplicitIndexStore explicitIndexStore, CpuClock cpuClock, HeapAllocation heapAllocation ) + ExplicitIndexStore explicitIndexStore, AtomicReference cpuClockRef, AtomicReference heapAllocationRef ) { // The passed in StoreReadLayer is the bottom most layer: Read-access to committed data. // To it we add: @@ -810,7 +849,7 @@ private StatementOperationParts buildStatementOperations( StoreReadLayer storeRe autoIndexing, constraintIndexCreator, explicitIndexStore ); QueryRegistrationOperations queryRegistrationOperations = - new StackingQueryRegistrationOperations( clock, cpuClock, heapAllocation ); + new StackingQueryRegistrationOperations( clock, cpuClockRef, heapAllocationRef ); StatementOperationParts parts = new StatementOperationParts( stateHandlingContext, stateHandlingContext, stateHandlingContext, stateHandlingContext, stateHandlingContext, stateHandlingContext, diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactionImplementation.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactionImplementation.java index 852d3150848e9..3263f8c99a0ef 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactionImplementation.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactionImplementation.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Supplier; @@ -176,7 +177,7 @@ public KernelTransactionImplementation( StatementOperationParts statementOperati TransactionHooks hooks, ConstraintIndexCreator constraintIndexCreator, Procedures procedures, TransactionHeaderInformationFactory headerInformationFactory, TransactionCommitProcess commitProcess, TransactionMonitor transactionMonitor, Supplier explicitIndexTxStateSupplier, - Pool pool, Clock clock, CpuClock cpuClock, HeapAllocation heapAllocation, + Pool pool, Clock clock, AtomicReference cpuClockRef, AtomicReference heapAllocationRef, TransactionTracer transactionTracer, LockTracer lockTracer, PageCursorTracerSupplier cursorTracerSupplier, StorageEngine storageEngine, AccessCapability accessCapability, Cursors cursors, AutoIndexing autoIndexing, ExplicitIndexStore explicitIndexStore ) @@ -199,7 +200,7 @@ public KernelTransactionImplementation( StatementOperationParts statementOperati this.currentStatement = new KernelStatement( this, this, storageStatement, procedures, accessCapability, lockTracer, statementOperations ); this.accessCapability = accessCapability; - this.statistics = new Statistics( this, cpuClock, heapAllocation ); + this.statistics = new Statistics( this, cpuClockRef, heapAllocationRef ); this.userMetaData = new HashMap<>(); AllStoreHolder allStoreHolder = new AllStoreHolder( storageEngine, storageStatement, this, cursors, explicitIndexStore ); @@ -956,20 +957,25 @@ public static class Statistics private volatile long heapAllocatedBytesWhenQueryStarted; private volatile long waitingTimeNanos; private volatile long transactionThreadId; - private final KernelTransactionImplementation transaction; - private final CpuClock cpuClock; - private final HeapAllocation heapAllocation; private volatile PageCursorTracer pageCursorTracer = PageCursorTracer.NULL; + private final KernelTransactionImplementation transaction; + private final AtomicReference cpuClockRef; + private final AtomicReference heapAllocationRef; + private CpuClock cpuClock; + private HeapAllocation heapAllocation; - public Statistics( KernelTransactionImplementation transaction, CpuClock cpuClock, HeapAllocation heapAllocation ) + public Statistics( KernelTransactionImplementation transaction, AtomicReference cpuClockRef, + AtomicReference heapAllocationRef ) { this.transaction = transaction; - this.cpuClock = cpuClock; - this.heapAllocation = heapAllocation; + this.cpuClockRef = cpuClockRef; + this.heapAllocationRef = heapAllocationRef; } - void init( long threadId, PageCursorTracer pageCursorTracer ) + protected void init( long threadId, PageCursorTracer pageCursorTracer ) { + this.cpuClock = cpuClockRef.get(); + this.heapAllocation = heapAllocationRef.get(); this.transactionThreadId = threadId; this.pageCursorTracer = pageCursorTracer; this.cpuTimeNanosWhenQueryStarted = cpuClock.cpuTimeNanos( transactionThreadId ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactions.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactions.java index ca61e42b4ad8e..6d2b6d77b6b8a 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactions.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactions.java @@ -22,6 +22,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Supplier; @@ -45,7 +46,6 @@ import org.neo4j.kernel.impl.locking.StatementLocks; import org.neo4j.kernel.impl.locking.StatementLocksFactory; import org.neo4j.kernel.impl.newapi.Cursors; -import org.neo4j.kernel.impl.newapi.KernelToken; import org.neo4j.kernel.impl.proc.Procedures; import org.neo4j.kernel.impl.store.TransactionId; import org.neo4j.kernel.impl.transaction.TransactionHeaderInformationFactory; @@ -85,8 +85,8 @@ public class KernelTransactions extends LifecycleAdapter implements Supplier cpuClockRef; + private final AtomicReference heapAllocationRef; private final AccessCapability accessCapability; private final Supplier explicitIndexTxStateSupplier; private final SystemNanoClock clock; @@ -132,7 +132,7 @@ public KernelTransactions( StatementLocksFactory statementLocksFactory, TransactionMonitor transactionMonitor, AvailabilityGuard availabilityGuard, Tracers tracers, StorageEngine storageEngine, Procedures procedures, TransactionIdStore transactionIdStore, SystemNanoClock clock, - CpuClock cpuClock, HeapAllocation heapAllocation, AccessCapability accessCapability, Cursors cursors, + AtomicReference cpuClockRef, AtomicReference heapAllocationRef, AccessCapability accessCapability, Cursors cursors, AutoIndexing autoIndexing, ExplicitIndexStore explicitIndexStore ) { @@ -149,8 +149,8 @@ public KernelTransactions( StatementLocksFactory statementLocksFactory, this.storageEngine = storageEngine; this.procedures = procedures; this.transactionIdStore = transactionIdStore; - this.cpuClock = cpuClock; - this.heapAllocation = heapAllocation; + this.cpuClockRef = cpuClockRef; + this.heapAllocationRef = heapAllocationRef; this.accessCapability = accessCapability; this.autoIndexing = autoIndexing; this.explicitIndexStore = explicitIndexStore; @@ -345,7 +345,7 @@ public KernelTransactionImplementation newInstance() new KernelTransactionImplementation( statementOperations, schemaWriteGuard, hooks, constraintIndexCreator, procedures, transactionHeaderInformationFactory, transactionCommitProcess, transactionMonitor, explicitIndexTxStateSupplier, localTxPool, - clock, cpuClock, heapAllocation, tracers.transactionTracer, tracers.lockTracer, + clock, cpuClockRef, heapAllocationRef, tracers.transactionTracer, tracers.lockTracer, tracers.pageCursorTracerSupplier, storageEngine, accessCapability, cursors, autoIndexing, explicitIndexStore ); this.transactions.add( tx ); return tx; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StackingQueryRegistrationOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StackingQueryRegistrationOperations.java index 8053aa2373130..338c9b88e7751 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StackingQueryRegistrationOperations.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StackingQueryRegistrationOperations.java @@ -19,6 +19,7 @@ */ package org.neo4j.kernel.impl.api; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; import org.neo4j.kernel.api.query.ExecutingQuery; @@ -34,17 +35,17 @@ public class StackingQueryRegistrationOperations implements QueryRegistrationOpe { private final MonotonicCounter lastQueryId = MonotonicCounter.newAtomicMonotonicCounter(); private final SystemNanoClock clock; - private final CpuClock cpuClock; - private final HeapAllocation heapAllocation; + private final AtomicReference cpuClockRef; + private final AtomicReference heapAllocationRef; public StackingQueryRegistrationOperations( SystemNanoClock clock, - CpuClock cpuClock, - HeapAllocation heapAllocation ) + AtomicReference cpuClockRef, + AtomicReference heapAllocationRef ) { this.clock = clock; - this.cpuClock = cpuClock; - this.heapAllocation = heapAllocation; + this.cpuClockRef = cpuClockRef; + this.heapAllocationRef = heapAllocationRef; } @Override @@ -75,7 +76,7 @@ public ExecutingQuery startQueryExecution( new ExecutingQuery( queryId, clientConnection, statement.username(), queryText, queryParameters, statement.getTransaction().getMetaData(), () -> statement.locks().activeLockCount(), statement.getPageCursorTracer(), - threadId, threadName, clock, cpuClock, heapAllocation ); + threadId, threadName, clock, cpuClockRef.get(), heapAllocationRef.get() ); registerExecutingQuery( statement, executingQuery ); return executingQuery; } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/api/KernelTransactionFactory.java b/community/kernel/src/test/java/org/neo4j/kernel/api/KernelTransactionFactory.java index 05d11b7ef2915..a9cdb84f39a14 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/api/KernelTransactionFactory.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/api/KernelTransactionFactory.java @@ -19,6 +19,7 @@ */ package org.neo4j.kernel.api; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import org.neo4j.collection.pool.Pool; @@ -96,7 +97,7 @@ static Instances kernelTransactionWithInternals( SecurityContext securityContext mock( TransactionRepresentationCommitProcess.class ), mock( TransactionMonitor.class ), mock( Supplier.class ), mock( Pool.class ), - Clocks.systemClock(), CpuClock.NOT_AVAILABLE, HeapAllocation.NOT_AVAILABLE, NULL, + Clocks.systemClock(), new AtomicReference<>( CpuClock.NOT_AVAILABLE ), new AtomicReference<>( HeapAllocation.NOT_AVAILABLE ), NULL, LockTracer.NONE, PageCursorTracerSupplier.NULL, storageEngine, new CanWrite(), new Cursors(), AutoIndexing.UNSUPPORTED, mock( diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelStatementTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelStatementTest.java index 65d0c96ba7bac..d9d2ca9f86a81 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelStatementTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelStatementTest.java @@ -22,6 +22,7 @@ import org.junit.Test; import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; import org.neo4j.graphdb.NotInTransactionException; import org.neo4j.graphdb.TransactionTerminatedException; @@ -106,7 +107,7 @@ public void reportQueryWaitingTimeToTransactionStatisticWhenFinishQueryExecution Procedures procedures = mock( Procedures.class ); KernelTransactionImplementation.Statistics statistics = new KernelTransactionImplementation.Statistics( transaction, - CpuClock.NOT_AVAILABLE, HeapAllocation.NOT_AVAILABLE ); + new AtomicReference<>( CpuClock.NOT_AVAILABLE ), new AtomicReference<>( HeapAllocation.NOT_AVAILABLE ) ); when( transaction.getStatistics() ).thenReturn( statistics ); when( transaction.executingQueries() ).thenReturn( ExecutingQueryList.EMPTY ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionImplementationTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionImplementationTest.java index b7c8bba80de0c..78e677ff37864 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionImplementationTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionImplementationTest.java @@ -31,6 +31,7 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import org.neo4j.graphdb.TransactionTerminatedException; @@ -721,8 +722,8 @@ public void reportTransactionStatistics() { KernelTransactionImplementation transaction = newTransaction( 100 ); KernelTransactionImplementation.Statistics statistics = - new KernelTransactionImplementation.Statistics( transaction, new ThreadBasedCpuClock(), - new ThreadBasedAllocation() ); + new KernelTransactionImplementation.Statistics( transaction, new AtomicReference<>( new ThreadBasedCpuClock() ), + new AtomicReference<>( new ThreadBasedAllocation() ) ); PredictablePageCursorTracer tracer = new PredictablePageCursorTracer(); statistics.init( 2, tracer ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionTerminationTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionTerminationTest.java index 5b23fe35325a3..6725df44beafc 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionTerminationTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionTerminationTest.java @@ -26,6 +26,7 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import org.neo4j.collection.pool.Pool; @@ -339,7 +340,8 @@ private static class TestKernelTransaction extends KernelTransactionImplementati super( mock( StatementOperationParts.class ), mock( SchemaWriteGuard.class ), new TransactionHooks(), mock( ConstraintIndexCreator.class ), new Procedures(), TransactionHeaderInformationFactory.DEFAULT, mock( TransactionCommitProcess.class ), monitor, () -> mock( ExplicitIndexTransactionState.class ), - mock( Pool.class ), Clocks.fakeClock(), CpuClock.NOT_AVAILABLE, HeapAllocation.NOT_AVAILABLE, + mock( Pool.class ), Clocks.fakeClock(), + new AtomicReference<>( CpuClock.NOT_AVAILABLE ), new AtomicReference<>( HeapAllocation.NOT_AVAILABLE ), TransactionTracer.NULL, LockTracer.NONE, PageCursorTracerSupplier.NULL, mock( StorageEngine.class, RETURNS_MOCKS ), new CanWrite(), mock( Cursors.class ), diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionTestBase.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionTestBase.java index ab050cca768af..b100cdc78243c 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionTestBase.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionTestBase.java @@ -22,6 +22,7 @@ import org.junit.Before; import java.util.Collection; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import org.neo4j.collection.pool.Pool; @@ -147,12 +148,10 @@ public KernelTransactionImplementation newTransaction( long lastTransactionIdWhe public KernelTransactionImplementation newNotInitializedTransaction() { - return new KernelTransactionImplementation( statementOperations, schemaWriteGuard, - hooks, null, null, headerInformationFactory, commitProcess, transactionMonitor, - explicitIndexStateSupplier, txPool, clock, CpuClock.NOT_AVAILABLE, HeapAllocation.NOT_AVAILABLE, - TransactionTracer.NULL, LockTracer.NONE, - PageCursorTracerSupplier.NULL, storageEngine, new CanWrite(), new Cursors(), AutoIndexing.UNSUPPORTED, mock( - ExplicitIndexStore.class) ); + return new KernelTransactionImplementation( statementOperations, schemaWriteGuard, hooks, null, null, headerInformationFactory, commitProcess, + transactionMonitor, explicitIndexStateSupplier, txPool, clock, new AtomicReference<>( CpuClock.NOT_AVAILABLE ), + new AtomicReference<>( HeapAllocation.NOT_AVAILABLE ), TransactionTracer.NULL, LockTracer.NONE, PageCursorTracerSupplier.NULL, storageEngine, + new CanWrite(), new Cursors(), AutoIndexing.UNSUPPORTED, mock( ExplicitIndexStore.class ) ); } public class CapturingCommitProcess implements TransactionCommitProcess diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionsTest.java index ed94181b6155c..09fbc4330b531 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionsTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTransactionsTest.java @@ -30,6 +30,7 @@ import java.util.concurrent.Future; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReferenceArray; import org.neo4j.graphdb.DatabaseShutdownException; @@ -584,13 +585,10 @@ private static KernelTransactions createTransactions( StorageEngine storageEngin StatementLocksFactory statementLocksFactory, StatementOperationParts statementOperations, SystemNanoClock clock, AvailabilityGuard availabilityGuard ) { - return new KernelTransactions( statementLocksFactory, - null, statementOperations, null, DEFAULT, - commitProcess, null, null, new TransactionHooks(), mock( TransactionMonitor.class ), - availabilityGuard, - tracers, storageEngine, new Procedures(), transactionIdStore, clock, CpuClock.NOT_AVAILABLE, - HeapAllocation.NOT_AVAILABLE, new CanWrite(), new Cursors(), AutoIndexing.UNSUPPORTED, mock( - ExplicitIndexStore.class) ); + return new KernelTransactions( statementLocksFactory, null, statementOperations, null, DEFAULT, commitProcess, null, null, new TransactionHooks(), + mock( TransactionMonitor.class ), availabilityGuard, tracers, storageEngine, new Procedures(), transactionIdStore, clock, + new AtomicReference<>( CpuClock.NOT_AVAILABLE ), new AtomicReference<>( HeapAllocation.NOT_AVAILABLE ), new CanWrite(), new Cursors(), + AutoIndexing.UNSUPPORTED, mock( ExplicitIndexStore.class ) ); } private static TestKernelTransactions createTestTransactions( StorageEngine storageEngine, @@ -653,11 +651,10 @@ private static class TestKernelTransactions extends KernelTransactions StorageEngine storageEngine, Procedures procedures, TransactionIdStore transactionIdStore, SystemNanoClock clock, AccessCapability accessCapability, Cursors cursors, AutoIndexing autoIndexing ) { - super( statementLocksFactory, constraintIndexCreator, statementOperations, schemaWriteGuard, - txHeaderFactory, transactionCommitProcess, indexConfigStore, explicitIndexProviderLookup, hooks, - transactionMonitor, availabilityGuard, tracers, storageEngine, procedures, transactionIdStore, - clock, CpuClock.NOT_AVAILABLE, HeapAllocation.NOT_AVAILABLE, accessCapability, cursors, - autoIndexing, mock( ExplicitIndexStore.class) ); + super( statementLocksFactory, constraintIndexCreator, statementOperations, schemaWriteGuard, txHeaderFactory, transactionCommitProcess, + indexConfigStore, explicitIndexProviderLookup, hooks, transactionMonitor, availabilityGuard, tracers, storageEngine, procedures, + transactionIdStore, clock, new AtomicReference<>( CpuClock.NOT_AVAILABLE ), new AtomicReference<>( HeapAllocation.NOT_AVAILABLE ), + accessCapability, cursors, autoIndexing, mock( ExplicitIndexStore.class ) ); } @Override diff --git a/enterprise/kernel/src/test/java/org/neo4j/kernel/enterprise/builtinprocs/ListQueriesProcedureTest.java b/enterprise/kernel/src/test/java/org/neo4j/kernel/enterprise/builtinprocs/ListQueriesProcedureTest.java index 1ab9e2348c10b..0cc82921c936a 100644 --- a/enterprise/kernel/src/test/java/org/neo4j/kernel/enterprise/builtinprocs/ListQueriesProcedureTest.java +++ b/enterprise/kernel/src/test/java/org/neo4j/kernel/enterprise/builtinprocs/ListQueriesProcedureTest.java @@ -57,6 +57,7 @@ import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -360,6 +361,40 @@ public void shouldDisableCpuTimeTracking() throws Exception assertThat( data, hasEntry( equalTo( "cpuTimeMillis" ), nullValue() ) ); } + @Test + public void cpuTimeTrackingShouldBeADynamicSetting() throws Exception + { + // given + String query = "MATCH (n) SET n.v = n.v + 1"; + Map data; + + // when + try ( Resource test = test( db::createNode, query ) ) + { + data = getQueryListing( query ); + } + // then + assertThat( data, hasEntry( equalTo( "cpuTimeMillis" ), notNullValue() ) ); + + // when + db.execute( "call dbms.setConfigValue('" + track_query_cpu_time.name() + "', 'false')" ); + try ( Resource test = test( db::createNode, query ) ) + { + data = getQueryListing( query ); + } + // then + assertThat( data, hasEntry( equalTo( "cpuTimeMillis" ), nullValue() ) ); + + // when + db.execute( "call dbms.setConfigValue('" + track_query_cpu_time.name() + "', 'true')" ); + try ( Resource test = test( db::createNode, query ) ) + { + data = getQueryListing( query ); + } + // then + assertThat( data, hasEntry( equalTo( "cpuTimeMillis" ), notNullValue() ) ); + } + @Test public void shouldDisableHeapAllocationTracking() throws Exception { @@ -378,6 +413,40 @@ public void shouldDisableHeapAllocationTracking() throws Exception assertThat( data, hasEntry( equalTo( "allocatedBytes" ), nullValue() ) ); } + @Test + public void heapAllocationTrackingShouldBeADynamicSetting() throws Exception + { + // given + String query = "MATCH (n) SET n.v = n.v + 1"; + Map data; + + // when + try ( Resource test = test( db::createNode, query ) ) + { + data = getQueryListing( query ); + } + // then + assertThat( data, hasEntry( equalTo( "allocatedBytes" ), notNullValue() ) ); + + // when + db.execute( "call dbms.setConfigValue('" + track_query_allocation.name() + "', 'false')" ); + try ( Resource test = test( db::createNode, query ) ) + { + data = getQueryListing( query ); + } + // then + assertThat( data, hasEntry( equalTo( "allocatedBytes" ), nullValue() ) ); + + // when + db.execute( "call dbms.setConfigValue('" + track_query_allocation.name() + "', 'true')" ); + try ( Resource test = test( db::createNode, query ) ) + { + data = getQueryListing( query ); + } + // then + assertThat( data, hasEntry( equalTo( "allocatedBytes" ), notNullValue() ) ); + } + private void shouldListUsedIndexes( String label, String property ) throws Exception { // given diff --git a/enterprise/kernel/src/test/java/org/neo4j/kernel/enterprise/builtinprocs/TransactionStatusResultTest.java b/enterprise/kernel/src/test/java/org/neo4j/kernel/enterprise/builtinprocs/TransactionStatusResultTest.java index 818f5b2b3e5ba..af3d659be3726 100644 --- a/enterprise/kernel/src/test/java/org/neo4j/kernel/enterprise/builtinprocs/TransactionStatusResultTest.java +++ b/enterprise/kernel/src/test/java/org/neo4j/kernel/enterprise/builtinprocs/TransactionStatusResultTest.java @@ -25,9 +25,9 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; -import org.neo4j.internal.kernel.api.security.SecurityContext; import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer; import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.KernelTransactionHandle; @@ -111,7 +111,7 @@ private void checkTransactionStatusWithoutQueries( TransactionStatusResult statu assertEquals( Long.valueOf( 1L ), statusResult.cpuTimeMillis ); assertEquals( 0L, statusResult.waitTimeMillis ); assertEquals( Long.valueOf( 1809 ), statusResult.idleTimeMillis ); - assertEquals( Long.valueOf( 0 ), statusResult.allocatedBytes ); + assertEquals( Long.valueOf( 1 ), statusResult.allocatedBytes ); assertEquals( 0L, statusResult.pageHits ); assertEquals( 0L, statusResult.pageFaults ); } @@ -135,7 +135,7 @@ private void checkTransactionStatus( TransactionStatusResult statusResult, Strin assertEquals( Long.valueOf( 1 ), statusResult.cpuTimeMillis ); assertEquals( 0L, statusResult.waitTimeMillis ); assertEquals( Long.valueOf( 1809 ), statusResult.idleTimeMillis ); - assertEquals( Long.valueOf( 0 ), statusResult.allocatedBytes ); + assertEquals( Long.valueOf( 1 ), statusResult.allocatedBytes ); assertEquals( 0, statusResult.pageHits ); assertEquals( 0, statusResult.pageFaults ); } @@ -178,15 +178,32 @@ public Stream activeLocks() public TransactionExecutionStatistic transactionStatistic() { KernelTransactionImplementation transaction = mock( KernelTransactionImplementation.class ); - KernelTransactionImplementation.Statistics statistics = - new KernelTransactionImplementation.Statistics( transaction, new CountingCpuClock(), new CountingHeapAllocation() ); - when( transaction.getStatistics() ).thenReturn( - statistics ); + TestStatistics statistics = + new TestStatistics( transaction, new AtomicReference<>( new CountingCpuClock() ), + new AtomicReference<>( new CountingHeapAllocation() ) ); + statistics.init( Thread.currentThread().getId(), PageCursorTracer.NULL ); + when( transaction.getStatistics() ).thenReturn( statistics ); return new TransactionExecutionStatistic( transaction, Clocks.fakeClock().forward( 2010, MILLISECONDS ), 200 ); } } + private static class TestStatistics extends KernelTransactionImplementation.Statistics + { + @Override + protected void init( long threadId, PageCursorTracer pageCursorTracer ) + { + super.init( threadId, pageCursorTracer ); + } + + TestStatistics( KernelTransactionImplementation transaction, AtomicReference cpuClockRef, + AtomicReference heapAllocationRef ) + { + super( transaction, cpuClockRef, heapAllocationRef ); + + } + } + private static class CountingSystemNanoClock extends SystemNanoClock { private long time;