in src/IdFix/Rules/RulesRunner.cs [308:424]
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()
};
}