[Mondrian] un-thread-safe code in Aggregation.getCellValue

John V. Sichi jsichi at gmail.com
Thu Jan 31 16:09:27 EST 2008


Looking at the code below (segmentRefs is a CopyOnWriteArrayList), isn't 
it broken?  It's called in a multi-threaded context without any 
synchronization, so the "old-style for loop" is problematic since the 
array size can be changed by other threads doing the same thing. 
CopyOnWriteArrayList provides an iterator for doing this safely.

         // Use old-style for loop for efficiency.
         int segmentRefCount = segmentRefs.size();
         for (int i = 0; i < segmentRefCount; i++) {
             SoftReference<Segment> segmentRef = segmentRefs.get(i);
             Segment segment = segmentRef.get();
             if (segment == null) {
                 // it's been garbage-collected
                 segmentRefs.remove(segmentRef);
                 --segmentRefCount;
                 --i;
                 continue;
             }

We saw a crash under concurrent load which matches this; it couldn't be 
reproduced, which isn't surprising since the code is memory-sensitive 
due to soft references.

Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
         at 
java.util.concurrent.CopyOnWriteArrayList.rangeCheck(CopyOnWriteArrayList.java:708)
         at 
java.util.concurrent.CopyOnWriteArrayList.get(CopyOnWriteArrayList.java:328)
         at 
mondrian.rolap.agg.Aggregation.getCellValue(Aggregation.java:664)
         at 
mondrian.rolap.agg.AggregationManager.getCellFromCache(AggregationManager.java:99)
         at 
mondrian.rolap.FastBatchingCellReader.get(FastBatchingCellReader.java:97)
         at 
mondrian.rolap.RolapEvaluator.evaluateCurrent(RolapEvaluator.java:540)
         at 
mondrian.calc.impl.MemberValueCalc.evaluate(MemberValueCalc.java:59)
...

JVS



More information about the Mondrian mailing list