/// <summary> /// Loads OPS config settings from its repository, performs init on in-process Order Processor Service. /// </summary> public static void initConfigOrderProcessService(object lockobject, bool force) { lock (lockobject) { if (!force && initialized) return; initialized = true; ConnectionStringSettings connSettingOPS = System.Configuration.ConfigurationManager.ConnectionStrings["OPS_CONFIGDB_SQL_CONN_STRING"]; Trade.OrderProcessorServiceConfigurationSettings.Settings.CONFIGDB_SQL_CONN_STRING = connSettingOPS.ConnectionString; Trade.OrderProcessorServiceConfigurationSettings.Settings OPSSettings = new Trade.OrderProcessorServiceConfigurationSettings.Settings(); ServiceConfigHelper configHelper = new ServiceConfigHelper(OPSSettings); Trade.OrderProcessorHostConfigurationImplementation.ConfigurationActions OPSConfigActions = new Trade.OrderProcessorHostConfigurationImplementation.ConfigurationActions(); Trade.OrderProcessorServiceConfigurationSettings.Settings.thisService = new Trade.OrderProcessorHostConfigurationImplementation.ConfigurationService(); Trade.OrderProcessorServiceConfigurationSettings.Settings.thisServiceConfigActions = OPSConfigActions; configHelper.InitializeConfigFromDatabase(false, ref Trade.OrderProcessorServiceConfigurationSettings.Settings.connectionPointList, ref Trade.OrderProcessorServiceConfigurationSettings.Settings.connectedServices, ref Trade.OrderProcessorServiceConfigurationSettings.Settings.connectedConfigServices, ref Trade.OrderProcessorServiceConfigurationSettings.Settings.hostedServices, ref Trade.OrderProcessorServiceConfigurationSettings.Settings.serviceHosts, Trade.OrderProcessorServiceConfigurationSettings.Settings.CONFIGDB_SQL_CONN_STRING); OPSConfigActions.initOrderForwardMode(); List<ConnectedServices> connectedServices = (List<ConnectedServices>)ConfigUtility.reflectGetField(OPSSettings, "connectedServices"); object OPSSettingsObject = (object)OPSSettings; if (ServiceConfigHelper.MasterServiceWebHost.MasterHost != null) { ServiceConfigHelper.initOnlineMethodsCS(connectedServices, ServiceConfigHelper.MasterServiceWebHost.MasterHost._connectedServiceContracts, ref OPSSettingsObject); } else if (ServiceConfigHelper.MasterServiceSelfHost.MasterHost != null) { ServiceConfigHelper.initOnlineMethodsCS(connectedServices, ServiceConfigHelper.MasterServiceSelfHost.MasterHost._connectedServiceContracts, ref OPSSettingsObject); } OPSConfigActions.InitCommunicationChannels(OPSSettings, null, ConfigUtility.INIT_ALL_CONNECTED_INSTANCES); } }
/// <summary> /// Loads BSL config settings from its repository, performs init on in-process Business Services. /// </summary> public static void initConfigBusinessService(object lockobject, bool force) { lock (lockobject) { if (!force && initialized) return; initialized = true; ConnectionStringSettings connSettingOPS = System.Configuration.ConfigurationManager.ConnectionStrings["OPS_CONFIGDB_SQL_CONN_STRING"]; ConnectionStringSettings connSettingBSL = System.Configuration.ConfigurationManager.ConnectionStrings["BSL_CONFIGDB_SQL_CONN_STRING"]; StockTraderWebApplicationSettings.Settings.BSL_CONFIGDB_SQL_CONN_STRING = connSettingBSL.ConnectionString; StockTraderWebApplicationSettings.Settings.OPS_CONFIGDB_SQL_CONN_STRING = connSettingOPS.ConnectionString; Trade.BusinessServiceConfigurationSettings.Settings.CONFIGDB_SQL_CONN_STRING = StockTraderWebApplicationSettings.Settings.BSL_CONFIGDB_SQL_CONN_STRING; Trade.BusinessServiceConfigurationSettings.Settings BSLSettings = new Trade.BusinessServiceConfigurationSettings.Settings(); ServiceConfigHelper configHelper = new ServiceConfigHelper(BSLSettings); Trade.BusinessServiceHostConfigurationImplementation.ConfigurationActions BSLConfigActions = new Trade.BusinessServiceHostConfigurationImplementation.ConfigurationActions(); Trade.BusinessServiceConfigurationSettings.Settings.thisService = new Trade.BusinessServiceHostConfigurationImplementation.ConfigurationService(); Trade.BusinessServiceConfigurationSettings.Settings.thisServiceConfigActions = BSLConfigActions; configHelper.InitializeConfigFromDatabase(false, ref Trade.BusinessServiceConfigurationSettings.Settings.connectionPointList, ref Trade.BusinessServiceConfigurationSettings.Settings.connectedServices, ref Trade.BusinessServiceConfigurationSettings.Settings.connectedConfigServices, ref Trade.BusinessServiceConfigurationSettings.Settings.hostedServices, ref Trade.BusinessServiceConfigurationSettings.Settings.serviceHosts, Trade.BusinessServiceConfigurationSettings.Settings.CONFIGDB_SQL_CONN_STRING); BSLConfigActions.initBusinessService(BSLSettings); if (Trade.BusinessServiceConfigurationSettings.Settings.ORDER_PROCESSING_MODE == StockTraderUtility.OPS_INPROCESS) { Trade.OrderProcessorServiceConfigurationSettings.Settings.CONFIGDB_SQL_CONN_STRING = StockTraderWebApplicationSettings.Settings.OPS_CONFIGDB_SQL_CONN_STRING; string thelockobject = "0"; Trade.BusinessServiceHostConfigurationImplementation.InitConfigInProcessOrderService.initConfigOrderProcessService(thelockobject,false); } RemoteNotifications remoteNotify = new RemoteNotifications(new Trade.BusinessServiceConfigurationSettings.Settings()); remoteNotify.notifyRemoteClientsAndHosts(false, ConfigUtility.ADD_HOSTS); List<ConnectedServices> connectedServices = (List<ConnectedServices>)ConfigUtility.reflectGetField(BSLSettings, "connectedServices"); object BSLSettingsObject = (object)BSLSettings; if (ServiceConfigHelper.MasterServiceWebHost.MasterHost != null) { ServiceConfigHelper.initOnlineMethodsCS(connectedServices, ServiceConfigHelper.MasterServiceWebHost.MasterHost._connectedServiceContracts, ref BSLSettingsObject); } else if (ServiceConfigHelper.MasterServiceSelfHost.MasterHost != null) { ServiceConfigHelper.initOnlineMethodsCS(connectedServices, ServiceConfigHelper.MasterServiceSelfHost.MasterHost._connectedServiceContracts, ref BSLSettingsObject); } BSLConfigActions.InitCommunicationChannels(BSLSettings, null, ConfigUtility.INIT_ALL_CONNECTED_INSTANCES); } }
/// <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; } } }
/// <summary> /// Will return the Primary and Generic Service Connection Points from the ConnectedServiceInstances table in the configuration database. /// </summary> /// <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="targetConfigServiceName">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="connectionPointTypes">The type of connection points to retrieve.</param> /// <param name="checkStatus">If true, a satus flag will be set indicating online status of the endpoint.</param> /// <param name="traversePath">Network path to the target host.</param> /// <param name="csUser">User to authenticate.</param> /// <returns>ConnectionPoints instance which is a linked list type.</returns> public override ConnectionPoints getConnectionPoints(string targetHostNameIdentifier, string targetConfigServiceName, List<int> connectionPointTypes, bool checkStatus, List<TraverseNode> traversePath, ServiceUsers csUser) { ServiceConfigHelper configHelper = new ServiceConfigHelper(settingsInstance); ConnectionPoints returnConnectionPoints = null; try { if (!(configHelper.setServiceRights(ref csUser, ConfigUtility.CONFIG_DEMO_ADMIN_RIGHTS) >= ConfigUtility.CONFIG_DEMO_ADMIN_RIGHTS)) return null; ConfigUtility.writeConfigConsoleMessage("\nRequest for Connection Points received.\n", EventLogEntryType.Information, true, settingsInstance); if (traversePath == null || traversePath.Count <= 1 || traversePath[0] == null) { bool SHARESERVICECONFIGURATIONDATA = (bool)ConfigUtility.reflectGetField(settingsInstance, "SHARESERVICECONFIGURATIONDATA"); if (!SHARESERVICECONFIGURATIONDATA) { List<ServiceUsers> thisServiceUsers = (List<ServiceUsers>)ConfigUtility.reflectGetField(settingsInstance, "thisServiceUsers"); ServiceUsers userLocalAdmin = thisServiceUsers.Find(delegate(ServiceUsers userExist) { return csUser.UserId.ToLower().Equals("localadmin") && userExist.Password.Equals(csUser.Password) && csUser.Rights == ConfigUtility.CONFIG_ADMIN_RIGHTS; }); if (userLocalAdmin == null) return null; } returnConnectionPoints = configHelper.getMyConnectionPoints(connectionPointTypes); string HOST_NAME_IDENTIFIER = (string)ConfigUtility.reflectGetField(settingsInstance, "HOST_NAME_IDENTIFIER"); string CONFIG_SERVICENAME_IDENTIFIER = (string)ConfigUtility.reflectGetField(settingsInstance, "CONFIG_SERVICENAME_IDENTIFIER"); bool GETCONNECTEDSERVICES = (bool)ConfigUtility.reflectGetField(settingsInstance, "CONFIGSHOWCONNECTEDSERVICES"); returnConnectionPoints.HostNameIdentifier = HOST_NAME_IDENTIFIER; List<HostListenEndPointInstance> checkOnlineList = new List<HostListenEndPointInstance>(); for (int i = 0; i < returnConnectionPoints.MyConnectionPoints.Count; i++) { switch (Trade.BusinessServiceConfigurationSettings.Settings.ORDER_PROCESSING_MODE) { case StockTraderUtility.OPS_INPROCESS: { break; } case StockTraderUtility.OPS_AZURE_HTTP_TMSEC_CLIENTCERT: { if (returnConnectionPoints.MyConnectionPoints[i].ServiceFriendlyName.Equals(StockTraderUtility.OPS_AZURE_HTTP_TMSEC_CLIENTCERT)) returnConnectionPoints.MyConnectionPoints[i].InUse = true; break; } case StockTraderUtility.OPS_AZURE_HTTP_TMSEC_USERNAME: { if (returnConnectionPoints.MyConnectionPoints[i].ServiceFriendlyName.Equals(StockTraderUtility.OPS_AZURE_HTTP_TMSEC_USERNAME)) returnConnectionPoints.MyConnectionPoints[i].InUse = true; break; } case StockTraderUtility.OPS_AZURE_TCP_TMSEC_CLIENTCERT: { if (returnConnectionPoints.MyConnectionPoints[i].ServiceFriendlyName.Equals(StockTraderUtility.OPS_AZURE_TCP_TMSEC_CLIENTCERT)) returnConnectionPoints.MyConnectionPoints[i].InUse = true; break; } case StockTraderUtility.OPS_AZURE_TCP_TMSEC_USERNAME: { if (returnConnectionPoints.MyConnectionPoints[i].ServiceFriendlyName.Equals(StockTraderUtility.OPS_AZURE_TCP_TMSEC_USERNAME)) returnConnectionPoints.MyConnectionPoints[i].InUse = true; break; } case StockTraderUtility.OPS_SELF_HOST_HTTP: { if (returnConnectionPoints.MyConnectionPoints[i].ServiceFriendlyName.Equals(StockTraderUtility.OPS_SELF_HOST_HTTP)) returnConnectionPoints.MyConnectionPoints[i].InUse = true; break; } case StockTraderUtility.OPS_SELF_HOST_HTTP_TMSEC_CLIENTCERT: { if (returnConnectionPoints.MyConnectionPoints[i].ServiceFriendlyName.Equals(StockTraderUtility.OPS_SELF_HOST_HTTP_TMSEC_CLIENTCERT)) returnConnectionPoints.MyConnectionPoints[i].InUse = true; break; } case StockTraderUtility.OPS_SELF_HOST_HTTP_TMSEC_USERNAME: { if (returnConnectionPoints.MyConnectionPoints[i].ServiceFriendlyName.Equals(StockTraderUtility.OPS_SELF_HOST_HTTP_TMSEC_USERNAME)) returnConnectionPoints.MyConnectionPoints[i].InUse = true; break; } case StockTraderUtility.OPS_SELF_HOST_MSMQ: { if (returnConnectionPoints.MyConnectionPoints[i].ServiceFriendlyName.Equals(StockTraderUtility.OPS_SELF_HOST_MSMQ)) returnConnectionPoints.MyConnectionPoints[i].InUse = true; break; } case StockTraderUtility.OPS_SELF_HOST_TCP: { if (returnConnectionPoints.MyConnectionPoints[i].ServiceFriendlyName.Equals(StockTraderUtility.OPS_SELF_HOST_TCP)) returnConnectionPoints.MyConnectionPoints[i].InUse = true; break; } case StockTraderUtility.OPS_SELF_HOST_TCP_TMSEC_CLIENTCERT: { if (returnConnectionPoints.MyConnectionPoints[i].ServiceFriendlyName.Equals(StockTraderUtility.OPS_SELF_HOST_TCP_TMSEC_CLIENTCERT)) returnConnectionPoints.MyConnectionPoints[i].InUse = true; break; } case StockTraderUtility.OPS_SELF_HOST_TCP_TMSEC_USERNAME: { if (returnConnectionPoints.MyConnectionPoints[i].ServiceFriendlyName.Equals(StockTraderUtility.OPS_SELF_HOST_TCP_TMSEC_USERNAME)) returnConnectionPoints.MyConnectionPoints[i].InUse = true; break; } case StockTraderUtility.OPS_SOAP: { if (returnConnectionPoints.MyConnectionPoints[i].ServiceFriendlyName.Equals(StockTraderUtility.OPS_SOAP)) returnConnectionPoints.MyConnectionPoints[i].InUse = true; break; } } if (checkStatus) { checkOnlineList.Add(returnConnectionPoints.MyConnectionPoints[i]); } } if (checkOnlineList.Count > 0) { RemoteNotifications remoteNotify = new RemoteNotifications(settingsInstance); //This call will set online offline status for each; all are checked concurrently on background threads; //Master thread joined to ensure all are done before returning. remoteNotify.checkConnectionPointOnlineStatus(checkOnlineList, false); } } else { if (traversePath != null && traversePath.Count > 1) { ConfigUtility.writeConfigConsoleMessage("-----> Forwarding Request to Remote Connected Service: " + traversePath[traversePath.Count - 1].MyNode.Address + "\n", EventLogEntryType.Information, true, settingsInstance); RemoteNotifications remoteNotify = new RemoteNotifications(settingsInstance); returnConnectionPoints = remoteNotify.getRemoteConnectionPoints(targetHostNameIdentifier, targetConfigServiceName, connectionPointTypes, checkStatus, traversePath, csUser); } } } catch (Exception e) { ServiceConfigHelper.logServiceOperationException(csUser, e.ToString(), settingsInstance); throw; } return returnConnectionPoints; }
/// <summary> /// This method performs the logic required when a specific configuration settings key is changed. This includes /// potentially updating configuration database, notifying nodes, and performing configuration actions. /// </summary> /// <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="targetConfigServiceName">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="oldKey">The key prior to update.</param> /// <param name="newKey">The updated key.</param> /// <param name="notifyNodes">If true, key update will be flowed to peer nodes.</param> /// <param name="action">Action to perform.</param> /// <param name="traversePath">Network path to the target host.</param> /// <param name="csUser">User to authenticate.</param> /// <returns>Int representing success code.</returns> public override int receiveConfigurationKey(string targetHostNameIdentifier, string targetConfigServiceNameIdentifier, ConfigurationKeyValues oldKey, ConfigurationKeyValues newKey, bool notifyNodes, string action, List<TraverseNode> traversePath, ServiceUsers csUser) { ServiceConfigHelper configHelper = new ServiceConfigHelper(settingsInstance); bool success = true; object theSettingsInstance = new Trade.BusinessServiceConfigurationSettings.Settings(); IConfigurationActions configActions; int returnCode = ConfigUtility.CLUSTER_UPDATE_FULL_SUCCESS; try { if (!(configHelper.setServiceRights(ref csUser, ConfigUtility.CONFIG_ADMIN_RIGHTS)>=ConfigUtility.CONFIG_ADMIN_RIGHTS)) return ConfigUtility.CLUSTER_UPDATE_FAIL_AUTHENTICATION; configActions = (IConfigurationActions)ConfigUtility.reflectGetField(settingsInstance, "thisServiceConfigActions"); if ((action != ConfigUtility.ADD_KEY && action != ConfigUtility.REMOVE_KEY) && (traversePath == null || traversePath.Count <= 1 || traversePath[0] == null)) { if (targetHostNameIdentifier != StockTraderUtility.ORDER_PROCESSOR_SERVICE_SELFHOST && targetHostNameIdentifier != StockTraderUtility.ORDER_PROCESSOR_SERVICE_AZURE) { if (!configActions.validateConfigurationKey(settingsInstance, newKey)) return ConfigUtility.CLUSTER_UPDATE_FAIL_VALIDATION; } } ConfigUtility.writeConfigConsoleMessage("\nReceived Request for Configuration Key Change, Action: " + action + ". Keyname: " + oldKey.ConfigurationKeyDisplayName + "\n", EventLogEntryType.Information, true, settingsInstance); ConfigUtility.writeConfigConsoleMessage("Value: " + newKey.ConfigurationKeyValue + "\n\n", EventLogEntryType.Information, true, settingsInstance); if (traversePath == null || traversePath.Count <= 1 || traversePath[0] == null) { bool SHARESERVICECONFIGURATIONDATA = (bool)ConfigUtility.reflectGetField(settingsInstance, "SHARESERVICECONFIGURATIONDATA"); if (!SHARESERVICECONFIGURATIONDATA) { List<ServiceUsers> thisServiceUsers = (List<ServiceUsers>)ConfigUtility.reflectGetField(settingsInstance, "thisServiceUsers"); ServiceUsers userLocalAdmin = thisServiceUsers.Find(delegate(ServiceUsers userExist) { return csUser.UserId.ToLower().Equals("localadmin") && userExist.Password.Equals(csUser.Password) && csUser.Rights == ConfigUtility.CONFIG_ADMIN_RIGHTS; }); if (userLocalAdmin == null) return ConfigUtility.CLUSTER_UPDATE_FULL_SUCCESS; } switch (targetHostNameIdentifier) { case StockTraderUtility.ORDER_PROCESSOR_SERVICE_SELFHOST: { theSettingsInstance = new Trade.OrderProcessorServiceConfigurationSettings.Settings(); Trade.OrderProcessorHostConfigurationImplementation.ConfigurationService configService = new Trade.OrderProcessorHostConfigurationImplementation.ConfigurationService(); int opsRetCode = configService.receiveConfigurationKey(targetHostNameIdentifier, targetConfigServiceNameIdentifier, oldKey, newKey, notifyNodes, action, traversePath, csUser); if (opsRetCode == ConfigUtility.CLUSTER_UPDATE_FULL_SUCCESS) success = true; break; } case StockTraderUtility.ORDER_PROCESSOR_SERVICE_AZURE: { goto case StockTraderUtility.ORDER_PROCESSOR_SERVICE_SELFHOST; } default: { if (notifyNodes) success = configHelper.sendConfigurationKeyUpdateLocal(oldKey, newKey, action, csUser); break; } } if (success) { if (targetHostNameIdentifier != StockTraderUtility.ORDER_PROCESSOR_SERVICE_SELFHOST) success = configActions.checkChangedSetting(theSettingsInstance, newKey, notifyNodes, csUser); if (notifyNodes && success) { RemoteNotifications remoteNotify = new RemoteNotifications(settingsInstance); return remoteNotify.sendKeyUpdateToClusterMembers(targetHostNameIdentifier, targetConfigServiceNameIdentifier, oldKey, newKey, action); } } else returnCode = ConfigUtility.CLUSTER_UPDATE_FAIL_PERSISTED; } else { if (traversePath != null && traversePath.Count > 1) { RemoteNotifications remoteKeyUpdate = new RemoteNotifications(settingsInstance); ConfigUtility.writeConfigConsoleMessage(" Forwarding Key to Remote Connected Service: " + traversePath[traversePath.Count - 1].MyNode.Address + "\n", EventLogEntryType.Information, true, settingsInstance); return (remoteKeyUpdate.sendConfigurationKeyUpdateRemote(targetHostNameIdentifier, targetConfigServiceNameIdentifier, oldKey, newKey, notifyNodes, action, traversePath, csUser)); } } } catch (Exception e) { ServiceConfigHelper.logServiceOperationException(csUser, e.ToString(), settingsInstance); throw; } return (returnCode); }
/// <summary> /// This method retrieves a specific configuration key from a configuration database for a service host. /// </summary> /// <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="targetConfigServiceName">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="settingsClassFieldName">The field name which is the primary key in the ConfigurationKeys table.</param> /// <param name="traversePath">Network path to target host.</param> /// <param name="csUser">User to authenticate.</param> /// <returns>A configuration key in form of data contract class ConfigurationKeyValues.</returns> public override ConfigurationKeyValues getServiceConfigurationKey(string targetHostNameIdentifier, string targetConfigServiceNameIdentifier, string settingsClassFieldName, List<TraverseNode> traversePath, ServiceUsers csUser) { ServiceConfigHelper configHelper = new ServiceConfigHelper(settingsInstance); object opsSettings = new Trade.OrderProcessorServiceConfigurationSettings.Settings(); ConfigurationKeyValues returnkey = null; try { if (!(configHelper.setServiceRights(ref csUser, ConfigUtility.CONFIG_ADMIN_RIGHTS)>=ConfigUtility.CONFIG_ADMIN_RIGHTS)) return null; ConfigUtility.writeConfigConsoleMessage("\nRequest for configuration key received.\n", EventLogEntryType.Information, true, settingsInstance); if (traversePath == null || traversePath.Count <= 1 || traversePath[0] == null) { bool SHARESERVICECONFIGURATIONDATA = (bool)ConfigUtility.reflectGetField(settingsInstance, "SHARESERVICECONFIGURATIONDATA"); if (!SHARESERVICECONFIGURATIONDATA) { List<ServiceUsers> thisServiceUsers = (List<ServiceUsers>)ConfigUtility.reflectGetField(settingsInstance, "thisServiceUsers"); ServiceUsers userLocalAdmin = thisServiceUsers.Find(delegate(ServiceUsers userExist) { return csUser.UserId.ToLower().Equals("localadmin") && userExist.Password.Equals(csUser.Password) && csUser.Rights == ConfigUtility.CONFIG_ADMIN_RIGHTS; }); if (userLocalAdmin == null) return null; } if (BusinessServiceConfigurationSettings.Settings.ORDER_PROCESSING_MODE == StockTraderUtility.OPS_INPROCESS) { switch (targetHostNameIdentifier) { case StockTraderUtility.ORDER_PROCESSOR_SERVICE_SELFHOST: { returnkey = callOPSConfigKeyLocal(targetHostNameIdentifier, targetConfigServiceNameIdentifier, settingsClassFieldName, traversePath, csUser); break; } case StockTraderUtility.ORDER_PROCESSOR_SERVICE_AZURE: { goto case StockTraderUtility.ORDER_PROCESSOR_SERVICE_SELFHOST; } default: { returnkey = configHelper.getServiceConfigurationKey(settingsClassFieldName); break; } } } else { returnkey = configHelper.getServiceConfigurationKey(settingsClassFieldName); } } else { if (traversePath != null && traversePath.Count > 1) { ConfigUtility.writeConfigConsoleMessage("-----> Forwarding Request to Remote Connected Service: " + traversePath[traversePath.Count - 1].MyNode.Address + "\n", EventLogEntryType.Information, true, settingsInstance); RemoteNotifications remoteNotify = new RemoteNotifications(settingsInstance); returnkey = remoteNotify.getRemoteServiceKey(targetHostNameIdentifier, targetConfigServiceNameIdentifier, settingsClassFieldName, traversePath, csUser); } } } catch (Exception e) { ServiceConfigHelper.logServiceOperationException(csUser, e.ToString(), settingsInstance); throw; } return returnkey; }
/// <summary> /// This method returns the composite configuration data for a service--the primary method /// used to collect and display the data for a series of connected services making up a composite /// application. /// </summary> /// <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="targetConfigServiceName">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="configurationLevel">The config key level to return.</param> /// <param name="probeDeeper">If true, one layer deeper in the connected services tree will be probed as well.</param> /// <param name="traversePath">The network traverse path to the target.</param> /// <param name="csUser">User to authenticate.</param> /// <returns>Linked List of ServiceConfigurationData.</returns> public override List<ServiceConfigurationData> getServiceConfiguration(string targetHostNameIdentifier, string targetConfigServiceName, int configurationLevel, bool probeDeeper, List<TraverseNode> traversePath, ServiceUsers csUser) { ServiceConfigHelper configHelper = new ServiceConfigHelper(settingsInstance); object opsSettings = new Trade.OrderProcessorServiceConfigurationSettings.Settings(); List<ServiceConfigurationData> returnCompositeConfigurationData = null; try { if (!(configHelper.setServiceRights(ref csUser, ConfigUtility.CONFIG_CONNECTED_SERVICE_RIGHTS) >= ConfigUtility.CONFIG_CONNECTED_SERVICE_RIGHTS)) { returnCompositeConfigurationData = new List<ServiceConfigurationData>(); return returnCompositeConfigurationData; } if (traversePath == null || traversePath.Count <= 1 || traversePath[0] == null) { //Step 1: Get list of all currently configured connected services. We need to adjust this list based on //the OrderMode setting, since we do not want to query for and return connected data for the Order Processor Service //if we are not running Order Processing remotely. List<ConnectedServices> retrieveConnectedServiceList = new List<ConnectedServices>(); if (Trade.BusinessServiceConfigurationSettings.Settings.connectedServices != null && Trade.BusinessServiceConfigurationSettings.Settings.connectedServices.Count > 0) retrieveConnectedServiceList.AddRange(Trade.BusinessServiceConfigurationSettings.Settings.connectedServices); //Step 2: Here we will remove the Order Processor Service if we are not running in a remote mode. switch (Trade.BusinessServiceConfigurationSettings.Settings.ORDER_PROCESSING_MODE) { case StockTraderUtility.OPS_INPROCESS: { //In this case, we want no Business Service connections--so remove by contract name. retrieveConnectedServiceList.RemoveAll(delegate(ConnectedServices cs) { return (cs.ServiceContract.Equals(Trade.BusinessServiceConfigurationSettings.Settings.OPS_CLIENT_CONNECTED_SERVICE_CONTRACT)); }); break; } default: { break; } } returnCompositeConfigurationData = configHelper.getMyServiceConfiguration(targetHostNameIdentifier, targetConfigServiceName, configurationLevel, csUser, retrieveConnectedServiceList, probeDeeper); //Now another special case for the Business Services app: it can run OPS Services in-process. In this case, //we will add data for OPS Services by invoking the config service in-process, and pointing to the OPS self-host repository. if (BusinessServiceConfigurationSettings.Settings.ORDER_PROCESSING_MODE == StockTraderUtility.OPS_INPROCESS) { List<ServiceConfigurationData> opsConfigData = null; Trade.OrderProcessorHostConfigurationImplementation.ConfigurationService opsServiceConfig = new Trade.OrderProcessorHostConfigurationImplementation.ConfigurationService(); if (ConfigUtility.onAzure) opsConfigData = opsServiceConfig.getServiceConfiguration(StockTraderUtility.ORDER_PROCESSOR_SERVICE_AZURE, StockTraderUtility.ORDER_PROCESSOR_SERVICE_CONFIG, configurationLevel, false, traversePath, csUser); else opsConfigData = opsServiceConfig.getServiceConfiguration(StockTraderUtility.ORDER_PROCESSOR_SERVICE_SELFHOST, StockTraderUtility.ORDER_PROCESSOR_SERVICE_CONFIG, configurationLevel, false, traversePath, csUser); if (opsConfigData != null) { for (int i = 0; i < opsConfigData.Count; i++) { opsConfigData[i].InProcessHost = Trade.BusinessServiceConfigurationSettings.Settings.HOST_NAME_IDENTIFIER; } returnCompositeConfigurationData.AddRange(opsConfigData); } } } else { if (traversePath != null && traversePath.Count > 1) { ConfigUtility.writeConfigConsoleMessage("-----> Forwarding Request to Remote Connected Service: " + traversePath[traversePath.Count - 1].MyNode.Address + "\n", EventLogEntryType.Information, true, settingsInstance); RemoteNotifications remoteNotify = new RemoteNotifications(settingsInstance); returnCompositeConfigurationData = remoteNotify.getRemoteServiceConfiguration(targetHostNameIdentifier, targetConfigServiceName, configurationLevel, probeDeeper, traversePath, csUser, false, null); } } } catch (Exception e) { ServiceConfigHelper.logServiceOperationException(csUser, e.ToString(), settingsInstance); throw; } return returnCompositeConfigurationData; }
/// <summary> /// Overrides the base method, performs app-specific logic on specific app-specific setting changes. For the /// Web app there are few app specific routines we need to run when OPS-specific app settings are changed in the repository. /// MAKE SURE TO CALL THE BASE checkChangedSetting method FIRST! /// </summary> /// <param name="settingsInstance">Instance of this host's Settings class.</param> /// <param name="updatedConfigurationKey">The key that has been updated.</param> /// <param name="block">True to block on any multi-threaded calls, typically the node receiving via /// Config Service endpoint blocks, nodes receiving via Node Service do not, if any threads are spun up.</param> /// <returns>bool as success code.</returns> public override bool checkChangedSetting(object settingsInstance, ConfigurationKeyValues updatedConfigurationKey,bool block,ServiceUsers csUser) { bool success = false; Trade.StockTraderWebApplicationConfigurationImplementation.ConfigurationService configService = new ConfigurationService(); ServiceConfigHelper configHelper = new ServiceConfigHelper(settingsInstance); success = base.checkChangedSetting(settingsInstance, updatedConfigurationKey, block, csUser); if (success) { switch (updatedConfigurationKey.ConfigurationKeyFieldName) { case "ACCESS_MODE": { setAccessMode(updatedConfigurationKey.ConfigurationKeyValue); ConfigurationKeyValues businessServiceKey = new ConfigurationKeyValues(); switch (Settings.ACCESS_MODE) { case StockTraderUtility.BSL_IISHOST_BSL_HTTP: { if (block) { businessServiceKey.ConfigurationKeyFieldName = "REFRESHCONFIG"; businessServiceKey.ConfigurationKeyValue = "RefreshConfig"; businessServiceKey.OriginatingConfigServiceName = StockTraderUtility.BUSINESS_SERVICES_CONFIG; refreshBSLConfig(businessServiceKey, configService, block, csUser); } InitCommunicationChannels(settingsInstance, null, ConfigUtility.INIT_ALL_CONNECTED_INSTANCES); break; } case StockTraderUtility.BSL_IISHOST_BSL_TCP: { goto case StockTraderUtility.BSL_IISHOST_BSL_HTTP; } case StockTraderUtility.BSL_IISHOST_TCP_TMSEC_CLIENTCERT: { goto case StockTraderUtility.BSL_IISHOST_BSL_HTTP; } case StockTraderUtility.BSL_IISHOST_TCP_TMSEC_USERNAME: { goto case StockTraderUtility.BSL_IISHOST_BSL_HTTP; } case StockTraderUtility.BSL_IISHOST_WSHTTP_MSEC_CLIENTCERT: { goto case StockTraderUtility.BSL_IISHOST_BSL_HTTP; } case StockTraderUtility.BSL_IISHOST_WSHTTP_TMSEC_CLIENTCERT: { goto case StockTraderUtility.BSL_IISHOST_BSL_HTTP; } case StockTraderUtility.BSL_IISHOST_WSHTTP_TMSEC_USERNAME: { goto case StockTraderUtility.BSL_IISHOST_BSL_HTTP; } case StockTraderUtility.BSL_AZURE_TCP_TMSEC_CLIENTCERT: { goto case StockTraderUtility.BSL_IISHOST_BSL_HTTP; } case StockTraderUtility.BSL_AZURE_TCP_TMSEC_USERNAME: { goto case StockTraderUtility.BSL_IISHOST_BSL_HTTP; } case StockTraderUtility.BSL_AZURE_WSHTTP_TMSEC_CLIENTCERT: { goto case StockTraderUtility.BSL_IISHOST_BSL_HTTP; } case StockTraderUtility.BSL_AZURE_WSHTTP_TMSEC_USERNAME: { goto case StockTraderUtility.BSL_IISHOST_BSL_HTTP; } case StockTraderUtility.BSL_INPROCESS: { InitConfigInProcessBusinessService.initConfigBusinessService(ConfigUtility.masterServiceWebHostSyncObject,true); break; } default: { break; } } success = true; break; } case "MAX_DISPLAY_ORDERS": { List<TraverseNode> traversePath=null; int successBSL = ConfigUtility.CLUSTER_UPDATE_FULL_SUCCESS; if (Settings.ACCESS_MODE == StockTraderUtility.BSL_SOAP) { success = true; break; } ConfigurationKeyValues businessServiceKey = null; ConfigurationKeyValues thisOldbusinessServiceKey = null; businessServiceKey = refreshBSL(out thisOldbusinessServiceKey, "MAX_QUERY_ORDERS", csUser); if (businessServiceKey != null && block) { businessServiceKey.ConfigurationKeyValue = updatedConfigurationKey.ConfigurationKeyValue; traversePath = configService.getTraversePath(null, Settings.BSL_CLIENT_ACTIVE_SERVICE_HOST_IDENTIFIER, StockTraderUtility.BUSINESS_SERVICES_CONFIG, csUser); successBSL = configService.receiveConfigurationKey(Settings.BSL_CLIENT_ACTIVE_SERVICE_HOST_IDENTIFIER,StockTraderUtility.BUSINESS_SERVICES_CONFIG, thisOldbusinessServiceKey,businessServiceKey,block, ConfigUtility.UPDATE_KEY_VALUE,traversePath,csUser); if (successBSL == ConfigUtility.CLUSTER_UPDATE_FULL_SUCCESS) success = true; } else success = false; break; } case "MAX_DISPLAY_TOP_ORDERS": { List<TraverseNode> traversePath = null; int successBSL = ConfigUtility.CLUSTER_UPDATE_FULL_SUCCESS; if (Settings.ACCESS_MODE == StockTraderUtility.BSL_SOAP) { success = true; break; } ConfigurationKeyValues businessServiceKey = null; ConfigurationKeyValues thisOldbusinessServiceKey = null; businessServiceKey = refreshBSL(out thisOldbusinessServiceKey, "MAX_QUERY_TOP_ORDERS", csUser); if (businessServiceKey != null && block) { businessServiceKey.ConfigurationKeyValue = updatedConfigurationKey.ConfigurationKeyValue; traversePath = configService.getTraversePath(null, Settings.BSL_CLIENT_ACTIVE_SERVICE_HOST_IDENTIFIER, StockTraderUtility.BUSINESS_SERVICES_CONFIG, csUser); successBSL = configService.receiveConfigurationKey(Settings.BSL_CLIENT_ACTIVE_SERVICE_HOST_IDENTIFIER, StockTraderUtility.BUSINESS_SERVICES_CONFIG, thisOldbusinessServiceKey, businessServiceKey, block, ConfigUtility.UPDATE_KEY_VALUE, traversePath, csUser); if (successBSL == ConfigUtility.CLUSTER_UPDATE_FULL_SUCCESS) success = true; } else success = false; break; } default: { success = true; break; } } } return success; }
/// <summary> /// This method builds a connection string based on DAL setting and settings for the database name, location, uid and password. /// Called on host initialization and also when the DAL or DB connection parameters are changed via ConfigWeb. /// </summary> private void buildConnString() { switch (Settings.DAL) { case Trade.Utility.StockTraderUtility.DAL_SQLSERVER: { if (!Settings.DBServer.Trim().ToLower().StartsWith("tcp:") && !Settings.DBServer.ToLower().Contains("sqlexpress")) Settings.DBServer = "tcp:" + Settings.DBServer; if (!Settings.DBServer.Trim().EndsWith(",1433") && !Settings.DBServer.ToLower().Contains("sqlexpress")) Settings.DBServer = Settings.DBServer + ",1433"; Settings.TRADEDB_SQL_CONN_STRING = "server=" + Settings.DBServer + ";database=" + Settings.Database + ";user id=" + Settings.UserID + ";password="******";min pool size=" + Settings.MinDBConnections + ";max pool size=" + Settings.MaxDBConnections; if (Settings.DBServer.ToLower().Contains("windows.net")) Settings.TRADEDB_SQL_CONN_STRING = Settings.TRADEDB_SQL_CONN_STRING + ";Trusted_Connection=False;Encrypt=True;TrustServerCertificate=True;Connect Timeout=60"; break; } case Trade.Utility.StockTraderUtility.DAL_ORACLE: { Settings.TRADEDB_SQL_CONN_STRING = "Data Source=" + Settings.Database + ";user id=" + Settings.UserID + ";password="******";min pool size=" + Settings.MinDBConnections + ";max pool size=" + Settings.MaxDBConnections + ";enlist=dynamic;"; break; } case Trade.Utility.StockTraderUtility.DAL_DB2: { Settings.TRADEDB_SQL_CONN_STRING = "Network Transport Library=TCPIP;Network Address=" + Settings.DBServer + ";Initial Catalog=" + Settings.Database + ";Package Collection=" + Settings.Database + ";Default Schema=Schema;User ID=" + Settings.UserID + ";Password="******";network port=50000;Units of Work=RUW; Connection Pooling=True;defer prepare=false;"; break; } } Trade.OrderProcessorServiceConfigurationSettings.Settings settingsInstance = new Settings(); ServiceConfigHelper configHelper = new ServiceConfigHelper(settingsInstance); configHelper.InitConnectedDatabaseSettings(settingsInstance); }