Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DocId.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DocId.java (revision 917557)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DocId.java (working copy)
@@ -20,6 +20,7 @@
import java.util.BitSet;
import org.apache.jackrabbit.core.id.NodeId;
+import org.apache.jackrabbit.spi.commons.name.HashCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,6 +33,22 @@
static final int[] EMPTY = new int[0];
/**
+ * All available DocIds that can be represented with a short.
+ */
+ private static final ShortPlainDocId[] SHORT_DOC_IDS = new ShortPlainDocId[Short.MAX_VALUE];
+
+ /**
+ * Cache of most recently used {@link PlainDocId}s, with 2^13 (8192) slots.
+ */
+ private static final HashCache DOC_ID_CACHE = new HashCache(13);
+
+ static {
+ for (short i = 0; i < SHORT_DOC_IDS.length; i++) {
+ SHORT_DOC_IDS[i] = new ShortPlainDocId(i);
+ }
+ }
+
+ /**
* Indicates a null DocId. Will be returned if the root node is asked for
* its parent.
*/
@@ -112,7 +129,11 @@
* @return a DocId based on a document number.
*/
static DocId create(int docNumber) {
- return new PlainDocId(docNumber);
+ if (docNumber < Short.MAX_VALUE) {
+ return SHORT_DOC_IDS[docNumber];
+ } else {
+ return (DocId) DOC_ID_CACHE.get(new PlainDocId(docNumber));
+ }
}
/**
@@ -201,9 +222,81 @@
public String toString() {
return "PlainDocId(" + docNumber + ")";
}
+
+ @Override
+ public int hashCode() {
+ // ensure a good distribution of hashCode values
+ int h = docNumber;
+ h ^= (h >>> 20) ^ (h >>> 12);
+ return h ^ (h >>> 7) ^ (h >>> 4);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof PlainDocId) {
+ PlainDocId other = (PlainDocId) obj;
+ return docNumber == other.docNumber;
+ }
+ return false;
+ }
}
/**
+ * DocId based on a document number using a short.
+ */
+ private static final class ShortPlainDocId extends DocId {
+
+ /**
+ * The document number or -1 if not set.
+ */
+ private final short docNumber;
+
+ /**
+ * Creates a DocId based on a document number.
+ *
+ * @param docNumber the lucene document number.
+ */
+ ShortPlainDocId(short docNumber) {
+ this.docNumber = docNumber;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ int[] getDocumentNumbers(MultiIndexReader reader, int[] docNumbers) {
+ if (docNumbers.length == 1) {
+ docNumbers[0] = docNumber;
+ return docNumbers;
+ } else {
+ return new int[]{docNumber};
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ DocId applyOffset(int offset) {
+ return new PlainDocId(offset + docNumber);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ boolean isValid(BitSet deleted) {
+ return !deleted.get(docNumber);
+ }
+
+ /**
+ * Returns a String representation for this DocId.
+ *
+ * @return a String representation for this DocId.
+ */
+ public String toString() {
+ return "ShortPlainDocId(" + docNumber + ")";
+ }
+ }
+
+ /**
* DocId based on a node id.
*/
private static final class UUIDDocId extends DocId {
Index: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java
===================================================================
--- jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java (revision 917557)
+++ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/HashCache.java (working copy)
@@ -28,20 +28,28 @@
public class HashCache {
/**
- * Size of the cache (must be a power of two). Note that this is the
- * maximum number of objects kept in the cache, but due to hashing it
- * can well be that only a part of the cache array is filled even if
- * many more distinct objects are being accessed.
+ * Array of cached objects, indexed by their hash codes
+ * (module size of the array).
*/
- private static final int SIZE_POWER_OF_2 = 1024;
+ private final Object[] array;
/**
- * Array of cached objects, indexed by their hash codes
- * (module size of the array).
+ * Creates a hash cache with 1024 slots.
*/
- private final Object[] array = new Object[SIZE_POWER_OF_2];
+ public HashCache() {
+ this(10);
+ }
/**
+ * Creates a hash cache with 2^exponent slots.
+ *
+ * @param exponent the exponent.
+ */
+ public HashCache(int exponent) {
+ this.array = new Object[2 << exponent];
+ }
+
+ /**
* If a cached copy of the given object already exists, then returns
* that copy. Otherwise the given object is cached and returned.
*
@@ -49,7 +57,7 @@
* @return the given object or a previously cached copy
*/
public Object get(Object object) {
- int position = object.hashCode() & (SIZE_POWER_OF_2 - 1);
+ int position = object.hashCode() & (array.length - 1);
Object previous = array[position];
if (object.equals(previous)) {
return previous;