[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