diff options
Diffstat (limited to 'src/core/Index/BufferedDeletes.cs')
-rw-r--r-- | src/core/Index/BufferedDeletes.cs | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/core/Index/BufferedDeletes.cs b/src/core/Index/BufferedDeletes.cs new file mode 100644 index 0000000..52ef1df --- /dev/null +++ b/src/core/Index/BufferedDeletes.cs @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * 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 obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System.Collections.Generic; +using Lucene.Net.Search; +using Lucene.Net.Support; + +namespace Lucene.Net.Index +{ + + /// <summary>Holds buffered deletes, by docID, term or query. We + /// hold two instances of this class: one for the deletes + /// prior to the last flush, the other for deletes after + /// the last flush. This is so if we need to abort + /// (discard all buffered docs) we can also discard the + /// buffered deletes yet keep the deletes done during + /// previously flushed segments. + /// </summary> + class BufferedDeletes + { + internal int numTerms; + internal IDictionary<Term,Num> terms = null; + internal IDictionary<Query, int> queries = new HashMap<Query, int>(); + internal List<int> docIDs = new List<int>(); + internal long bytesUsed; + internal bool doTermSort; + + public BufferedDeletes(bool doTermSort) + { + this.doTermSort = doTermSort; + if (doTermSort) + { + //TODO: Used in place of TreeMap + terms = new SortedDictionary<Term, Num>(); + } + else + { + terms = new HashMap<Term, Num>(); + } + } + + + // Number of documents a delete term applies to. + internal sealed class Num + { + internal int num; + + internal Num(int num) + { + this.num = num; + } + + internal int GetNum() + { + return num; + } + + internal void SetNum(int num) + { + // Only record the new number if it's greater than the + // current one. This is important because if multiple + // threads are replacing the same doc at nearly the + // same time, it's possible that one thread that got a + // higher docID is scheduled before the other + // threads. + if (num > this.num) + this.num = num; + } + } + + internal virtual int Size() + { + // We use numTerms not terms.size() intentionally, so + // that deletes by the same term multiple times "count", + // ie if you ask to flush every 1000 deletes then even + // dup'd terms are counted towards that 1000 + return numTerms + queries.Count + docIDs.Count; + } + + internal virtual void Update(BufferedDeletes @in) + { + numTerms += @in.numTerms; + bytesUsed += @in.bytesUsed; + foreach (KeyValuePair<Term, Num> term in @in.terms) + { + terms[term.Key] = term.Value; + } + foreach (KeyValuePair<Query, int> term in @in.queries) + { + queries[term.Key] = term.Value; + } + + docIDs.AddRange(@in.docIDs); + @in.Clear(); + } + + internal virtual void Clear() + { + terms.Clear(); + queries.Clear(); + docIDs.Clear(); + numTerms = 0; + bytesUsed = 0; + } + + internal virtual void AddBytesUsed(long b) + { + bytesUsed += b; + } + + internal virtual bool Any() + { + return terms.Count > 0 || docIDs.Count > 0 || queries.Count > 0; + } + + // Remaps all buffered deletes based on a completed + // merge + internal virtual void Remap(MergeDocIDRemapper mapper, SegmentInfos infos, int[][] docMaps, int[] delCounts, MergePolicy.OneMerge merge, int mergeDocCount) + { + lock (this) + { + IDictionary<Term, Num> newDeleteTerms; + + // Remap delete-by-term + if (terms.Count > 0) + { + if (doTermSort) + { + newDeleteTerms = new SortedDictionary<Term, Num>(); + } + else + { + newDeleteTerms = new HashMap<Term, Num>(); + } + foreach(var entry in terms) + { + Num num = entry.Value; + newDeleteTerms[entry.Key] = new Num(mapper.Remap(num.GetNum())); + } + } + else + newDeleteTerms = null; + + // Remap delete-by-docID + List<int> newDeleteDocIDs; + + if (docIDs.Count > 0) + { + newDeleteDocIDs = new List<int>(docIDs.Count); + foreach(int num in docIDs) + { + newDeleteDocIDs.Add(mapper.Remap(num)); + } + } + else + newDeleteDocIDs = null; + + // Remap delete-by-query + HashMap<Query, int> newDeleteQueries; + + if (queries.Count > 0) + { + newDeleteQueries = new HashMap<Query, int>(queries.Count); + foreach(var entry in queries) + { + int num = entry.Value; + newDeleteQueries[entry.Key] = mapper.Remap(num); + } + } + else + newDeleteQueries = null; + + if (newDeleteTerms != null) + terms = newDeleteTerms; + if (newDeleteDocIDs != null) + docIDs = newDeleteDocIDs; + if (newDeleteQueries != null) + queries = newDeleteQueries; + } + } + } +}
\ No newline at end of file |