/// <summary> /// Executes a rule collection against the supplied connection /// </summary> /// <param name="collection">The rule collection to execute</param> /// <param name="connection">The connection used to retrieve entries for processing</param> /// <returns><see cref="RuleCollectionResult"/> or null if canceled</returns> private RuleCollectionResult ExecuteRuleCollection(RuleCollection collection, LdapConnection connection) { // these count all the totals for the connection against which this RuleCollection is being run var stopWatch = new Stopwatch(); long skipCount = 0; long entryCount = 0; long duplicateCount = 0; long errorCount = 0; this.OnStatusUpdate?.Invoke("Please wait while the LDAP Connection is established."); var searchRequest = collection.CreateSearchRequest(); this.OnStatusUpdate?.Invoke("LDAP Connection established."); var errors = new List <ComposedRuleResult>(); this.OnStatusUpdate?.Invoke("Beginning query"); while (true) { var searchResponse = (SearchResponse)connection.SendRequest(searchRequest); // verify support for paged results if (searchResponse.Controls.Length != 1 || !(searchResponse.Controls[0] is PageResultResponseControl)) { this.OnStatusUpdate?.Invoke("The server cannot page the result set."); throw new InvalidOperationException("The server cannot page the result set."); } foreach (SearchResultEntry entry in searchResponse.Entries) { if (this.CancellationPending) { return(null); } if (collection.Skip(entry)) { skipCount++; continue; } // this tracks the number of entries we have processed and not skipped entryCount++; foreach (var composedRule in collection.Rules) { // run each composed rule which can produce multiple results var results = composedRule.Execute(entry); for (var i = 0; i < results.Length; i++) { if (!results[i].Success) { errorCount++; if (results[i].Results.Any(r => (r.ErrorTypeFlags & ErrorType.Duplicate) != 0)) { duplicateCount++; } errors.Add(results[i]); } } } } // handle paging var cookie = searchResponse.Controls.OfType <PageResultResponseControl>().First().Cookie; // if this is true, there are no more pages to request if (cookie.Length == 0) { break; } searchRequest.Controls.OfType <PageResultRequestControl>().First().Cookie = cookie; } // we are all done, stop tracking time stopWatch.Stop(); return(new RuleCollectionResult { TotalDuplicates = duplicateCount, TotalErrors = errorCount, TotalFound = skipCount + entryCount, TotalSkips = skipCount, TotalProcessed = entryCount, Elapsed = stopWatch.Elapsed, Errors = errors.ToArray() }); }
/// <summary> /// Executes a rule collection against the supplied connection /// </summary> /// <param name="collection">The rule collection to execute</param> /// <param name="connection">The connection used to retrieve entries for processing</param> /// <returns><see cref="RuleCollectionResult"/> or null if canceled</returns> private RuleCollectionResult ExecuteRuleCollection(RuleCollection collection, LdapConnection connection) { // these count all the totals for the connection against which this RuleCollection is being run var stopWatch = new Stopwatch(); long skipCount = 0; long entryCount = 0; long duplicateCount = 0; long errorCount = 0; this.OnStatusUpdate?.Invoke(StringLiterals.LdapConnectionEstablishing); var searchRequest = collection.CreateSearchRequest(); this.OnStatusUpdate?.Invoke(StringLiterals.LdapConnectionEstablished); var errors = new List <ComposedRuleResult>(); this.OnStatusUpdate?.Invoke(StringLiterals.BeginningQuery); while (true) { var searchResponse = (SearchResponse)connection.SendRequest(searchRequest); // verify support for paged results if (searchResponse.Controls.Length != 1 || !(searchResponse.Controls[0] is PageResultResponseControl)) { this.OnStatusUpdate?.Invoke(StringLiterals.CannotPageResultSet); throw new InvalidOperationException(StringLiterals.CannotPageResultSet); } foreach (SearchResultEntry entry in searchResponse.Entries) { if (this.CancellationPending) { return(null); } if (collection.Skip(entry)) { skipCount++; continue; } // this tracks the number of entries we have processed and not skipped entryCount++; foreach (var composedRule in collection.Rules) { // run each composed rule which can produce multiple results var results = composedRule.Execute(entry); for (var i = 0; i < results.Length; i++) { var result = results[i]; if (!result.Success) { errorCount++; if (result.Results.Any(r => (r.ErrorTypeFlags & ErrorType.Duplicate) != 0)) { duplicateCount++; if (result.ProposedAction == ActionType.Edit) { // Add original LDAP entry with the same value. var originalEntry = DuplicateStore.GetOriginalSearchResultEntry(result.AttributeName, result.OriginalValue); var additionalResult = new ComposedRuleResult { AttributeName = result.AttributeName, EntityDistinguishedName = originalEntry.DistinguishedName, EntityCommonName = originalEntry.Attributes[StringLiterals.Cn][0].ToString(), ObjectType = ComposedRule.GetObjectType(entry), OriginalValue = result.OriginalValue, ProposedAction = result.ProposedAction, ProposedValue = result.ProposedValue, Results = new RuleResult[] { new RuleResult(false) { ErrorTypeFlags = ErrorType.Duplicate, ProposedAction = result.ProposedAction, UpdatedValue = result.OriginalValue } }, Success = result.Success }; errors.Add(additionalResult); } } errors.Add(result); } } } } // handle paging var cookie = searchResponse.Controls.OfType <PageResultResponseControl>().First().Cookie; // if this is true, there are no more pages to request if (cookie.Length == 0) { break; } searchRequest.Controls.OfType <PageResultRequestControl>().First().Cookie = cookie; } // we are all done, stop tracking time stopWatch.Stop(); return(new RuleCollectionResult { TotalDuplicates = duplicateCount, TotalErrors = errorCount, TotalFound = skipCount + entryCount, TotalSkips = skipCount, TotalProcessed = entryCount, Elapsed = stopWatch.Elapsed, Errors = errors.ToArray() }); }