You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ck...@apache.org on 2007/08/15 09:16:11 UTC
svn commit: r566042 - in
/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene:
./ hits/
Author: ckiehl
Date: Wed Aug 15 00:16:10 2007
New Revision: 566042
URL: http://svn.apache.org/viewvc?view=rev&rev=566042
Log:
JCR-1041: Avoid using BitSets in ChildAxisQuery to minimize memory usage
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/AdaptingHits.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/ArrayHits.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/BitSetHits.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/Hits.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/HitsIntersection.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/ScorerHits.java
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ChildAxisQuery.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ChildAxisQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ChildAxisQuery.java?view=diff&rev=566042&r1=566041&r2=566042
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ChildAxisQuery.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ChildAxisQuery.java Wed Aug 15 00:16:10 2007
@@ -18,6 +18,10 @@
import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.core.query.LocationStepQueryNode;
+import org.apache.jackrabbit.core.query.lucene.hits.AdaptingHits;
+import org.apache.jackrabbit.core.query.lucene.hits.Hits;
+import org.apache.jackrabbit.core.query.lucene.hits.HitsIntersection;
+import org.apache.jackrabbit.core.query.lucene.hits.ScorerHits;
import org.apache.jackrabbit.core.state.ItemStateException;
import org.apache.jackrabbit.core.state.ItemStateManager;
import org.apache.jackrabbit.core.state.NodeState;
@@ -37,7 +41,6 @@
import java.io.IOException;
import java.util.ArrayList;
-import java.util.BitSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -238,19 +241,14 @@
private final IndexReader reader;
/**
- * BitSet storing the id's of selected documents
- */
- private final BitSet hits;
-
- /**
- * List of UUIDs of selected nodes
+ * The next document id to return
*/
- private List uuids = null;
+ private int nextDoc = -1;
/**
- * The next document id to return
+ * A <code>Hits</code> instance containing all hits
*/
- private int nextDoc = -1;
+ private Hits hits;
/**
* Creates a new <code>ChildAxisScorer</code>.
@@ -261,7 +259,6 @@
protected ChildAxisScorer(Similarity similarity, IndexReader reader) {
super(similarity);
this.reader = reader;
- this.hits = new BitSet(reader.maxDoc());
}
/**
@@ -269,7 +266,10 @@
*/
public boolean next() throws IOException {
calculateChildren();
- nextDoc = hits.nextSetBit(nextDoc + 1);
+ do {
+ nextDoc = hits.next();
+ } while (nextDoc >= 0 && !indexIsValid(nextDoc));
+
return nextDoc > -1;
}
@@ -292,8 +292,10 @@
*/
public boolean skipTo(int target) throws IOException {
calculateChildren();
- nextDoc = hits.nextSetBit(target);
- return nextDoc > -1;
+ nextDoc = hits.skipTo(target);
+ while (!indexIsValid(nextDoc))
+ next();
+ return nextDoc > -1;
}
/**
@@ -307,117 +309,113 @@
}
private void calculateChildren() throws IOException {
- if (uuids == null) {
- uuids = new ArrayList();
+ if (hits == null) {
+
+ // collect all context nodes
+ List uuids = new ArrayList();
+ final Hits contextHits = new AdaptingHits();
contextScorer.score(new HitCollector() {
public void collect(int doc, float score) {
- hits.set(doc);
+ contextHits.set(doc);
}
});
- // collect nameTest hits
- final BitSet nameTestHits = new BitSet();
- if (nameTestScorer != null) {
- nameTestScorer.score(new HitCollector() {
- public void collect(int doc, float score) {
- nameTestHits.set(doc);
- }
- });
- }
-
// read the uuids of the context nodes
- for (int i = hits.nextSetBit(0); i >= 0; i = hits.nextSetBit(i + 1)) {
+ int i = contextHits.next();
+ while (i > -1) {
String uuid = reader.document(i).get(FieldNames.UUID);
uuids.add(uuid);
+ i = contextHits.next();
}
+
+ // collect all children of the context nodes
+ Hits childrenHits = new AdaptingHits();
- // collect the doc ids of all child nodes. we reuse the existing
- // bitset.
- hits.clear();
TermDocs docs = reader.termDocs();
try {
for (Iterator it = uuids.iterator(); it.hasNext();) {
docs.seek(new Term(FieldNames.PARENT, (String) it.next()));
while (docs.next()) {
- hits.set(docs.doc());
+ childrenHits.set(docs.doc());
}
}
} finally {
docs.close();
}
- // filter out the child nodes that do not match the name test
- // if there is any name test at all.
+
if (nameTestScorer != null) {
- hits.and(nameTestHits);
+ hits = new HitsIntersection(childrenHits, new ScorerHits(nameTestScorer));
+ } else {
+ hits = childrenHits;
}
+ }
+ }
- // filter by index
- if (position != LocationStepQueryNode.NONE) {
- for (int i = hits.nextSetBit(0); i >= 0; i = hits.nextSetBit(i + 1)) {
- Document node = reader.document(i);
- NodeId parentId = NodeId.valueOf(node.get(FieldNames.PARENT));
- NodeId id = NodeId.valueOf(node.get(FieldNames.UUID));
- try {
- NodeState state = (NodeState) itemMgr.getItemState(parentId);
- if (nameTest == null) {
- // only select this node if it is the child at
- // specified position
- if (position == LocationStepQueryNode.LAST) {
- // only select last
- List childNodes = state.getChildNodeEntries();
- if (childNodes.size() == 0
- || !((NodeState.ChildNodeEntry) childNodes.get(childNodes.size() - 1))
- .getId().equals(id)) {
- hits.flip(i);
- }
- } else {
- List childNodes = state.getChildNodeEntries();
- if (position < 1
- || childNodes.size() < position
- || !((NodeState.ChildNodeEntry) childNodes.get(position - 1)).getId().equals(id)) {
- hits.flip(i);
- }
+ private boolean indexIsValid(int i) throws IOException {
+ if (position != LocationStepQueryNode.NONE) {
+ Document node = reader.document(i);
+ NodeId parentId = NodeId.valueOf(node.get(FieldNames.PARENT));
+ NodeId id = NodeId.valueOf(node.get(FieldNames.UUID));
+ try {
+ NodeState state = (NodeState) itemMgr.getItemState(parentId);
+ if (nameTest == null) {
+ // only select this node if it is the child at
+ // specified position
+ if (position == LocationStepQueryNode.LAST) {
+ // only select last
+ List childNodes = state.getChildNodeEntries();
+ if (childNodes.size() == 0
+ || !((NodeState.ChildNodeEntry) childNodes.get(childNodes.size() - 1))
+ .getId().equals(id)) {
+ return false;
+ }
+ } else {
+ List childNodes = state.getChildNodeEntries();
+ if (position < 1
+ || childNodes.size() < position
+ || !((NodeState.ChildNodeEntry) childNodes.get(position - 1)).getId().equals(id)) {
+ return false;
+ }
+ }
+ } else {
+ // select the node when its index is equal to
+ // specified position
+ if (position == LocationStepQueryNode.LAST) {
+ // only select last
+ NodeState.ChildNodeEntry entry =
+ state.getChildNodeEntry(id);
+ if (entry == null) {
+ // no such child node, probably deleted meanwhile
+ return false;
+ } else {
+ // only use the last one
+ QName name = entry.getName();
+ List childNodes = state.getChildNodeEntries(name);
+ if (childNodes.size() == 0
+ || !((NodeState.ChildNodeEntry) childNodes.get(childNodes.size() - 1))
+ .getId().equals(id)) {
+ return false;
}
+ }
+ } else {
+ NodeState.ChildNodeEntry entry =
+ state.getChildNodeEntry(id);
+ if (entry == null) {
+ // no such child node, probably has been deleted meanwhile
+ return false;
} else {
- // select the node when its index is equal to
- // specified position
- if (position == LocationStepQueryNode.LAST) {
- // only select last
- NodeState.ChildNodeEntry entry =
- state.getChildNodeEntry(id);
- if (entry == null) {
- // no such child node, probably deleted meanwhile
- hits.flip(i);
- } else {
- // only use the last one
- QName name = entry.getName();
- List childNodes = state.getChildNodeEntries(name);
- if (childNodes.size() == 0
- || !((NodeState.ChildNodeEntry) childNodes.get(childNodes.size() - 1))
- .getId().equals(id)) {
- hits.flip(i);
- }
- }
- } else {
- NodeState.ChildNodeEntry entry =
- state.getChildNodeEntry(id);
- if (entry == null) {
- // no such child node, probably has been deleted meanwhile
- hits.flip(i);
- } else {
- if (entry.getIndex() != position) {
- hits.flip(i);
- }
- }
+ if (entry.getIndex() != position) {
+ return false;
}
}
- } catch (ItemStateException e) {
- // ignore this node, probably has been deleted meanwhile
- hits.flip(i);
}
}
+ } catch (ItemStateException e) {
+ // ignore this node, probably has been deleted meanwhile
+ return false;
}
}
+ return true;
}
}
}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/AdaptingHits.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/AdaptingHits.java?view=auto&rev=566042
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/AdaptingHits.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/AdaptingHits.java Wed Aug 15 00:16:10 2007
@@ -0,0 +1,123 @@
+/*
+ * 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.hits;
+
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is an implementation of Hits which starts with marking hits in an
+ * ArrayHits instance and switches to a BitSetHits instance if at least the
+ * threshold of 8kb for the ArrayHits is reached and a BitSetHits instance
+ * would consume less memory.
+ */
+public class AdaptingHits implements Hits {
+
+ /**
+ * Logger instance for this class.
+ */
+ private static final Logger log = LoggerFactory.getLogger(AdaptingHits.class);
+
+ /**
+ * The lower threshold before a conversion is tried
+ */
+ private static final int DEFAULT_THRESHOLD = 2048;
+
+ /**
+ * Internal hits instance
+ */
+ private Hits hits;
+
+ /**
+ * The maximum doc number in hits. Used to calculate the expected
+ * BitSetHits memory footprint.
+ */
+ private int maxDoc;
+
+ /**
+ * The total number of hits. Used to calculate the memory footprint of the
+ * initial ArrayHits instance.
+ */
+ private int docCount;
+
+ private int threshold;
+
+ public AdaptingHits() {
+ this(DEFAULT_THRESHOLD);
+ }
+
+ public AdaptingHits(int threshold) {
+ this.threshold = threshold;
+ hits = new ArrayHits();
+ maxDoc = 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int next() throws IOException {
+ // delegate to the internal Hits instance
+ return hits.next();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void set(int doc) {
+ hits.set(doc);
+ docCount++;
+ if (doc > maxDoc) {
+ maxDoc = doc;
+ }
+
+ if (docCount > threshold && (hits instanceof ArrayHits)) {
+ int intArraySize = docCount * 4;
+ int bitSetSize = maxDoc / 8;
+ if (bitSetSize < intArraySize) {
+ log.debug("BitSet is smaller than int[]: "
+ + bitSetSize + " vs " + intArraySize);
+ BitSetHits bitSetHits = new BitSetHits();
+ int i = 0;
+ while (i > -1) {
+ try {
+ i = hits.next();
+ if (i > -1)
+ bitSetHits.set(i);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ hits = bitSetHits;
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int skipTo(int target) throws IOException {
+ // delegate to the internal Hits instance
+ return hits.skipTo(target);
+ }
+
+ Hits getInternalHits() {
+ return hits;
+ }
+
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/ArrayHits.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/ArrayHits.java?view=auto&rev=566042
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/ArrayHits.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/ArrayHits.java Wed Aug 15 00:16:10 2007
@@ -0,0 +1,95 @@
+/*
+ * 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.hits;
+
+import java.util.Arrays;
+
+/**
+ * Uses an integer array to store the hit set. This implementation uses less
+ * memory than {@link BitSetHits} if the total number of documents is high and
+ * and the number of hits is low or if your hits doc numbers are mostly in the
+ * upper part of your doc number range.
+ * If you don't know about your hit distribution in advance use
+ * {@link AdaptingHits} instead.
+ */
+public class ArrayHits implements Hits {
+
+ private static final int INITIAL_SIZE = 100;
+ private int[] hits;
+ private int index;
+ private boolean initialized;
+
+ public ArrayHits() {
+ this(INITIAL_SIZE);
+ }
+
+ public ArrayHits(int initialSize) {
+ hits = new int[initialSize];
+ index = 0;
+ initialized = false;
+ }
+
+ private void initialize() {
+ if (!initialized) {
+ Arrays.sort(hits);
+ index = hits.length - index;
+ initialized = true;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void set(int doc) {
+ if (initialized) {
+ throw new IllegalStateException(
+ "You must not call set() after next() or skipTo()");
+ }
+ if (index >= hits.length) {
+ int[] resizedHits = new int[hits.length * 2];
+ System.arraycopy(hits, 0, resizedHits, 0, hits.length);
+ hits = resizedHits;
+ }
+ hits[index++] = doc;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int next() {
+ initialize();
+ if (index >= hits.length)
+ return -1;
+
+ return hits[index++];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int skipTo(int target) {
+ initialize();
+ for (int i = index; i < hits.length; i++) {
+ int nextDocValue = hits[i];
+ if (nextDocValue >= target) {
+ index = i;
+ break;
+ }
+ }
+ return next();
+ }
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/BitSetHits.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/BitSetHits.java?view=auto&rev=566042
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/BitSetHits.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/BitSetHits.java Wed Aug 15 00:16:10 2007
@@ -0,0 +1,58 @@
+/*
+ * 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.hits;
+
+import java.util.BitSet;
+
+/**
+ * Uses a BitSet instance to store the hit set. Keep in mind that this BitSet
+ * is at least as large as the highest doc number in the hit set. This means it
+ * might need of lot of memory for large indexes.
+ */
+public class BitSetHits implements Hits {
+ private BitSet hits;
+ private int index;
+
+ public BitSetHits() {
+ hits = new BitSet();
+ index = 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void set(int doc) {
+ hits.set(doc);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int next() {
+ int result = hits.nextSetBit(index);
+ index = result + 1;
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int skipTo(int target) {
+ index = target;
+ return next();
+ }
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/Hits.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/Hits.java?view=auto&rev=566042
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/Hits.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/Hits.java Wed Aug 15 00:16:10 2007
@@ -0,0 +1,45 @@
+/*
+ * 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.hits;
+
+import java.io.IOException;
+
+/**
+ * Representation of a set of hits
+ */
+public interface Hits {
+
+ /**
+ * Marks the document with doc number <code>doc</code> as a hit.
+ * Implementations may throw an exception if you call set() after next() or
+ * skipTo() has been called.
+ */
+ void set(int doc);
+
+ /**
+ * Return the doc number of the next hit in the set. Subsequent calls never
+ * return the same doc number.
+ */
+ int next() throws IOException;
+
+ /**
+ * Skips to the first match beyond the current whose document number is
+ * greater than or equal to the given target.
+ */
+ int skipTo(int target) throws IOException;
+
+}
\ No newline at end of file
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/HitsIntersection.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/HitsIntersection.java?view=auto&rev=566042
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/HitsIntersection.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/HitsIntersection.java Wed Aug 15 00:16:10 2007
@@ -0,0 +1,80 @@
+/*
+ * 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.hits;
+
+import java.io.IOException;
+
+/**
+ * Creates the intersection of two hit sets.
+ */
+public class HitsIntersection implements Hits {
+
+ private final Hits hits1;
+ private final Hits hits2;
+
+ private int nextChildrenHit = -1;
+ private int nextNameTestHit = -1;
+
+ public HitsIntersection(Hits hits1, Hits hits2) {
+ this.hits1 = hits1;
+ this.hits2 = hits2;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void set(int doc) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int next() throws IOException {
+ do {
+ if (nextChildrenHit == nextNameTestHit) {
+ nextNameTestHit = hits2.next();
+ nextChildrenHit = hits1.next();
+ } else if (nextNameTestHit < nextChildrenHit) {
+ nextNameTestHit = hits2.skipTo(nextChildrenHit);
+ } else {
+ nextChildrenHit = hits1.skipTo(nextNameTestHit);
+ }
+ } while (nextChildrenHit > -1 && nextNameTestHit > -1
+ && nextNameTestHit != nextChildrenHit);
+
+ int nextDoc = -1;
+ if (nextChildrenHit == nextNameTestHit) {
+ nextDoc = nextChildrenHit;
+ }
+ return nextDoc;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int skipTo(int target) throws IOException {
+ nextChildrenHit = hits1.skipTo(target);
+ nextNameTestHit = hits2.skipTo(target);
+ if (nextChildrenHit == nextNameTestHit) {
+ return nextChildrenHit;
+ } else {
+ return next();
+ }
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/ScorerHits.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/ScorerHits.java?view=auto&rev=566042
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/ScorerHits.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/hits/ScorerHits.java Wed Aug 15 00:16:10 2007
@@ -0,0 +1,62 @@
+/*
+ * 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.hits;
+
+import java.io.IOException;
+
+import org.apache.lucene.search.Scorer;
+
+/**
+ * Wraps a {@link org.apache.lucene.search.Scorer} in a {@link Hits} instance.
+ */
+public class ScorerHits implements Hits {
+
+ private final Scorer scorer;
+
+ public ScorerHits(Scorer scorer) {
+ this.scorer = scorer;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void set(int doc) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int next() throws IOException {
+ if (scorer.next()) {
+ return scorer.doc();
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int skipTo(int target) throws IOException {
+ if (scorer.skipTo(target)) {
+ return scorer.doc();
+ } else {
+ return -1;
+ }
+ }
+}