diff --git a/src/main/java/net/spy/memcached/internal/result/SMGetResult.java b/src/main/java/net/spy/memcached/internal/result/SMGetResult.java index 7cf588fa4..6caef6afa 100644 --- a/src/main/java/net/spy/memcached/internal/result/SMGetResult.java +++ b/src/main/java/net/spy/memcached/internal/result/SMGetResult.java @@ -18,9 +18,9 @@ public abstract class SMGetResult { protected final List missedKeyList; protected final Map missedKeyMap; protected final Map trimmedKeyMap; - protected List mergedTrimmedKeys; + protected volatile List mergedTrimmedKeys; - protected final List> mergedResult; + protected volatile List> mergedResult; protected volatile CollectionOperationStatus resultOperationStatus = null; protected volatile CollectionOperationStatus failedOperationStatus = null; diff --git a/src/main/java/net/spy/memcached/internal/result/SMGetResultImpl.java b/src/main/java/net/spy/memcached/internal/result/SMGetResultImpl.java index 4b35cf658..922edb344 100644 --- a/src/main/java/net/spy/memcached/internal/result/SMGetResultImpl.java +++ b/src/main/java/net/spy/memcached/internal/result/SMGetResultImpl.java @@ -1,5 +1,6 @@ package net.spy.memcached.internal.result; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -90,6 +91,64 @@ public void mergeSMGetElements(final List> eachResult) { } } + private void mergeSMGetElements2(final List> eachResult) { + if (mergedResult.isEmpty()) { + // merged result is empty, add all. + mergedResult.addAll(eachResult); + + while (mergedResult.size() > count) { + mergedResult.remove(count); + } + return; + } + + final int eachSize = eachResult.size(); + final int oldMergedSize = mergedResult.size(); + final List> newMergedResult = new ArrayList>(count); + + int eachPos = 0, oldMergedPos = 0, comp; + boolean bkeyDuplicated; + + while (eachPos < eachSize && oldMergedPos < oldMergedSize && newMergedResult.size() < count) { + final SMGetElement eachElem = eachResult.get(eachPos); + final SMGetElement oldMergedElem = mergedResult.get(oldMergedPos); + + comp = eachElem.compareBkeyTo(oldMergedElem); + bkeyDuplicated = (comp == 0); + if (bkeyDuplicated) { + // Duplicated bkey. Compare the "cache key". + comp = eachElem.compareKeyTo(oldMergedElem); + assert comp != 0 : "Unexpected smget elements. Duplicated cache key : " + eachElem.getKey(); + } + if ((reverse) ? (comp > 0) : (comp < 0)) { + newMergedResult.add(eachElem); + eachPos++; + + if (unique && bkeyDuplicated) { + // NOT the first cache key with the same bkey. do NOT insert. + oldMergedPos++; + } + } else { + newMergedResult.add(oldMergedElem); + oldMergedPos++; + + if (unique && bkeyDuplicated) { + // NOT the first cache key with the same bkey. do NOT insert. + eachPos++; + } + } + } + + while (eachPos < eachSize && newMergedResult.size() < count) { + newMergedResult.add(eachResult.get(eachPos++)); + } + while (oldMergedPos < oldMergedSize && newMergedResult.size() < count) { + newMergedResult.add(mergedResult.get(oldMergedPos++)); + } + + mergedResult = newMergedResult; + } + @Override public void makeResultOperationStatus() { refineTrimmedKeys();