/// <summary> /// Checks whether this merge involves any segments /// already participating in a merge. If not, this merge /// is "registered", meaning we record that its segments /// are now participating in a merge, and true is /// returned. Else (the merge conflicts) false is /// returned. /// </summary> internal bool RegisterMerge(MergePolicy.OneMerge merge) { lock (this) { if (merge.RegisterDone) { return true; } Debug.Assert(merge.Segments.Count > 0); if (StopMerges) { merge.Abort(); throw new MergePolicy.MergeAbortedException("merge is aborted: " + SegString(merge.Segments)); } bool isExternal = false; foreach (SegmentCommitInfo info in merge.Segments) { if (mergingSegments.Contains(info)) { if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "reject merge " + SegString(merge.Segments) + ": segment " + SegString(info) + " is already marked for merge"); } return false; } if (!segmentInfos.Contains(info)) { if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "reject merge " + SegString(merge.Segments) + ": segment " + SegString(info) + " does not exist in live infos"); } return false; } if (info.Info.Dir != directory) { isExternal = true; } if (SegmentsToMerge.ContainsKey(info)) { merge.MaxNumSegments = MergeMaxNumSegments; } } EnsureValidMerge(merge); PendingMerges.AddLast(merge); if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "add merge to pendingMerges: " + SegString(merge.Segments) + " [total " + PendingMerges.Count + " pending]"); } merge.MergeGen = MergeGen; merge.IsExternal = isExternal; // OK it does not conflict; now record that this merge // is running (while synchronized) to avoid race // condition where two conflicting merges from different // threads, start if (infoStream.IsEnabled("IW")) { StringBuilder builder = new StringBuilder("registerMerge merging= ["); foreach (SegmentCommitInfo info in mergingSegments) { builder.Append(info.Info.Name).Append(", "); } builder.Append("]"); // don't call mergingSegments.toString() could lead to ConcurrentModException // since merge updates the segments FieldInfos if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", builder.ToString()); } } foreach (SegmentCommitInfo info in merge.Segments) { if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "registerMerge info=" + SegString(info)); } mergingSegments.Add(info); } Debug.Assert(merge.EstimatedMergeBytes == 0); Debug.Assert(merge.TotalMergeBytes == 0); foreach (SegmentCommitInfo info in merge.Segments) { if (info.Info.DocCount > 0) { int delCount = NumDeletedDocs(info); Debug.Assert(delCount <= info.Info.DocCount); double delRatio = ((double)delCount) / info.Info.DocCount; merge.EstimatedMergeBytes += (long)(info.SizeInBytes() * (1.0 - delRatio)); merge.TotalMergeBytes += info.SizeInBytes(); } } // Merge is now registered merge.RegisterDone = true; return true; } }
/// <summary>Checks whether this merge involves any segments /// already participating in a merge. If not, this merge /// is "registered", meaning we record that its segments /// are now participating in a merge, and true is /// returned. Else (the merge conflicts) false is /// returned. /// </summary> internal bool RegisterMerge(MergePolicy.OneMerge merge) { lock (this) { if (merge.registerDone) return true; if (stopMerges) { merge.Abort(); throw new MergePolicy.MergeAbortedException("merge is aborted: " + merge.SegString(directory)); } int count = merge.segments.Count; bool isExternal = false; for (int i = 0; i < count; i++) { SegmentInfo info = merge.segments.Info(i); if (mergingSegments.Contains(info)) { return false; } if (segmentInfos.IndexOf(info) == -1) { return false; } if (info.dir != directory) { isExternal = true; } if (segmentsToOptimize.Contains(info)) { merge.optimize = true; merge.maxNumSegmentsOptimize = optimizeMaxNumSegments; } } EnsureContiguousMerge(merge); pendingMerges.AddLast(merge); if (infoStream != null) Message("add merge to pendingMerges: " + merge.SegString(directory) + " [total " + pendingMerges.Count + " pending]"); merge.mergeGen = mergeGen; merge.isExternal = isExternal; // OK it does not conflict; now record that this merge // is running (while synchronized) to avoid race // condition where two conflicting merges from different // threads, start for (int i = 0; i < count; i++) { SegmentInfo si = merge.segments.Info(i); mergingSegments[si] = si; } // Merge is now registered merge.registerDone = true; return true; } }