MultiSegmentReader doesn't have svn:eol-style=native, and was commited with DOS line endings ... hopefully just setting the property will fix it

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@576731 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Chris M. Hostetter 2007-09-18 06:46:17 +00:00
parent e7179ea866
commit ec0c99a3c6
1 changed files with 475 additions and 475 deletions

View File

@ -1,475 +1,475 @@
package org.apache.lucene.index; package org.apache.lucene.index;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. * this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0 * 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 not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import org.apache.lucene.document.Document; import org.apache.lucene.document.Document;
import org.apache.lucene.document.FieldSelector; import org.apache.lucene.document.FieldSelector;
import org.apache.lucene.store.Directory; import org.apache.lucene.store.Directory;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Set; import java.util.Set;
/** /**
* An IndexReader which reads indexes with multiple segments. * An IndexReader which reads indexes with multiple segments.
*/ */
class MultiSegmentReader extends IndexReader { class MultiSegmentReader extends IndexReader {
protected IndexReader[] subReaders; protected IndexReader[] subReaders;
private int[] starts; // 1st docno for each segment private int[] starts; // 1st docno for each segment
private Hashtable normsCache = new Hashtable(); private Hashtable normsCache = new Hashtable();
private int maxDoc = 0; private int maxDoc = 0;
private int numDocs = -1; private int numDocs = -1;
private boolean hasDeletions = false; private boolean hasDeletions = false;
/** Construct reading the named set of readers. */ /** Construct reading the named set of readers. */
MultiSegmentReader(Directory directory, SegmentInfos sis, boolean closeDirectory, IndexReader[] subReaders) { MultiSegmentReader(Directory directory, SegmentInfos sis, boolean closeDirectory, IndexReader[] subReaders) {
super(directory, sis, closeDirectory); super(directory, sis, closeDirectory);
initialize(subReaders); initialize(subReaders);
} }
private void initialize(IndexReader[] subReaders) { private void initialize(IndexReader[] subReaders) {
this.subReaders = subReaders; this.subReaders = subReaders;
starts = new int[subReaders.length + 1]; // build starts array starts = new int[subReaders.length + 1]; // build starts array
for (int i = 0; i < subReaders.length; i++) { for (int i = 0; i < subReaders.length; i++) {
starts[i] = maxDoc; starts[i] = maxDoc;
maxDoc += subReaders[i].maxDoc(); // compute maxDocs maxDoc += subReaders[i].maxDoc(); // compute maxDocs
if (subReaders[i].hasDeletions()) if (subReaders[i].hasDeletions())
hasDeletions = true; hasDeletions = true;
} }
starts[subReaders.length] = maxDoc; starts[subReaders.length] = maxDoc;
} }
public TermFreqVector[] getTermFreqVectors(int n) throws IOException { public TermFreqVector[] getTermFreqVectors(int n) throws IOException {
ensureOpen(); ensureOpen();
int i = readerIndex(n); // find segment num int i = readerIndex(n); // find segment num
return subReaders[i].getTermFreqVectors(n - starts[i]); // dispatch to segment return subReaders[i].getTermFreqVectors(n - starts[i]); // dispatch to segment
} }
public TermFreqVector getTermFreqVector(int n, String field) public TermFreqVector getTermFreqVector(int n, String field)
throws IOException { throws IOException {
ensureOpen(); ensureOpen();
int i = readerIndex(n); // find segment num int i = readerIndex(n); // find segment num
return subReaders[i].getTermFreqVector(n - starts[i], field); return subReaders[i].getTermFreqVector(n - starts[i], field);
} }
public void getTermFreqVector(int docNumber, String field, TermVectorMapper mapper) throws IOException { public void getTermFreqVector(int docNumber, String field, TermVectorMapper mapper) throws IOException {
ensureOpen(); ensureOpen();
int i = readerIndex(docNumber); // find segment num int i = readerIndex(docNumber); // find segment num
subReaders[i].getTermFreqVector(docNumber - starts[i], field, mapper); subReaders[i].getTermFreqVector(docNumber - starts[i], field, mapper);
} }
public void getTermFreqVector(int docNumber, TermVectorMapper mapper) throws IOException { public void getTermFreqVector(int docNumber, TermVectorMapper mapper) throws IOException {
ensureOpen(); ensureOpen();
int i = readerIndex(docNumber); // find segment num int i = readerIndex(docNumber); // find segment num
subReaders[i].getTermFreqVector(docNumber - starts[i], mapper); subReaders[i].getTermFreqVector(docNumber - starts[i], mapper);
} }
public boolean isOptimized() { public boolean isOptimized() {
return false; return false;
} }
public synchronized int numDocs() { public synchronized int numDocs() {
// Don't call ensureOpen() here (it could affect performance) // Don't call ensureOpen() here (it could affect performance)
if (numDocs == -1) { // check cache if (numDocs == -1) { // check cache
int n = 0; // cache miss--recompute int n = 0; // cache miss--recompute
for (int i = 0; i < subReaders.length; i++) for (int i = 0; i < subReaders.length; i++)
n += subReaders[i].numDocs(); // sum from readers n += subReaders[i].numDocs(); // sum from readers
numDocs = n; numDocs = n;
} }
return numDocs; return numDocs;
} }
public int maxDoc() { public int maxDoc() {
// Don't call ensureOpen() here (it could affect performance) // Don't call ensureOpen() here (it could affect performance)
return maxDoc; return maxDoc;
} }
// inherit javadoc // inherit javadoc
public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
ensureOpen(); ensureOpen();
int i = readerIndex(n); // find segment num int i = readerIndex(n); // find segment num
return subReaders[i].document(n - starts[i], fieldSelector); // dispatch to segment reader return subReaders[i].document(n - starts[i], fieldSelector); // dispatch to segment reader
} }
public boolean isDeleted(int n) { public boolean isDeleted(int n) {
// Don't call ensureOpen() here (it could affect performance) // Don't call ensureOpen() here (it could affect performance)
int i = readerIndex(n); // find segment num int i = readerIndex(n); // find segment num
return subReaders[i].isDeleted(n - starts[i]); // dispatch to segment reader return subReaders[i].isDeleted(n - starts[i]); // dispatch to segment reader
} }
public boolean hasDeletions() { public boolean hasDeletions() {
// Don't call ensureOpen() here (it could affect performance) // Don't call ensureOpen() here (it could affect performance)
return hasDeletions; return hasDeletions;
} }
protected void doDelete(int n) throws CorruptIndexException, IOException { protected void doDelete(int n) throws CorruptIndexException, IOException {
numDocs = -1; // invalidate cache numDocs = -1; // invalidate cache
int i = readerIndex(n); // find segment num int i = readerIndex(n); // find segment num
subReaders[i].deleteDocument(n - starts[i]); // dispatch to segment reader subReaders[i].deleteDocument(n - starts[i]); // dispatch to segment reader
hasDeletions = true; hasDeletions = true;
} }
protected void doUndeleteAll() throws CorruptIndexException, IOException { protected void doUndeleteAll() throws CorruptIndexException, IOException {
for (int i = 0; i < subReaders.length; i++) for (int i = 0; i < subReaders.length; i++)
subReaders[i].undeleteAll(); subReaders[i].undeleteAll();
hasDeletions = false; hasDeletions = false;
numDocs = -1; // invalidate cache numDocs = -1; // invalidate cache
} }
private int readerIndex(int n) { // find reader for doc n: private int readerIndex(int n) { // find reader for doc n:
int lo = 0; // search starts array int lo = 0; // search starts array
int hi = subReaders.length - 1; // for first element less int hi = subReaders.length - 1; // for first element less
while (hi >= lo) { while (hi >= lo) {
int mid = (lo + hi) >> 1; int mid = (lo + hi) >> 1;
int midValue = starts[mid]; int midValue = starts[mid];
if (n < midValue) if (n < midValue)
hi = mid - 1; hi = mid - 1;
else if (n > midValue) else if (n > midValue)
lo = mid + 1; lo = mid + 1;
else { // found a match else { // found a match
while (mid+1 < subReaders.length && starts[mid+1] == midValue) { while (mid+1 < subReaders.length && starts[mid+1] == midValue) {
mid++; // scan to last match mid++; // scan to last match
} }
return mid; return mid;
} }
} }
return hi; return hi;
} }
public boolean hasNorms(String field) throws IOException { public boolean hasNorms(String field) throws IOException {
ensureOpen(); ensureOpen();
for (int i = 0; i < subReaders.length; i++) { for (int i = 0; i < subReaders.length; i++) {
if (subReaders[i].hasNorms(field)) return true; if (subReaders[i].hasNorms(field)) return true;
} }
return false; return false;
} }
private byte[] ones; private byte[] ones;
private byte[] fakeNorms() { private byte[] fakeNorms() {
if (ones==null) ones=SegmentReader.createFakeNorms(maxDoc()); if (ones==null) ones=SegmentReader.createFakeNorms(maxDoc());
return ones; return ones;
} }
public synchronized byte[] norms(String field) throws IOException { public synchronized byte[] norms(String field) throws IOException {
ensureOpen(); ensureOpen();
byte[] bytes = (byte[])normsCache.get(field); byte[] bytes = (byte[])normsCache.get(field);
if (bytes != null) if (bytes != null)
return bytes; // cache hit return bytes; // cache hit
if (!hasNorms(field)) if (!hasNorms(field))
return fakeNorms(); return fakeNorms();
bytes = new byte[maxDoc()]; bytes = new byte[maxDoc()];
for (int i = 0; i < subReaders.length; i++) for (int i = 0; i < subReaders.length; i++)
subReaders[i].norms(field, bytes, starts[i]); subReaders[i].norms(field, bytes, starts[i]);
normsCache.put(field, bytes); // update cache normsCache.put(field, bytes); // update cache
return bytes; return bytes;
} }
public synchronized void norms(String field, byte[] result, int offset) public synchronized void norms(String field, byte[] result, int offset)
throws IOException { throws IOException {
ensureOpen(); ensureOpen();
byte[] bytes = (byte[])normsCache.get(field); byte[] bytes = (byte[])normsCache.get(field);
if (bytes==null && !hasNorms(field)) bytes=fakeNorms(); if (bytes==null && !hasNorms(field)) bytes=fakeNorms();
if (bytes != null) // cache hit if (bytes != null) // cache hit
System.arraycopy(bytes, 0, result, offset, maxDoc()); System.arraycopy(bytes, 0, result, offset, maxDoc());
for (int i = 0; i < subReaders.length; i++) // read from segments for (int i = 0; i < subReaders.length; i++) // read from segments
subReaders[i].norms(field, result, offset + starts[i]); subReaders[i].norms(field, result, offset + starts[i]);
} }
protected void doSetNorm(int n, String field, byte value) protected void doSetNorm(int n, String field, byte value)
throws CorruptIndexException, IOException { throws CorruptIndexException, IOException {
normsCache.remove(field); // clear cache normsCache.remove(field); // clear cache
int i = readerIndex(n); // find segment num int i = readerIndex(n); // find segment num
subReaders[i].setNorm(n-starts[i], field, value); // dispatch subReaders[i].setNorm(n-starts[i], field, value); // dispatch
} }
public TermEnum terms() throws IOException { public TermEnum terms() throws IOException {
ensureOpen(); ensureOpen();
return new MultiTermEnum(subReaders, starts, null); return new MultiTermEnum(subReaders, starts, null);
} }
public TermEnum terms(Term term) throws IOException { public TermEnum terms(Term term) throws IOException {
ensureOpen(); ensureOpen();
return new MultiTermEnum(subReaders, starts, term); return new MultiTermEnum(subReaders, starts, term);
} }
public int docFreq(Term t) throws IOException { public int docFreq(Term t) throws IOException {
ensureOpen(); ensureOpen();
int total = 0; // sum freqs in segments int total = 0; // sum freqs in segments
for (int i = 0; i < subReaders.length; i++) for (int i = 0; i < subReaders.length; i++)
total += subReaders[i].docFreq(t); total += subReaders[i].docFreq(t);
return total; return total;
} }
public TermDocs termDocs() throws IOException { public TermDocs termDocs() throws IOException {
ensureOpen(); ensureOpen();
return new MultiTermDocs(subReaders, starts); return new MultiTermDocs(subReaders, starts);
} }
public TermPositions termPositions() throws IOException { public TermPositions termPositions() throws IOException {
ensureOpen(); ensureOpen();
return new MultiTermPositions(subReaders, starts); return new MultiTermPositions(subReaders, starts);
} }
protected void doCommit() throws IOException { protected void doCommit() throws IOException {
for (int i = 0; i < subReaders.length; i++) for (int i = 0; i < subReaders.length; i++)
subReaders[i].commit(); subReaders[i].commit();
} }
void startCommit() { void startCommit() {
super.startCommit(); super.startCommit();
for (int i = 0; i < subReaders.length; i++) { for (int i = 0; i < subReaders.length; i++) {
subReaders[i].startCommit(); subReaders[i].startCommit();
} }
} }
void rollbackCommit() { void rollbackCommit() {
super.rollbackCommit(); super.rollbackCommit();
for (int i = 0; i < subReaders.length; i++) { for (int i = 0; i < subReaders.length; i++) {
subReaders[i].rollbackCommit(); subReaders[i].rollbackCommit();
} }
} }
protected synchronized void doClose() throws IOException { protected synchronized void doClose() throws IOException {
for (int i = 0; i < subReaders.length; i++) for (int i = 0; i < subReaders.length; i++)
subReaders[i].close(); subReaders[i].close();
} }
public Collection getFieldNames (IndexReader.FieldOption fieldNames) { public Collection getFieldNames (IndexReader.FieldOption fieldNames) {
// maintain a unique set of field names // maintain a unique set of field names
ensureOpen(); ensureOpen();
Set fieldSet = new HashSet(); Set fieldSet = new HashSet();
for (int i = 0; i < subReaders.length; i++) { for (int i = 0; i < subReaders.length; i++) {
IndexReader reader = subReaders[i]; IndexReader reader = subReaders[i];
Collection names = reader.getFieldNames(fieldNames); Collection names = reader.getFieldNames(fieldNames);
fieldSet.addAll(names); fieldSet.addAll(names);
} }
return fieldSet; return fieldSet;
} }
static class MultiTermEnum extends TermEnum { static class MultiTermEnum extends TermEnum {
private SegmentMergeQueue queue; private SegmentMergeQueue queue;
private Term term; private Term term;
private int docFreq; private int docFreq;
public MultiTermEnum(IndexReader[] readers, int[] starts, Term t) public MultiTermEnum(IndexReader[] readers, int[] starts, Term t)
throws IOException { throws IOException {
queue = new SegmentMergeQueue(readers.length); queue = new SegmentMergeQueue(readers.length);
for (int i = 0; i < readers.length; i++) { for (int i = 0; i < readers.length; i++) {
IndexReader reader = readers[i]; IndexReader reader = readers[i];
TermEnum termEnum; TermEnum termEnum;
if (t != null) { if (t != null) {
termEnum = reader.terms(t); termEnum = reader.terms(t);
} else } else
termEnum = reader.terms(); termEnum = reader.terms();
SegmentMergeInfo smi = new SegmentMergeInfo(starts[i], termEnum, reader); SegmentMergeInfo smi = new SegmentMergeInfo(starts[i], termEnum, reader);
if (t == null ? smi.next() : termEnum.term() != null) if (t == null ? smi.next() : termEnum.term() != null)
queue.put(smi); // initialize queue queue.put(smi); // initialize queue
else else
smi.close(); smi.close();
} }
if (t != null && queue.size() > 0) { if (t != null && queue.size() > 0) {
next(); next();
} }
} }
public boolean next() throws IOException { public boolean next() throws IOException {
SegmentMergeInfo top = (SegmentMergeInfo)queue.top(); SegmentMergeInfo top = (SegmentMergeInfo)queue.top();
if (top == null) { if (top == null) {
term = null; term = null;
return false; return false;
} }
term = top.term; term = top.term;
docFreq = 0; docFreq = 0;
while (top != null && term.compareTo(top.term) == 0) { while (top != null && term.compareTo(top.term) == 0) {
queue.pop(); queue.pop();
docFreq += top.termEnum.docFreq(); // increment freq docFreq += top.termEnum.docFreq(); // increment freq
if (top.next()) if (top.next())
queue.put(top); // restore queue queue.put(top); // restore queue
else else
top.close(); // done with a segment top.close(); // done with a segment
top = (SegmentMergeInfo)queue.top(); top = (SegmentMergeInfo)queue.top();
} }
return true; return true;
} }
public Term term() { public Term term() {
return term; return term;
} }
public int docFreq() { public int docFreq() {
return docFreq; return docFreq;
} }
public void close() throws IOException { public void close() throws IOException {
queue.close(); queue.close();
} }
} }
static class MultiTermDocs implements TermDocs { static class MultiTermDocs implements TermDocs {
protected IndexReader[] readers; protected IndexReader[] readers;
protected int[] starts; protected int[] starts;
protected Term term; protected Term term;
protected int base = 0; protected int base = 0;
protected int pointer = 0; protected int pointer = 0;
private TermDocs[] readerTermDocs; private TermDocs[] readerTermDocs;
protected TermDocs current; // == readerTermDocs[pointer] protected TermDocs current; // == readerTermDocs[pointer]
public MultiTermDocs(IndexReader[] r, int[] s) { public MultiTermDocs(IndexReader[] r, int[] s) {
readers = r; readers = r;
starts = s; starts = s;
readerTermDocs = new TermDocs[r.length]; readerTermDocs = new TermDocs[r.length];
} }
public int doc() { public int doc() {
return base + current.doc(); return base + current.doc();
} }
public int freq() { public int freq() {
return current.freq(); return current.freq();
} }
public void seek(Term term) { public void seek(Term term) {
this.term = term; this.term = term;
this.base = 0; this.base = 0;
this.pointer = 0; this.pointer = 0;
this.current = null; this.current = null;
} }
public void seek(TermEnum termEnum) throws IOException { public void seek(TermEnum termEnum) throws IOException {
seek(termEnum.term()); seek(termEnum.term());
} }
public boolean next() throws IOException { public boolean next() throws IOException {
for(;;) { for(;;) {
if (current!=null && current.next()) { if (current!=null && current.next()) {
return true; return true;
} }
else if (pointer < readers.length) { else if (pointer < readers.length) {
base = starts[pointer]; base = starts[pointer];
current = termDocs(pointer++); current = termDocs(pointer++);
} else { } else {
return false; return false;
} }
} }
} }
/** Optimized implementation. */ /** Optimized implementation. */
public int read(final int[] docs, final int[] freqs) throws IOException { public int read(final int[] docs, final int[] freqs) throws IOException {
while (true) { while (true) {
while (current == null) { while (current == null) {
if (pointer < readers.length) { // try next segment if (pointer < readers.length) { // try next segment
base = starts[pointer]; base = starts[pointer];
current = termDocs(pointer++); current = termDocs(pointer++);
} else { } else {
return 0; return 0;
} }
} }
int end = current.read(docs, freqs); int end = current.read(docs, freqs);
if (end == 0) { // none left in segment if (end == 0) { // none left in segment
current = null; current = null;
} else { // got some } else { // got some
final int b = base; // adjust doc numbers final int b = base; // adjust doc numbers
for (int i = 0; i < end; i++) for (int i = 0; i < end; i++)
docs[i] += b; docs[i] += b;
return end; return end;
} }
} }
} }
/* A Possible future optimization could skip entire segments */ /* A Possible future optimization could skip entire segments */
public boolean skipTo(int target) throws IOException { public boolean skipTo(int target) throws IOException {
for(;;) { for(;;) {
if (current != null && current.skipTo(target-base)) { if (current != null && current.skipTo(target-base)) {
return true; return true;
} else if (pointer < readers.length) { } else if (pointer < readers.length) {
base = starts[pointer]; base = starts[pointer];
current = termDocs(pointer++); current = termDocs(pointer++);
} else } else
return false; return false;
} }
} }
private TermDocs termDocs(int i) throws IOException { private TermDocs termDocs(int i) throws IOException {
if (term == null) if (term == null)
return null; return null;
TermDocs result = readerTermDocs[i]; TermDocs result = readerTermDocs[i];
if (result == null) if (result == null)
result = readerTermDocs[i] = termDocs(readers[i]); result = readerTermDocs[i] = termDocs(readers[i]);
result.seek(term); result.seek(term);
return result; return result;
} }
protected TermDocs termDocs(IndexReader reader) protected TermDocs termDocs(IndexReader reader)
throws IOException { throws IOException {
return reader.termDocs(); return reader.termDocs();
} }
public void close() throws IOException { public void close() throws IOException {
for (int i = 0; i < readerTermDocs.length; i++) { for (int i = 0; i < readerTermDocs.length; i++) {
if (readerTermDocs[i] != null) if (readerTermDocs[i] != null)
readerTermDocs[i].close(); readerTermDocs[i].close();
} }
} }
} }
static class MultiTermPositions extends MultiTermDocs implements TermPositions { static class MultiTermPositions extends MultiTermDocs implements TermPositions {
public MultiTermPositions(IndexReader[] r, int[] s) { public MultiTermPositions(IndexReader[] r, int[] s) {
super(r,s); super(r,s);
} }
protected TermDocs termDocs(IndexReader reader) throws IOException { protected TermDocs termDocs(IndexReader reader) throws IOException {
return (TermDocs)reader.termPositions(); return (TermDocs)reader.termPositions();
} }
public int nextPosition() throws IOException { public int nextPosition() throws IOException {
return ((TermPositions)current).nextPosition(); return ((TermPositions)current).nextPosition();
} }
public int getPayloadLength() { public int getPayloadLength() {
return ((TermPositions)current).getPayloadLength(); return ((TermPositions)current).getPayloadLength();
} }
public byte[] getPayload(byte[] data, int offset) throws IOException { public byte[] getPayload(byte[] data, int offset) throws IOException {
return ((TermPositions)current).getPayload(data, offset); return ((TermPositions)current).getPayload(data, offset);
} }
// TODO: Remove warning after API has been finalized // TODO: Remove warning after API has been finalized
public boolean isPayloadAvailable() { public boolean isPayloadAvailable() {
return ((TermPositions) current).isPayloadAvailable(); return ((TermPositions) current).isPayloadAvailable();
} }
} }
} }