/// <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> /// Simple constructor. Make sure to instantiate the settings instance class, which is defined in the base class. /// </summary> public ConfigurationService() { settingsInstance = new Trade.BusinessServiceConfigurationSettings.Settings(); }
/// <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> public override ConfigurationKeyValues getServiceConfigurationKey(string targetHostNameIdentifier, string targetConfigServiceNameIdentifier, string settingsClassFieldName, List<TraverseNode> traversePath, ServiceUsers csUser) { ServiceConfigHelper configHelper = new ServiceConfigHelper(settingsInstance); object bslSettings = new Trade.BusinessServiceConfigurationSettings.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 (targetHostNameIdentifier != StockTraderUtility.WEB_APPLICATION && targetHostNameIdentifier != StockTraderUtility.WEB_APPLICATION_Azure && StockTraderWebApplicationSettings.Settings.ACCESS_MODE == StockTraderUtility.BSL_INPROCESS) { returnkey = callBSLConfigKeyLocal(targetHostNameIdentifier, targetConfigServiceNameIdentifier, settingsClassFieldName, traversePath, csUser); } 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 bslSettings = new Trade.BusinessServiceConfigurationSettings.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.StockTraderWebApplicationSettings.Settings.connectedServices != null && Trade.StockTraderWebApplicationSettings.Settings.connectedServices.Count > 0) retrieveConnectedServiceList.AddRange(Trade.StockTraderWebApplicationSettings.Settings.connectedServices); //Step 2: Here we will remove the Order Processor Service if we are not running in a remote mode. switch (Trade.StockTraderWebApplicationSettings.Settings.ACCESS_MODE) { case StockTraderUtility.BSL_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.StockTraderWebApplicationSettings.Settings.BSL_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 (Trade.StockTraderWebApplicationSettings.Settings.ACCESS_MODE == StockTraderUtility.BSL_INPROCESS) { string theTargetHost = null; string theTargetConfig = null; List<ServiceConfigurationData> bslConfigData = null; switch (targetHostNameIdentifier) { case StockTraderUtility.IISHOST_BUSINESS_SERVICES: { theTargetHost = targetHostNameIdentifier; theTargetConfig = targetConfigServiceName; break; } case StockTraderUtility.AZURE_BUSINESS_SERVICES: { goto case StockTraderUtility.IISHOST_BUSINESS_SERVICES; } case StockTraderUtility.ORDER_PROCESSOR_SERVICE_SELFHOST: { goto case StockTraderUtility.IISHOST_BUSINESS_SERVICES; } case StockTraderUtility.ORDER_PROCESSOR_SERVICE_AZURE: { goto case StockTraderUtility.IISHOST_BUSINESS_SERVICES; } default: { theTargetHost = StockTraderUtility.WEB_APPLICATION; theTargetConfig = StockTraderUtility.WEBAPPLICATION_CONFIG; break; } } Trade.BusinessServiceHostConfigurationImplementation.ConfigurationService bslServiceConfig = new Trade.BusinessServiceHostConfigurationImplementation.ConfigurationService(); bslConfigData = bslServiceConfig.getServiceConfiguration(theTargetHost, theTargetConfig, configurationLevel, false, traversePath, csUser); if (bslConfigData != null) { for (int i = 0; i < bslConfigData.Count; i++) { bslConfigData[i].InProcessHost = Trade.StockTraderWebApplicationSettings.Settings.HOST_NAME_IDENTIFIER; } returnCompositeConfigurationData.AddRange(bslConfigData); } } } 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; }