/// <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;
        }