19 using System.Collections.Generic;
21 namespace Lucene.Net.Index
50 public const double LEVEL_LOG_SPAN = 0.75;
55 public const int DEFAULT_MERGE_FACTOR = 10;
60 public static readonly
int DEFAULT_MAX_MERGE_DOCS = System.Int32.MaxValue;
66 public static double DEFAULT_NO_CFS_RATIO = 0.1;
68 private int mergeFactor = DEFAULT_MERGE_FACTOR;
70 internal long minMergeSize;
71 internal long maxMergeSize;
72 internal int maxMergeDocs = DEFAULT_MAX_MERGE_DOCS;
74 protected double internalNoCFSRatio = DEFAULT_NO_CFS_RATIO;
77 protected internal bool internalCalibrateSizeByDeletes =
true;
79 private bool useCompoundFile =
true;
80 private bool useCompoundDocStore =
true;
86 protected internal virtual bool Verbose()
88 return writer != null && writer.Verbose;
91 public double NoCFSRatio
93 get {
return internalNoCFSRatio; }
96 if (value < 0.0 || value > 1.0)
98 throw new ArgumentException(
"noCFSRatio must be 0.0 to 1.0 inclusive; got " + value);
100 this.internalNoCFSRatio = value;
109 private void Message(System.String message)
112 writer.Message(
"LMP: " + message);
126 public virtual int MergeFactor
128 get {
return mergeFactor; }
132 throw new System.ArgumentException(
"mergeFactor cannot be less than 2");
133 this.mergeFactor = value;
139 return useCompoundFile;
145 public virtual void SetUseCompoundFile(
bool useCompoundFile)
147 this.useCompoundFile = useCompoundFile;
150 [System.Diagnostics.CodeAnalysis.SuppressMessage(
"Microsoft.Design",
"CA1024:UsePropertiesWhereAppropriate")]
151 public virtual bool GetUseCompoundFile()
153 return useCompoundFile;
159 return useCompoundDocStore;
166 public virtual void SetUseCompoundDocStore(
bool useCompoundDocStore)
168 this.useCompoundDocStore = useCompoundDocStore;
176 [System.Diagnostics.CodeAnalysis.SuppressMessage(
"Microsoft.Design",
"CA1024:UsePropertiesWhereAppropriate")]
177 public virtual bool GetUseCompoundDocStore()
179 return useCompoundDocStore;
185 public virtual bool CalibrateSizeByDeletes
187 set { this.internalCalibrateSizeByDeletes = value; }
188 get {
return internalCalibrateSizeByDeletes; }
191 abstract protected internal long Size(
SegmentInfo info);
193 protected internal virtual long SizeDocs(
SegmentInfo info)
195 if (internalCalibrateSizeByDeletes)
197 int delCount = writer.NumDeletedDocs(info);
198 return (info.
docCount - (
long) delCount);
206 protected internal virtual long SizeBytes(SegmentInfo info)
208 long byteSize = info.SizeInBytes();
209 if (internalCalibrateSizeByDeletes)
211 int delCount = writer.NumDeletedDocs(info);
212 float delRatio = (info.docCount <= 0?0.0f:((float) delCount / (
float) info.docCount));
213 return (info.docCount <= 0?byteSize:(
long) (byteSize * (1.0f - delRatio)));
221 private bool IsOptimized(SegmentInfos infos,
int maxNumSegments, ISet<SegmentInfo> segmentsToOptimize)
223 int numSegments = infos.Count;
224 int numToOptimize = 0;
225 SegmentInfo optimizeInfo = null;
226 for (
int i = 0; i < numSegments && numToOptimize <= maxNumSegments; i++)
228 SegmentInfo info = infos.Info(i);
229 if (segmentsToOptimize.Contains(info))
236 return numToOptimize <= maxNumSegments && (numToOptimize != 1 || IsOptimized(optimizeInfo));
243 private bool IsOptimized(SegmentInfo info)
245 bool hasDeletions = writer.NumDeletedDocs(info) > 0;
246 return !hasDeletions && !info.HasSeparateNorms() && info.dir == writer.Directory &&
247 (info.GetUseCompoundFile() == useCompoundFile || internalNoCFSRatio < 1.0);
263 System.Diagnostics.Debug.Assert(maxNumSegments > 0);
265 if (!IsOptimized(infos, maxNumSegments, segmentsToOptimize))
271 int last = infos.Count;
275 if (segmentsToOptimize.Contains(info))
289 while (last - maxNumSegments + 1 >= mergeFactor)
291 spec.
Add(MakeOneMerge(infos, infos.
Range(last - mergeFactor, last)));
297 if (0 == spec.
merges.Count)
299 if (maxNumSegments == 1)
304 if (last > 1 || !IsOptimized(infos.
Info(0)))
305 spec.
Add(MakeOneMerge(infos, infos.
Range(0, last)));
307 else if (last > maxNumSegments)
319 int finalMergeSize = last - maxNumSegments + 1;
325 for (
int i = 0; i < last - finalMergeSize + 1; i++)
328 for (
int j = 0; j < finalMergeSize; j++)
329 sumSize += Size(infos.
Info(j + i));
330 if (i == 0 || (sumSize < 2 * Size(infos.
Info(i - 1)) && sumSize < bestSize))
337 spec.
Add(MakeOneMerge(infos, infos.
Range(bestStart, bestStart + finalMergeSize)));
356 int numSegments = segmentInfos.Count;
359 Message(
"findMergesToExpungeDeletes: " + numSegments +
" segments");
362 int firstSegmentWithDeletions = - 1;
363 for (
int i = 0; i < numSegments; i++)
366 int delCount = writer.NumDeletedDocs(info);
370 Message(
" segment " + info.
name +
" has deletions");
371 if (firstSegmentWithDeletions == - 1)
372 firstSegmentWithDeletions = i;
373 else if (i - firstSegmentWithDeletions == mergeFactor)
378 Message(
" add merge " + firstSegmentWithDeletions +
" to " + (i - 1) +
" inclusive");
379 spec.
Add(MakeOneMerge(segmentInfos, segmentInfos.
Range(firstSegmentWithDeletions, i)));
380 firstSegmentWithDeletions = i;
383 else if (firstSegmentWithDeletions != - 1)
389 Message(
" add merge " + firstSegmentWithDeletions +
" to " + (i - 1) +
" inclusive");
390 spec.
Add(MakeOneMerge(segmentInfos, segmentInfos.
Range(firstSegmentWithDeletions, i)));
391 firstSegmentWithDeletions = - 1;
395 if (firstSegmentWithDeletions != - 1)
398 Message(
" add merge " + firstSegmentWithDeletions +
" to " + (numSegments - 1) +
" inclusive");
399 spec.
Add(MakeOneMerge(segmentInfos, segmentInfos.
Range(firstSegmentWithDeletions, numSegments)));
416 int numSegments = infos.Count;
418 Message(
"findMerges: " + numSegments +
" segments");
422 float[] levels =
new float[numSegments];
423 float norm = (float) System.Math.Log(mergeFactor);
425 for (
int i = 0; i < numSegments; i++)
428 long size = Size(info);
433 levels[i] = (float) System.Math.Log(size) / norm;
437 if (minMergeSize <= 0)
438 levelFloor = (float) 0.0;
441 levelFloor = (float) (System.Math.Log(minMergeSize) / norm);
454 while (start < numSegments)
459 float maxLevel = levels[start];
460 for (
int i = 1 + start; i < numSegments; i++)
462 float level = levels[i];
463 if (level > maxLevel)
470 if (maxLevel < levelFloor)
472 levelBottom = - 1.0F;
475 levelBottom = (float) (maxLevel - LEVEL_LOG_SPAN);
478 if (levelBottom < levelFloor && maxLevel >= levelFloor)
479 levelBottom = levelFloor;
482 int upto = numSegments - 1;
483 while (upto >= start)
485 if (levels[upto] >= levelBottom)
492 Message(
" level " + levelBottom +
" to " + maxLevel +
": " + (1 + upto - start) +
" segments");
495 int end = start + mergeFactor;
496 while (end <= 1 + upto)
498 bool anyTooLarge =
false;
499 for (
int i = start; i < end; i++)
502 anyTooLarge |= (Size(info) >= maxMergeSize || SizeDocs(info) >= maxMergeDocs);
510 Message(
" " + start +
" to " + end +
": add this merge");
511 spec.
Add(MakeOneMerge(infos, infos.
Range(start, end)));
514 Message(
" " + start +
" to " + end +
": contains segment over maxMergeSize or maxMergeDocs; skipping");
517 end = start + mergeFactor;
529 if (!useCompoundFile)
533 else if (internalNoCFSRatio == 1.0)
542 totSize += Size(info);
547 mergeSize += Size(info);
550 doCFS = mergeSize <= internalNoCFSRatio * totSize;
553 return new OneMerge(infosToMerge, doCFS);
574 public virtual int MaxMergeDocs
576 set { this.maxMergeDocs = value; }
577 get {
return maxMergeDocs; }