gemmellr commented on code in PR #4029:
URL: https://github.com/apache/activemq-artemis/pull/4029#discussion_r850314227


##########
artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java:
##########
@@ -1846,43 +1844,47 @@ private final class ExpiryReaper extends 
ActiveMQScheduledComponent {
          super(scheduledExecutorService, executor, checkPeriod, timeUnit, 
onDemand);
       }
 
-      volatile CountDownLatch inUseLatch;
+      volatile Iterator<Queue> iterator;

Review Comment:
   Can it be private? Does it actually need to be volatile? If so that suggests 
multiple threads setting/using it, in which case the rest of the usage probably 
isnt safe (see later comment).



##########
artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueImpl.java:
##########
@@ -2434,13 +2430,13 @@ public void run() {
                   }
                   if (++elementsIterated >= MAX_DELIVERIES_IN_LOOP) {
                      logger.debug("Breaking loop of expiring");
-                     scannerRunning.incrementAndGet();
+                     rescheduled = true;

Review Comment:
   Relating to the line above this one, rather than this line...
   
   Rather than just logging _"Breaking loop of expiring"_ it might be nice to 
note the queue name as the completion message does, and mention it is 
rescheduling.



##########
artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java:
##########
@@ -1846,43 +1844,47 @@ private final class ExpiryReaper extends 
ActiveMQScheduledComponent {
          super(scheduledExecutorService, executor, checkPeriod, timeUnit, 
onDemand);
       }
 
-      volatile CountDownLatch inUseLatch;
+      volatile Iterator<Queue> iterator;
 
 
       @Override
       public void stop() {
          super.stop();
          // this will do a best effort to stop the current latch.
          // no big deal if it failed. this is just to optimize this component 
stop.
-         CountDownLatch latch = inUseLatch;
-         if (latch != null) {
-            latch.countDown();
-         }

Review Comment:
   There is a 2 line comment left above this, which appears to be about this 
code, so it should be removed too.
   
   In fact the whole method can seemingly be removed, all it does now is call 
the super.
   EDIT: or, could/should stop() be clearing the iterator as well rather than 
just relying on 'moveNext()' to do so later?



##########
artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/QueueImpl.java:
##########
@@ -2454,10 +2450,10 @@ public void run() {
 
                   if (doneCallback != null) {
                      doneCallback.run();
-                     doneCallback = null;
                   }
                }
 
+

Review Comment:
   Empty line addition seems unecessary...but helpful to refer to the existing 
log message below it.
   The _"Scanning for expires on " + QueueImpl.this.getName() + " done"_ 
message doesnt line up with when it calls the _doneCallback_, as it would be 
logged every time through, even after the rescheduling. It might be nice if the 
'done' messaging did align as it would then work in concert with the other 
[suggested] logging to be much clearer on what is happening when.



##########
artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java:
##########
@@ -1846,43 +1844,47 @@ private final class ExpiryReaper extends 
ActiveMQScheduledComponent {
          super(scheduledExecutorService, executor, checkPeriod, timeUnit, 
onDemand);
       }
 
-      volatile CountDownLatch inUseLatch;
+      volatile Iterator<Queue> iterator;
 
 
       @Override
       public void stop() {
          super.stop();
          // this will do a best effort to stop the current latch.
          // no big deal if it failed. this is just to optimize this component 
stop.
-         CountDownLatch latch = inUseLatch;
-         if (latch != null) {
-            latch.countDown();
-         }
       }
 
-
       @Override
       public void run() {
-         // The reaper thread should be finished case the PostOffice is gone
-         // This is to avoid leaks on PostOffice between stops and starts
-         for (Queue queue : iterableOf(getLocalQueues())) {
-            if (!isStarted()) {
-               break;
-            }
-            try {
-               CountDownLatch latch = new CountDownLatch(1);
-               this.inUseLatch = latch;
-               queue.expireReferences(latch::countDown);
-               // the idea is in fact to block the Reaper while the Queue is 
executing reaping.
-               // This would avoid another eventual expiry to be called if the 
period for reaping is too small
-               // This should also avoid bursts in CPU consumption because of 
the expiry reaping
-               if (!latch.await(10, TimeUnit.SECONDS)) {
-                  ActiveMQServerLogger.LOGGER.errorExpiringMessages(new 
TimeoutException(queue.getName().toString()));
-               }
-            } catch (Exception e) {
-               ActiveMQServerLogger.LOGGER.errorExpiringMessages(e);
-            }
+         if (iterator != null) {
+            logger.debug("iterator is not finished yet");

Review Comment:
   The message could make it more obvious what isnt finished to avoid needing 
to check the source, e.g "Existing expiry reaper iterator is not finished yet, 
not beginning new sweep."
   
   It would also be good to then add related messages, such as add below that 
it _is_ starting a new expiry sweep. Perhaps even add another one later that it 
has finished a sweep, in moveNext(). That way you can easily see when it 
starts/finishes/skips.



##########
artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/PostOfficeImpl.java:
##########
@@ -1846,43 +1844,47 @@ private final class ExpiryReaper extends 
ActiveMQScheduledComponent {
          super(scheduledExecutorService, executor, checkPeriod, timeUnit, 
onDemand);
       }
 
-      volatile CountDownLatch inUseLatch;
+      volatile Iterator<Queue> iterator;
 
 
       @Override
       public void stop() {
          super.stop();
          // this will do a best effort to stop the current latch.
          // no big deal if it failed. this is just to optimize this component 
stop.
-         CountDownLatch latch = inUseLatch;
-         if (latch != null) {
-            latch.countDown();
-         }
       }
 
-
       @Override
       public void run() {
-         // The reaper thread should be finished case the PostOffice is gone
-         // This is to avoid leaks on PostOffice between stops and starts
-         for (Queue queue : iterableOf(getLocalQueues())) {
-            if (!isStarted()) {
-               break;
-            }
-            try {
-               CountDownLatch latch = new CountDownLatch(1);
-               this.inUseLatch = latch;
-               queue.expireReferences(latch::countDown);
-               // the idea is in fact to block the Reaper while the Queue is 
executing reaping.
-               // This would avoid another eventual expiry to be called if the 
period for reaping is too small
-               // This should also avoid bursts in CPU consumption because of 
the expiry reaping
-               if (!latch.await(10, TimeUnit.SECONDS)) {
-                  ActiveMQServerLogger.LOGGER.errorExpiringMessages(new 
TimeoutException(queue.getName().toString()));
-               }
-            } catch (Exception e) {
-               ActiveMQServerLogger.LOGGER.errorExpiringMessages(e);
-            }
+         if (iterator != null) {
+            logger.debug("iterator is not finished yet");
+            return;
          }
+
+         iterator = iterableOf(getLocalQueues()).iterator();
+
+         moveNext();
+      }
+
+      private void done() {
+         executor.execute(this::moveNext);
+      }
+
+      private void moveNext() {
+         Queue queue;
+         if (!iterator.hasNext() || !this.isStarted()) {
+            queue = null;
+         } else {
+            queue = iterator.next();
+         }
+
+         if (queue == null) {
+            iterator = null;
+            return;
+         }

Review Comment:
   Related to earlier comments...if _iterator_ needs to be volatile due to 
multiple threads setting it, it would probably be needed to assign it to a new 
variable and use that (after a null check) to ensure it is consistently used 
for e.g hasNext() and later next(), and not being be re-read on each use and 
potentially changing or being nulled between calls (or even before getting into 
this method).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to