Exemple #1
0
        internal void ReloadMapping(RelayNodeGroupDefinition groupDefinition, RelayNodeConfig newConfig, ForwardingConfig newForwardingConfig)
        {
            RelayNodeClusterDefinition myClusterDefinition = newConfig.GetMyCluster();

            Activated         = groupDefinition.Activated;
            GroupDefinition   = groupDefinition;
            _clusterByRange   = groupDefinition.UseIdRanges;
            _forwardingConfig = newForwardingConfig;

            if (groupDefinition.RelayNodeClusters.Length == Clusters.Count)
            {
                //same number of clusters, just let the clusters rebuild themselves. the clusters will entirely rebuild, so shuffinling around servers should be okay
                if (_log.IsDebugEnabled)
                {
                    _log.DebugFormat("Rebuilding existing clusters in group {0}.", groupDefinition.Name);
                }
                for (int i = 0; i < groupDefinition.RelayNodeClusters.Length; i++)
                {
                    Clusters[i].ReloadMapping(groupDefinition.RelayNodeClusters[i], newConfig, newForwardingConfig);
                    if (groupDefinition.RelayNodeClusters[i] == myClusterDefinition)
                    {
                        MyCluster = Clusters[i];
                    }
                }
                if (myClusterDefinition == null && MyCluster != null)
                {
                    if (_log.IsInfoEnabled)
                    {
                        _log.InfoFormat("Group {0} no longer contains this server. Removing.", GroupName);
                    }
                    //this group no longer contains "me". If it DID contain "me", it would've been set above.
                    MyCluster = null;
                }
            }
            else
            {
                //build new clusters and replace the existing ones with them
                if (_log.IsInfoEnabled)
                {
                    _log.InfoFormat("Number of clusters in group {0} changed, rebuilding.", groupDefinition.Name);
                }
                NodeCluster        myCluster   = null;
                List <NodeCluster> newClusters = new List <NodeCluster>();
                foreach (RelayNodeClusterDefinition clusterDefintion in groupDefinition.RelayNodeClusters)
                {
                    NodeCluster nodeCluster = new NodeCluster(clusterDefintion, newConfig, this, newForwardingConfig);
                    if (clusterDefintion == myClusterDefinition)
                    {
                        myCluster = nodeCluster;
                    }
                    newClusters.Add(nodeCluster);
                }
                Clusters  = newClusters;
                MyCluster = myCluster;
            }
            _nodeReselectTimer.Change(NodeReselectIntervalMilliseconds, NodeReselectIntervalMilliseconds);
        }
        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be disposed.
        protected virtual void Dispose(bool disposing)
        {
            if (!isDisposed)
            {
                if (disposing)
                {
                    if (replyLock != null)
                    {
                        replyLock.Dispose();
                    }
                    if (Log.IsInfoEnabled)
                    {
                        Log.InfoFormat("Dispose() MatchMaker is Disposed");
                    }
                }
                //Any unmanaged code should be released here

                // Note that this is not thread safe.
                // Another thread could start disposing the object
                // after the managed resources are disposed,
                // but before the disposed flag is set to true.
                // If thread safety is necessary, it must be
                // implemented by the client.
                isDisposed = true;
            }
        }
Exemple #3
0
        private void ExtractCommonConfigValues(ForwardingConfig config)
        {
            NodeGroup.MaximumQueuedItems = config.MaximumTaskQueueDepth;

            if (config.QueueConfig != null)
            {
                _log.InfoFormat("Error queue config:  Enabled={0} DequeueInterval={1} ItemsPerDequeue={2} MaxCount={3} PersistenceFolder={4} MaxPersistedMB={5} PersistenceFileSize={6}",
                                config.QueueConfig.Enabled,
                                config.QueueConfig.DequeueIntervalSeconds,
                                config.QueueConfig.ItemsPerDequeue,
                                config.QueueConfig.MaxCount,
                                config.QueueConfig.PersistenceFolder,
                                config.QueueConfig.MaxPersistedMB,
                                config.QueueConfig.PersistenceFileSize);
            }
        }
Exemple #4
0
        /// <summary>
        /// Our Xen hosted machines all think they have the same IP address at the NIC level. When
        /// they boot, an Environment variable "IPADDRESS" is set to give us a locally visible
        /// copy of their external IP address.
        /// </summary>
        /// <returns>Returns <see langword="null"/> if no environment address is defined; otherwise, returns the IP address.</returns>
        public static IPAddress GetEnvironmentDefinedIPAddress()
        {
            IPAddress environmentIP = null;

            try
            {
                string environmentIPstring = Environment.GetEnvironmentVariable("IPADDRESS", EnvironmentVariableTarget.Machine);
                if (String.IsNullOrEmpty(environmentIPstring) == false)
                {
                    if (IPAddress.TryParse(environmentIPstring, out environmentIP))
                    {
                        if (_log.IsInfoEnabled)
                        {
                            _log.InfoFormat("Got IPAddress {0} from environment variable \"IPADDRESS\"", environmentIP);
                        }
                    }
                    else
                    {
                        if (_log.IsWarnEnabled)
                        {
                            _log.WarnFormat("Could not parse address {0} from environment variable \"IPADDRESS\"", environmentIPstring);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                _log.ErrorFormat("Exception getting IP address from environment variable \"IPAddress\": {0}", e);
                throw;
            }

            return(environmentIP);
        }
Exemple #5
0
        public void DatabaseFailureLog(string str, params object[] args)
        {
            var sb = new StringBuilder();

            sb.AppendFormat(str, args);
            LogWrapper.InfoFormat("[FATAL] {0}", sb.ToString());
        }
Exemple #6
0
        public void Boot(string str, params object[] args)
        {
            var sb = new StringBuilder();

            sb.AppendFormat(str, args);
            LogWrapper.InfoFormat("[BOOT] {0}", sb.ToString());
        }
        internal void ReloadMapping(RelayNodeConfig newConfig, ForwardingConfig forwardingConfig)
        {
            RelayNodeMapping relayNodeMapping = newConfig.RelayNodeMapping;
            RelayNodeGroupDefinitionCollection groupDefinitions = relayNodeMapping.RelayNodeGroups;

            foreach (RelayNodeGroupDefinition groupDefinition in groupDefinitions)
            {
                if (Contains(groupDefinition.Name))
                {
                    this[groupDefinition.Name].ReloadMapping(groupDefinition, newConfig, forwardingConfig);
                }
                else
                {
                    if (_log.IsInfoEnabled)
                    {
                        _log.InfoFormat("Adding new node group {0}", groupDefinition.Name);
                    }
                    Add(new NodeGroup(groupDefinition, newConfig, forwardingConfig));
                }
            }

            bool removedOne;

            //make sure if any groups have been removed they are removed!
            do
            {
                removedOne = false;
                foreach (NodeGroup group in this)
                {
                    if (!groupDefinitions.Contains(group.GroupName))
                    {
                        if (_log.IsInfoEnabled)
                        {
                            _log.InfoFormat("Removing node group {0}", group.GroupName);
                        }
                        Remove(group.GroupName);
                        removedOne = true;
                        break;                         //collection modified can't continue with foreach!
                    }
                }
            } while (removedOne);

            _groupsByTypeId = GenerateGroupsByTypeId(newConfig.TypeSettings);
        }
Exemple #8
0
        private static void _handleFileChange(Object sender, FileSystemEventArgs e)
        {
            _log.InfoFormat("Configuration section '{0}' is being refreshed...", _getSectionName());


            ConfigurationManager.RefreshSection(_getSectionName());
            //clear to cause a reload
            _section = null;
            TriggerRefresh();
        }
Exemple #9
0
        public static bool InstallCounters()
        {
            string message;

            try
            {
                if (Log.IsInfoEnabled)
                {
                    Log.InfoFormat("CounterInstaller:InstallCounters() Creating performance counter category {0}"
                                   , BerkeleyDbCounters.PerformanceCategoryName);
                }
                Console.WriteLine("Creating performance counter category " + BerkeleyDbCounters.PerformanceCategoryName);
                CounterCreationDataCollection counterDataCollection = new CounterCreationDataCollection();

                for (int i = 0; i < BerkeleyDbCounters.PerformanceCounterNames.Length; i++)
                {
                    counterDataCollection.Add(new CounterCreationData(BerkeleyDbCounters.PerformanceCounterNames[i],
                                                                      BerkeleyDbCounters.PerformanceCounterHelp[i], BerkeleyDbCounters.PerformanceCounterTypes[i]));
                    message = "Creating perfomance counter " + BerkeleyDbCounters.PerformanceCounterNames[i];
                    Console.WriteLine(message);
                    if (Log.IsInfoEnabled)
                    {
                        Log.InfoFormat("CounterInstaller:InstallCounters() {0}"
                                       , message);
                    }
                }

                PerformanceCounterCategory.Create(BerkeleyDbCounters.PerformanceCategoryName, "Counters for the MySpace Data Relay", PerformanceCounterCategoryType.MultiInstance, counterDataCollection);
                return(true);
            }
            catch (Exception ex)
            {
                message = "Error creating Perfomance Counter Category " + BerkeleyDbCounters.PerformanceCategoryName + ": " + ex + ". Counter category will not be used.";
                Console.WriteLine(message);
                if (Log.IsErrorEnabled)
                {
                    Log.Error(string.Format("CounterInstaller:InstallCounters() {0}", message), ex);
                }
                return(false);
            }
        }
        private void InitializeCounters()
        {
            _log.InfoFormat("Verifying performance counter installation for category '{0}'...", _category);

            try
            {
                if (!PerformanceCounterCategory.Exists(_category))
                {
                    _log.WarnFormat("Performance counters in category '{0}' are not installed.", _category);
                    return;
                }

                // Zero all counters in the current category.
                _log.InfoFormat("Zeroing all performance counters in category/instance '{0}'/'{1}' ", _category, _instanceName);

                var cat = new PerformanceCounterCategory(_category);
                if (cat.InstanceExists(_instanceName))
                {
                    foreach (PerformanceCounter counter in cat.GetCounters(_instanceName))
                    {
                        try
                        {
                            counter.ReadOnly = false;
                            counter.RawValue = 0;
                        }
                        finally
                        {
                            counter.Dispose();
                        }
                    }
                }
            }
            catch (Exception x)
            {
                _log.Error(String.Format("Initializing perf counter category/instance {0}/{1} failed.", _category, _instanceName), x);
            }
        }
Exemple #11
0
 public static void HandleExceptionResponse(string response, string formatedMessage)
 {
     if (response != null)
     {
         if (response.IndexOf("IndexMissingException") > -1)
         {
             throw new IndexMissingException(formatedMessage);
         }
         if (response.IndexOf("TypeMissingException") > -1)
         {
             throw new TypeMissingException(formatedMessage);
         }
         if (response.IndexOf("SearchPhaseExecutionException") > -1)
         {
             throw new SearchPhaseExecutionException(formatedMessage);
         }
         _logger.HandleException(new ElasticSearchException(formatedMessage), "ElasticSearchException");
     }
     _logger.InfoFormat("{0}\r\n{1}", response, formatedMessage);
 }
        /// <summary>
        /// Handles the case when the Assembly Directory's contents changes.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AssemblyDirChanged(object sender, FileSystemEventArgs e)
        {
            if (!_reloadOnAssemblyChanges)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.DebugFormat("File {0} changed but reloads are disabled.", e.Name);
                }
                return;
            }

            if (!FileCausesRestart(e.Name))
            {
                if (_log.IsDebugEnabled)
                {
                    _log.DebugFormat("Ignored file {0} changed", e.Name);
                }
                return;
            }

            string thisMinute = DateTime.Now.Hour.ToString() + ":" + DateTime.Now.Minute.ToString();

            lock (_resourceLock)
            {
                if (_log.IsInfoEnabled)
                {
                    if (_pendingAssemblyFileNames.Add(e.Name) == false) //returns false if the item didn't already exist
                    {
                        _log.InfoFormat(
                            "Got change for {0} during {1}. Processing {2} seconds after the last file change hasn't occured for {2} seconds",
                            e.Name,
                            thisMinute,
                            _reloadWindowSeconds);
                    }
                }
                _currentFileSetChangeTime = DateTime.UtcNow;
            }
        }
Exemple #13
0
        internal void ReloadConfig(RelayNodeConfig newConfiguration)
        {
            if (newConfiguration != null)
            {
                if (log.IsInfoEnabled)
                {
                    log.Info("Reloading configs.");
                }

                fatalFailureTimeout = newConfiguration.FatalShutdownTimeout < 0
                                        ? TimeSpan.FromMinutes(5)
                                        : TimeSpan.FromSeconds(newConfiguration.FatalShutdownTimeout);

                if (newConfiguration.GetMyNode() != null)
                {
                    MyZone = newConfiguration.GetMyNode().Zone;
                }

                SetClusterAddresses(newConfiguration);

                messageTracer.ReloadConfig(newConfiguration.TypeSettings.MaxTypeId, newConfiguration.TraceSettings);
                messageTracer.Activated = newConfiguration.OutputTraceInfo;

                //TODO: handle changes in component definition
                components.ReloadConfig(newConfiguration, newConfiguration.IgnoredMessageTypes);

                if (newConfiguration.TransportSettings != null)
                {
                    if (newConfiguration.TransportSettings.ListenPort != portNumber)
                    {
                        log.InfoFormat("Changing Socket Transport Port to {0}",
                                       newConfiguration.TransportSettings.ListenPort);
                        portNumber = newConfiguration.TransportSettings.ListenPort;
                        SocketServerAdapter.ChangePort(portNumber);
                    }
                    if (newConfiguration.TransportSettings.HttpListenPort != httpPortNumber)
                    {
                        if (httpPortNumber < 1 && newConfiguration.TransportSettings.HttpListenPort > 0)                         //there was no http server and now we want one
                        {
                            httpPortNumber = newConfiguration.TransportSettings.HttpListenPort;
                            StartHttpServer();
                        }
                        else if (newConfiguration.TransportSettings.HttpListenPort < 1 && httpPortNumber > 0)                         //shut off a running server
                        {
                            httpPortNumber = newConfiguration.TransportSettings.HttpListenPort;
                            StopHttpServer();
                        }
                        else                         //just change the port on an existing server
                        {
                            log.InfoFormat("Changing Http Transport Port to {0}",
                                           newConfiguration.TransportSettings.HttpListenPort);
                            httpPortNumber = newConfiguration.TransportSettings.HttpListenPort;
                            _httpServer.ChangePort(httpPortNumber);
                        }
                    }
                }

                if (newConfiguration.NumberOfThreads != configuration.NumberOfThreads)
                {
                    if (log.IsInfoEnabled)
                    {
                        log.InfoFormat("Changing number of relay node threads from {0} to {1}",
                                       configuration.NumberOfThreads, newConfiguration.NumberOfThreads);
                    }
                    try
                    {
                        Dispatcher   oldInDispatcher = inDispatcher;
                        Dispatcher   newInDispatcher;
                        const string inThreadsName = "DataRelayNode";
                        if (newConfiguration.NumberOfThreads > 0)
                        {
                            newInDispatcher = new Dispatcher(newConfiguration.NumberOfThreads, ThreadPriority.Normal, true, inThreadsName);
                        }
                        else
                        {
                            newInDispatcher = new Dispatcher()
                            {
                                Name = inThreadsName
                            };
                        }

                        DispatcherQueue newInQueue = new DispatcherQueue("DataRelayDispatcherQueue", newInDispatcher, TaskExecutionPolicy.ConstrainQueueDepthThrottleExecution, newConfiguration.MaximumMessageQueueDepth);

                        Interlocked.Exchange(ref inMessagePort, new Port <RelayMessage>());
                        Interlocked.Exchange(ref inMessageWithContextPort, new Port <RelayMessageWithContext>());
                        Interlocked.Exchange(ref inMessagesPort, new Port <IList <RelayMessage> >());

                        Arbiter.Activate(newInQueue,
                                         Arbiter.Receive <RelayMessage>(true, inMessagePort, HandleInMessage));
                        Arbiter.Activate(newInQueue,
                                         Arbiter.Receive <RelayMessageWithContext>(true, inMessageWithContextPort, HandleInMessage));
                        Arbiter.Activate(newInQueue,
                                         Arbiter.Receive <IList <RelayMessage> >(true, inMessagesPort, HandleInMessages));

                        inMessageQueue = newInQueue;
                        inDispatcher   = newInDispatcher;
                        oldInDispatcher.Dispose();
                    }
                    catch (Exception e)
                    {
                        if (log.IsErrorEnabled)
                        {
                            log.ErrorFormat("Error changing number of relay node threads: {0}", e);
                        }
                    }
                }
                else
                {
                    //not rebuilding the queue, but reset its max queue depth anyway
                    inMessageQueue.MaximumQueueDepth = newConfiguration.MaximumMessageQueueDepth;
                }

                SetupOutMessagesOnRelayThreads(newConfiguration);

                queuedTaskThreshold = (int)Math.Floor(0.9 * newConfiguration.MaximumMessageQueueDepth);
                configuration       = newConfiguration;
                if (log.IsInfoEnabled)
                {
                    log.Info("Done Reloading configs.");
                }
            }
            else
            {
                if (log.IsErrorEnabled)
                {
                    log.Error("Attempt to reload null config");
                }
            }
        }
Exemple #14
0
        public RestResponse Process(string clusterName, string strUrl, string reqdata, string encoding, Method method)
        {
            DateTime start = DateTime.Now;

            var    result      = new RestResponse();
            string responseStr = string.Empty;
            string url         = null;

            try
            {
                if (!strUrl.StartsWith("/"))
                {
                    strUrl = "/" + strUrl;
                }
                url = ESNodeManager.Instance.GetHttpNode(clusterName) + strUrl;
                WebRequest request = WebRequest.Create(url);
                request.Method = method.ToString();
                if (reqdata != null)
                {
                    byte[] buf = Encoding.GetEncoding(encoding).GetBytes(reqdata);
                    request.ContentType   = "application/json; charset=" + encoding;
                    request.ContentLength = buf.Length;

                    if (method != Method.GET || reqdata.Length > 0)
                    {
                        Stream s = request.GetRequestStream();
                        s.Write(buf, 0, buf.Length);
                        s.Close();
                    }
                }

                using (var webResponse = (HttpWebResponse)request.GetResponse())
                {
                    using (Stream stream = webResponse.GetResponseStream())
                    {
                        long contentLength = webResponse.ContentLength;
                        var  bytes         = new byte[contentLength];
                        bytes = ReadFully(stream);
                        stream.Close();
                        responseStr = Encoding.GetEncoding(encoding).GetString(bytes);
                        result.SetBody(responseStr);
                        result.Status = Status.OK;
                    }
                }

                DateTime endtime = DateTime.Now;
                _logger.InfoFormat("Request Success,Method:{2},Url:{0},Body:{1},Time:{3}", url, reqdata, method,
                                   endtime - start);
            }
            catch (WebException e)
            {
                DateTime endtime = DateTime.Now;
                if (e.Response != null)
                {
                    Stream stream = e.Response.GetResponseStream();
                    if (stream != null)
                    {
                        try
                        {
                            var reader = new StreamReader(stream);
                            responseStr = reader.ReadToEnd();
                            result.SetBody(responseStr);
                        }
                        catch (System.Exception exception)
                        {
                            _logger.Error(exception);
                        }
                    }
                }
                string msg = string.Format("Method:{2}, Url: {0},Body:{1},Encoding:{3},Time:{5},Response:{4}", url,
                                           reqdata,
                                           method, encoding, responseStr, endtime - start);
                result.Status = Status.INTERNAL_SERVER_ERROR;
                ExceptionHandler.HandleExceptionResponse(responseStr, msg);
            }
            return(result);
        }
Exemple #15
0
        internal void ReloadMapping(RelayNodeClusterDefinition relayNodeClusterDefinition, RelayNodeConfig newConfig, ForwardingConfig forwardingConfig)
        {
            _minimumId  = relayNodeClusterDefinition.MinId;
            _maximumId  = relayNodeClusterDefinition.MaxId;
            _mapNetwork = forwardingConfig.MapNetwork;

            //figure out if anything changed. if it did, rebuild

            bool rebuild = false;

            ushort newLocalZone = newConfig.GetLocalZone();

            if (newLocalZone != _localZone)
            {
                rebuild    = true;
                _localZone = newLocalZone;
            }
            else
            {
                if ((_zoneDefinitions == null && newConfig.RelayNodeMapping.ZoneDefinitions != null) ||
                    (_zoneDefinitions != null && newConfig.RelayNodeMapping.ZoneDefinitions == null) ||
                    (_zoneDefinitions != null && !_zoneDefinitions.Equals(newConfig.RelayNodeMapping.ZoneDefinitions)))
                {
                    rebuild          = true;
                    _zoneDefinitions = newConfig.RelayNodeMapping.ZoneDefinitions;
                }
            }


            int effectiveSize = (!_meInThisCluster ? Nodes.Count : Nodes.Count + 1);

            //if there's a different number of nodes, we definitely have to rebuild
            if (relayNodeClusterDefinition.RelayNodes.Length != effectiveSize)
            {
                if (_log.IsInfoEnabled)
                {
                    _log.InfoFormat("Number of nodes in a cluster in group {0} changed from {1} to {2}, rebuilding", _nodeGroup.GroupName, effectiveSize, relayNodeClusterDefinition.RelayNodes.Length);
                }
                rebuild = true;
            }
            else
            {
                //if any of the nodes we do have aren't in the config, rebuild
                foreach (Node node in Nodes)
                {
                    if (!relayNodeClusterDefinition.ContainsNode(node.EndPoint.Address, node.EndPoint.Port))
                    {
                        if (_log.IsInfoEnabled)
                        {
                            _log.InfoFormat("Node {0} is no longer found in its cluster in group {1}, rebuilding.",
                                            node, _nodeGroup.GroupName);
                        }
                        rebuild = true;
                        break;
                    }
                }
                if (!rebuild && _nodeGroup.NodeSelectionHopWindowSize != NodeSelectionHopWindowSize)
                {
                    NodeSelectionHopWindowSize = _nodeGroup.NodeSelectionHopWindowSize;
                    rebuild = true;
                }

                if (!rebuild && _meInThisCluster)
                {
                    if (!relayNodeClusterDefinition.ContainsNode(Me.EndPoint.Address, Me.EndPoint.Port))
                    {
                        if (_log.IsInfoEnabled)
                        {
                            _log.InfoFormat("Node {0} (this machine) is no longer found in its cluster in group {1}, rebuilding.",
                                            Me, _nodeGroup.GroupName);
                        }
                        rebuild = true;
                    }
                }

                //or if there are any nodes in the config that aren't here, rebuild
                if (!rebuild)
                {
                    foreach (RelayNodeDefinition nodeDefinition in relayNodeClusterDefinition.RelayNodes)
                    {
                        if (!ContainsNode(nodeDefinition))
                        {
                            if (_log.IsInfoEnabled)
                            {
                                _log.InfoFormat("Node {0} is defined in the new config but does not exist in this cluster in group {1}, rebuilding.",
                                                nodeDefinition, _nodeGroup.GroupName);
                            }
                            rebuild = true;
                            break;
                        }
                    }
                }
            }

            if (rebuild)
            {
                Dictionary <ushort, List <Node> > newZoneNodes = new Dictionary <ushort, List <Node> >();
                List <Node> newNodes = new List <Node>();

                RelayNodeDefinition meDefinition = newConfig.GetMyNode();
                DispatcherQueue     nodeInQueue, nodeOutQueue;

                if (meDefinition != null)
                {
                    GetMessageQueuesFor(meDefinition, relayNodeClusterDefinition,
                                        NodeManager.Instance.InMessageDispatcher, NodeManager.Instance.OutMessageDispatcher,
                                        out nodeInQueue, out nodeOutQueue);
                    //Me is in the new config
                    //Either create it new or overwrite the old one
                    Me = new Node(meDefinition, _nodeGroup, this, forwardingConfig,
                                  nodeInQueue, nodeOutQueue);
                }
                else
                {
                    //me is NOT in the new config.
                    Me = null;
                }
                ushort maxDetectedZone = _localZone;
                foreach (RelayNodeDefinition nodeDefinition in relayNodeClusterDefinition.RelayNodes)
                {
                    if (nodeDefinition != meDefinition)
                    {
                        GetMessageQueuesFor(nodeDefinition, relayNodeClusterDefinition,
                                            NodeManager.Instance.InMessageDispatcher, NodeManager.Instance.OutMessageDispatcher,
                                            out nodeInQueue, out nodeOutQueue);

                        Node node = new Node(nodeDefinition, _nodeGroup, this, forwardingConfig,
                                             nodeInQueue, nodeOutQueue);

                        newNodes.Add(node);
                        if (node.DetectedZone > maxDetectedZone)
                        {
                            maxDetectedZone = node.DetectedZone;
                        }
                        if (node.Zone > maxDetectedZone)
                        {
                            maxDetectedZone = node.Zone;
                        }
                        if (!newZoneNodes.ContainsKey(nodeDefinition.Zone))
                        {
                            newZoneNodes[nodeDefinition.Zone] = new List <Node>();
                        }

                        newZoneNodes[nodeDefinition.Zone].Add(node);
                    }
                }
                Nodes                = newNodes;
                ZoneNodes            = newZoneNodes;
                _nodesByNumberOfHops = CalculateTopography(Nodes, MaximumHops);
                _nodeLayers          = CalculateNodeLayers(_nodesByNumberOfHops, NodeSelectionHopWindowSize);
                _nodesByDetectedZone = CalculateNodesByDetectedZone(Nodes, maxDetectedZone);
                lock (_chooseLock)
                {
                    ChosenNode = null;
                }
                ChosenZoneNodes = new Dictionary <ushort, Node>();
            }
            else
            {
                //just reload the configs to get any new network or queue settings
                bool   hitMe    = false;
                string meString = String.Empty;
                if (Me != null)
                {
                    meString = Me.ToString();
                }
                for (int i = 0; i < relayNodeClusterDefinition.RelayNodes.Length; i++)
                {
                    string definitionString = relayNodeClusterDefinition.RelayNodes[i].Host + ":" + relayNodeClusterDefinition.RelayNodes[i].Port;
                    if (definitionString == meString)
                    {
                        hitMe = true;
                        Me.ReloadMapping(relayNodeClusterDefinition.RelayNodes[i], forwardingConfig);
                    }
                    else
                    {
                        Nodes[(hitMe ? i - 1 : i)].ReloadMapping(relayNodeClusterDefinition.RelayNodes[i], forwardingConfig);
                    }
                }
                lock (_chooseLock)
                {
                    ChosenNode = null;
                }
            }
        }
        internal void ReloadConfig(RelayNodeConfig config, ForwardingConfig newForwardingConfig)
        {
            if (config.RelayNodeMapping == null)
            {
                if (_log.IsErrorEnabled)
                {
                    _log.Error("Got new config with no defined groups.");
                }
            }
            else
            {
                if (config.RelayNodeMapping.Validate())
                {
                    _zoneDefinitions = config.RelayNodeMapping.ZoneDefinitions;                         //make sure this is set before reloading the mapping so any changes propogate
                    Dictionary <string, Dictionary <string, MessageQueue> > errorQueues = GetErrorQueues();
                    NodeGroups.ReloadMapping(config, newForwardingConfig);
                    //note that if a node changes groups, the error queue won't make it!
                    NodeGroups.PopulateQueues(errorQueues, false);
                }
                else
                {
                    if (_log.IsErrorEnabled)
                    {
                        _log.Error("Forwarder not reloading invalid config.");
                    }
                }
            }

            Config = config;

            _myNodeDefinition = GetMyNodeDefinition();
            bool doNewInDispatcher, doNewOutDispatcher;

            if (newForwardingConfig.NumberOfThreads != ForwardingConfig.NumberOfThreads)
            {
                doNewInDispatcher = true;
            }
            else
            {
                doNewInDispatcher = false;
            }
            if (newForwardingConfig.NumberOfOutMessageThreads != ForwardingConfig.NumberOfOutMessageThreads)
            {
                doNewOutDispatcher = true;
            }
            else
            {
                doNewOutDispatcher = false;
            }


            if (doNewInDispatcher || doNewOutDispatcher)
            {
                Dispatcher oldInDispatcher = null, newInDispatcher, oldOutDispatcher = null, newOutDispatcher;

                if (doNewInDispatcher)
                {
                    if (_log.IsInfoEnabled)
                    {
                        _log.InfoFormat("Changing number of messaging threads from {0} to {1}", ForwardingConfig.NumberOfThreads, newForwardingConfig.NumberOfThreads);
                    }
                    oldInDispatcher = InMessageDispatcher;
                    newInDispatcher = new Dispatcher(newForwardingConfig.NumberOfThreads, ThreadPriority.Normal, true, "Relay Forwarder");
                }
                else
                {
                    newInDispatcher = InMessageDispatcher;
                }
                if (doNewOutDispatcher)
                {
                    if (_log.IsInfoEnabled)
                    {
                        _log.InfoFormat("Changing number of out message threads from {0} to {1}", ForwardingConfig.NumberOfOutMessageThreads, newForwardingConfig.NumberOfOutMessageThreads);
                    }
                    oldOutDispatcher = OutMessageDispatcher;
                    newOutDispatcher = new Dispatcher(newForwardingConfig.NumberOfOutMessageThreads, ThreadPriority.Normal, true, "Relay Forwarder");
                }
                else
                {
                    newOutDispatcher = OutMessageDispatcher;
                }

                InMessageDispatcher  = newInDispatcher;
                OutMessageDispatcher = newOutDispatcher;

                NodeGroups.SetNewDispatchers(newInDispatcher, newOutDispatcher);

                ForwardingConfig = newForwardingConfig;

                if (doNewInDispatcher)
                {
                    if (_log.IsInfoEnabled)
                    {
                        _log.Info("Disposing old in message Dispatcher");
                    }
                    oldInDispatcher.Dispose();
                }
                if (doNewOutDispatcher)
                {
                    if (_log.IsInfoEnabled)
                    {
                        _log.Info("Disposing old out message Dispatcher");
                    }
                    oldOutDispatcher.Dispose();
                }
            }
            else
            {
                ForwardingConfig = newForwardingConfig;
            }
        }