4.1.16.3 Server Behavior of the IDL_DRSQuerySitesByCost Method
Informative summary of behavior: Given a site fromSite and an array of sites toSites, the server returns an array that contains the cost from fromSite to each element of toSite, where the cost is defined as follows.
The server computes a weighted graph G = (V, A). Each vertex in V corresponds to a site object. Each arc in A corresponds to a siteLink object that connects two vertices in V; the weight of an arc is the value of attribute cost on the arc's siteLink object. The cost of a path in the graph is the sum of the arc weights on the path. The cost from one site to another is the minimum-cost path between the two sites.
The model just described corresponds to fully transitive communications between sites: If site a communicates with site b and site b communicates with site c, then site a communicates with site c by routing through b. Replication can be configured to restrict transitive communication to sites specified in the same siteLinkBridge object. Suppose there is a siteLink object for site a and site b, and a siteLink object for site b and site c, but no siteLink object for site a and site c. If both of the siteLink objects are specified on the same siteLinkBridge object, site a can communicate with site c by routing through b. If no such siteLinkBridge object exists, site a cannot communicate with site c.
To calculate the cost when siteLinkBridge objects are used, let nBridges be the number of siteLinkBridge objects. For each k in the subrange [0 .. nBridges-1], construct a weighted graph G[k] = (V, A[k]) using siteLinkBridge object b[k]. Graph G[k] has the same vertex set as G, but its arc set A[k] is a subset of A, including only the arcs listed in attribute siteLinkList on siteLinkBridge object b[k]. Then the cost from site a to site c is the minimum of the following costs:
The cost of the arc, if any, from a to c in G.
For each k in the subrange [0 .. nBridges-1], the cost of the minimum cost path, if any, from a to c in G[k].
Any authenticated user can perform this operation; no access checking is performed.<36>
-
ULONG IDL_DRSQuerySitesByCost( [in, ref] DRS_HANDLE hDrs, [in] DWORD dwInVersion, [in, ref, switch_is(dwInVersion)] DRS_MSG_QUERYSITESREQ *pmsgIn, [out, ref] DWORD *pdwOutVersion, [out, ref, switch_is(*pdwOutVersion)] DRS_MSG_QUERYSITESREPLY *pmsgOut) msgIn: DRS_MSG_QUERYSITESREQ_V1 vSet, slSet, sbSet : set of DSName aSet, aSetB, aSetC, aSetD: WeightedArcSet siteContainer, ipObject, fromSite, toSite: DSName u, v, sl, sb: DSName i, c: integer min: WeightedArc ul : ULONG ValidateDRSInput(hDrs, 24) pdwOutVersion^ := 1 pmsgOut^.V1.cToSites := 0 pmsgOut^.V1. rgCostInfo := null pmsgOut^.V1.dwFlags := 0 /* Perform input validation, * initialize siteContainer, ipObject, fromSite. */ if dwInVersion ≠ 1 then return ERROR_DS_DRA_INVALID_PARAMETER endif msgIn := pmsgIn^.V1 ul := ValidateSiteRDN(msgIn.pwszFromSite) if 0 ≠ ul then return ul endif if msgIn.cToSites > 0 and msgIn.rgszToSites = null then return ERROR_INVALID_PARAMETER endif for i := 0 to msgIn.cToSites – 1 ul := ValidateSiteRDN(msgIn.rgszToSites[i]) if 0 ≠ ul then return ul endif endfor siteContainer := DescendantObject(ConfigNC(), "CN=Sites,") ipObject := DescendantObject(ConfigNC(), "CN=IP,CN=Inter-Site Transports,CN=Sites,") fromSite := select one v from children siteContainer where site in v!objectClass and v!name = msgIn.pwszFromSite if fromSite = null then return ERROR_DS_OBJ_NOT_FOUND endif /* Construct the vertex set vSet. */ vSet := select all v from children siteContainer where site in v!objectClass if vSet = {} then return ERROR_DS_OBJ_NOT_FOUND endif /* Construct the arc set aSet. */ slSet := select all v from children ipObject where siteLink in v!objectClass foreach sl in slSet foreach u in sl!siteList foreach v in sl!siteList - {u} aSet := aSet + {[initial: u, final: v, cost: sl!cost]} endfor endfor endfor /* Construct minimum-cost arc set aSetC. * See [MS-ADTS] section 6.1.1.2.2.3.1, "IP Transport Container", for * the definition of the NTDSTRANSPORT_OPT_BRIDGES_REQUIRED option. */ if NTDSTRANSPORT_OPT_BRIDGES_REQUIRED in ipObject!options then /* Perform construction using siteLinkBridge objects. * Initial minimum cost is the cost of a direct arc if any. */ aSetC := aSet sbSet := select all v from children ipObject where siteLinkBridge in v!objectclass foreach sb in sbSet /* Compute the minimum cost using this siteLinkBridge. */ aSetB := {} foreach sl in sb!siteLinkList foreach u in sl!siteList foreach v in sl!siteList - {u} aSetB := aSetB + {[initial: u, final: v, cost: sl!cost)} endfor endfor endfor aSetD := MinWeightPath(vSet, aSetB) /* Here aSetD contains the minimum cost arc set using this * siteLinkBridge. Improve the current minimum cost using * aSetD. */ foreach [initial: u, final: v, cost: c] in aSetD min := select one t from aSetC where t.initial = u and t.final = v if min = null then aSetC := aSetC + {[initial: u, final: v, cost: c)} else if min.cost > c then aSetC := aSetC - {[initial: u, final: v, cost: min.cost]} + {[initial: u, final: v, cost: c)} endif endfor endfor else /* Fully transitive network, ignore siteLinkBridge objects. */ aSetC := MinWeightPath(vSet, aSet) endif /* Construct result message. */ pdwOutVersion^ := 1 pmsgOut^.V1.cToSites := msgIn.cToSites pmsgOut^.V1.dwFlags := 0 for i:= 0 to msgIn.cToSites - 1 toSite := select one v from children siteContainer where site in v!objectClass and v!name = msgIn.rgszToSites[i] if not (toSite in vSet) then pmsgOut^.V1.rgCostInfo[i].dwErrorCode := ERROR_DS_OBJ_NOT_FOUND pmsgOut^.V1.rgCostInfo[i].dwCost := 0xffffffff else min := select one t from aSetC where t.initial = fromSite and t.final = toSite if min ≠ null then pmsgOut^.V1.rgCostInfo[i].dwErrorCode := 0 pmsgOut^.V1.rgCostInfo[i].dwCost := min.cost else pmsgOut^.V1.rgCostInfo[i].dwErrorCode = 0 pmsgOut^.V1.rgCostInfo[i].dwCost := 0xffffffff endif endif endfor return 0