Index: lucene/src/java/org/apache/lucene/index/TermInfosReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/TermInfosReader.java (revision 943873) +++ lucene/src/java/org/apache/lucene/index/TermInfosReader.java (working copy) @@ -53,7 +53,31 @@ } } - private final DoubleBarrelLRUCache termsCache = new DoubleBarrelLRUCache(DEFAULT_CACHE_SIZE); + private static class CloneableTerm extends DoubleBarrelLRUCache.CloneableKey { + private final Term term; + + public CloneableTerm(Term t) { + this.term = new Term(t.field(), t.text()); + } + + @Override + public Object clone() { + return new CloneableTerm(term); + } + + @Override + public boolean equals(Object _other) { + CloneableTerm other = (CloneableTerm) _other; + return term.equals(other.term); + } + + @Override + public int hashCode() { + return term.hashCode(); + } + } + + private final DoubleBarrelLRUCache termsCache = new DoubleBarrelLRUCache(DEFAULT_CACHE_SIZE); /** * Per-thread resources managed by ThreadLocal @@ -190,7 +214,9 @@ ensureIndexIsRead(); - TermInfoAndOrd tiOrd = termsCache.get(term); + final CloneableTerm cacheKey = new CloneableTerm(term); + + TermInfoAndOrd tiOrd = termsCache.get(cacheKey); ThreadResources resources = getThreadResources(); if (!mustSeekEnum && tiOrd != null) { @@ -219,7 +245,7 @@ // wipe out the cache when they iterate over a large numbers // of terms in order if (tiOrd == null) { - termsCache.put(term, new TermInfoAndOrd(ti, (int) enumerator.position)); + termsCache.put(cacheKey, new TermInfoAndOrd(ti, (int) enumerator.position)); } else { assert sameTermInfo(ti, tiOrd, enumerator); assert (int) enumerator.position == tiOrd.termOrd; @@ -248,7 +274,7 @@ if (enumerator.term() != null && term.compareTo(enumerator.term()) == 0) { ti = enumerator.termInfo(); if (tiOrd == null) { - termsCache.put(term, new TermInfoAndOrd(ti, (int) enumerator.position)); + termsCache.put(cacheKey, new TermInfoAndOrd(ti, (int) enumerator.position)); } else { assert sameTermInfo(ti, tiOrd, enumerator); assert (int) enumerator.position == tiOrd.termOrd; Index: lucene/src/java/org/apache/lucene/util/DoubleBarrelLRUCache.java =================================================================== --- lucene/src/java/org/apache/lucene/util/DoubleBarrelLRUCache.java (revision 943873) +++ lucene/src/java/org/apache/lucene/util/DoubleBarrelLRUCache.java (working copy) @@ -28,8 +28,9 @@ *

At any given time, one hash is primary and the other * is secondary. {@link #get} first checks primary, and if * that's a miss, checks secondary. If secondary has the - * entry, it's promoted to primary. Once primary is full, - * the secondary is cleared and the two are swapped.

+ * entry, it's promoted to primary (NOTE: the key is + * cloned at this point). Once primary is full, the + * secondary is cleared and the two are swapped.

* *

This is not as space efficient as other possible * concurrent approaches (see LUCENE-2075): to achieve @@ -41,7 +42,7 @@ * @lucene.internal */ -final public class DoubleBarrelLRUCache { +final public class DoubleBarrelLRUCache { public static abstract class CloneableKey { abstract public Object clone(); @@ -78,7 +79,7 @@ result = secondary.get(key); if (result != null) { // Promote to primary - put(key, result); + put((K) key.clone(), result); } } return result;