From e76bffaf9634b2f69c1c85fe39b3c26c68cee461 Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Sun, 13 Nov 2005 15:21:54 +0000 Subject: [PATCH] Catch errors that may occur if LRUMap is used incorrectly These can be used for debugging if LRUMap has a bug bug 32573 git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@333022 13f79535-47bb-0310-9956-ffa450edef68 --- .../commons/collections/map/LRUMap.java | 59 +++++++++++++++---- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/src/java/org/apache/commons/collections/map/LRUMap.java b/src/java/org/apache/commons/collections/map/LRUMap.java index b4b66958f..aaaccb0e8 100644 --- a/src/java/org/apache/commons/collections/map/LRUMap.java +++ b/src/java/org/apache/commons/collections/map/LRUMap.java @@ -191,6 +191,9 @@ public class LRUMap entry.before = header.before; header.before.after = entry; header.before = entry; + } else if (entry == header) { + throw new IllegalStateException("Can't move header to MRU" + + " (please report this to commons-dev@jakarta.apache.org)"); } } @@ -228,18 +231,32 @@ public class LRUMap LinkEntry reuse = header.after; boolean removeLRUEntry = false; if (scanUntilRemovable) { - while (reuse != header) { + while (reuse != header && reuse != null) { if (removeLRU(reuse)) { removeLRUEntry = true; break; } reuse = reuse.after; } + if (reuse == null) { + throw new IllegalStateException( + "Entry.after=null, header.after" + header.after + " header.before" + header.before + + " key=" + key + " value=" + value + " size=" + size + " maxSize=" + maxSize + + " Please check that your keys are immutable, and that you have used synchronization properly." + + " If so, then please report this to commons-dev@jakarta.apache.org as a bug."); + } } else { removeLRUEntry = removeLRU(reuse); } if (removeLRUEntry) { + if (reuse == null) { + throw new IllegalStateException( + "reuse=null, header.after=" + header.after + " header.before" + header.before + + " key=" + key + " value=" + value + " size=" + size + " maxSize=" + maxSize + + " Please check that your keys are immutable, and that you have used synchronization properly." + + " If so, then please report this to commons-dev@jakarta.apache.org as a bug."); + } reuseMapping(reuse, hashIndex, hashCode, key, value); } else { super.addMapping(hashIndex, hashCode, key, value); @@ -264,19 +281,35 @@ public class LRUMap // find the entry before the entry specified in the hash table // remember that the parameters (except the first) refer to the new entry, // not the old one - int removeIndex = hashIndex(entry.hashCode, data.length); - HashEntry loop = data[removeIndex]; - HashEntry previous = null; - while (loop != entry) { - previous = loop; - loop = loop.next; + try { + int removeIndex = hashIndex(entry.hashCode, data.length); + HashEntry[] tmp = data; // may protect against some sync issues + HashEntry loop = tmp[removeIndex]; + HashEntry previous = null; + while (loop != entry && loop != null) { + previous = loop; + loop = loop.next; + } + if (loop == null) { + throw new IllegalStateException( + "Entry.next=null, data[removeIndex]=" + data[removeIndex] + " previous=" + previous + + " key=" + key + " value=" + value + " size=" + size + " maxSize=" + maxSize + + " Please check that your keys are immutable, and that you have used synchronization properly." + + " If so, then please report this to commons-dev@jakarta.apache.org as a bug."); + } + + // reuse the entry + modCount++; + removeEntry(entry, removeIndex, previous); + reuseEntry(entry, hashIndex, hashCode, key, value); + addEntry(entry, hashIndex); + } catch (NullPointerException ex) { + throw new IllegalStateException( + "NPE, entry=" + entry + " entryIsHeader=" + (entry==header) + + " key=" + key + " value=" + value + " size=" + size + " maxSize=" + maxSize + + " Please check that your keys are immutable, and that you have used synchronization properly." + + " If so, then please report this to commons-dev@jakarta.apache.org as a bug."); } - - // reuse the entry - modCount++; - removeEntry(entry, removeIndex, previous); - reuseEntry(entry, hashIndex, hashCode, key, value); - addEntry(entry, hashIndex); } /**