public override void Merge(DocValuesFieldUpdates other) { BinaryDocValuesFieldUpdates otherUpdates = (BinaryDocValuesFieldUpdates)other; int newSize = Size + otherUpdates.Size; if (newSize > int.MaxValue) { throw new InvalidOperationException("cannot support more than Integer.MAX_VALUE doc/value entries; size=" + Size + " other.size=" + otherUpdates.Size); } Docs = Docs.Grow(newSize); Offsets = Offsets.Grow(newSize); Lengths = Lengths.Grow(newSize); DocsWithField = FixedBitSet.EnsureCapacity(DocsWithField, (int)Docs.Size()); for (int i = 0; i < otherUpdates.Size; i++) { int doc = (int)otherUpdates.Docs.Get(i); if (otherUpdates.DocsWithField.Get(i)) { DocsWithField.Set(Size); } Docs.Set(Size, doc); Offsets.Set(Size, Values.Length + otherUpdates.Offsets.Get(i)); // correct relative offset Lengths.Set(Size, otherUpdates.Lengths.Get(i)); ++Size; } Values.Append(otherUpdates.Values); }
internal int DocIDUpto = -1; // unassigned until applied, and confusing that it's here, when it's just used in BufferedDeletes... /// <summary> /// Constructor. /// </summary> /// <param name="term"> the <seealso cref="Term"/> which determines the documents that will be updated </param> /// <param name="field"> the <seealso cref="NumericDocValuesField"/> to update </param> /// <param name="value"> the updated value </param> protected internal DocValuesUpdate(DocValuesFieldUpdates.Type_e type, Term term, string field, object value) { this.Type = type; this.Term = term; this.Field = field; this.Value = value; }
public override void Merge(DocValuesFieldUpdates other) { if (Debugging.AssertsEnabled) { Debugging.Assert(other is NumericDocValuesFieldUpdates); } NumericDocValuesFieldUpdates otherUpdates = (NumericDocValuesFieldUpdates)other; if (size + otherUpdates.size > int.MaxValue) { throw new InvalidOperationException("cannot support more than System.Int32.MaxValue doc/value entries; size=" + size + " other.size=" + otherUpdates.size); } docs = docs.Grow(size + otherUpdates.size); values = values.Grow(size + otherUpdates.size); docsWithField = FixedBitSet.EnsureCapacity(docsWithField, (int)docs.Count); for (int i = 0; i < otherUpdates.size; i++) { int doc = (int)otherUpdates.docs.Get(i); if (otherUpdates.docsWithField.Get(i)) { docsWithField.Set(size); } docs.Set(size, doc); values.Set(size, otherUpdates.values.Get(i)); ++size; } }
public override void Merge(DocValuesFieldUpdates other) { BinaryDocValuesFieldUpdates otherUpdates = (BinaryDocValuesFieldUpdates)other; int newSize = size + otherUpdates.size; if (newSize > int.MaxValue) { throw new InvalidOperationException("cannot support more than System.Int32.MaxValue doc/value entries; size=" + size + " other.size=" + otherUpdates.size); } docs = docs.Grow(newSize); offsets = offsets.Grow(newSize); lengths = lengths.Grow(newSize); docsWithField = FixedBitSet.EnsureCapacity(docsWithField, (int)docs.Count); for (int i = 0; i < otherUpdates.size; i++) { int doc = (int)otherUpdates.docs.Get(i); if (otherUpdates.docsWithField.Get(i)) { docsWithField.Set(size); } docs.Set(size, doc); offsets.Set(size, values.Length + otherUpdates.offsets.Get(i)); // correct relative offset lengths.Set(size, otherUpdates.lengths.Get(i)); ++size; } values.Append(otherUpdates.values); }
public override void Merge(DocValuesFieldUpdates other) { Debug.Assert(other is NumericDocValuesFieldUpdates); NumericDocValuesFieldUpdates otherUpdates = (NumericDocValuesFieldUpdates)other; if (Size + otherUpdates.Size > int.MaxValue) { throw new InvalidOperationException("cannot support more than Integer.MAX_VALUE doc/value entries; size=" + Size + " other.size=" + otherUpdates.Size); } Docs = Docs.Grow(Size + otherUpdates.Size); Values = Values.Grow(Size + otherUpdates.Size); DocsWithField = FixedBitSet.EnsureCapacity(DocsWithField, (int)Docs.Size()); for (int i = 0; i < otherUpdates.Size; i++) { int doc = (int)otherUpdates.Docs.Get(i); if (otherUpdates.DocsWithField.Get(i)) { DocsWithField.Set(Size); } Docs.Set(Size, doc); Values.Set(Size, otherUpdates.Values.Get(i)); ++Size; } }
public override void Merge(DocValuesFieldUpdates other) { BinaryDocValuesFieldUpdates otherUpdates = (BinaryDocValuesFieldUpdates)other; int newSize = Size + otherUpdates.Size; if (newSize > int.MaxValue) { throw new InvalidOperationException("cannot support more than Integer.MAX_VALUE doc/value entries; size=" + Size + " other.size=" + otherUpdates.Size); } Docs = Docs.Grow(newSize); Offsets = Offsets.Grow(newSize); Lengths = Lengths.Grow(newSize); DocsWithField = FixedBitSet.EnsureCapacity(DocsWithField, (int)Docs.Size()); for (int i = 0; i < otherUpdates.Size; i++) { int doc = (int)otherUpdates.Docs.Get(i); if (otherUpdates.DocsWithField.Get(i)) { DocsWithField.Set(Size); } Docs.Set(Size, doc); Offsets.Set(Size, Values.Length + otherUpdates.Offsets.Get(i)); // correct relative offset Lengths.Set(Size, otherUpdates.Lengths.Get(i)); ++Size; } Values.Append(otherUpdates.Values); }
/// <summary> /// Merge with another <see cref="DocValuesFieldUpdates"/>. this is called for a /// segment which received updates while it was being merged. The given updates /// should override whatever updates are in that instance. /// </summary> public abstract void Merge(DocValuesFieldUpdates other);
// DocValues updates private void ApplyDocValuesUpdates <T1>(IEnumerable <T1> updates, ReadersAndUpdates rld, SegmentReader reader, DocValuesFieldUpdates.Container dvUpdatesContainer) where T1 : DocValuesUpdate { lock (this) { Fields fields = reader.Fields; if (fields == null) { // this reader has no postings return; } // TODO: we can process the updates per DV field, from last to first so that // if multiple terms affect same document for the same field, we add an update // only once (that of the last term). To do that, we can keep a bitset which // marks which documents have already been updated. So e.g. if term T1 // updates doc 7, and then we process term T2 and it updates doc 7 as well, // we don't apply the update since we know T1 came last and therefore wins // the update. // We can also use that bitset as 'liveDocs' to pass to TermEnum.docs(), so // that these documents aren't even returned. string currentField = null; TermsEnum termsEnum = null; DocsEnum docs = null; //System.out.println(Thread.currentThread().getName() + " numericDVUpdate reader=" + reader); foreach (DocValuesUpdate update in updates) { Term term = update.Term; int limit = update.DocIDUpto; // TODO: we traverse the terms in update order (not term order) so that we // apply the updates in the correct order, i.e. if two terms udpate the // same document, the last one that came in wins, irrespective of the // terms lexical order. // we can apply the updates in terms order if we keep an updatesGen (and // increment it with every update) and attach it to each NumericUpdate. Note // that we cannot rely only on docIDUpto because an app may send two updates // which will get same docIDUpto, yet will still need to respect the order // those updates arrived. if (!term.Field().Equals(currentField)) { // if we change the code to process updates in terms order, enable this assert // assert currentField == null || currentField.compareTo(term.field()) < 0; currentField = term.Field(); Terms terms = fields.Terms(currentField); if (terms != null) { termsEnum = terms.Iterator(termsEnum); } else { termsEnum = null; continue; // no terms in that field } } if (termsEnum == null) { continue; } // System.out.println(" term=" + term); if (termsEnum.SeekExact(term.Bytes())) { // we don't need term frequencies for this DocsEnum docsEnum = termsEnum.Docs(rld.LiveDocs, docs, DocsEnum.FLAG_NONE); //System.out.println("BDS: got docsEnum=" + docsEnum); DocValuesFieldUpdates dvUpdates = dvUpdatesContainer.GetUpdates(update.Field, update.Type); if (dvUpdates == null) { dvUpdates = dvUpdatesContainer.NewUpdates(update.Field, update.Type, reader.MaxDoc); } int doc; while ((doc = docsEnum.NextDoc()) != DocIdSetIterator.NO_MORE_DOCS) { //System.out.println(Thread.currentThread().getName() + " numericDVUpdate term=" + term + " doc=" + docID); if (doc >= limit) { break; // no more docs that can be updated for this term } dvUpdates.Add(doc, update.Value); } } } } }
/// <summary> /// Carefully merges deletes and updates for the segments we just merged. this /// is tricky because, although merging will clear all deletes (compacts the /// documents) and compact all the updates, new deletes and updates may have /// been flushed to the segments since the merge was started. this method /// "carries over" such new deletes and updates onto the newly merged segment, /// and saves the resulting deletes and updates files (incrementing the delete /// and DV generations for merge.info). If no deletes were flushed, no new /// deletes file is saved. /// </summary> private ReadersAndUpdates CommitMergedDeletesAndUpdates(MergePolicy.OneMerge merge, MergeState mergeState) { lock (this) { Debug.Assert(TestPoint("startCommitMergeDeletes")); IList<SegmentCommitInfo> sourceSegments = merge.Segments; if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "commitMergeDeletes " + SegString(merge.Segments)); } // Carefully merge deletes that occurred after we // started merging: int docUpto = 0; long minGen = long.MaxValue; // Lazy init (only when we find a delete to carry over): MergedDeletesAndUpdates holder = new MergedDeletesAndUpdates(); DocValuesFieldUpdates.Container mergedDVUpdates = new DocValuesFieldUpdates.Container(); for (int i = 0; i < sourceSegments.Count; i++) { SegmentCommitInfo info = sourceSegments[i]; minGen = Math.Min(info.BufferedDeletesGen, minGen); int docCount = info.Info.DocCount; Bits prevLiveDocs = merge.Readers[i].LiveDocs; ReadersAndUpdates rld = readerPool.Get(info, false); // We hold a ref so it should still be in the pool: Debug.Assert(rld != null, "seg=" + info.Info.Name); Bits currentLiveDocs = rld.LiveDocs; IDictionary<string, DocValuesFieldUpdates> mergingFieldUpdates = rld.MergingFieldUpdates; string[] mergingFields; DocValuesFieldUpdates[] dvFieldUpdates; DocValuesFieldUpdates.Iterator[] updatesIters; if (mergingFieldUpdates.Count == 0) { mergingFields = null; updatesIters = null; dvFieldUpdates = null; } else { mergingFields = new string[mergingFieldUpdates.Count]; dvFieldUpdates = new DocValuesFieldUpdates[mergingFieldUpdates.Count]; updatesIters = new DocValuesFieldUpdates.Iterator[mergingFieldUpdates.Count]; int idx = 0; foreach (KeyValuePair<string, DocValuesFieldUpdates> e in mergingFieldUpdates) { string field = e.Key; DocValuesFieldUpdates updates = e.Value; mergingFields[idx] = field; dvFieldUpdates[idx] = mergedDVUpdates.GetUpdates(field, updates.Type); if (dvFieldUpdates[idx] == null) { dvFieldUpdates[idx] = mergedDVUpdates.NewUpdates(field, updates.Type, mergeState.SegmentInfo.DocCount); } updatesIters[idx] = updates.GetIterator(); updatesIters[idx].NextDoc(); // advance to first update doc ++idx; } } // System.out.println("[" + Thread.currentThread().getName() + "] IW.commitMergedDeletes: info=" + info + ", mergingUpdates=" + mergingUpdates); if (prevLiveDocs != null) { // If we had deletions on starting the merge we must // still have deletions now: Debug.Assert(currentLiveDocs != null); Debug.Assert(prevLiveDocs.Length() == docCount); Debug.Assert(currentLiveDocs.Length() == docCount); // There were deletes on this segment when the merge // started. The merge has collapsed away those // deletes, but, if new deletes were flushed since // the merge started, we must now carefully keep any // newly flushed deletes but mapping them to the new // docIDs. // Since we copy-on-write, if any new deletes were // applied after merging has started, we can just // check if the before/after liveDocs have changed. // If so, we must carefully merge the liveDocs one // doc at a time: if (currentLiveDocs != prevLiveDocs) { // this means this segment received new deletes // since we started the merge, so we // must merge them: for (int j = 0; j < docCount; j++) { if (!prevLiveDocs.Get(j)) { Debug.Assert(!currentLiveDocs.Get(j)); } else { if (!currentLiveDocs.Get(j)) { if (holder.MergedDeletesAndUpdates_Renamed == null || !holder.InitializedWritableLiveDocs) { holder.Init(readerPool, merge, mergeState, true); } holder.MergedDeletesAndUpdates_Renamed.Delete(holder.DocMap.Map(docUpto)); if (mergingFields != null) // advance all iters beyond the deleted document { SkipDeletedDoc(updatesIters, j); } } else if (mergingFields != null) { MaybeApplyMergedDVUpdates(merge, mergeState, docUpto, holder, mergingFields, dvFieldUpdates, updatesIters, j); } docUpto++; } } } else if (mergingFields != null) { // need to check each non-deleted document if it has any updates for (int j = 0; j < docCount; j++) { if (prevLiveDocs.Get(j)) { // document isn't deleted, check if any of the fields have an update to it MaybeApplyMergedDVUpdates(merge, mergeState, docUpto, holder, mergingFields, dvFieldUpdates, updatesIters, j); // advance docUpto for every non-deleted document docUpto++; } else { // advance all iters beyond the deleted document SkipDeletedDoc(updatesIters, j); } } } else { docUpto += info.Info.DocCount - info.DelCount - rld.PendingDeleteCount; } } else if (currentLiveDocs != null) { Debug.Assert(currentLiveDocs.Length() == docCount); // this segment had no deletes before but now it // does: for (int j = 0; j < docCount; j++) { if (!currentLiveDocs.Get(j)) { if (holder.MergedDeletesAndUpdates_Renamed == null || !holder.InitializedWritableLiveDocs) { holder.Init(readerPool, merge, mergeState, true); } holder.MergedDeletesAndUpdates_Renamed.Delete(holder.DocMap.Map(docUpto)); if (mergingFields != null) // advance all iters beyond the deleted document { SkipDeletedDoc(updatesIters, j); } } else if (mergingFields != null) { MaybeApplyMergedDVUpdates(merge, mergeState, docUpto, holder, mergingFields, dvFieldUpdates, updatesIters, j); } docUpto++; } } else if (mergingFields != null) { // no deletions before or after, but there were updates for (int j = 0; j < docCount; j++) { MaybeApplyMergedDVUpdates(merge, mergeState, docUpto, holder, mergingFields, dvFieldUpdates, updatesIters, j); // advance docUpto for every non-deleted document docUpto++; } } else { // No deletes or updates before or after docUpto += info.Info.DocCount; } } Debug.Assert(docUpto == merge.Info_Renamed.Info.DocCount); if (mergedDVUpdates.Any()) { // System.out.println("[" + Thread.currentThread().getName() + "] IW.commitMergedDeletes: mergedDeletes.info=" + mergedDeletes.info + ", mergedFieldUpdates=" + mergedFieldUpdates); bool success = false; try { // if any error occurs while writing the field updates we should release // the info, otherwise it stays in the pool but is considered not "live" // which later causes false exceptions in pool.dropAll(). // NOTE: currently this is the only place which throws a true // IOException. If this ever changes, we need to extend that try/finally // block to the rest of the method too. holder.MergedDeletesAndUpdates_Renamed.WriteFieldUpdates(directory, mergedDVUpdates); success = true; } finally { if (!success) { holder.MergedDeletesAndUpdates_Renamed.DropChanges(); readerPool.Drop(merge.Info_Renamed); } } } if (infoStream.IsEnabled("IW")) { if (holder.MergedDeletesAndUpdates_Renamed == null) { infoStream.Message("IW", "no new deletes or field updates since merge started"); } else { string msg = holder.MergedDeletesAndUpdates_Renamed.PendingDeleteCount + " new deletes"; if (mergedDVUpdates.Any()) { msg += " and " + mergedDVUpdates.Size() + " new field updates"; } msg += " since merge started"; infoStream.Message("IW", msg); } } merge.Info_Renamed.BufferedDeletesGen = minGen; return holder.MergedDeletesAndUpdates_Renamed; } }
private void MaybeApplyMergedDVUpdates(MergePolicy.OneMerge merge, MergeState mergeState, int docUpto, MergedDeletesAndUpdates holder, string[] mergingFields, DocValuesFieldUpdates[] dvFieldUpdates, DocValuesFieldUpdates.Iterator[] updatesIters, int curDoc) { int newDoc = -1; for (int idx = 0; idx < mergingFields.Length; idx++) { DocValuesFieldUpdates.Iterator updatesIter = updatesIters[idx]; if (updatesIter.Doc() == curDoc) // document has an update { if (holder.MergedDeletesAndUpdates_Renamed == null) { holder.Init(readerPool, merge, mergeState, false); } if (newDoc == -1) // map once per all field updates, but only if there are any updates { newDoc = holder.DocMap.Map(docUpto); } DocValuesFieldUpdates dvUpdates = dvFieldUpdates[idx]; dvUpdates.Add(newDoc, updatesIter.Value()); updatesIter.NextDoc(); // advance to next document } else { Debug.Assert(updatesIter.Doc() > curDoc, "field=" + mergingFields[idx] + " updateDoc=" + updatesIter.Doc() + " curDoc=" + curDoc); } } }
private void SkipDeletedDoc(DocValuesFieldUpdates.Iterator[] updatesIters, int deletedDoc) { foreach (DocValuesFieldUpdates.Iterator iter in updatesIters) { if (iter.Doc() == deletedDoc) { iter.NextDoc(); } // when entering the method, all iterators must already be beyond the // deleted document, or right on it, in which case we advance them over // and they must be beyond it now. Debug.Assert(iter.Doc() > deletedDoc, "updateDoc=" + iter.Doc() + " deletedDoc=" + deletedDoc); } }
public override void Merge(DocValuesFieldUpdates other) { Debug.Assert(other is NumericDocValuesFieldUpdates); NumericDocValuesFieldUpdates otherUpdates = (NumericDocValuesFieldUpdates)other; if (Size + otherUpdates.Size > int.MaxValue) { throw new InvalidOperationException("cannot support more than Integer.MAX_VALUE doc/value entries; size=" + Size + " other.size=" + otherUpdates.Size); } Docs = Docs.Grow(Size + otherUpdates.Size); Values = Values.Grow(Size + otherUpdates.Size); DocsWithField = FixedBitSet.EnsureCapacity(DocsWithField, (int)Docs.Size()); for (int i = 0; i < otherUpdates.Size; i++) { int doc = (int)otherUpdates.Docs.Get(i); if (otherUpdates.DocsWithField.Get(i)) { DocsWithField.Set(Size); } Docs.Set(Size, doc); Values.Set(Size, otherUpdates.Values.Get(i)); ++Size; } }
// Writes field updates (new _X_N updates files) to the directory public virtual void WriteFieldUpdates(Directory dir, DocValuesFieldUpdates.Container dvUpdates) { lock (this) { //Debug.Assert(Thread.holdsLock(Writer)); //System.out.println("rld.writeFieldUpdates: seg=" + info + " numericFieldUpdates=" + numericFieldUpdates); Debug.Assert(dvUpdates.Any()); // Do this so we can delete any created files on // exception; this saves all codecs from having to do // it: TrackingDirectoryWrapper trackingDir = new TrackingDirectoryWrapper(dir); FieldInfos fieldInfos = null; bool success = false; try { Codec codec = Info.Info.Codec; // reader could be null e.g. for a just merged segment (from // IndexWriter.commitMergedDeletes). SegmentReader reader = this.Reader == null ? new SegmentReader(Info, Writer.Config.ReaderTermsIndexDivisor, IOContext.READONCE) : this.Reader; try { // clone FieldInfos so that we can update their dvGen separately from // the reader's infos and write them to a new fieldInfos_gen file FieldInfos.Builder builder = new FieldInfos.Builder(Writer.GlobalFieldNumberMap); // cannot use builder.add(reader.getFieldInfos()) because it does not // clone FI.attributes as well FI.dvGen foreach (FieldInfo fi in reader.FieldInfos) { FieldInfo clone = builder.Add(fi); // copy the stuff FieldInfos.Builder doesn't copy if (fi.Attributes() != null) { foreach (KeyValuePair<string, string> e in fi.Attributes()) { clone.PutAttribute(e.Key, e.Value); } } clone.DocValuesGen = fi.DocValuesGen; } // create new fields or update existing ones to have NumericDV type foreach (string f in dvUpdates.NumericDVUpdates.Keys) { builder.AddOrUpdate(f, NumericDocValuesField.TYPE); } // create new fields or update existing ones to have BinaryDV type foreach (string f in dvUpdates.BinaryDVUpdates.Keys) { builder.AddOrUpdate(f, BinaryDocValuesField.fType); } fieldInfos = builder.Finish(); long nextFieldInfosGen = Info.NextFieldInfosGen; string segmentSuffix = nextFieldInfosGen.ToString(CultureInfo.InvariantCulture);//Convert.ToString(nextFieldInfosGen, Character.MAX_RADIX)); SegmentWriteState state = new SegmentWriteState(null, trackingDir, Info.Info, fieldInfos, Writer.Config.TermIndexInterval, null, IOContext.DEFAULT, segmentSuffix); DocValuesFormat docValuesFormat = codec.DocValuesFormat(); DocValuesConsumer fieldsConsumer = docValuesFormat.FieldsConsumer(state); bool fieldsConsumerSuccess = false; try { // System.out.println("[" + Thread.currentThread().getName() + "] RLD.writeFieldUpdates: applying numeric updates; seg=" + info + " updates=" + numericFieldUpdates); foreach (KeyValuePair<string, NumericDocValuesFieldUpdates> e in dvUpdates.NumericDVUpdates) { string field = e.Key; NumericDocValuesFieldUpdates fieldUpdates = e.Value; FieldInfo fieldInfo = fieldInfos.FieldInfo(field); Debug.Assert(fieldInfo != null); fieldInfo.DocValuesGen = nextFieldInfosGen; // write the numeric updates to a new gen'd docvalues file fieldsConsumer.AddNumericField(fieldInfo, GetLongEnumerable(reader, field, fieldUpdates)); } // System.out.println("[" + Thread.currentThread().getName() + "] RAU.writeFieldUpdates: applying binary updates; seg=" + info + " updates=" + dvUpdates.binaryDVUpdates); foreach (KeyValuePair<string, BinaryDocValuesFieldUpdates> e in dvUpdates.BinaryDVUpdates) { string field = e.Key; BinaryDocValuesFieldUpdates dvFieldUpdates = e.Value; FieldInfo fieldInfo = fieldInfos.FieldInfo(field); Debug.Assert(fieldInfo != null); // System.out.println("[" + Thread.currentThread().getName() + "] RAU.writeFieldUpdates: applying binary updates; seg=" + info + " f=" + dvFieldUpdates + ", updates=" + dvFieldUpdates); fieldInfo.DocValuesGen = nextFieldInfosGen; // write the numeric updates to a new gen'd docvalues file fieldsConsumer.AddBinaryField(fieldInfo, GetBytesRefEnumerable(reader, field, dvFieldUpdates)); } codec.FieldInfosFormat().FieldInfosWriter.Write(trackingDir, Info.Info.Name, segmentSuffix, fieldInfos, IOContext.DEFAULT); fieldsConsumerSuccess = true; } finally { if (fieldsConsumerSuccess) { fieldsConsumer.Dispose(); } else { IOUtils.CloseWhileHandlingException(fieldsConsumer); } } } finally { if (reader != this.Reader) { // System.out.println("[" + Thread.currentThread().getName() + "] RLD.writeLiveDocs: closeReader " + reader); reader.Dispose(); } } success = true; } finally { if (!success) { // Advance only the nextWriteDocValuesGen so that a 2nd // attempt to write will write to a new file Info.AdvanceNextWriteFieldInfosGen(); // Delete any partially created file(s): foreach (string fileName in trackingDir.CreatedFiles) { try { dir.DeleteFile(fileName); } catch (Exception) { // Ignore so we throw only the first exc } } } } Info.AdvanceFieldInfosGen(); // copy all the updates to mergingUpdates, so they can later be applied to the merged segment if (IsMerging) { foreach (KeyValuePair<string, NumericDocValuesFieldUpdates> e in dvUpdates.NumericDVUpdates) { DocValuesFieldUpdates updates; if (!MergingDVUpdates.TryGetValue(e.Key, out updates)) { MergingDVUpdates[e.Key] = e.Value; } else { updates.Merge(e.Value); } } foreach (KeyValuePair<string, BinaryDocValuesFieldUpdates> e in dvUpdates.BinaryDVUpdates) { DocValuesFieldUpdates updates; if (!MergingDVUpdates.TryGetValue(e.Key, out updates)) { MergingDVUpdates[e.Key] = e.Value; } else { updates.Merge(e.Value); } } } // create a new map, keeping only the gens that are in use IDictionary<long, ISet<string>> genUpdatesFiles = Info.UpdatesFiles; IDictionary<long, ISet<string>> newGenUpdatesFiles = new Dictionary<long, ISet<string>>(); long fieldInfosGen = Info.FieldInfosGen; foreach (FieldInfo fi in fieldInfos) { long dvGen = fi.DocValuesGen; if (dvGen != -1 && !newGenUpdatesFiles.ContainsKey(dvGen)) { if (dvGen == fieldInfosGen) { newGenUpdatesFiles[fieldInfosGen] = trackingDir.CreatedFiles; } else { newGenUpdatesFiles[dvGen] = genUpdatesFiles[dvGen]; } } } Info.GenUpdatesFiles = newGenUpdatesFiles; // wrote new files, should checkpoint() Writer.Checkpoint(); // if there is a reader open, reopen it to reflect the updates if (Reader != null) { SegmentReader newReader = new SegmentReader(Info, Reader, LiveDocs_Renamed, Info.Info.DocCount - Info.DelCount - PendingDeleteCount_Renamed); bool reopened = false; try { Reader.DecRef(); Reader = newReader; reopened = true; } finally { if (!reopened) { newReader.DecRef(); } } } } }
/// <summary> /// Merge with another <seealso cref="DocValuesFieldUpdates"/>. this is called for a /// segment which received updates while it was being merged. The given updates /// should override whatever updates are in that instance. /// </summary> public abstract void Merge(DocValuesFieldUpdates other);