Parallelize AD searching
Where multiple queries are required to complete a search, the query is parallelized
This commit is contained in:
@@ -233,7 +233,7 @@ namespace Disco.Services.Interop.ActiveDirectory
|
|||||||
|
|
||||||
var ldapSamAccountName = computerId.Item2.EndsWith("$") ? computerId.Item2 : computerId.Item2 + "$";
|
var ldapSamAccountName = computerId.Item2.EndsWith("$") ? computerId.Item2 : computerId.Item2 + "$";
|
||||||
var ldapFilter = string.Format(ldapFilterTemplate, ldapSamAccountName);
|
var ldapFilter = string.Format(ldapFilterTemplate, ldapSamAccountName);
|
||||||
var ldapResult = ADInterop.SearchDomain(Domain, DomainController, Domain.DistinguishedName, ldapFilter, 1, loadProperites).FirstOrDefault();
|
var ldapResult = ADInterop.SearchAll(Domain, DomainController, ldapFilter, 1, loadProperites).FirstOrDefault();
|
||||||
|
|
||||||
if (ldapResult != null)
|
if (ldapResult != null)
|
||||||
MachineAccount = ldapResult.AsMachineAccount(loadAdditionalProperties);
|
MachineAccount = ldapResult.AsMachineAccount(loadAdditionalProperties);
|
||||||
|
|||||||
@@ -317,34 +317,56 @@ namespace Disco.Services.Interop.ActiveDirectory.Internal
|
|||||||
{
|
{
|
||||||
return SearchAll(Domain, LdapFilter, null, LoadProperties);
|
return SearchAll(Domain, LdapFilter, null, LoadProperties);
|
||||||
}
|
}
|
||||||
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(IEnumerable<Tuple<ActiveDirectoryDomain, DomainController>> DomainsWithController, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
|
||||||
{
|
|
||||||
var query = DomainsWithController
|
|
||||||
.SelectMany(d => SearchAll(d.Item1, d.Item2, LdapFilter, ResultLimit, LoadProperties));
|
|
||||||
|
|
||||||
if (ResultLimit.HasValue)
|
|
||||||
query = query.Take(ResultLimit.Value);
|
|
||||||
|
|
||||||
return query.ToList();
|
|
||||||
}
|
|
||||||
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(IEnumerable<ActiveDirectoryDomain> Domains, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(IEnumerable<ActiveDirectoryDomain> Domains, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
{
|
{
|
||||||
var query = Domains
|
if (Domains == null || Domains.Count() == 0)
|
||||||
.SelectMany(domain => SearchAll(domain, LdapFilter, ResultLimit, LoadProperties));
|
return Enumerable.Empty<ActiveDirectorySearchResult>();
|
||||||
|
|
||||||
|
var queries = Domains.Select(d => Tuple.Create(d, (DomainController)null)).ToList();
|
||||||
|
|
||||||
|
return SearchAll(queries, LdapFilter, ResultLimit, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(IEnumerable<Tuple<ActiveDirectoryDomain, DomainController>> DomainsWithController, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
var queries = DomainsWithController.ToList();
|
||||||
|
|
||||||
|
IEnumerable<ActiveDirectorySearchResult> results;
|
||||||
|
|
||||||
|
switch (queries.Count)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
results = Enumerable.Empty<ActiveDirectorySearchResult>();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
var singleQuery = queries.First();
|
||||||
|
results = SearchDomain(singleQuery.Item1, singleQuery.Item2, null, LdapFilter, ResultLimit, LoadProperties);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
var taskFactory = new TaskFactory<IEnumerable<ActiveDirectorySearchResult>>();
|
||||||
|
var tasks = queries
|
||||||
|
.Select(query =>
|
||||||
|
taskFactory.StartNew(() =>
|
||||||
|
SearchDomain(query.Item1, query.Item2, null, LdapFilter, ResultLimit, LoadProperties))
|
||||||
|
).ToArray();
|
||||||
|
Task.WaitAll(tasks);
|
||||||
|
results = tasks.SelectMany(t => t.Result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (ResultLimit.HasValue)
|
if (ResultLimit.HasValue)
|
||||||
query = query.Take(ResultLimit.Value);
|
results = results.Take(ResultLimit.Value);
|
||||||
|
|
||||||
return query.ToList();
|
return results.ToList();
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(ActiveDirectoryDomain Domain, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
return SearchAll(Domain, null, LdapFilter, ResultLimit, LoadProperties);
|
||||||
}
|
}
|
||||||
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(ActiveDirectoryDomain Domain, DomainController DomainController, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(ActiveDirectoryDomain Domain, DomainController DomainController, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
{
|
{
|
||||||
return SearchDomain(Domain, DomainController, null, LdapFilter, ResultLimit, LoadProperties);
|
return SearchDomain(Domain, DomainController, null, LdapFilter, ResultLimit, LoadProperties);
|
||||||
}
|
}
|
||||||
public static IEnumerable<ActiveDirectorySearchResult> SearchAll(ActiveDirectoryDomain Domain, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
|
||||||
{
|
|
||||||
return SearchDomain(Domain, null, LdapFilter, ResultLimit, LoadProperties);
|
|
||||||
}
|
|
||||||
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(string LdapFilter, string[] LoadProperties)
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(string LdapFilter, string[] LoadProperties)
|
||||||
{
|
{
|
||||||
return SearchScope(Domains, LdapFilter, LoadProperties);
|
return SearchScope(Domains, LdapFilter, LoadProperties);
|
||||||
@@ -369,25 +391,9 @@ namespace Disco.Services.Interop.ActiveDirectory.Internal
|
|||||||
{
|
{
|
||||||
return SearchScope(Domain, DomainController, LdapFilter, null, LoadProperties);
|
return SearchScope(Domain, DomainController, LdapFilter, null, LoadProperties);
|
||||||
}
|
}
|
||||||
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(IEnumerable<Tuple<ActiveDirectoryDomain, DomainController>> DomainsWithController, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
|
||||||
{
|
|
||||||
var query = DomainsWithController
|
|
||||||
.SelectMany(d => SearchScope(d.Item1, d.Item2, LdapFilter, ResultLimit, LoadProperties));
|
|
||||||
|
|
||||||
if (ResultLimit.HasValue)
|
|
||||||
query = query.Take(ResultLimit.Value);
|
|
||||||
|
|
||||||
return query.ToList();
|
|
||||||
}
|
|
||||||
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(IEnumerable<ActiveDirectoryDomain> Domains, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(IEnumerable<ActiveDirectoryDomain> Domains, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
{
|
{
|
||||||
var query = Domains
|
return SearchScope(Domains.Select(d => Tuple.Create(d, (DomainController)null)), LdapFilter, ResultLimit, LoadProperties);
|
||||||
.SelectMany(domain => SearchScope(domain, LdapFilter, ResultLimit, LoadProperties));
|
|
||||||
|
|
||||||
if (ResultLimit.HasValue)
|
|
||||||
query = query.Take(ResultLimit.Value);
|
|
||||||
|
|
||||||
return query.ToList();
|
|
||||||
}
|
}
|
||||||
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(ActiveDirectoryDomain Domain, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(ActiveDirectoryDomain Domain, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
{
|
{
|
||||||
@@ -395,23 +401,49 @@ namespace Disco.Services.Interop.ActiveDirectory.Internal
|
|||||||
}
|
}
|
||||||
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(ActiveDirectoryDomain Domain, DomainController DomainController, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(ActiveDirectoryDomain Domain, DomainController DomainController, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
{
|
{
|
||||||
if (Domain.SearchContainers == null)
|
if (Domain.SearchContainers == null || Domain.SearchContainers.Count == 0)
|
||||||
return Enumerable.Empty<ActiveDirectorySearchResult>();
|
return Enumerable.Empty<ActiveDirectorySearchResult>();
|
||||||
|
|
||||||
var query = Domain.SearchContainers
|
var query = new List<Tuple<ActiveDirectoryDomain, DomainController>>() {
|
||||||
.SelectMany(container => SearchDomain(Domain, DomainController, container, LdapFilter, ResultLimit, LoadProperties));
|
Tuple.Create(Domain, DomainController)
|
||||||
|
};
|
||||||
|
|
||||||
|
return SearchScope(query, LdapFilter, ResultLimit, LoadProperties);
|
||||||
|
}
|
||||||
|
public static IEnumerable<ActiveDirectorySearchResult> SearchScope(IEnumerable<Tuple<ActiveDirectoryDomain, DomainController>> DomainsWithController, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
|
{
|
||||||
|
var queries = DomainsWithController.SelectMany(d => d.Item1.SearchContainers, (d, sc) => Tuple.Create(d.Item1, d.Item2, sc)).ToList();
|
||||||
|
|
||||||
|
IEnumerable<ActiveDirectorySearchResult> results;
|
||||||
|
|
||||||
|
switch (queries.Count)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
results = Enumerable.Empty<ActiveDirectorySearchResult>();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
var singleQuery = queries.First();
|
||||||
|
results = SearchDomain(singleQuery.Item1, singleQuery.Item2, singleQuery.Item3, LdapFilter, ResultLimit, LoadProperties);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
var taskFactory = new TaskFactory<IEnumerable<ActiveDirectorySearchResult>>();
|
||||||
|
var tasks = queries
|
||||||
|
.Select(query =>
|
||||||
|
taskFactory.StartNew(() =>
|
||||||
|
SearchDomain(query.Item1, query.Item2, query.Item3, LdapFilter, ResultLimit, LoadProperties).ToList())
|
||||||
|
).ToArray();
|
||||||
|
Task.WaitAll(tasks);
|
||||||
|
results = tasks.SelectMany(t => t.Result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (ResultLimit.HasValue)
|
if (ResultLimit.HasValue)
|
||||||
query = query.Take(ResultLimit.Value);
|
results = results.Take(ResultLimit.Value);
|
||||||
|
|
||||||
return query.ToList();
|
return results.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<ActiveDirectorySearchResult> SearchDomain(ActiveDirectoryDomain Domain, string SearchRoot, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
private static IEnumerable<ActiveDirectorySearchResult> SearchDomain(ActiveDirectoryDomain Domain, DomainController DomainController, string SearchRoot, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
||||||
{
|
|
||||||
return SearchDomain(Domain, null, SearchRoot, LdapFilter, ResultLimit, LoadProperties);
|
|
||||||
}
|
|
||||||
public static IEnumerable<ActiveDirectorySearchResult> SearchDomain(ActiveDirectoryDomain Domain, DomainController DomainController, string SearchRoot, string LdapFilter, int? ResultLimit, string[] LoadProperties)
|
|
||||||
{
|
{
|
||||||
string ldapServer = DomainController == null ? Domain.DnsName : DomainController.Name;
|
string ldapServer = DomainController == null ? Domain.DnsName : DomainController.Name;
|
||||||
string searchRoot = SearchRoot ?? Domain.DistinguishedName;
|
string searchRoot = SearchRoot ?? Domain.DistinguishedName;
|
||||||
|
|||||||
Reference in New Issue
Block a user