Author: mreutegg
Date: Wed Mar 21 06:17:12 2007
New Revision: 520878
URL: http://svn.apache.org/viewvc?view=rev&rev=520878
Log:
JCR-805: Introduce a temprary cache for intermediate query results
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PerQueryCache.java (with props)
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MatchAllScorer.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHits.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/RangeQuery.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardQuery.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MatchAllScorer.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MatchAllScorer.java?view=diff&rev=520878&r1=520877&r2=520878
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MatchAllScorer.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MatchAllScorer.java Wed Mar 21 06:17:12 2007
@@ -27,12 +27,12 @@
import java.io.IOException;
import java.util.BitSet;
+import java.util.Map;
+import java.util.HashMap;
/**
* The MatchAllScorer implements a Scorer that scores / collects all
* documents in the index that match a field.
- * In case there are no filters, this MatchAllScores simply collects
- * all documents in the index that are not marked as deleted.
*/
class MatchAllScorer extends Scorer {
@@ -136,6 +136,21 @@
* the search index.
*/
private void calculateDocFilter() throws IOException {
+ PerQueryCache cache = PerQueryCache.getInstance();
+ Map readerCache = (Map) cache.get(MatchAllScorer.class, reader);
+ if (readerCache == null) {
+ readerCache = new HashMap();
+ cache.put(MatchAllScorer.class, reader, readerCache);
+ }
+ // get BitSet for field
+ docFilter = (BitSet) readerCache.get(field);
+
+ if (docFilter != null) {
+ // use cached BitSet;
+ return;
+ }
+
+ // otherwise calculate new
docFilter = new BitSet(reader.maxDoc());
// we match all terms
TermEnum terms = reader.terms(new Term(FieldNames.PROPERTIES, field));
@@ -157,5 +172,8 @@
} finally {
terms.close();
}
+
+ // put BitSet into cache
+ readerCache.put(field, docFilter);
}
}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PerQueryCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PerQueryCache.java?view=auto&rev=520878
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PerQueryCache.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PerQueryCache.java Wed Mar 21 06:17:12 2007
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query.lucene;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * PerQueryCache implements a hash map on a per thread basis for
+ * the purpose of caching results while a query is executed. When the query
+ * finished the cache can be disposed by calling:
+ * PerQueryCache.getInstance().dispose().
+ */
+class PerQueryCache {
+
+ /**
+ * The internal map of this PerQueryCache.
+ */
+ private final Map map = new HashMap();
+
+ /**
+ * Private constructor.
+ */
+ private PerQueryCache() {
+ }
+
+ /**
+ * The per thread cache instance.
+ */
+ private static final ThreadLocal CACHE = new ThreadLocal();
+
+ /**
+ * @return PerQueryCache for the current thread.
+ */
+ static PerQueryCache getInstance() {
+ PerQueryCache cache = (PerQueryCache) CACHE.get();
+ if (cache == null) {
+ cache = new PerQueryCache();
+ CACHE.set(cache);
+ }
+ return cache;
+ }
+
+ /**
+ * Returns the value from the cache with the given type and
+ * key.
+ *
+ * @param type the query type.
+ * @param key the key object.
+ * @return the value assigned to type and key or
+ * null if it does not exist in the cache.
+ */
+ Object get(Class type, Object key) {
+ return map.get(new Key(type, key));
+ }
+
+ /**
+ * Puts the value into the cache and assigns it to
+ * type and key.
+ *
+ * @param type the query type.
+ * @param key the key object.
+ * @param value the value to cache.
+ * @return the existing value in the cache assigned to type and
+ * key or null if there was none.
+ */
+ Object put(Class type, Object key, Object value) {
+ return map.put(new Key(type, key), value);
+ }
+
+ /**
+ * Disposes the PerQueryCache for the current thread.
+ */
+ void dispose() {
+ CACHE.set(null);
+ }
+
+ /**
+ * Simple key class.
+ */
+ private static final class Key {
+
+ /**
+ * The query type.
+ */
+ private final Class type;
+
+ /**
+ * The key object.
+ */
+ private final Object key;
+
+ /**
+ * Creates a new internal Key object.
+ *
+ * @param type the query type.
+ * @param key the key object.
+ */
+ private Key(Class type, Object key) {
+ this.type = type;
+ this.key = key;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int hashCode() {
+ return type.hashCode() ^ key.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof Key) {
+ Key other = (Key) obj;
+ return type == other.type && key.equals(other.key);
+ }
+ return false;
+ }
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PerQueryCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHits.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHits.java?view=diff&rev=520878&r1=520877&r2=520878
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHits.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryHits.java Wed Mar 21 06:17:12 2007
@@ -62,6 +62,7 @@
*/
public final void close() throws IOException {
reader.close();
+ PerQueryCache.getInstance().dispose();
}
/**
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/RangeQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/RangeQuery.java?view=diff&rev=520878&r1=520877&r2=520878
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/RangeQuery.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/RangeQuery.java Wed Mar 21 06:17:12 2007
@@ -29,15 +29,14 @@
import org.apache.lucene.index.TermDocs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.commons.collections.map.LRUMap;
import java.io.IOException;
import java.util.BitSet;
import java.util.Map;
-import java.util.WeakHashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.HashMap;
/**
* Implements a variant of the lucene class {@link org.apache.lucene.search.RangeQuery}.
@@ -53,12 +52,6 @@
private static final Logger log = LoggerFactory.getLogger(RangeQuery.class);
/**
- * Simple result cache for previously calculated hits.
- * key=IndexReader value=Map{key=String:range,value=BitSet:hits}
- */
- private static final Map cache = new WeakHashMap();
-
- /**
* The lower term. May be null if upperTerm is not
* null.
*/
@@ -292,15 +285,14 @@
key.append(transform);
this.cacheKey = key.toString();
// check cache
- synchronized (cache) {
- Map m = (Map) cache.get(reader);
+ PerQueryCache cache = PerQueryCache.getInstance();
+ Map m = (Map) cache.get(RangeQueryScorer.class, reader);
if (m == null) {
- m = new LRUMap(10);
- cache.put(reader, m);
+ m = new HashMap();
+ cache.put(RangeQueryScorer.class, reader, m);
}
resultMap = m;
- }
- synchronized (resultMap) {
+
BitSet result = (BitSet) resultMap.get(cacheKey);
if (result == null) {
result = new BitSet(reader.maxDoc());
@@ -308,7 +300,6 @@
hitsCalculated = true;
}
hits = result;
- }
}
/**
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardQuery.java?view=diff&rev=520878&r1=520877&r2=520878
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardQuery.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardQuery.java Wed Mar 21 06:17:12 2007
@@ -31,12 +31,11 @@
import org.apache.lucene.search.Similarity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.commons.collections.map.LRUMap;
import java.io.IOException;
import java.util.BitSet;
-import java.util.WeakHashMap;
import java.util.Map;
+import java.util.HashMap;
/**
* Implements a wildcard query on a lucene field with an embedded property name
@@ -77,12 +76,6 @@
private final int transform;
/**
- * Simple result cache for previously calculated hits.
- * key=IndexReader value=Map{key=String:pattern,value=BitSet:hits}
- */
- private static final Map cache = new WeakHashMap();
-
- /**
* Creates a new WildcardQuery.
*
* @param field the name of the field to search.
@@ -255,15 +248,14 @@
this.reader = reader;
this.cacheKey = field + '\uFFFF' + propName + '\uFFFF' + transform +'\uFFFF' + pattern;
// check cache
- synchronized (cache) {
- Map m = (Map) cache.get(reader);
+ PerQueryCache cache = PerQueryCache.getInstance();
+ Map m = (Map) cache.get(WildcardQueryScorer.class, reader);
if (m == null) {
- m = new LRUMap(10);
- cache.put(reader, m);
+ m = new HashMap();
+ cache.put(WildcardQueryScorer.class, reader, m);
}
resultMap = m;
- }
- synchronized (resultMap) {
+
BitSet result = (BitSet) resultMap.get(cacheKey);
if (result == null) {
result = new BitSet(reader.maxDoc());
@@ -271,7 +263,6 @@
hitsCalculated = true;
}
hits = result;
- }
}
/**