This is an automated email from the ASF dual-hosted git repository.

clebertsuconic pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git

commit b4230c62bf178497d94d7e81471470c9c51871a4
Author: Domenico Francesco Bruscino <brus...@apache.org>
AuthorDate: Sat Jun 24 09:41:16 2023 +0200

    ARTEMIS-4332 Add store operation trackers
---
 .../impl/journal/OperationContextImpl.java         | 36 +++++++++++++++++--
 .../impl/journal/OperationContextUnitTest.java     | 41 ++++++++++++++++++++++
 2 files changed, 75 insertions(+), 2 deletions(-)

diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/OperationContextImpl.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/OperationContextImpl.java
index ceb402809c..0a17c8d2d8 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/OperationContextImpl.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/OperationContextImpl.java
@@ -28,6 +28,9 @@ import 
org.apache.activemq.artemis.core.journal.impl.SimpleWaitIOCallback;
 import org.apache.activemq.artemis.core.persistence.OperationContext;
 import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
 import org.apache.activemq.artemis.utils.ExecutorFactory;
+import org.apache.commons.collections.Buffer;
+import org.apache.commons.collections.BufferUtils;
+import org.apache.commons.collections.buffer.CircularFifoBuffer;
 
 /**
  * Each instance of OperationContextImpl is associated with an executor 
(usually an ordered Executor).
@@ -38,6 +41,9 @@ import org.apache.activemq.artemis.utils.ExecutorFactory;
  * If there are no pending IO operations, the tasks are just executed at the 
callers thread without any context switch.
  *
  * So, if you are doing operations that are not dependent on IO (e.g 
NonPersistentMessages) you wouldn't have any context switch.
+ *
+ * If you need to track store operations you can set the system property 
"ARTEMIS_OPCONTEXT_MAX_DEBUG_TRACKERS"
+ * with the max number of trackers that you want to keep in memory.
  */
 public class OperationContextImpl implements OperationContext {
 
@@ -104,6 +110,24 @@ public class OperationContextImpl implements 
OperationContext {
 
    private final Executor executor;
 
+   private static int maxDebugTrackers = Integer.parseInt(
+      System.getProperty("ARTEMIS_OPCONTEXT_MAX_DEBUG_TRACKERS", "0"));
+
+   private Buffer debugTrackers = OperationContextImpl.maxDebugTrackers > 0 ?
+      BufferUtils.synchronizedBuffer(new 
CircularFifoBuffer(OperationContextImpl.maxDebugTrackers)) : null;
+
+   protected static int getMaxDebugTrackers() {
+      return OperationContextImpl.maxDebugTrackers;
+   }
+
+   protected static void setMaxDebugTrackers(int maxDebugTrackers) {
+      OperationContextImpl.maxDebugTrackers = maxDebugTrackers;
+   }
+
+   protected Buffer getDebugTrackers() {
+      return debugTrackers;
+   }
+
    public OperationContextImpl(final Executor executor) {
       super();
       this.executor = executor;
@@ -122,7 +146,10 @@ public class OperationContextImpl implements 
OperationContext {
 
    @Override
    public void storeLineUp() {
-      STORE_LINEUP_UPDATER.incrementAndGet(this);
+      long storeLineUpValue = STORE_LINEUP_UPDATER.incrementAndGet(this);
+      if (debugTrackers != null) {
+         debugTrackers.add(new Exception(">" + storeLineUpValue));
+      }
    }
 
    @Override
@@ -216,7 +243,12 @@ public class OperationContextImpl implements 
OperationContext {
 
    @Override
    public synchronized void done() {
-      stored++;
+      this.stored++;
+
+      if (debugTrackers != null) {
+         debugTrackers.add(new Exception("<" + stored));
+      }
+
       checkTasks();
    }
 
diff --git 
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/persistence/impl/journal/OperationContextUnitTest.java
 
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/persistence/impl/journal/OperationContextUnitTest.java
index 997d8808be..6e95d6a3b3 100644
--- 
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/persistence/impl/journal/OperationContextUnitTest.java
+++ 
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/persistence/impl/journal/OperationContextUnitTest.java
@@ -422,4 +422,45 @@ public class OperationContextUnitTest extends 
ActiveMQTestBase {
       Assert.assertEquals(0, operations.get());
    }
 
+   @Test
+   public void testContextWithoutDebugTrackers() {
+      ExecutorService executor = 
Executors.newSingleThreadExecutor(ActiveMQThreadFactory.defaultThreadFactory(getClass().getName()));
+      runAfter(executor::shutdownNow);
+
+      Assert.assertEquals(0, OperationContextImpl.getMaxDebugTrackers());
+      OperationContextImpl context = new OperationContextImpl(executor);
+      Assert.assertNull(context.getDebugTrackers());
+
+      context.storeLineUp();
+      Assert.assertNull(context.getDebugTrackers());
+
+      context.done();
+      Assert.assertNull(context.getDebugTrackers());
+   }
+
+   @Test
+   public void testContextWithDebugTrackers() {
+      int maxStoreOperationTrackers = 
OperationContextImpl.getMaxDebugTrackers();
+      ExecutorService executor = 
Executors.newSingleThreadExecutor(ActiveMQThreadFactory.defaultThreadFactory(getClass().getName()));
+      runAfter(executor::shutdownNow);
+
+      OperationContextImpl.setMaxDebugTrackers(1);
+      try {
+         Assert.assertEquals(1, OperationContextImpl.getMaxDebugTrackers());
+         OperationContextImpl context = new OperationContextImpl(executor);
+         Assert.assertNotNull(context.getDebugTrackers());
+
+         context.storeLineUp();
+         Assert.assertEquals(1, context.getDebugTrackers().size());
+         Assert.assertEquals("storeLineUp", 
((Exception)context.getDebugTrackers().get()).getStackTrace()[0].getMethodName());
+         Assert.assertEquals("testContextWithDebugTrackers", 
((Exception)context.getDebugTrackers().get()).getStackTrace()[1].getMethodName());
+
+         context.done();
+         Assert.assertEquals(1, context.getDebugTrackers().size());
+         Assert.assertEquals("done", 
((Exception)context.getDebugTrackers().get()).getStackTrace()[0].getMethodName());
+         Assert.assertEquals("testContextWithDebugTrackers", 
((Exception)context.getDebugTrackers().get()).getStackTrace()[1].getMethodName());
+      } finally {
+         OperationContextImpl.setMaxDebugTrackers(maxStoreOperationTrackers);
+      }
+   }
 }

Reply via email to