2 using System
.Collections
;
3 using System
.Runtime
.CompilerServices
;
5 using Lucene
.Net
.Documents
;
6 using Lucene
.Net
.Store
;
8 namespace Lucene
.Net
.Index
10 /* ====================================================================
11 * The Apache Software License, Version 1.1
13 * Copyright (c) 2001 The Apache Software Foundation. All rights
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in
25 * the documentation and/or other materials provided with the
28 * 3. The end-user documentation included with the redistribution,
29 * if any, must include the following acknowledgment:
30 * "This product includes software developed by the
31 * Apache Software Foundation (http://www.apache.org/)."
32 * Alternately, this acknowledgment may appear in the software itself,
33 * if and wherever such third-party acknowledgments normally appear.
35 * 4. The names "Apache" and "Apache Software Foundation" and
36 * "Apache Lucene" must not be used to endorse or promote products
37 * derived from this software without prior written permission. For
38 * written permission, please contact apache@apache.org.
40 * 5. Products derived from this software may not be called "Apache",
41 * "Apache Lucene", nor may "Apache" appear in their name, without
42 * prior written permission of the Apache Software Foundation.
44 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
45 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
47 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
48 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
50 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
51 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
52 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
53 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
54 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * ====================================================================
58 * This software consists of voluntary contributions made by many
59 * individuals on behalf of the Apache Software Foundation. For more
60 * information on the Apache Software Foundation, please see
61 * <http://www.apache.org/>.
64 sealed class SegmentsReader
: IndexReader
66 private SegmentReader
[] readers
;
67 private int[] starts
; // 1st docno for each segment
68 private Hashtable normsCache
= new Hashtable();
69 private int maxDoc
= 0;
70 private int numDocs
= -1;
71 private bool hasDeletions
= false;
73 internal SegmentsReader(Directory directory
, SegmentReader
[] r
)
77 starts
= new int[readers
.Length
+ 1]; // build starts array
78 for (int i
= 0; i
< readers
.Length
; i
++)
81 maxDoc
+= readers
[i
].MaxDoc(); // compute maxDocs
83 if (readers
[i
].HasDeletions())
86 starts
[readers
.Length
] = maxDoc
;
89 [MethodImpl(MethodImplOptions
.Synchronized
)]
90 override public int NumDocs()
94 int n
= 0; // cache miss--recompute
95 for (int i
= 0; i
< readers
.Length
; i
++)
96 n
+= readers
[i
].NumDocs(); // sum from readers
102 override public int MaxDoc()
107 override public Document
Document(int n
)
109 int i
= ReaderIndex(n
); // find segment num
110 return readers
[i
].Document(n
- starts
[i
]); // dispatch to segment reader
113 override public bool IsDeleted(int n
)
115 int i
= ReaderIndex(n
); // find segment num
116 return readers
[i
].IsDeleted(n
- starts
[i
]); // dispatch to segment reader
119 public override bool HasDeletions()
124 [MethodImpl(MethodImplOptions
.Synchronized
)]
125 override protected internal void DoDelete(int n
)
127 numDocs
= -1; // invalidate cache
128 int i
= ReaderIndex(n
); // find segment num
129 readers
[i
].DoDelete(n
- starts
[i
]); // dispatch to segment reader
133 public override void UndeleteAll()
135 for (int i
= 0; i
< readers
.Length
; i
++)
136 readers
[i
].UndeleteAll();
139 private int ReaderIndex(int n
)
140 { // find reader for doc n:
141 int lo
= 0; // search starts array
142 int hi
= readers
.Length
- 1; // for first element less
146 int mid
= (lo
+ hi
) >> 1;
147 int midValue
= starts
[mid
];
150 else if (n
> midValue
)
154 while (mid
+1 < readers
.Length
&& starts
[mid
+1] == midValue
)
156 mid
++; // scan to last match
164 [MethodImpl(MethodImplOptions
.Synchronized
)]
165 override public byte[] Norms(String field
)
167 byte[] bytes
= (byte[])normsCache
[field
];
169 return bytes
; // cache hit
171 bytes
= new byte[MaxDoc()];
172 for (int i
= 0; i
< readers
.Length
; i
++)
173 readers
[i
].Norms(field
, bytes
, starts
[i
]);
174 normsCache
.Add(field
, bytes
); // update cache
178 override public TermEnum
Terms()
180 return new SegmentsTermEnum(readers
, starts
, null);
183 override public TermEnum
Terms(Term term
)
185 return new SegmentsTermEnum(readers
, starts
, term
);
188 override public int DocFreq(Term t
)
190 int total
= 0; // sum freqs in segments
191 for (int i
= 0; i
< readers
.Length
; i
++)
192 total
+= readers
[i
].DocFreq(t
);
196 override public TermDocs
TermDocs()
198 return new SegmentsTermDocs(readers
, starts
);
201 override public TermPositions
TermPositions()
203 return new SegmentsTermPositions(readers
, starts
);
206 [MethodImpl(MethodImplOptions
.Synchronized
)]
207 override protected internal void DoClose()
209 for (int i
= 0; i
< readers
.Length
; i
++)
213 override public ICollection
GetFieldNames()
215 // maintain a unique set of field names
216 Hashtable fieldSet
= new Hashtable();
217 for (int i
= 0; i
< readers
.Length
; i
++)
219 SegmentReader reader
= readers
[i
];
220 ICollection names
= reader
.GetFieldNames();
221 // iterate through the field names and add them to the set
222 foreach (string de
in names
)
227 return fieldSet
.Keys
;
230 public override ICollection
GetFieldNames(bool indexed
)
232 // maintain a unique set of field names
233 Hashtable fieldSet
= new Hashtable();
234 for (int i
= 0; i
< readers
.Length
; i
++)
236 SegmentReader reader
= readers
[i
];
237 ICollection names
= reader
.GetFieldNames(indexed
);
238 foreach (string de
in names
)
243 return fieldSet
.Keys
;
247 class SegmentsTermEnum
: TermEnum
249 private SegmentMergeQueue queue
;
254 internal SegmentsTermEnum(SegmentReader
[] readers
, int[] starts
, Term t
)
256 queue
= new SegmentMergeQueue(readers
.Length
);
257 for (int i
= 0; i
< readers
.Length
; i
++)
259 SegmentReader reader
= readers
[i
];
260 SegmentTermEnum termEnum
;
264 termEnum
= (SegmentTermEnum
)reader
.Terms(t
);
267 termEnum
= (SegmentTermEnum
)reader
.Terms();
269 SegmentMergeInfo smi
= new SegmentMergeInfo(starts
[i
], termEnum
, reader
);
270 if (t
== null ? smi
.Next() : termEnum
.Term() != null)
271 queue
.Put(smi
); // initialize queue
276 if (t
!= null && queue
.Size() > 0)
282 override public bool Next()
284 SegmentMergeInfo top
= (SegmentMergeInfo
)queue
.Top();
294 while (top
!= null && term
.CompareTo(top
.term
) == 0)
297 docFreq
+= top
.termEnum
.DocFreq(); // increment freq
299 queue
.Put(top
); // restore queue
301 top
.Close(); // done with a segment
302 top
= (SegmentMergeInfo
)queue
.Top();
307 override public Term
Term()
312 override public int DocFreq()
317 override public void Close()
323 class SegmentsTermDocs
: TermDocs
325 protected SegmentReader
[] readers
;
326 protected int[] starts
;
329 protected int _base
= 0;
330 protected int pointer
= 0;
332 private SegmentTermDocs
[] segTermDocs
;
333 protected SegmentTermDocs current
; // == segTermDocs[pointer]
335 internal SegmentsTermDocs(SegmentReader
[] r
, int[] s
)
340 segTermDocs
= new SegmentTermDocs
[r
.Length
];
345 return _base
+ current
.doc
;
352 public void Seek(Term term
)
360 public void Seek(TermEnum termEnum
)
362 Seek(termEnum
.Term());
367 if (current
!= null && current
.Next())
371 else if (pointer
< readers
.Length
)
373 _base
= starts
[pointer
];
374 current
= TermDocs(pointer
++);
382 /// Optimized implementation.
384 /// <param name="docs"></param>
385 /// <param name="freqs"></param>
386 /// <returns></returns>
387 public int Read(int[] docs
, int[] freqs
)
391 while (current
== null)
393 if (pointer
< readers
.Length
)
394 { // try next segment
395 _base
= starts
[pointer
];
396 current
= TermDocs(pointer
++);
403 int end
= current
.Read(docs
, freqs
);
405 { // none left in segment
410 int b
= _base
; // adjust doc numbers
411 for (int i
= 0; i
< end
; i
++)
419 /// As yet unoptimized implementation.
421 /// <param name="target"></param>
422 /// <returns></returns>
423 public bool SkipTo(int target
)
429 } while (target
> Doc());
433 private SegmentTermDocs
TermDocs(int i
)
437 SegmentTermDocs result
= segTermDocs
[i
];
439 result
= segTermDocs
[i
] = TermDocs(readers
[i
]);
444 virtual protected SegmentTermDocs
TermDocs(SegmentReader reader
)
446 return (SegmentTermDocs
)reader
.TermDocs();
451 for (int i
= 0; i
< segTermDocs
.Length
; i
++)
453 if (segTermDocs
[i
] != null)
454 segTermDocs
[i
].Close();
459 class SegmentsTermPositions
: SegmentsTermDocs
, TermPositions
461 internal SegmentsTermPositions(SegmentReader
[] r
, int[] s
) : base(r
,s
)
465 override protected SegmentTermDocs
TermDocs(SegmentReader reader
)
467 return (SegmentTermDocs
)reader
.TermPositions();
470 public int NextPosition()
472 return ((SegmentTermPositions
)current
).NextPosition();