You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-commits@lucene.apache.org by ot...@apache.org on 2007/04/09 19:13:46 UTC
svn commit: r526842 - in /lucene/java/trunk: ./
src/java/org/apache/lucene/search/ src/test/org/apache/lucene/search/
Author: otis
Date: Mon Apr 9 10:13:44 2007
New Revision: 526842
URL: http://svn.apache.org/viewvc?view=rev&rev=526842
Log:
- LUCENE-853: Filter caching on the remote side of the RMI connection.
Added:
lucene/java/trunk/src/java/org/apache/lucene/search/FilterManager.java
lucene/java/trunk/src/java/org/apache/lucene/search/RemoteCachingWrapperFilter.java
lucene/java/trunk/src/test/org/apache/lucene/search/CachingWrapperFilterHelper.java
lucene/java/trunk/src/test/org/apache/lucene/search/RemoteCachingWrapperFilterHelper.java
lucene/java/trunk/src/test/org/apache/lucene/search/TestRemoteCachingWrapperFilter.java
Modified:
lucene/java/trunk/CHANGES.txt
lucene/java/trunk/src/java/org/apache/lucene/search/CachingWrapperFilter.java
Modified: lucene/java/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/java/trunk/CHANGES.txt?view=diff&rev=526842&r1=526841&r2=526842
==============================================================================
--- lucene/java/trunk/CHANGES.txt (original)
+++ lucene/java/trunk/CHANGES.txt Mon Apr 9 10:13:44 2007
@@ -109,10 +109,14 @@
(Michael Busch)
4. LUCENE-834: Added BoostingTermQuery which can boost scores based on the values of a payload (see #3 above.) (Grant Ingersoll)
+
5. LUCENE-834: Similarity has a new method for scoring payloads called scorePayloads that can be overridden to take advantage
of payload storage (see #3 above)
+
6. LUCENE-834: Added isPayloadAvailable() onto TermPositions interface and implemented it in the appropriate places (Grant Ingersoll)
+ 7. LUCENE-853: Added RemoteCachingWrapperFilter to enable caching of Filters on the remote side of the RMI connection.
+ (Matt Ericson via Otis Gospodnetic)
Optimizations
Modified: lucene/java/trunk/src/java/org/apache/lucene/search/CachingWrapperFilter.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/CachingWrapperFilter.java?view=diff&rev=526842&r1=526841&r2=526842
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/CachingWrapperFilter.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/CachingWrapperFilter.java Mon Apr 9 10:13:44 2007
@@ -30,13 +30,13 @@
* caching, keeping the two concerns decoupled yet composable.
*/
public class CachingWrapperFilter extends Filter {
- private Filter filter;
+ protected Filter filter;
/**
* @todo What about serialization in RemoteSearchable? Caching won't work.
* Should transient be removed?
*/
- private transient Map cache;
+ protected transient Map cache;
/**
* @param filter Filter to cache results of
Added: lucene/java/trunk/src/java/org/apache/lucene/search/FilterManager.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/FilterManager.java?view=auto&rev=526842
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/FilterManager.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/FilterManager.java Mon Apr 9 10:13:44 2007
@@ -0,0 +1,205 @@
+package org.apache.lucene.search;
+
+/**
+ * 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.
+ */
+
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeSet;
+
+/**
+ * Filter caching singleton. It can be used by {@link org.apache.lucene.search.RemoteCachingWrapperFilter}
+ * or just to save filters locally for reuse.
+ * This class makes it possble to cache Filters even when using RMI, as it
+ * keeps the cache on the seaercher side of the RMI connection.
+ *
+ * Also could be used as a persistent storage for any filter as long as the
+ * filter provides a proper hashCode(), as that is used as the key in the cache.
+ *
+ * The cache is periodically cleaned up from a separate thread to ensure the
+ * cache doesn't exceed the maximum size.
+ * @author Matt Ericson
+ */
+public class FilterManager {
+
+ protected static FilterManager manager;
+
+ /** The default maximum number of Filters in the cache */
+ protected static final int DEFAULT_CACHE_CLEAN_SIZE = 100;
+ /** The default frequency of cache clenup */
+ protected static final long DEFAULT_CACHE_SLEEP_TIME = 1000 * 60 * 10;
+
+ /** The cache itself */
+ protected Map cache;
+ /** Maximum allowed cache size */
+ protected int cacheCleanSize;
+ /** Cache cleaning frequency */
+ protected long cleanSleepTime;
+ /** Cache cleaner that runs in a separate thread */
+ protected FilterCleaner filterCleaner;
+
+ public synchronized static FilterManager getInstance() {
+ if (manager == null) {
+ manager = new FilterManager();
+ }
+ return manager;
+ }
+
+ /**
+ * Sets up the FilterManager singleton.
+ */
+ protected FilterManager() {
+ cache = new HashMap();
+ cacheCleanSize = DEFAULT_CACHE_CLEAN_SIZE; // Let the cache get to 100 items
+ cleanSleepTime = DEFAULT_CACHE_SLEEP_TIME; // 10 minutes between cleanings
+
+ filterCleaner = new FilterCleaner();
+ Thread fcThread = new Thread(filterCleaner);
+ // setto be a Daemon so it doesn't have to be stopped
+ fcThread.setDaemon(true);
+ fcThread.start();
+ }
+
+ /**
+ * Sets the max size that cache should reach before it is cleaned up
+ * @param cacheCleanSize maximum allowed cache size
+ */
+ public void setCacheSize(int cacheCleanSize) {
+ this.cacheCleanSize = cacheCleanSize;
+ }
+
+ /**
+ * Sets the cache cleaning frequency in milliseconds.
+ * @param cleanSleepTime cleaning frequency in millioseconds
+ */
+ public void setCleanThreadSleepTime(long cleanSleepTime) {
+ this.cleanSleepTime = cleanSleepTime;
+ }
+
+ /**
+ * Returns the cached version of the filter. Allows the caller to pass up
+ * a small filter but this will keep a persistent version around and allow
+ * the caching filter to do its job.
+ *
+ * @param filter The input filter
+ * @return The cached version of the filter
+ */
+ public Filter getFilter(Filter filter) {
+ synchronized(cache) {
+ FilterItem fi = null;
+ fi = (FilterItem)cache.get(new Integer(filter.hashCode()));
+ if (fi != null) {
+ fi.timestamp = new Date().getTime();
+ return fi.filter;
+ }
+ cache.put(new Integer(filter.hashCode()), new FilterItem(filter));
+ return filter;
+ }
+ }
+
+ /**
+ * Holds the filter and the last time the filter was used, to make LRU-based
+ * cache cleaning possible.
+ * TODO: Clean this up when we switch to Java 1.5
+ */
+ protected class FilterItem {
+ public Filter filter;
+ public long timestamp;
+
+ public FilterItem (Filter filter) {
+ this.filter = filter;
+ this.timestamp = new Date().getTime();
+ }
+ }
+
+
+ /**
+ * Keeps the cache from getting too big.
+ * If we were using Java 1.5, we could use LinkedHashMap and we would not need this thread
+ * to clean out the cache.
+ *
+ * The SortedSet sortedFilterItems is used only to sort the items from the cache,
+ * so when it's time to clean up we have the TreeSet sort the FilterItems by
+ * timestamp.
+ *
+ * Removes 1.5 * the numbers of items to make the cache smaller.
+ * For example:
+ * If cache clean size is 10, and the cache is at 15, we would remove (15 - 10) * 1.5 = 7.5 round up to 8.
+ * This way we clean the cache a bit more, and avoid having the cache cleaner having to do it frequently.
+ */
+ protected class FilterCleaner implements Runnable {
+
+ private boolean running = true;
+ private TreeSet sortedFilterItems;
+
+ public FilterCleaner() {
+ sortedFilterItems = new TreeSet(new Comparator() {
+ public int compare(Object a, Object b) {
+ if( a instanceof Map.Entry && b instanceof Map.Entry) {
+ FilterItem fia = (FilterItem) ((Map.Entry)a).getValue();
+ FilterItem fib = (FilterItem) ((Map.Entry)b).getValue();
+ if ( fia.timestamp == fib.timestamp ) {
+ return 0;
+ }
+ // smaller timestamp first
+ if ( fia.timestamp < fib.timestamp ) {
+ return -1;
+ }
+ // larger timestamp last
+ return 1;
+ } else {
+ throw new ClassCastException("Objects are not Map.Entry");
+ }
+ }
+ });
+ }
+
+ public void run () {
+ while (running) {
+
+ // sort items from oldest to newest
+ // we delete the oldest filters
+ if (cache.size() > cacheCleanSize) {
+ // empty the temporary set
+ sortedFilterItems.clear();
+ synchronized (cache) {
+ sortedFilterItems.addAll(cache.entrySet());
+ Iterator it = sortedFilterItems.iterator();
+ int numToDelete = (int) ((cache.size() - cacheCleanSize) * 1.5);
+ int counter = 0;
+ // loop over the set and delete all of the cache entries not used in a while
+ while (it.hasNext() && counter++ < numToDelete) {
+ Map.Entry entry = (Map.Entry)it.next();
+ cache.remove(entry.getKey());
+ }
+ }
+ // empty the set so we don't tie up the memory
+ sortedFilterItems.clear();
+ }
+ // take a nap
+ try {
+ Thread.sleep(cleanSleepTime);
+ } catch (InterruptedException e) {
+ // just keep going
+ }
+ }
+ }
+ }
+}
Added: lucene/java/trunk/src/java/org/apache/lucene/search/RemoteCachingWrapperFilter.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/RemoteCachingWrapperFilter.java?view=auto&rev=526842
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/RemoteCachingWrapperFilter.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/RemoteCachingWrapperFilter.java Mon Apr 9 10:13:44 2007
@@ -0,0 +1,58 @@
+package org.apache.lucene.search;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.BitSet;
+
+import org.apache.lucene.index.IndexReader;
+
+/**
+ * Provides caching of {@link Filter}s themselves on the remote end of an RMI connection.
+ * The cache is keyed on Filter's hashCode(), so if it sees the same filter twice
+ * it will reuse the original version.
+ * <p/>
+ * NOTE: This does NOT cache the Filter bits, but rather the Filter itself.
+ * Thus, this works hand-in-hand with {@link CachingWrapperFilter} to keep both
+ * file Filter cache and the Filter bits on the remote end, close to the searcher.
+ * <p/>
+ * Usage:
+ * <p/>
+ * To cache a result you must do something like
+ * RemoteCachingWrapperFilter f = new RemoteCachingWrapperFilter(new CachingWrapperFilter(myFilter));
+ * <p/>
+ * @author Matt Ericson
+ */
+public class RemoteCachingWrapperFilter extends Filter {
+ protected Filter filter;
+
+ public RemoteCachingWrapperFilter(Filter filter) {
+ this.filter = filter;
+ }
+
+ /**
+ * Uses the {@link FilterManager} to keep the cache for a filter on the
+ * searcher side of a remote connection.
+ * @param reader the index reader for the Filter
+ * @return the bitset
+ */
+ public BitSet bits(IndexReader reader) throws IOException {
+ Filter cachedFilter = FilterManager.getInstance().getFilter(filter);
+ return cachedFilter.bits(reader);
+ }
+}
Added: lucene/java/trunk/src/test/org/apache/lucene/search/CachingWrapperFilterHelper.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/search/CachingWrapperFilterHelper.java?view=auto&rev=526842
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/search/CachingWrapperFilterHelper.java (added)
+++ lucene/java/trunk/src/test/org/apache/lucene/search/CachingWrapperFilterHelper.java Mon Apr 9 10:13:44 2007
@@ -0,0 +1,80 @@
+package org.apache.lucene.search;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.BitSet;
+import java.util.WeakHashMap;
+
+import junit.framework.TestCase;
+
+import org.apache.lucene.index.IndexReader;
+
+/**
+ * A unit test helper class to test when the filter is getting cached and when it is not.
+ */
+public class CachingWrapperFilterHelper extends CachingWrapperFilter {
+
+ private boolean shouldHaveCache = false;
+
+ /**
+ * @param filter Filter to cache results of
+ */
+ public CachingWrapperFilterHelper(Filter filter) {
+ super(filter);
+ }
+
+ public void setShouldHaveCache(boolean shouldHaveCache) {
+ this.shouldHaveCache = shouldHaveCache;
+ }
+
+ public BitSet bits(IndexReader reader) throws IOException {
+ if (cache == null) {
+ cache = new WeakHashMap();
+ }
+
+ synchronized (cache) { // check cache
+ BitSet cached = (BitSet) cache.get(reader);
+ if (shouldHaveCache) {
+ TestCase.assertNotNull("Cache should have data ", cached);
+ } else {
+ TestCase.assertNull("Cache should be null " + cached , cached);
+ }
+ if (cached != null) {
+ return cached;
+ }
+ }
+
+ final BitSet bits = filter.bits(reader);
+
+ synchronized (cache) { // update cache
+ cache.put(reader, bits);
+ }
+
+ return bits;
+ }
+
+ public String toString() {
+ return "CachingWrapperFilterHelper("+filter+")";
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof CachingWrapperFilterHelper)) return false;
+ return this.filter.equals((CachingWrapperFilterHelper)o);
+ }
+}
Added: lucene/java/trunk/src/test/org/apache/lucene/search/RemoteCachingWrapperFilterHelper.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/search/RemoteCachingWrapperFilterHelper.java?view=auto&rev=526842
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/search/RemoteCachingWrapperFilterHelper.java (added)
+++ lucene/java/trunk/src/test/org/apache/lucene/search/RemoteCachingWrapperFilterHelper.java Mon Apr 9 10:13:44 2007
@@ -0,0 +1,60 @@
+package org.apache.lucene.search;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.BitSet;
+
+import junit.framework.TestCase;
+
+import org.apache.lucene.index.IndexReader;
+
+/**
+ * A unit test helper class to help with RemoteCachingWrapperFilter testing and
+ * assert that it is working correctly.
+ * @author Matt Ericson
+ */
+public class RemoteCachingWrapperFilterHelper extends RemoteCachingWrapperFilter {
+
+ private boolean shouldHaveCache;
+
+ public RemoteCachingWrapperFilterHelper(Filter filter, boolean shouldHaveCache) {
+ super(filter);
+ this.shouldHaveCache = shouldHaveCache;
+ }
+
+ public void shouldHaveCache(boolean shouldHaveCache) {
+ this.shouldHaveCache = shouldHaveCache;
+ }
+
+ public BitSet bits(IndexReader reader) throws IOException {
+ Filter cachedFilter = FilterManager.getInstance().getFilter(filter);
+
+ TestCase.assertNotNull("Filter should not be null", cachedFilter);
+ if (!shouldHaveCache) {
+ TestCase.assertSame("First time filter should be the same ", filter, cachedFilter);
+ } else {
+ TestCase.assertNotSame("We should have a cached version of the filter", filter, cachedFilter);
+ }
+
+ if (filter instanceof CachingWrapperFilterHelper) {
+ ((CachingWrapperFilterHelper)cachedFilter).setShouldHaveCache(shouldHaveCache);
+ }
+ return cachedFilter.bits(reader);
+ }
+}
Added: lucene/java/trunk/src/test/org/apache/lucene/search/TestRemoteCachingWrapperFilter.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/search/TestRemoteCachingWrapperFilter.java?view=auto&rev=526842
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/search/TestRemoteCachingWrapperFilter.java (added)
+++ lucene/java/trunk/src/test/org/apache/lucene/search/TestRemoteCachingWrapperFilter.java Mon Apr 9 10:13:44 2007
@@ -0,0 +1,127 @@
+package org.apache.lucene.search;
+
+/**
+ * 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.
+ */
+
+import java.rmi.Naming;
+import java.rmi.registry.LocateRegistry;
+
+import junit.framework.TestCase;
+
+import org.apache.lucene.analysis.SimpleAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.store.RAMDirectory;
+
+/**
+ * Tests that the index is cached on the searcher side of things.
+ * NOTE: This is copied from TestRemoteSearchable since it already had a remote index set up.
+ * @author Matt Ericson
+ */
+public class TestRemoteCachingWrapperFilter extends TestCase {
+ public TestRemoteCachingWrapperFilter(String name) {
+ super(name);
+ }
+
+ private static Searchable getRemote() throws Exception {
+ try {
+ return lookupRemote();
+ } catch (Throwable e) {
+ startServer();
+ return lookupRemote();
+ }
+ }
+
+ private static Searchable lookupRemote() throws Exception {
+ return (Searchable)Naming.lookup("//localhost/Searchable");
+ }
+
+ private static void startServer() throws Exception {
+ // construct an index
+ RAMDirectory indexStore = new RAMDirectory();
+ IndexWriter writer = new IndexWriter(indexStore,new SimpleAnalyzer(),true);
+ Document doc = new Document();
+ doc.add(new Field("test", "test text", Field.Store.YES, Field.Index.TOKENIZED));
+ doc.add(new Field("type", "A", Field.Store.YES, Field.Index.TOKENIZED));
+ doc.add(new Field("other", "other test text", Field.Store.YES, Field.Index.TOKENIZED));
+ writer.addDocument(doc);
+ //Need a second document to search for
+ doc = new Document();
+ doc.add(new Field("test", "test text", Field.Store.YES, Field.Index.TOKENIZED));
+ doc.add(new Field("type", "B", Field.Store.YES, Field.Index.TOKENIZED));
+ doc.add(new Field("other", "other test text", Field.Store.YES, Field.Index.TOKENIZED));
+ writer.addDocument(doc);
+ writer.optimize();
+ writer.close();
+
+ // publish it
+ LocateRegistry.createRegistry(1099);
+ Searchable local = new IndexSearcher(indexStore);
+ RemoteSearchable impl = new RemoteSearchable(local);
+ Naming.rebind("//localhost/Searchable", impl);
+ }
+
+ private static void search(Query query, Filter filter, int hitNumber, String typeValue) throws Exception {
+ Searchable[] searchables = { getRemote() };
+ Searcher searcher = new MultiSearcher(searchables);
+ Hits result = searcher.search(query,filter);
+ assertEquals(1, result.length());
+ Document document = result.doc(hitNumber);
+ assertTrue("document is null and it shouldn't be", document != null);
+ assertEquals(typeValue, document.get("type"));
+ assertTrue("document.getFields() Size: " + document.getFields().size() + " is not: " + 3, document.getFields().size() == 3);
+ }
+
+
+ public void testTermRemoteFilter() throws Exception {
+ CachingWrapperFilterHelper cwfh = new CachingWrapperFilterHelper(new QueryFilter(new TermQuery(new Term("type", "a"))));
+
+ // This is what we are fixing - if one uses a CachingWrapperFilter(Helper) it will never
+ // cache the filter on the remote site
+ cwfh.setShouldHaveCache(false);
+ search(new TermQuery(new Term("test", "test")), cwfh, 0, "A");
+ cwfh.setShouldHaveCache(false);
+ search(new TermQuery(new Term("test", "test")), cwfh, 0, "A");
+
+ // This is how we fix caching - we wrap a Filter in the RemoteCachingWrapperFilter(Handler - for testing)
+ // to cache the Filter on the searcher (remote) side
+ RemoteCachingWrapperFilterHelper rcwfh = new RemoteCachingWrapperFilterHelper(cwfh, false);
+ search(new TermQuery(new Term("test", "test")), rcwfh, 0, "A");
+
+ // 2nd time we do the search, we should be using the cached Filter
+ rcwfh.shouldHaveCache(true);
+ search(new TermQuery(new Term("test", "test")), rcwfh, 0, "A");
+
+ // assert that we get the same cached Filter, even if we create a new instance of RemoteCachingWrapperFilter(Helper)
+ // this should pass because the Filter parameters are the same, and the cache uses Filter's hashCode() as cache keys,
+ // and Filters' hashCode() builds on Filter parameters, not the Filter instance itself
+ rcwfh = new RemoteCachingWrapperFilterHelper(new QueryFilter(new TermQuery(new Term("type", "a"))), false);
+ rcwfh.shouldHaveCache(false);
+ search(new TermQuery(new Term("test", "test")), rcwfh, 0, "A");
+
+ rcwfh = new RemoteCachingWrapperFilterHelper(new QueryFilter(new TermQuery(new Term("type", "a"))), false);
+ rcwfh.shouldHaveCache(true);
+ search(new TermQuery(new Term("test", "test")), rcwfh, 0, "A");
+
+ // assert that we get a non-cached version of the Filter because this is a new Query (type:b)
+ rcwfh = new RemoteCachingWrapperFilterHelper(new QueryFilter(new TermQuery(new Term("type", "b"))), false);
+ rcwfh.shouldHaveCache(false);
+ search(new TermQuery(new Term("type", "b")), rcwfh, 0, "B");
+ }
+}