[jbosscache-commits] JBoss Cache SVN: r6790 - in searchable/trunk/src: test/java/org/jboss/cache/search and 1 other directory.
jbosscache-commits at lists.jboss.org
jbosscache-commits at lists.jboss.org
Thu Sep 25 11:38:37 EDT 2008
Author: navssurtani
Date: 2008-09-25 11:38:36 -0400 (Thu, 25 Sep 2008)
New Revision: 6790
Modified:
searchable/trunk/src/main/java/org/jboss/cache/search/CacheQuery.java
searchable/trunk/src/main/java/org/jboss/cache/search/CacheQueryImpl.java
searchable/trunk/src/main/java/org/jboss/cache/search/LazyQueryResultIterator.java
searchable/trunk/src/main/java/org/jboss/cache/search/QueryResultIteratorImpl.java
searchable/trunk/src/test/java/org/jboss/cache/search/LazyQueryResultIteratorTest.java
searchable/trunk/src/test/java/org/jboss/cache/search/QueryResultIteratorImplTest.java
Log:
Wrote up lazy iterator test ... Should release RC1
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/CacheQuery.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/CacheQuery.java 2008-09-25 14:38:10 UTC (rev 6789)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/CacheQuery.java 2008-09-25 15:38:36 UTC (rev 6790)
@@ -48,11 +48,22 @@
List<Object> list();
/**
- * Returns the results of a search as a {@link QueryResultIterator}.
+ * Returns the results of a search as a {@link QueryResultIterator} with a given
+ * integer parameter - the fetchSize.
*
+ * @param fetchSize integer to be given to the implementation constructor.
* @return a QueryResultIterator which can be used to iterate through the results that were found.
*/
+ QueryResultIterator iterator(int fetchSize);
+
+ /**
+ * Returns the results of a search as a {@link QueryResultIterator}. This calls {@link CacheQuery#iterator(int fetchSize)}
+ * but uses a default fetchSize of 1.
+ *
+ * @return a QueryResultIterator which can be used to iterate through the results that were found.
+ */
+
QueryResultIterator iterator();
/**
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/CacheQueryImpl.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/CacheQueryImpl.java 2008-09-25 14:38:10 UTC (rev 6789)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/CacheQueryImpl.java 2008-09-25 15:38:36 UTC (rev 6790)
@@ -53,6 +53,7 @@
/**
* Implementation class of the CacheQuery interface.
* <p/>
+ *
* @author Navin Surtani (<a href="mailto:nsurtani at redhat.com">nsurtani at redhat.com</a>)
*/
public class CacheQueryImpl implements CacheQuery
@@ -77,6 +78,7 @@
public CacheQueryImpl(Query luceneQuery, SearchFactoryImplementor searchFactory, Cache cache)
{
+
this.luceneQuery = luceneQuery;
// this.cache = cache;
entityLoader = new CacheEntityLoader(cache);
@@ -203,9 +205,13 @@
//TODO How do we deal with this if the parameter is too high.
}
-
public QueryResultIterator iterator() throws HibernateException
{
+ return iterator (1);
+ }
+
+ public QueryResultIterator iterator(int fetchSize) throws HibernateException
+ {
List<CacheEntityId> ids = null;
IndexSearcher searcher = buildSearcher(searchFactory);
if (searcher == null)
@@ -243,7 +249,7 @@
}
- return new QueryResultIteratorImpl(ids, entityLoader);
+ return new QueryResultIteratorImpl(ids, entityLoader, fetchSize);
}
public QueryResultIterator lazyIterator()
@@ -267,13 +273,15 @@
}
catch (IOException e)
{
- try {
- IndexSearcherCloser.closeSearcher( searcher, searchFactory.getReaderProvider() );
+ try
+ {
+ IndexSearcherCloser.closeSearcher(searcher, searchFactory.getReaderProvider());
}
- catch (SearchException ee) {
+ catch (SearchException ee)
+ {
//we have the initial issue already
}
- throw new HibernateException( "Unable to query Lucene index", e );
+ throw new HibernateException("Unable to query Lucene index", e);
}
@@ -356,7 +364,7 @@
}
this.maxResults = maxResults;
}
-
+
private IndexSearcher buildSearcher(SearchFactoryImplementor searchFactoryImplementor)
{
Map<Class, DocumentBuilder<Object>> builders = searchFactoryImplementor.getDocumentBuilders();
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/LazyQueryResultIterator.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/LazyQueryResultIterator.java 2008-09-25 14:38:10 UTC (rev 6789)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/LazyQueryResultIterator.java 2008-09-25 15:38:36 UTC (rev 6790)
@@ -50,7 +50,7 @@
private Hits hits;
private IndexSearcher searcher;
private SearchFactoryImplementor searchFactory;
- private Object[] buffer;
+ Object[] buffer;
public LazyQueryResultIterator(DocumentExtractor extractor, CacheEntityLoader entityLoader, Hits hits,
IndexSearcher searcher, SearchFactoryImplementor searchFactory, int first, int max, int fetchSize)
@@ -71,7 +71,7 @@
this.searchFactory = searchFactory;
//Create an buffer with size fetchSize (which is the size of the required buffer.
- buffer = new Object[fetchSize];
+ buffer = new Object[this.fetchSize];
}
public void jumpToResult(int index) throws IndexOutOfBoundsException
@@ -137,13 +137,15 @@
public Object next()
{
+ if (!hasNext()) throw new IndexOutOfBoundsException("Index is out of bounds. There is no next");
+
Object toReturn = null;
int bufferSize = buffer.length;
// make sure the index we are after is in the buffer. If it is, then index >= bufferIndex and index <= (bufferIndex + bufferSize).
if (bufferIndex >= 0 // buffer init check
&& index >= bufferIndex // lower boundary
- && index <= (bufferIndex + bufferSize)) // upper boundary
+ && index < (bufferIndex + bufferSize)) // upper boundary
{
// now we can get this from the buffer. Sweet!
int indexToReturn = index - bufferIndex;
@@ -167,7 +169,7 @@
// ignore loop below, in needs fixing
//now loop through bufferSize times to add the rest of the objects into the list.
- for (int i = 1; i <= bufferSize; i++)
+ for (int i = 1; i < bufferSize; i++)
{
String bufferDocumentId = (String) extractor.extract(hits, index + i).id;
CacheEntityId bufferId = new CacheEntityId(bufferDocumentId);
@@ -193,6 +195,8 @@
public Object previous()
{
+ if (!hasPrevious()) throw new IndexOutOfBoundsException("Index is out of bounds. There is no previous");
+
Object toReturn = null;
int bufferSize = buffer.length;
@@ -219,7 +223,7 @@
buffer[0] = toReturn;
//now loop through bufferSize times to add the rest of the objects into the list.
- for (int i = 1; i <= bufferSize; i++)
+ for (int i = 1; i < bufferSize; i++)
{
String bufferDocumentId = (String) extractor.extract(hits, index - i).id; //In this case it has to be index - i because previous() is called.
CacheEntityId bufferId = new CacheEntityId(bufferDocumentId);
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/QueryResultIteratorImpl.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/QueryResultIteratorImpl.java 2008-09-25 14:38:10 UTC (rev 6789)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/QueryResultIteratorImpl.java 2008-09-25 15:38:36 UTC (rev 6790)
@@ -18,19 +18,23 @@
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
+ */
package org.jboss.cache.search;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.Arrays;
/**
* This is the implementation class for the interface QueryResultIterator which extends ListIterator. It is what is
* returned when the iterator() method is run on a CacheQuery instance.
- *
* <p/>
+ * <p/>
*
* @author Navin Surtani (<a href="mailto:nsurtani at redhat.com">nsurtani at redhat.com</a>)
*/
@@ -42,12 +46,25 @@
private CacheEntityLoader entityLoader;
private int lowerLimit = 0;
private int upperLimit = 0;
+ private int fetchSize = 0;
+ private int bufferIndex = -1; // this is the index at which the buffer was populated. Hence, the first element of the buffer is at this index in the overall result set.
+ private Object[] buffer;
+ private static final Log log = LogFactory.getLog(QueryResultIteratorImpl.class);
- public QueryResultIteratorImpl(List<CacheEntityId> idList, CacheEntityLoader entityLoader)
+
+ public QueryResultIteratorImpl(List<CacheEntityId> idList, CacheEntityLoader entityLoader, int fetchSize)
{
+ if (fetchSize < 1)
+ {
+ throw new IllegalArgumentException("Incorrect value for fetchsize passed. Your fetchSize is less than 1");
+ }
+
this.idList = idList;
this.entityLoader = entityLoader;
upperLimit = idList.size() - 1;
+ this.fetchSize = fetchSize;
+
+ buffer = new Object[this.fetchSize];
}
/**
@@ -163,8 +180,53 @@
*/
public Object next()
{
- if (!hasNext()) throw new NoSuchElementException("Out of boundaries");
- Object toReturn = entityLoader.load(idList.get(index));
+ if (!hasNext()) throw new IndexOutOfBoundsException("Out of boundaries. There is no next");
+
+ Object toReturn;
+ int bufferSize = buffer.length;
+
+ // make sure the index we are after is in the buffer. If it is, then index >= bufferIndex and index <= (bufferIndex + bufferSize).
+ if (bufferIndex >= 0 // buffer init check
+ && index >= bufferIndex // lower boundary
+ && index < (bufferIndex + bufferSize)) // upper boundary //TODO: - Why does this logic work but <= not. >= works with previous() however.
+ {
+ // now we can get this from the buffer. Sweet!
+ int indexToReturn = index - bufferIndex;
+ toReturn = buffer[indexToReturn];
+ }
+
+ else
+ {
+ // We need to populate the buffer.
+
+ toReturn = entityLoader.load(idList.get(index));
+
+ //Wiping bufferObjects and the bufferIndex so that there is no stale data.
+
+ Arrays.fill(buffer, null);
+ buffer[0] = toReturn;
+
+ // we now need to buffer item at index "index", as well as the next "fetchsize - 1" elements. I.e., a total of fetchsize elements will be buffered.
+ //now loop through bufferSize times to add the rest of the objects into the list.
+
+ for (int i = 1; i < bufferSize; i++)
+ {
+ if (index + i > upperLimit)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Your current index + bufferSize exceeds the size of your number of hits");
+ }
+ break;
+ }
+
+ Object toBuffer = entityLoader.load(idList.get(index + i));
+ buffer[i] = toBuffer;
+ }
+ bufferIndex = index;
+
+ }
+
index++;
return toReturn;
}
@@ -187,8 +249,51 @@
public Object previous()
{
- if (!hasPrevious()) throw new NoSuchElementException("Out of boundaries");
- Object toReturn = entityLoader.load(idList.get(index));
+ if (!hasPrevious()) throw new IndexOutOfBoundsException("Index is out of bounds. There is no previous");
+
+ Object toReturn;
+ int bufferSize = buffer.length;
+
+ // make sure the index we are after is in the buffer. If it is, then index >= bufferIndex and index <= (bufferIndex + bufferSize).
+
+ if (bufferIndex >= 0 // buffer init check
+ && index <= bufferIndex // lower boundary
+ && index >= (bufferIndex + bufferSize)) // upper boundary
+ {
+ // now we can get this from the buffer. Sweet!
+ int indexToReturn = bufferIndex - index; // Unlike next() we have to make sure that we are subtracting index from bufferIndex
+ toReturn = buffer[indexToReturn];
+ }
+ else
+ {
+ toReturn = entityLoader.load(idList.get(index));
+ //Wiping bufferObjects and the bufferIndex so that there is no stale data.
+
+ Arrays.fill(buffer, null);
+ buffer[0] = toReturn;
+
+ // we now need to buffer item at index "index", as well as the next "fetchsize - 1" elements. I.e., a total of fetchsize elements will be buffered.
+ // ignore loop below, in needs fixing
+ //now loop through bufferSize times to add the rest of the objects into the list.
+
+ for (int i = 1; i < bufferSize; i++)
+ {
+ if (index - i < lowerLimit)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Your current index - bufferSize exceeds the size of your number of hits");
+ }
+ break;
+ }
+
+ Object toBuffer = entityLoader.load(idList.get(index - i));
+ buffer[i] = toBuffer;
+ }
+ bufferIndex = index;
+
+
+ }
index--;
return toReturn;
}
@@ -248,5 +353,5 @@
{
throw new UnsupportedOperationException("Not supported as you are trying to change something in the cache");
}
-
+
}
Modified: searchable/trunk/src/test/java/org/jboss/cache/search/LazyQueryResultIteratorTest.java
===================================================================
--- searchable/trunk/src/test/java/org/jboss/cache/search/LazyQueryResultIteratorTest.java 2008-09-25 14:38:10 UTC (rev 6789)
+++ searchable/trunk/src/test/java/org/jboss/cache/search/LazyQueryResultIteratorTest.java 2008-09-25 15:38:36 UTC (rev 6790)
@@ -1,13 +1,285 @@
package org.jboss.cache.search;
-import org.testng.annotations.Test;
+import org.testng.annotations.*;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Cache;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.search.test.Person;
+import org.jboss.cache.search.helper.IndexCleanUp;
+
/**
* @author Navin Surtani (<a href="mailto:nsurtani at redhat.com">nsurtani at redhat.com</a>)
*/
- at Test(groups="functional")
+ at Test(groups = "functional")
public class LazyQueryResultIteratorTest
{
- //Need to use mock-objects for this test.
-
+ SearchableCache searchableCache;
+ QueryParser parser = null;
+ Query luceneQuery = null;
+ CacheQuery cacheQuery = null;
+ LazyQueryResultIterator iterator = null;
+ int fetchSize = 1;
+ Person person1, person2, person3, person4, person5, person6, person7, person8, person9, person10;
+ StringBuilder builder;
+
+
+ @BeforeTest
+ public void setUpBeforeTest() throws ParseException
+ {
+ Cache coreCache = new DefaultCacheFactory().createCache();
+ searchableCache = new SearchableCacheFactory().createSearchableCache(coreCache, Person.class);
+
+ person1 = new Person();
+ person2 = new Person();
+ person3 = new Person();
+ person4 = new Person();
+ person5 = new Person();
+ person6 = new Person();
+ person7 = new Person();
+ person8 = new Person();
+ person9 = new Person();
+ person10 = new Person();
+
+ person1.setBlurb("cat");
+ person2.setBlurb("cat");
+ person3.setBlurb("cat");
+ person4.setBlurb("cat");
+ person5.setBlurb("cat");
+ person6.setBlurb("cat");
+ person7.setBlurb("cat");
+ person8.setBlurb("cat");
+ person9.setBlurb("cat");
+ person10.setBlurb("cat");
+
+ searchableCache.put(Fqn.fromString("/a"), "key1", person1);
+ searchableCache.put(Fqn.fromString("/a"), "key2", person2);
+ searchableCache.put(Fqn.fromString("/a"), "key3", person3);
+ searchableCache.put(Fqn.fromString("/a"), "key4", person4);
+ searchableCache.put(Fqn.fromString("/a"), "key5", person5);
+ searchableCache.put(Fqn.fromString("/a"), "key6", person6);
+ searchableCache.put(Fqn.fromString("/a"), "key7", person7);
+ searchableCache.put(Fqn.fromString("/a"), "key8", person8);
+ searchableCache.put(Fqn.fromString("/a"), "key9", person9);
+ searchableCache.put(Fqn.fromString("/a"), "key10", person10);
+
+
+ }
+
+ @AfterTest
+ public void tearDownAfterTest()
+ {
+ IndexCleanUp.cleanUpIndexes();
+ }
+
+ @BeforeMethod
+ public void setUp() throws ParseException
+ {
+ parser = new QueryParser("blurb", new StandardAnalyzer());
+ luceneQuery = parser.parse("cat");
+ cacheQuery = searchableCache.createQuery(luceneQuery);
+ iterator = (LazyQueryResultIterator) cacheQuery.lazyIterator();
+
+ }
+
+
+ @AfterMethod
+ public void tearDown()
+ {
+ iterator = null;
+ parser = null;
+ luceneQuery = null;
+ cacheQuery = null;
+ }
+
+ public void testJumpToResult() throws IndexOutOfBoundsException
+ {
+ iterator.jumpToResult(0);
+ assert iterator.isFirst();
+
+ iterator.jumpToResult(1);
+ assert iterator.isAfterFirst();
+
+ iterator.jumpToResult(9);
+ assert iterator.isLast();
+
+ iterator.jumpToResult(8);
+ assert iterator.isBeforeLast();
+ }
+
+ public void testFirst()
+ {
+ assert iterator.isFirst() : "We should be pointing at the first element";
+ Object next = iterator.next();
+ assert next == person1;
+ assert !iterator.isFirst();
+
+ iterator.first();
+
+ assert iterator.isFirst() : "We should be pointing at the first element";
+ next = iterator.next();
+ assert next == person1;
+ assert !iterator.isFirst();
+
+ }
+
+ public void testLast()
+ {
+ //Jumps to the last element
+ iterator.last();
+
+ //Makes sure that the iterator is pointing at the last element.
+ assert iterator.isLast();
+
+ iterator.first();
+
+ //Check that the iterator is NOT pointing at the last element.
+ assert !iterator.isLast();
+ }
+
+ public void testAfterFirst()
+ {
+ //Jump to the second element.
+ iterator.afterFirst();
+
+ //Check this
+ assert iterator.isAfterFirst();
+
+ //Previous element in the list
+ Object previous = iterator.previous();
+
+ //Check that previous is the first element.
+ assert previous == person2;
+
+ //Make sure that the iterator isn't pointing at the second element.
+ assert !iterator.isAfterFirst();
+
+ }
+
+ public void testBeforeLast()
+ {
+ //Jump to the penultimate element.
+ iterator.beforeLast();
+
+ //Check this
+ assert iterator.isBeforeLast();
+
+ //Next element - which should be the last.
+ Object next = iterator.next();
+
+ //Check that next is the penultimate element.
+ assert next == person9;
+
+ //Make sure that the iterator is not pointing at the penultimate element.
+ assert !iterator.isBeforeLast();
+ }
+
+ public void testIsFirst()
+ {
+ iterator.first();
+ assert iterator.isFirst();
+
+ iterator.next();
+ assert !iterator.isFirst();
+ }
+
+ public void testIsLast()
+ {
+ iterator.last();
+ assert iterator.isLast();
+
+ iterator.previous();
+ assert !iterator.isLast();
+ }
+
+ public void testIsAfterFirst()
+ {
+ iterator.afterFirst();
+ assert iterator.isAfterFirst();
+
+ iterator.previous();
+ assert !iterator.isAfterFirst();
+ }
+
+ public void testIsBeforeLast()
+ {
+ iterator.beforeLast();
+ assert iterator.isBeforeLast();
+ }
+
+ public void testNextAndHasNext()
+ {
+ iterator.first();
+
+ // This is so that we can "rebuild" the keystring for the nextAndHasNext and the previousAndHasPrevious methods.
+ builder = new StringBuilder();
+
+ for (int i = 1; i <= 10; i++)
+ {
+ builder.delete(0, 4); // In this case we know that there are 4 characters in this string. so each time we come into the loop we want to clear the builder.
+ builder.append("key");
+ builder.append(i);
+ String keyString = builder.toString();
+ Object expectedValue = searchableCache.get("/a", keyString);
+ assert iterator.hasNext(); // should have next as long as we are less than the number of elements.
+
+ Object next = iterator.next();
+
+ assert expectedValue == next; // tests next()
+ }
+ assert !iterator.hasNext(); // this should now NOT be true.
+ }
+
+ public void testPreviousAndHasPrevious()
+ {
+ iterator.last();
+
+ // This is so that we can "rebuild" the keystring for the nextAndHasNext and the previousAndHasPrevious methods.
+ builder = new StringBuilder();
+
+ for (int i = 10; i >= 1; i--)
+ {
+ builder.delete(0, 5); // In this case we know that there are 4 characters in this string. so each time we come into the loop we want to clear the builder.
+ builder.append("key");
+ builder.append(i);
+ String keyString = builder.toString();
+
+
+ Object expectedValue = searchableCache.get("/a", keyString);
+
+ assert iterator.hasPrevious(); // should have previous as long as we are less than the number of elements.
+
+ Object previous = iterator.previous();
+
+ assert expectedValue == previous; // tests previous()
+ }
+ assert !iterator.hasPrevious(); // this should now NOT be true.
+
+ }
+
+ public void testNextIndex()
+ {
+ iterator.first();
+ assert iterator.nextIndex() == 1;
+
+ iterator.last();
+ assert iterator.nextIndex() == 10; //Index will be the index of the last element + 1.
+
+ }
+
+ public void testPreviousIndex()
+ {
+ iterator.first();
+ assert iterator.previousIndex() == -1;
+
+ iterator.last();
+ assert iterator.previousIndex() == 8; //Index will be that of the last element - 1.
+ }
+
}
+
+
Modified: searchable/trunk/src/test/java/org/jboss/cache/search/QueryResultIteratorImplTest.java
===================================================================
--- searchable/trunk/src/test/java/org/jboss/cache/search/QueryResultIteratorImplTest.java 2008-09-25 14:38:10 UTC (rev 6789)
+++ searchable/trunk/src/test/java/org/jboss/cache/search/QueryResultIteratorImplTest.java 2008-09-25 15:38:36 UTC (rev 6790)
@@ -22,6 +22,7 @@
List<CacheEntityId> ids;
Map<CacheEntityId, Object> dummyResults;
QueryResultIterator iterator;
+ int fetchSize = 1;
@BeforeMethod
public void setUp()
@@ -52,7 +53,7 @@
// now create a dummy entity loader
CacheEntityLoader dummyLoader = new DummyEntityLoader(ids, dummyResults);
- iterator = new QueryResultIteratorImpl(ids, dummyLoader);
+ iterator = new QueryResultIteratorImpl(ids, dummyLoader, fetchSize);
}
@AfterMethod
@@ -149,7 +150,7 @@
assert next == dummyResults.get(ids.get(size - 2));
//Make sure that the iterator is not pointing at the penultimate element.
- assert !iterator.isAfterFirst();
+ assert !iterator.isBeforeLast();
}
public void testIsFirst()
@@ -190,6 +191,7 @@
iterator.first();
for (int i = 0; i < ids.size(); i++)
{
+ System.out.println("Loop number count: - " + (i+1));
Object expectedValue = dummyResults.get(ids.get(i));
assert iterator.hasNext(); // should have next as long as we are less than the number of elements.
assert expectedValue == iterator.next(); // tests next()
@@ -229,16 +231,6 @@
assert iterator.previousIndex() == (ids.size() - 2);
}
-// public void testPreviousAndNext()
-// {
-// iterator.jumpToResult(5);
-// for (int i = 0; i < 10; i++) // repeat 10 times
-// {
-// assert iterator.next() == iterator.previous();
-// }
-//
-// }
-
public static class DummyEntityLoader extends CacheEntityLoader
{
private List<CacheEntityId> allKnownIds;
More information about the jbosscache-commits
mailing list