public void RemoveDocumentsMatching([NotNull] Func <DocumentInfo, bool> predicate) { if (predicate == null) { throw new ArgumentNullException("predicate"); } lock (lockIndex) { var oldDocuments = state.documents; var allDocumentsToRemove = new HashSet <DocumentInfo>(oldDocuments.Where(predicate)); if (!allDocumentsToRemove.Any()) { return; } var newDocuments = oldDocuments.Except(allDocumentsToRemove); predicate = allDocumentsToRemove.Contains; var oldIndex = state.wordIndex; var newIndex = new InternalSortedList <string, IImmutableSet <DocumentInfo> >(this.wordComparer, oldIndex.Count); foreach (var item in oldIndex) { var newValue = item.Value.Except(item.Value.Where(predicate)); if (newValue.Count > 0) { newIndex.AddSorted(item.Key, newValue); } } this.state = new State(newIndex, newDocuments); } }
private ImmutableIndex(InternalSortedList <string, IImmutableSet <DocumentInfo> > wordIndex, IImmutableSet <DocumentInfo> allDocuments) { this.wordComparer = (StringComparisonComparer)wordIndex.KeyComparer; this.state = new State(wordIndex, allDocuments); }
public State(InternalSortedList <string, IImmutableSet <DocumentInfo> > wordIndex, IImmutableSet <DocumentInfo> allDocuments) { this.wordIndex = wordIndex; this.documents = allDocuments; }
public Task Merge([NotNull] DocumentInfo document, [NotNull] IEnumerable <string> indexWords) { if (document == null) { throw new ArgumentNullException("document"); } if (indexWords == null) { throw new ArgumentNullException("indexWords"); } var sourceWords = new SortedSet <string>(indexWords, wordComparer).ToList(); bool hasWords = sourceWords.Any(); var singleDocumentList = ImmutableHashSet.Create(document); // Merge join sorted word list with wordIndex list lock (lockIndex) { IImmutableSet <DocumentInfo> oldDocuments = state.documents; IImmutableSet <DocumentInfo> newDocuments; bool isNewDocument; if (hasWords) { newDocuments = oldDocuments.Add(document); isNewDocument = newDocuments != oldDocuments; // new if was added to document set } else { newDocuments = oldDocuments.Remove(document); isNewDocument = newDocuments == oldDocuments; // new if wasn't contained before in document set if (isNewDocument) { return(CompletedTask.Instance); } } var oldIndex = state.wordIndex; var newIndex = new InternalSortedList <string, IImmutableSet <DocumentInfo> >(this.wordComparer, oldIndex.Count + sourceWords.Count); int idxSource = 0; int idxTarget = 0; while (true) { int compareResult = 0; if (idxTarget >= oldIndex.Count) { compareResult = -1; } if (idxSource >= sourceWords.Count) { if (compareResult != 0) { break; } compareResult = 1; } if (compareResult == 0) { compareResult = wordComparer.Compare(sourceWords[idxSource], oldIndex[idxTarget].Key); } if (compareResult < 0) { // add and include newIndex.AddSorted(sourceWords[idxSource], singleDocumentList); idxSource += 1; //idxTarget += 1; } else if (compareResult > 0) { var item = oldIndex[idxTarget]; if (!isNewDocument) { var newValue = item.Value.Remove(document); if (newValue.Count > 0) { newIndex.AddSorted(item.Key, newValue); } } else { newIndex.AddSorted(item.Key, item.Value); } idxTarget += 1; } else { var item = oldIndex[idxTarget]; newIndex.AddSorted(item.Key, item.Value.Add(document)); idxSource += 1; idxTarget += 1; } } this.state = new State(newIndex, newDocuments); } return(CompletedTask.Instance); }