Beispiel #1
0
        protected object TraverseChild <T>(T child, string name, object parent)
        {
            var t = this as ITraverser <T>;

            if (t != null)
            {
                var node = new TraverseNode <T>(child, name, parent);
                t.Traverse(node);
                return(node.Result);
            }

            var unknown = this as ITraverser;

            if (unknown != null)
            {
                var node = new TraverseNode <object>(child, name, parent);
                unknown.Traverse(node);
                return(node.Result);
            }

            throw new TraverserNotImplementedException(string.Format("Cannot traverse an instance of “{0}” type. Please implement a proper ITraverser interface.", child.GetType().Name));
        }
        /// <summary>
        /// This is a very key service operation that really makes eveything work fast, across 3 dimensions:
        /// x-horizontal connected services, y-layers deep, virtualized across z-virtual clustered hosts within a given service domain.  It
        /// will be the preceeding call to almost all other Config Service calls, to get the fastest path to a target 
        /// connected Config Service host on the network.
        /// </summary>
        /// <param name="queriedNodeList">This list is used to prevent circular references in a connected tree of nodes from being queried, and creating a race condition.</param>
        /// <param name="targetHostNameIdentifier">The name of the target host we are seeking, as specified in the target's HOST_NAME_IDENTIFIER settings key.</param>
        /// <param name="targetConfigServiceNameIdentifier">The fully qualified name of the Configuration Service implementation class for the host we are seeking, used in
        /// conjunction with targetHostNameIdentifier to uniquely identify a target host.</param>
        /// <param name="csUser">The user requesting the path.</param>
        /// <returns>A network traverse path consisting of a List of TraverseNode types.</returns>
        public override List<TraverseNode> getTraversePath(List<TraverseNode> queriedNodeList, string targetHostNameIdentifier, string targetConfigServiceNameIdentifier, ServiceUsers csUser)
        {
            switch (Trade.BusinessServiceConfigurationSettings.Settings.ORDER_PROCESSING_MODE)
            {
                case StockTraderUtility.OPS_INPROCESS:
                    {
                        if (targetHostNameIdentifier.Equals(StockTraderUtility.ORDER_PROCESSOR_SERVICE_SELFHOST))
                        {
                            ServiceConfigHelper configHelper = new ServiceConfigHelper(settingsInstance);
                            TraverseNode myNode = null;
                            List<TraverseNode> thisPath = new List<TraverseNode>();
                            try
                            {
                                if (!(configHelper.setServiceRights(ref csUser, ConfigUtility.CONFIG_CONNECTED_SERVICE_RIGHTS)>=ConfigUtility.CONFIG_CONNECTED_SERVICE_RIGHTS))
                                    return null;
                                ConfigUtility.writeConfigConsoleMessage("\nRequest for traverse path received. Target Service Host: " + targetHostNameIdentifier + " hosting target ConfigService: " + targetConfigServiceNameIdentifier + ".\n", EventLogEntryType.Information, true, settingsInstance);
                                string HOST_NAME_IDENTIFIER = (string)ConfigUtility.reflectGetField(settingsInstance, "HOST_NAME_IDENTIFIER");
                                string CONFIG_SERVICENAME_IDENTIFIER = (string)ConfigUtility.reflectGetField(settingsInstance, "CONFIG_SERVICENAME_IDENTIFIER");
                                int NODE_ACTIVE_ID = (int)ConfigUtility.reflectGetField(settingsInstance, "NODE_ACTIVE_ID");
                                //This logic is used to ensure we construct a valid endpoint based on whether our config service
                                //is using an external load balancer such as Windows Network Load Balancing or hardware load-balancer.  This
                                //would typically be the case for any service exposed to the Internet cloud where clients could be coming from
                                //anywhere and we thus need to virtualize our Internet DNS name--or even intranet DNS name.
                                List<HostedServices> hostedServices = (List<HostedServices>)ConfigUtility.reflectGetField(settingsInstance, "hostedServices");
                                //We may have this service listening on lots of different endpoints.
                                //We need to map the correct Service Endpoint (which implies a binding) to the incoming client request using this WCF property
                                //on the operation context.  However note this is contained in the traversepath (TraverseNode) data structure,
                                //but given new design not currently used within Config Service/ConfigWeb as we dynamically figure out a new valid path on subsequent requests
                                //(given valid paths might change within seconds from original request).
                                //However, returning the correct information here may be important for those extending Config Service, as the
                                //addresses will be valid addresses given incoming request all the way up the stack from the original request.  Those that want could
                                //override this method any choose not to return *any* actual endpoint information for services this service connects to.
                                //Just a choice; independent of security which should always be set on the WCF binding itself (wsHttp or netTcp for ConfigService)
                                //, which, if set  with digital certs, InfoCard, Windows Auth (Kerberos) would be really locked down to identity of caller at the 
                                //transport and/or message level to begin with (meaning we would never be at this point in code if the client was not valid!).
                                string currentRequestEndpoint = OperationContext.Current.EndpointDispatcher.EndpointAddress.ToString();
                                List<HostListenEndPointInstance> myConfigEndpoints = (List<HostListenEndPointInstance>)ConfigUtility.reflectGetField(settingsInstance, "hostConfigListenEndpoints");
                                if (ConfigUtility.onAzure)
                                {
                                    Uri myUri = new Uri(currentRequestEndpoint);
                                    string myHostMachine = myUri.Host;
                                    string path = myUri.AbsolutePath.ToLower();
                                    ConfigUtility.writeConfigConsoleMessage("\n*** currentRequestPath: " + path, EventLogEntryType.Information, true, settingsInstance);
                                    HostListenEndPointInstance theConfigEndpoint = myConfigEndpoints.Find(delegate(HostListenEndPointInstance hExist)
                                    {
                                        Uri uri = new Uri(hExist.RemoteAddress);
                                        return uri.AbsolutePath.ToLower().Equals(path) && uri.Scheme.Equals(myUri.Scheme);
                                    }
                                    );
                                    if (theConfigEndpoint != null)
                                    {
                                        HostedServices thisService = hostedServices.Find(delegate(HostedServices hsExist)
                                        {
                                            return hsExist.HostedServiceID == theConfigEndpoint.HostedServiceID;
                                        }
                                        );
                                        string myName = ServiceConfigHelper.getHostNameForServiceHosting(thisService, settingsInstance);
                                        currentRequestEndpoint = currentRequestEndpoint.Replace(myHostMachine, myName);
                                    }
                                }

                                HostListenEndPointInstance myEp = ServiceConfigHelper.currentRequestFindMatchingListenEndpoint(currentRequestEndpoint, myConfigEndpoints);
                                if (myConfigEndpoints!=null && myConfigEndpoints.Count>0)
                                    ConfigUtility.writeConfigConsoleMessage("\n*** currentRequestEndpoint: " + currentRequestEndpoint + " myConfigEndpoints[0].RemoteAddress: " + myConfigEndpoints[0].RemoteAddress, EventLogEntryType.Information, true, settingsInstance);
                                if (myEp == null)
                                {
                                    ConfigUtility.writeConfigConsoleMessage("myEp is null, returning null path", EventLogEntryType.Information, true, settingsInstance);
                                    return null;
                                }
                                //If we are already in the path, then return null now.  This prevents circular service references within the tree from causing a race
                                //condition.  TODO is to add information about the reference so it shows up in physical maps within ConfigWeb, for now
                                //we will just return null and prevent a race condition.
                                if (queriedNodeList == null)
                                    queriedNodeList = new List<TraverseNode>();
                                TraverseNode me = queriedNodeList.Find(delegate(TraverseNode tn) { return (tn.MyNode.HostNameIdentifier.Equals(HOST_NAME_IDENTIFIER) && tn.MyNode.ConfigServiceImplementationClassName.Equals(CONFIG_SERVICENAME_IDENTIFIER)); });
                                if (me != null)
                                    return null;
                                //Note this does not populate peer nodes such that if using external load balancer, actual physical nodes remain 
                                //hidden behind the virtualized endpoint and are not returned.
                                myNode = new TraverseNode(new ServiceNode(NODE_ACTIVE_ID, myEp.RemoteAddress, ConfigSettings.MESSAGE_ONLINE, myEp.ActiveSince, HOST_NAME_IDENTIFIER, null, CONFIG_SERVICENAME_IDENTIFIER), null);
                                myNode.MyInProcNode = myNode.MyNode;
                                myNode.OSName = OSInfo.Name;
                                queriedNodeList.Add(myNode);
                                thisPath.Add(myNode);
                            }
                            catch (Exception e)
                            {
                                ServiceConfigHelper.logServiceOperationException(csUser, e.ToString(), settingsInstance);
                                throw;
                            }
                            return thisPath;
                        }
                        else
                            return base.getTraversePath(queriedNodeList, targetHostNameIdentifier, targetConfigServiceNameIdentifier, csUser);
                    }
                default:
                    {
                        List<TraverseNode> returnList = base.getTraversePath(queriedNodeList, targetHostNameIdentifier, targetConfigServiceNameIdentifier, csUser);
                        return returnList;
                    }
            }
        }