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

cshannon pushed a commit to branch activemq-5.19.x
in repository https://gitbox.apache.org/repos/asf/activemq.git


The following commit(s) were added to refs/heads/activemq-5.19.x by this push:
     new 4f3bafbcb7 AMQ-9823 - properly clear ack set from ackAndPreparedMap
4f3bafbcb7 is described below

commit 4f3bafbcb76f86fc89bf3a172044ccea602a27e6
Author: Christopher L. Shannon <[email protected]>
AuthorDate: Thu Dec 18 16:35:02 2025 -0500

    AMQ-9823 - properly clear ack set from ackAndPreparedMap
    
    Fix the logic that removes prepared acks from the ackAndPreparedMap
    that were loaded during XA recovery on commit/rollback so that if the
    set of acks for a key is empty the set it is removed from the map
    
    (cherry picked from commit 5cc1e73b6ade9cb9d0fed5c3702c22fbebee9dcb)
---
 .../apache/activemq/store/kahadb/KahaDBStore.java  |  2 +-
 .../activemq/store/kahadb/KahaDBStoreTest.java     | 33 ++++++++++++++++++++++
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git 
a/activemq-kahadb-store/src/main/java/org/apache/activemq/store/kahadb/KahaDBStore.java
 
b/activemq-kahadb-store/src/main/java/org/apache/activemq/store/kahadb/KahaDBStore.java
index 63273bcce7..0c526b6399 100644
--- 
a/activemq-kahadb-store/src/main/java/org/apache/activemq/store/kahadb/KahaDBStore.java
+++ 
b/activemq-kahadb-store/src/main/java/org/apache/activemq/store/kahadb/KahaDBStore.java
@@ -465,7 +465,7 @@ public class KahaDBStore extends MessageDatabase implements 
PersistenceAdapter,
                         Set<String> ackedAndPrepared = 
ackedAndPreparedMap.get(key);
                         if (ackedAndPrepared != null) {
                             ackedAndPrepared.remove(id);
-                            if (ackedAndPreparedMap.isEmpty()) {
+                            if (ackedAndPrepared.isEmpty()) {
                                 ackedAndPreparedMap.remove(key);
                             }
                         }
diff --git 
a/activemq-unit-tests/src/test/java/org/apache/activemq/store/kahadb/KahaDBStoreTest.java
 
b/activemq-unit-tests/src/test/java/org/apache/activemq/store/kahadb/KahaDBStoreTest.java
index 46f7772cf2..edfb006c48 100644
--- 
a/activemq-unit-tests/src/test/java/org/apache/activemq/store/kahadb/KahaDBStoreTest.java
+++ 
b/activemq-unit-tests/src/test/java/org/apache/activemq/store/kahadb/KahaDBStoreTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.activemq.store.kahadb;
 
+import java.util.ArrayList;
 import java.util.Vector;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -32,6 +33,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 public class KahaDBStoreTest {
@@ -106,4 +108,35 @@ public class KahaDBStoreTest {
 
         assertTrue("no exceptions " + exceptions, exceptions.isEmpty());
     }
+
+    @Test
+    public void testTrackAndForgetRecoveredAcks() throws Exception {
+        final ArrayList<MessageAck> acks = new ArrayList<>();
+        for (int i = 0; i < 10; i++) {
+            MessageAck ack = new MessageAck();
+            ack.setLastMessageId(new MessageId(producerId, i));
+            acks.add(ack);
+        }
+
+        // Add track 10 recovered acks and verify they are in the
+        // ackedAndPreparedMap. There should be 1 entry for the dest
+        // that contains a set of the ids
+        underTest.trackRecoveredAcks(acks);
+        assertEquals(1, underTest.ackedAndPreparedMap.size());
+        assertEquals(10, underTest.ackedAndPreparedMap.get(
+                underTest.getDestination().getPhysicalName()).size());
+
+        // forget 5 of the recovered acks
+        // there should now only be 5 remaining that are tracked
+        underTest.forgetRecoveredAcks(new ArrayList<>(acks.subList(0, 5)), 
false);
+        assertEquals(5, underTest.ackedAndPreparedMap.get(
+                underTest.getDestination().getPhysicalName()).size());
+
+        // forget the rest, the ackedAndPreparedMap should now be empty
+        // because any entries that contain a set of size 0 should be removed
+        // from the map entirely. Before AMQ-9823 this was keeping an empty set
+        // in the map leading to a possible small memory leak
+        underTest.forgetRecoveredAcks(new ArrayList<>(acks.subList(5, 10)), 
false);
+        assertTrue(underTest.ackedAndPreparedMap.isEmpty());
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information, visit: https://activemq.apache.org/contact


Reply via email to