@@ -301,8 +301,15 @@ protected void suspendBookieForceLedgerAcks(BookieId address) {
301
301
}
302
302
303
303
protected void resumeBookieWriteAcks (BookieId address ) {
304
- suspendedBookiesForForceLedgerAcks .remove (address );
305
- List <Runnable > pendingResponses = deferredBookieForceLedgerResponses .remove (address );
304
+ List <Runnable > pendingResponses ;
305
+
306
+ // why use the BookieId instance as the object monitor? there is a date race problem if not
307
+ // see https://github.com/apache/bookkeeper/issues/4200
308
+ synchronized (address ) {
309
+ suspendedBookiesForForceLedgerAcks .remove (address );
310
+ pendingResponses = deferredBookieForceLedgerResponses .remove (address );
311
+ }
312
+
306
313
if (pendingResponses != null ) {
307
314
pendingResponses .forEach (Runnable ::run );
308
315
}
@@ -654,11 +661,17 @@ protected void setupBookieClientForceLedger() {
654
661
callback .forceLedgerComplete (BKException .Code .OK , ledgerId , bookieSocketAddress , ctx );
655
662
});
656
663
};
657
- if (suspendedBookiesForForceLedgerAcks .contains (bookieSocketAddress )) {
658
- List <Runnable > queue = deferredBookieForceLedgerResponses .computeIfAbsent (bookieSocketAddress ,
659
- (k ) -> new CopyOnWriteArrayList <>());
660
- queue .add (activity );
661
- } else {
664
+ List <Runnable > queue = null ;
665
+
666
+ synchronized (bookieSocketAddress ) {
667
+ if (suspendedBookiesForForceLedgerAcks .contains (bookieSocketAddress )) {
668
+ queue = deferredBookieForceLedgerResponses .computeIfAbsent (bookieSocketAddress ,
669
+ (k ) -> new CopyOnWriteArrayList <>());
670
+ queue .add (activity );
671
+ }
672
+ }
673
+
674
+ if (queue == null ) {
662
675
activity .run ();
663
676
}
664
677
return null ;
0 commit comments