34
34
import java .util .concurrent .*;
35
35
import java .util .stream .Collectors ;
36
36
37
+ import static com .evolvedbinary .j8fu .tuple .Tuple .Tuple ;
37
38
import static org .exist .storage .lock .LockTable .LockAction .Action .*;
38
39
import static org .exist .util .ThreadUtils .newInstanceThread ;
39
40
@@ -84,9 +85,9 @@ public class LockTable {
84
85
/**
85
86
* Reference count of acquired locks by id and type
86
87
*
87
- * Map<Id, Map<Lock Type, Map<Lock Mode, Map<Owner, HoldCount >>>>
88
+ * Map<Id, Map<Lock Type, Map<Lock Mode, Map<Owner, LockCountTraces >>>>
88
89
*/
89
- private final ConcurrentMap <String , Map <LockType , Map <LockMode , Map <String , Integer >>>> acquired = new ConcurrentHashMap <>();
90
+ private final ConcurrentMap <String , Map <LockType , Map <LockMode , Map <String , LockCountTraces >>>> acquired = new ConcurrentHashMap <>();
90
91
91
92
/**
92
93
* The {@link #queue} holds lock events and lock listener events
@@ -269,7 +270,7 @@ public Map<String, Map<LockType, List<LockModeOwner>>> getAttempting() {
269
270
*
270
271
* @return acquired lock information
271
272
*/
272
- public Map <String , Map <LockType , Map <LockMode , Map <String , Integer >>>> getAcquired () {
273
+ public Map <String , Map <LockType , Map <LockMode , Map <String , LockCountTraces >>>> getAcquired () {
273
274
return new HashMap <>(acquired );
274
275
}
275
276
@@ -291,15 +292,34 @@ public String getOwnerThread() {
291
292
}
292
293
}
293
294
295
+ public static class LockCountTraces {
296
+ int count ;
297
+ @ Nullable final List <StackTraceElement []> traces ;
298
+
299
+ public LockCountTraces (final int count , @ Nullable final List <StackTraceElement []> traces ) {
300
+ this .count = count ;
301
+ this .traces = traces ;
302
+ }
303
+
304
+ public int getCount () {
305
+ return count ;
306
+ }
307
+
308
+ @ Nullable
309
+ public List <StackTraceElement []> getTraces () {
310
+ return traces ;
311
+ }
312
+ }
313
+
294
314
private static class QueueConsumer implements Runnable {
295
315
private final TransferQueue <Either <ListenerAction , LockAction >> queue ;
296
316
private final ConcurrentMap <String , Map <LockType , List <LockModeOwner >>> attempting ;
297
- private final ConcurrentMap <String , Map <LockType , Map <LockMode , Map <String , Integer >>>> acquired ;
317
+ private final ConcurrentMap <String , Map <LockType , Map <LockMode , Map <String , LockCountTraces >>>> acquired ;
298
318
private final List <LockEventListener > listeners = new ArrayList <>();
299
319
300
320
QueueConsumer (final TransferQueue <Either <ListenerAction , LockAction >> queue ,
301
321
final ConcurrentMap <String , Map <LockType , List <LockModeOwner >>> attempting ,
302
- final ConcurrentMap <String , Map <LockType , Map <LockMode , Map <String , Integer >>>> acquired ) {
322
+ final ConcurrentMap <String , Map <LockType , Map <LockMode , Map <String , LockCountTraces >>>> acquired ) {
303
323
this .queue = queue ;
304
324
this .attempting = attempting ;
305
325
this .acquired = acquired ;
@@ -458,12 +478,16 @@ private void incrementAcquired(final LockAction lockAction) {
458
478
459
479
ownerHolds .compute (lockAction .threadName , (threadName , holdCount ) -> {
460
480
if (holdCount == null ) {
461
- holdCount = 0 ;
481
+ holdCount = new LockCountTraces (1 , List (lockAction .stackTrace ));
482
+ } else {
483
+ holdCount = append (holdCount , lockAction .stackTrace );
462
484
}
463
- return ++ holdCount ;
485
+ return holdCount ;
464
486
});
465
487
466
- final int lockModeHolds = ownerHolds .values ().stream ().collect (Collectors .summingInt (Integer ::intValue ));
488
+ final int lockModeHolds = ownerHolds .values ().stream ()
489
+ .map (LockCountTraces ::getCount )
490
+ .collect (Collectors .summingInt (Integer ::intValue ));
467
491
notifyListenersOfAcquire (lockAction , lockModeHolds );
468
492
469
493
return ownerHolds ;
@@ -476,6 +500,34 @@ private void incrementAcquired(final LockAction lockAction) {
476
500
});
477
501
}
478
502
503
+ private static @ Nullable <T > List <T > List (@ Nullable final T item ) {
504
+ if (item == null ) {
505
+ return null ;
506
+ }
507
+
508
+ final List <T > list = new ArrayList <>();
509
+ list .add (item );
510
+ return list ;
511
+ }
512
+
513
+ private static LockCountTraces append (final LockCountTraces holdCount , @ Nullable final StackTraceElement [] trace ) {
514
+ List <StackTraceElement []> traces = holdCount .traces ;
515
+ if (traces != null ) {
516
+ traces .add (trace );
517
+ }
518
+ holdCount .count ++;
519
+ return holdCount ;
520
+ }
521
+
522
+ private static LockCountTraces removeLast (final LockCountTraces holdCount ) {
523
+ List <StackTraceElement []> traces = holdCount .traces ;
524
+ if (traces != null ) {
525
+ traces .remove (traces .size () - 1 );
526
+ }
527
+ holdCount .count --;
528
+ return holdCount ;
529
+ }
530
+
479
531
private void decrementAcquired (final LockAction lockAction ) {
480
532
acquired .compute (lockAction .id , (id , acqu ) -> {
481
533
if (acqu == null ) {
@@ -498,17 +550,17 @@ private void decrementAcquired(final LockAction lockAction) {
498
550
if (holdCount == null ) {
499
551
LOG .error ("No entry found when trying to decrementAcquired for: id={}, lockType={}, lockMode={}, threadName={}" , lockAction .id , lockAction .lockType , lockAction .mode , lockAction .threadName );
500
552
return null ;
501
- } else if (holdCount == 0 ) {
553
+ } else if (holdCount . count == 0 ) {
502
554
LOG .error ("Negative release when trying to decrementAcquired for: id={}, lockType={}, lockMode={}, threadName={}" , lockAction .id , lockAction .lockType , lockAction .mode , lockAction .threadName );
503
555
return null ;
504
- } else if (holdCount == 1 ) {
556
+ } else if (holdCount . count == 1 ) {
505
557
return null ;
506
558
} else {
507
- return -- holdCount ;
559
+ return removeLast ( holdCount ) ;
508
560
}
509
561
});
510
562
511
- final int lockModeHolds = ownerHolds .values ().stream ().collect (Collectors .summingInt (Integer ::intValue ));
563
+ final int lockModeHolds = ownerHolds .values ().stream ().map ( LockCountTraces :: getCount ). collect (Collectors .summingInt (Integer ::intValue ));
512
564
513
565
notifyListenersOfRelease (lockAction , lockModeHolds );
514
566
@@ -701,7 +753,7 @@ private void sanityCheckLockLifecycles(final LockAction lockAction) {
701
753
LOG .trace ("QUEUE: {} (read={} write={})" , lockAction .toString (), read , write );
702
754
}
703
755
704
- lockCounts .put (lockAction .id , new Tuple2 <> (read , write ));
756
+ lockCounts .put (lockAction .id , Tuple (read , write ));
705
757
}
706
758
}
707
759
}
0 commit comments