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:

  1. The cost of the arc, if any, from a to c in G.

  2. 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