Author: mreutegg
Date: Wed Dec 5 06:19:18 2007
New Revision: 601342
URL: http://svn.apache.org/viewvc?rev=601342&view=rev
Log:
JCR-1213: UUIDDocId cache does not work properly because of weakReferences in combination
with new instance for combined indexreader
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ForeignSegmentDocId.java
(with props)
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/CachingMultiReader.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DocId.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndex.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndexReader.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ReadOnlyIndexReader.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedIndexReader.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/CachingMultiReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/CachingMultiReader.java?rev=601342&r1=601341&r2=601342&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/CachingMultiReader.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/CachingMultiReader.java
Wed Dec 5 06:19:18 2007
@@ -16,6 +16,7 @@
*/
package org.apache.jackrabbit.core.query.lucene;
+import org.apache.jackrabbit.uuid.UUID;
import org.apache.lucene.index.MultiReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
@@ -24,6 +25,7 @@
import java.io.IOException;
import java.util.Map;
import java.util.IdentityHashMap;
+import java.util.HashMap;
/**
* Extends a <code>MultiReader</code> with support for cached <code>TermDocs</code>
@@ -44,6 +46,11 @@
private final Map readersByBase = new IdentityHashMap();
/**
+ * Map of {@link OffsetReader}s, identified by creation tick.
+ */
+ private final Map readersByCreationTick = new HashMap();
+
+ /**
* Document number cache if available. May be <code>null</code>.
*/
private final DocNumberCache cache;
@@ -79,6 +86,8 @@
maxDoc += subReaders[i].maxDoc();
OffsetReader offsetReader = new OffsetReader(subReaders[i], starts[i]);
readersByBase.put(subReaders[i].getBase().getBase(), offsetReader);
+ readersByCreationTick.put(
+ Long.valueOf(subReaders[i].getCreationTick()), offsetReader);
}
starts[subReaders.length] = maxDoc;
}
@@ -176,8 +185,40 @@
return readers;
}
- //------------------------< internal >--------------------------------------
+ /**
+ * {@inheritDoc}
+ */
+ public ForeignSegmentDocId createDocId(UUID uuid) throws IOException {
+ Term id = new Term(FieldNames.UUID, uuid.toString());
+ int doc;
+ long tick;
+ for (int i = 0; i < subReaders.length; i++) {
+ TermDocs docs = subReaders[i].termDocs(id);
+ try {
+ if (docs.next()) {
+ doc = docs.doc();
+ tick = subReaders[i].getCreationTick();
+ return new ForeignSegmentDocId(doc, tick);
+ }
+ } finally {
+ docs.close();
+ }
+ }
+ return null;
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public int getDocumentNumber(ForeignSegmentDocId docId) {
+ OffsetReader r = (OffsetReader) readersByCreationTick.get(
+ new Long(docId.getCreationTick()));
+ if (r != null && !r.reader.isDeleted(docId.getDocNumber())) {
+ return r.offset + docId.getDocNumber();
+ }
+ return -1;
+ }
+
/**
* Returns the reader index for document <code>n</code>.
* Implementation copied from lucene MultiReader class.
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DocId.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DocId.java?rev=601342&r1=601341&r2=601342&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DocId.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DocId.java
Wed Dec 5 06:19:18 2007
@@ -16,15 +16,10 @@
*/
package org.apache.jackrabbit.core.query.lucene;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermDocs;
import org.apache.jackrabbit.uuid.UUID;
import java.io.IOException;
import java.util.BitSet;
-import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
/**
* Implements a document id which can be based on a Node uuid or a lucene
@@ -43,7 +38,7 @@
* @param reader the index reader.
* @return always <code>-1</code>.
*/
- final int getDocumentNumber(IndexReader reader) {
+ final int getDocumentNumber(MultiIndexReader reader) {
return -1;
}
@@ -75,7 +70,7 @@
* if it is invalid (e.g. does not exist).
* @throws IOException if an error occurs while reading from the index.
*/
- abstract int getDocumentNumber(IndexReader reader) throws IOException;
+ abstract int getDocumentNumber(MultiIndexReader reader) throws IOException;
/**
* Applies an offset to this <code>DocId</code>. The returned <code>DocId</code>
@@ -141,7 +136,7 @@
/**
* @inheritDoc
*/
- int getDocumentNumber(IndexReader reader) {
+ int getDocumentNumber(MultiIndexReader reader) {
return docNumber;
}
@@ -185,17 +180,10 @@
private final long msb;
/**
- * The index reader that was used to calculate the document number.
- * If <code>null</code> then the document number has not yet been
- * calculated.
+ * The previously calculated foreign segment document id.
*/
- private Reference reader;
-
- /**
- * The previously calculated document number.
- */
- private int docNumber;
-
+ private ForeignSegmentDocId doc;
+
/**
* Creates a <code>DocId</code> based on a Node uuid.
*
@@ -212,32 +200,26 @@
/**
* @inheritDoc
*/
- int getDocumentNumber(IndexReader reader) throws IOException {
- synchronized (this) {
- if (this.reader != null && reader.equals(this.reader.get())) {
- return docNumber;
- }
+ int getDocumentNumber(MultiIndexReader reader) throws IOException {
+ int realDoc = -1;
+ ForeignSegmentDocId segDocId = doc;
+ if (segDocId != null) {
+ realDoc = reader.getDocumentNumber(segDocId);
}
- Term id = new Term(FieldNames.UUID, new UUID(msb, lsb).toString());
- TermDocs docs = reader.termDocs(id);
- int doc = -1;
- try {
- if (docs.next()) {
- doc = docs.doc();
+ if (realDoc == -1) {
+ // Cached doc was invalid => create new one
+ segDocId = reader.createDocId(new UUID(msb, lsb));
+ if (segDocId != null) {
+ realDoc = reader.getDocumentNumber(segDocId);
+ doc = segDocId;
}
- } finally {
- docs.close();
- }
- synchronized (this) {
- docNumber = doc;
- this.reader = new WeakReference(reader);
}
- return doc;
+ return realDoc;
}
/**
* This implementation will return <code>this</code>. Document number
is
- * not known until resolved in {@link #getDocumentNumber(IndexReader)}.
+ * not known until resolved in {@link #getDocumentNumber(MultiIndexReader)}.
*
* @inheritDoc
*/
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ForeignSegmentDocId.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ForeignSegmentDocId.java?rev=601342&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ForeignSegmentDocId.java
(added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ForeignSegmentDocId.java
Wed Dec 5 06:19:18 2007
@@ -0,0 +1,94 @@
+/*
+ * 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.io.IOException;
+import java.util.BitSet;
+
+/**
+ * A <code>DocId</code> that contains a document number and the creation tick
+ * of the index segment.
+ */
+final class ForeignSegmentDocId extends DocId {
+
+ /**
+ * The document number.
+ */
+ private final int docNumber;
+
+ /**
+ * The creation tick of the index segment.
+ */
+ private final long creationTick;
+
+ /**
+ * Creates a <code>DocId</code> based on a document number in the index
+ * segment with the given <code>creationTick</code>.
+ *
+ * @param docNumber the lucene document number.
+ * @param creationTick the creation tick of the index segment.
+ */
+ ForeignSegmentDocId(int docNumber, long creationTick) {
+ this.docNumber = docNumber;
+ this.creationTick = creationTick;
+ }
+
+ /**
+ * @return the document number in the foreign index segment.
+ */
+ int getDocNumber() {
+ return docNumber;
+ }
+
+ /**
+ * @return the creation tick of the foreign index segment.
+ */
+ long getCreationTick() {
+ return creationTick;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ int getDocumentNumber(MultiIndexReader reader) throws IOException {
+ return reader.getDocumentNumber(this);
+ }
+
+ /**
+ * This implementation will return <code>this</code>. Document number is
+ * not known until resolved in {@link #getDocumentNumber(MultiIndexReader)}.
+ *
+ * {@inheritDoc}
+ */
+ DocId applyOffset(int offset) {
+ return this;
+ }
+
+ /**
+ * Always returns <code>true</code> because this calls is in context of the
+ * index segment where this DocId lives. Within this segment this DocId is
+ * always valid. Whether the target of this DocId is valid can only be
+ * checked in the method {@link #getDocumentNumber(MultiIndexReader)}.
+ *
+ * @param deleted the deleted documents in the segment where this DocId
+ * lives.
+ * @return always <code>true</code>.
+ */
+ boolean isValid(BitSet deleted) {
+ return true;
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ForeignSegmentDocId.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndex.java?rev=601342&r1=601341&r2=601342&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndex.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndex.java
Wed Dec 5 06:19:18 2007
@@ -689,7 +689,7 @@
* @return an <code>IndexReader</code>.
* @throws IOException if an error occurs constructing the <code>IndexReader</code>.
*/
- public IndexReader getIndexReader() throws IOException {
+ public CachingMultiReader getIndexReader() throws IOException {
synchronized (updateMonitor) {
if (multiReader != null) {
multiReader.incrementRefCount();
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndexReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndexReader.java?rev=601342&r1=601341&r2=601342&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndexReader.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiIndexReader.java
Wed Dec 5 06:19:18 2007
@@ -17,6 +17,9 @@
package org.apache.jackrabbit.core.query.lucene;
import org.apache.lucene.index.IndexReader;
+import org.apache.jackrabbit.uuid.UUID;
+
+import java.io.IOException;
/**
* <code>MultiIndexReader</code> exposes methods to get access to the contained
@@ -29,4 +32,25 @@
* <code>MultiIndexReader</code>.
*/
public IndexReader[] getIndexReaders();
+
+ /**
+ * Creates a document id for the given <code>uuid</code>.
+ *
+ * @param uuid the uuid of the node.
+ * @return a foreign segment doc id or <code>null</code> if there is no node
+ * with the given <code>uuid</code>.
+ * @throws IOException if an error occurs while reading from the index.
+ */
+ public ForeignSegmentDocId createDocId(UUID uuid) throws IOException;
+
+ /**
+ * Returns the document number for the passed <code>docId</code>. If the
id
+ * is invalid <code>-1</code> is returned.
+ *
+ * @param docId the document id to resolve.
+ * @return the document number or <code>-1</code> if it is invalid (e.g.
+ * does not exist).
+ * @throws IOException if an error occurs while reading from the index.
+ */
+ public int getDocumentNumber(ForeignSegmentDocId docId) throws IOException;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ReadOnlyIndexReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ReadOnlyIndexReader.java?rev=601342&r1=601341&r2=601342&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ReadOnlyIndexReader.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ReadOnlyIndexReader.java
Wed Dec 5 06:19:18 2007
@@ -98,6 +98,16 @@
}
/**
+ * Returns the tick value when the underlying {@link CachingIndexReader} was
+ * created.
+ *
+ * @return the creation tick for the underlying reader.
+ */
+ long getCreationTick() {
+ return reader.getCreationTick();
+ }
+
+ /**
* Updates the deleted documents in this index reader. When this method
* returns this index reader will have the same documents marked as deleted
* as the passed <code>reader</code>.
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java?rev=601342&r1=601341&r2=601342&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
Wed Dec 5 06:19:18 2007
@@ -770,19 +770,18 @@
protected IndexReader getIndexReader(boolean includeSystemIndex)
throws IOException {
QueryHandler parentHandler = getContext().getParentHandler();
- IndexReader parentReader = null;
+ CachingMultiReader parentReader = null;
if (parentHandler instanceof SearchIndex && includeSystemIndex) {
parentReader = ((SearchIndex) parentHandler).index.getIndexReader();
}
- IndexReader reader = index.getIndexReader();
+ CachingMultiReader reader = index.getIndexReader();
if (parentReader != null) {
- // todo FIXME not type safe
- CachingMultiReader[] readers = {(CachingMultiReader) reader,
- (CachingMultiReader) parentReader};
- reader = new CombinedIndexReader(readers);
+ CachingMultiReader[] readers = {reader, parentReader};
+ return new CombinedIndexReader(readers);
+ } else {
+ return reader;
}
- return reader;
}
/**
@@ -1190,6 +1189,34 @@
hash = 31 * hash + subReaders[i].hashCode();
}
return hash;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ForeignSegmentDocId createDocId(UUID uuid) throws IOException {
+ for (int i = 0; i < subReaders.length; i++) {
+ CachingMultiReader subReader = subReaders[i];
+ ForeignSegmentDocId doc = subReader.createDocId(uuid);
+ if (doc != null) {
+ return doc;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getDocumentNumber(ForeignSegmentDocId docId) {
+ for (int i = 0; i < subReaders.length; i++) {
+ CachingMultiReader subReader = subReaders[i];
+ int realDoc = subReader.getDocumentNumber(docId);
+ if (realDoc >= 0) {
+ return realDoc;
+ }
+ }
+ return -1;
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedIndexReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedIndexReader.java?rev=601342&r1=601341&r2=601342&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedIndexReader.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedIndexReader.java
Wed Dec 5 06:19:18 2007
@@ -55,6 +55,16 @@
}
/**
+ * Returns the tick value when the underlying {@link CachingIndexReader} was
+ * created.
+ *
+ * @return the creation tick for the underlying reader.
+ */
+ long getCreationTick() {
+ return getBase().getCreationTick();
+ }
+
+ /**
* Returns the <code>DocId</code> of the parent of <code>n</code>
or
* {@link DocId#NULL} if <code>n</code> does not have a parent
* (<code>n</code> is the root node).
|