Exemplo n.º 1
0
 private static List <Node>[] CalculateNodesByDetectedZone(IEnumerable <Node> nodes, ushort maxDetectedZone)
 {
     List <Node>[] nodesByDetectedZone = new List <Node> [maxDetectedZone + 1];
     for (int i = 0; i < nodesByDetectedZone.Length; i++)
     {
         nodesByDetectedZone[i] = new List <Node>(1);
     }
     try
     {
         foreach (Node node in nodes)
         {
             if (node.DetectedZone != 0)
             {
                 nodesByDetectedZone[node.DetectedZone].Add(node);
             }
             else
             {
                 nodesByDetectedZone[node.Zone].Add(node);
             }
         }
     }
     catch (Exception e)
     {
         if (_log.IsErrorEnabled)
         {
             _log.ErrorFormat("Error calculating nodes by detected zone: {0}", e);
         }
         nodesByDetectedZone = null;
     }
     return(nodesByDetectedZone);
 }
Exemplo n.º 2
0
        static ManagedSocket()
        {
            MemoryStream serverCapabilityRequestStream = null, serverCapabilityRequestStreamNetworkOrdered = null;

            try
            {
                serverCapabilityRequestStream = new MemoryStream();
                serverCapabilityRequestStreamNetworkOrdered = new MemoryStream();

                SocketClient.WriteMessageToStream(ServerCapabilityRequestCommandId, 1, null, true, false,
                                                  serverCapabilityRequestStream);
                serverCapabilityRequestStream.Seek(0, SeekOrigin.Begin);
                ServerCapabilityRequestMessage = serverCapabilityRequestStream.ToArray();

                SocketClient.WriteMessageToStream(ServerCapabilityRequestCommandId, 1, null, true, true,
                                                  serverCapabilityRequestStreamNetworkOrdered);
                serverCapabilityRequestStreamNetworkOrdered.Seek(0, SeekOrigin.Begin);
                ServerCapabilityRequestMessageNetworkOrdered = serverCapabilityRequestStreamNetworkOrdered.ToArray();
            }
            catch (Exception e)
            {
                log.ErrorFormat("Error initializing server capability streams: {0}", e);
            }
            finally
            {
                if (serverCapabilityRequestStream != null)
                {
                    serverCapabilityRequestStream.Close();
                }
                if (serverCapabilityRequestStreamNetworkOrdered != null)
                {
                    serverCapabilityRequestStreamNetworkOrdered.Close();
                }
            }
        }
Exemplo n.º 3
0
        private static List <ObjectDependency> ProcessDependencies(ObjectReference header,
                                                                   IEnumerable <ObjectDependency> dependencyList, OperationType op)
        {
            List <ObjectDependency> retained = null;

            foreach (var dependency in dependencyList)
            {
                var retain = false;
                try
                {
                    retain = dependency.Notify(header, op);
                }
                catch (Exception exc)
                {
                    if (_log.IsErrorEnabled)
                    {
                        _log.ErrorFormat("Dependent '{0}' for object id='{1}' threw {2}: {3}",
                                         dependency, header, exc.GetType().FullName,
                                         exc.Message);
                    }
                }
                if (retain)
                {
                    if (retained == null)
                    {
                        retained = new List <ObjectDependency>();
                    }
                    retained.Add(dependency);
                }
            }
            return(retained);
        }
Exemplo n.º 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);
        }
        private bool DoValidityCheck()
        {
            Dictionary <string, bool> definedNodes = new Dictionary <string, bool>();

            foreach (RelayNodeGroupDefinition groupDefinition in RelayNodeGroups)
            {
                foreach (RelayNodeClusterDefinition clusterDefinition in groupDefinition.RelayNodeClusters)
                {
                    foreach (RelayNodeDefinition nodeDefinition in clusterDefinition.RelayNodes)
                    {
                        if (definedNodes.ContainsKey(nodeDefinition.ToString()))
                        {
                            if (log.IsErrorEnabled)
                            {
                                log.ErrorFormat("Node mapping failed validation because of duplicate node {0} in group {1}", nodeDefinition, groupDefinition.Name);
                            }
                            return(false);
                        }
                        else
                        {
                            definedNodes.Add(nodeDefinition.ToString(), true);
                        }
                    }
                }
            }
            return(true);
        }
Exemplo n.º 6
0
        private void UpdateServerServiceStatus(MonitorEventArgs <ServiceControllerStatus> args)
        {
            LogWrapper.ErrorFormat("ServerService {0} has status {1}", _controller.ServiceName, args.Package.ToString());

            // TODO: Update a label on the main form

            if (args.Package == ServiceControllerStatus.Stopped)
            {
                _controller.Start();
            }
        }
Exemplo n.º 7
0
        private Future <RelayMessage> NoMatchingServer(TypeSetting typeSetting, RelayMessage relayMessage)
        {
            var noMatchingServerMessage = String.Format("No Data Relay server is in the server mapping for group/id {0}/{1}", typeSetting.GroupName, relayMessage.Id);

            _log.ErrorFormat(noMatchingServerMessage);

            var serverNotFoundFuture = new FuturePublisher <RelayMessage>();

            serverNotFoundFuture.SetError(new ApplicationException(noMatchingServerMessage));  // TODO: use a better exception type
            return(serverNotFoundFuture.Future);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Ends the handling of a message and returns the memory stream to send back to the client.
        /// </summary>
        /// <param name="asyncResult">The <see cref="IAsyncResult"/> returned from <see cref="BeginHandleMessage"/>.</param>
        /// <returns>Retuns a <see cref="MemoryStream"/> to send back to the client, if the stream is <see langword="null"/> an empty response is sent.</returns>
        public MemoryStream EndHandleMessage(IAsyncResult asyncResult)
        {
            MemoryStream             replyStream       = null;
            SocketHandlerAsyncResult socketAsyncResult = (SocketHandlerAsyncResult)asyncResult;

            if (socketAsyncResult.Exception != null)
            {
                if (log.IsErrorEnabled)
                {
                    log.ErrorFormat("Exception handling async message: {0}", socketAsyncResult.Exception);
                }
                throw socketAsyncResult.Exception;
            }

            //only 1 should be not null
            int replyCount = 0;

            if (socketAsyncResult.ReplyMessage != null)
            {
                replyCount++;
            }
            if (socketAsyncResult.ReplyMessages != null)
            {
                replyCount++;
            }
            if (socketAsyncResult.RuntimeInfo != null)
            {
                replyCount++;
            }
            if (replyCount > 1)
            {
                throw new InvalidOperationException(
                          string.Format("Only 1 reply at a time is supported. ReplyMessage: {0}, ReplyMessages: {1}, RuntimeInfo: {2}",
                                        socketAsyncResult.ReplyMessage,
                                        socketAsyncResult.ReplyMessages,
                                        socketAsyncResult.RuntimeInfo));
            }

            if (socketAsyncResult.ReplyMessage != null)
            {
                replyStream = RelayMessageFormatter.WriteRelayMessage(socketAsyncResult.ReplyMessage);
            }
            else if (socketAsyncResult.ReplyMessages != null)
            {
                replyStream = RelayMessageFormatter.WriteRelayMessageList(socketAsyncResult.ReplyMessages);
            }
            else if (socketAsyncResult.RuntimeInfo != null)
            {
                replyStream = (MemoryStream)RelayMessageFormatter.WriteRuntimeInfo(socketAsyncResult.RuntimeInfo);
            }

            return(replyStream);
        }
Exemplo n.º 9
0
 /// <summary>
 /// Handles the <see cref="AssemblyDirChanged"/> event, to signal for the assembly change.
 /// </summary>
 private void ProcessAssemblyChange()
 {
     lock (_resourceLock)
     {
         _currentFileSetChangeTime = null;
         _pendingAssemblyFileNames.Clear();
         if (_nodeChanged != null)
         {
             try
             {
                 _nodeChanged();
             }
             catch (Exception ex)
             {
                 if (_log.IsErrorEnabled)
                 {
                     _log.ErrorFormat("Error Changing Node Assembly: {0}", ex);
                 }
             }
         }
     }
 }
Exemplo n.º 10
0
        public void Initialize(string instanceName)
        {
            if (!PerformanceCounterCategory.Exists(PerformanceCategoryName))
            {
                CreatePerformanceCounterCategory();
            }
            BdbInstanceInfo bdbInstanceInfo;

            if (Instances.TryGetValue(instanceName, out bdbInstanceInfo))
            {
                Log.Info("Performance counters instance " + instanceName + " is already exists, instance will not be re-initialized.");
            }
            else
            {
                try
                {
                    bdbInstanceInfo = new BdbInstanceInfo();
                    int numCounters = PerformanceCounterNames.Length;
                    bdbInstanceInfo.counters = new PerformanceCounter[numCounters];
                    for (int i = 0; i < numCounters; i++)
                    {
                        bdbInstanceInfo.counters[i] = new PerformanceCounter(
                            PerformanceCategoryName,
                            PerformanceCounterNames[i],
                            instanceName,
                            false
                            );
                    }

                    bdbInstanceInfo.getHitCounter      = new MinuteAggregateCounter();
                    bdbInstanceInfo.getAttemptCounter  = new MinuteAggregateCounter();
                    bdbInstanceInfo.saveHitCounter     = new MinuteAggregateCounter();
                    bdbInstanceInfo.saveAttemptCounter = new MinuteAggregateCounter();

                    Instances.Add(instanceName, bdbInstanceInfo);

                    ResetCounters(bdbInstanceInfo.counters);
                    StartTimer();
                }
                catch (Exception ex)
                {
                    if (Log.IsErrorEnabled)
                    {
                        Log.ErrorFormat("BerkeleyDbCounters:Initialize() Exception creating Memory Store Counters: {0}. The counters might need to be reinstalled via InstallUtil."
                                        , ex);
                    }
                }
                Log.DebugFormat("Performance counters instance {0} initialized.", instanceName);
            }
        }
Exemplo n.º 11
0
 private void ExitLimiter()
 {
     if (_useLimiter)
     {
         try
         {
             _connectionLimiter.Release();
         }
         catch (SemaphoreFullException)
         {
             logger.ErrorFormat("Connection pool for {0} released a connection too many times", _target);
         }
     }
 }
Exemplo n.º 12
0
        public string DecodeStr(byte[] bytes)
        {
            if (bytes != null && bytes.Length > 0)
            {
                string str = Encoding.UTF8.GetString(bytes);

                if (string.IsNullOrEmpty(str))
                {
                    _logger.ErrorFormat("occured when deserialize the response.bytes:{0}", bytes);
                }
                return(str);
            }

            return(string.Empty);
        }
Exemplo n.º 13
0
        private int CompareIndex(byte[] arr1, byte[] arr2)
        {
            try
            {
                int    retVal = 0;
                short  int16o1, int16o2;
                int    int32o1, int32o2;
                long   int64o1, int64o2;
                ushort uint16o1, uint16o2;
                uint   uint32o1, uint32o2;
                ulong  uint64o1, uint64o2;
                string stro1, stro2;
                float  flto1, flto2;
                double dblo1, dblo2;

                switch (dataType)
                {
                case DataType.UInt16:
                    uint16o1     = BitConverter.ToUInt16(arr1, startIndex1);
                    uint16o2     = BitConverter.ToUInt16(arr2, startIndex2);
                    retVal       = uint16o1.CompareTo(uint16o2);
                    startIndex1 += SIZE_OF_INT16;
                    startIndex2 += SIZE_OF_INT16;
                    break;

                case DataType.Int16:
                    int16o1      = BitConverter.ToInt16(arr1, startIndex1);
                    int16o2      = BitConverter.ToInt16(arr2, startIndex2);
                    retVal       = int16o1.CompareTo(int16o2);
                    startIndex1 += SIZE_OF_INT16;
                    startIndex2 += SIZE_OF_INT16;
                    break;

                case DataType.UInt32:
                    uint32o1     = BitConverter.ToUInt32(arr1, startIndex1);
                    uint32o2     = BitConverter.ToUInt32(arr2, startIndex2);
                    retVal       = uint32o1.CompareTo(uint32o2);
                    startIndex1 += SIZE_OF_INT32;
                    startIndex2 += SIZE_OF_INT32;
                    break;

                case DataType.Int32:
                case DataType.SmallDateTime:
                    int32o1      = BitConverter.ToInt32(arr1, startIndex1);
                    int32o2      = BitConverter.ToInt32(arr2, startIndex2);
                    retVal       = int32o1.CompareTo(int32o2);
                    startIndex1 += SIZE_OF_INT32;
                    startIndex2 += SIZE_OF_INT32;
                    break;

                case DataType.UInt64:
                    uint64o1     = BitConverter.ToUInt64(arr1, startIndex1);
                    uint64o2     = BitConverter.ToUInt64(arr2, startIndex2);
                    retVal       = uint64o1.CompareTo(uint64o2);
                    startIndex1 += SIZE_OF_INT64;
                    startIndex2 += SIZE_OF_INT64;
                    break;

                case DataType.Int64:
                case DataType.DateTime:
                    int64o1      = BitConverter.ToInt64(arr1, startIndex1);
                    int64o2      = BitConverter.ToInt64(arr2, startIndex2);
                    retVal       = int64o1.CompareTo(int64o2);
                    startIndex1 += SIZE_OF_INT64;
                    startIndex2 += SIZE_OF_INT64;
                    break;

                case DataType.String:
                    stro1        = stringEncoder.GetString(arr1);
                    stro2        = stringEncoder.GetString(arr2);
                    retVal       = string.Compare(stro1, stro2);
                    startIndex1 += stro1.Length;
                    startIndex2 += stro2.Length;
                    break;

                case DataType.Byte:
                    retVal       = arr1[startIndex1].CompareTo(arr2[startIndex2]);
                    startIndex1 += SIZE_OF_BYTE;
                    startIndex2 += SIZE_OF_BYTE;
                    break;

                case DataType.Float:
                    flto1        = BitConverter.ToSingle(arr1, startIndex1);
                    flto2        = BitConverter.ToSingle(arr2, startIndex2);
                    retVal       = flto1.CompareTo(flto2);
                    startIndex1 += SIZE_OF_FLOAT;
                    startIndex2 += SIZE_OF_FLOAT;
                    break;

                case DataType.Double:
                    dblo1        = BitConverter.ToDouble(arr1, startIndex1);
                    dblo2        = BitConverter.ToDouble(arr2, startIndex2);
                    retVal       = dblo1.CompareTo(dblo2);
                    startIndex1 += SIZE_OF_DOUBLE;
                    startIndex2 += SIZE_OF_DOUBLE;
                    break;
                }
                return(retVal);
            }
            catch (Exception)
            {
                Log.Error("Error inside IndexCacheComparer");
                Log.ErrorFormat("arr1.Length = {0}, arr1 = {1}", arr1.Length, GetReadableByteArray(arr1));
                Log.ErrorFormat("startIndex1 = {0}", startIndex1);
                Log.ErrorFormat("arr2.Length = {0}, arr2 = {1}", arr2.Length, GetReadableByteArray(arr2));
                Log.ErrorFormat("startIndex2 = {0}", startIndex2);
                Log.ErrorFormat("IndexCacheComparer.TagHashCode = {0}", tagHashCode);
                Log.Error("IndexCacheComparer.SortOrderList = ");
                int i = 0;
                foreach (SortOrder so in sortOrderList)
                {
                    Log.ErrorFormat("SortOrderList[{0}].DataType = {1}", i, so.DataType);
                    Log.ErrorFormat("SortOrderList[{0}].SortBy = {1}", i, so.SortBy);
                    i++;
                }
                throw;
            }
        }
Exemplo n.º 14
0
 /// <summary>
 /// error
 /// </summary>
 /// <param name="exception"></param>
 public static void ErrorFormat(string info, params object[] args)
 {
     _log.ErrorFormat(info, args);
 }
Exemplo n.º 15
0
        /// <summary>
        /// Initializes the <see cref="RelayNode"/> with the given <see cref="ComponentRunState"/>s,
        /// must be called before calling <see cref="Start"/>
        /// </summary>
        /// <param name="componentRunStates"></param>
        public void Initialize(ComponentRunState[] componentRunStates)
        {
            try
            {
                if (log.IsInfoEnabled)
                {
                    if (componentRunStates == null)
                    {
                        log.Info("Initializing Relay Node.");
                    }
                    else
                    {
                        log.Info("Initialzing Relay Node with Component Run States.");
                    }
                }

                EnvironmentManager.EnvironmentChanged += EnvironmentChangedHandler;

                GetConfig();

                if (configuration == null)
                {
                    throw new ConfigurationErrorsException("config failed to load, is null");
                }

                SetClusterAddresses(configuration);

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

                components = new RelayComponents(configuration);

                if (configuration != null)
                {
                    messageTracer           = new MessageTracer(configuration.TypeSettings.MaxTypeId, configuration.TraceSettings);
                    messageTracer.Activated = configuration.OutputTraceInfo;

                    const string inThreadsName = "DataRelayNode";
                    if (configuration.NumberOfThreads > 0)
                    {
                        inDispatcher = new Dispatcher(configuration.NumberOfThreads, ThreadPriority.Normal, true, inThreadsName);
                    }
                    else
                    {
                        inDispatcher = new Dispatcher()
                        {
                            Name = inThreadsName
                        };
                    }

                    const string outThreadsName = "DataRelayNodeOUT";
                    if (configuration.OutMessagesOnRelayThreads)
                    {
                        if (configuration.NumberOfOutMessageThreads > 0)
                        {
                            outDispatcher = new Dispatcher(configuration.NumberOfOutMessageThreads, ThreadPriority.Normal, true, outThreadsName);
                        }
                        else
                        {
                            outDispatcher = new Dispatcher {
                                Name = outThreadsName
                            };
                        }

                        outMessagePort  = new Port <RelayMessageAsyncResult>();
                        outMessagesPort = new Port <RelayMessageListAsyncResult>();

                        outMessageQueue = new DispatcherQueue("DataRelayDispatcherQueueOUT", outDispatcher, TaskExecutionPolicy.ConstrainQueueDepthThrottleExecution, configuration.MaximumOutMessageQueueDepth);
                        Arbiter.Activate(outMessageQueue,
                                         Arbiter.ReceiveWithIterator(true, outMessagePort, HandleOutMessage));
                        Arbiter.Activate(outMessageQueue,
                                         Arbiter.ReceiveWithIterator(true, outMessagesPort, HandleOutMessages));
                    }

                    inMessageQueue = new DispatcherQueue("DataRelayDispatcherQueue", inDispatcher, TaskExecutionPolicy.ConstrainQueueDepthThrottleExecution, configuration.MaximumMessageQueueDepth);

                    queuedTaskThreshold = (int)Math.Floor(0.9 * configuration.MaximumMessageQueueDepth);


                    // setup RelayServicesClient before initalizing components
                    RelayServicesClient.Instance.RelayNodeServices = this;

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


                    //by having after the Arbiter.Activate it allows Initialize components to use
                    //IRelayNodeServices that require Message handling
                    components.Initialize(componentRunStates, configuration.IgnoredMessageTypes);

                    queuedMessageCounterTimer = new Timer(CountQueuedMessages, null, 5000, 5000);
                }
            }
            catch (Exception ex)
            {
                if (log.IsErrorEnabled)
                {
                    log.ErrorFormat("Exception initializing relay node: {0}", ex);
                }
                throw;                 //should bring server down
            }
        }
Exemplo n.º 16
0
 internal static void LogNodeException(RelayMessage message, Node node, Exception ex)
 {
     if (_log.IsErrorEnabled)
     {
         if (ex is SocketException)
         {
             SocketException sex = (SocketException)ex;
             _log.ErrorFormat("Socket error {0} while handling {1} for node {2}.", sex.SocketErrorCode, message, node.ToExtendedString());
         }
         else
         {
             _log.ErrorFormat("Error handling {0} for node {1}: {2}", message, node.ToExtendedString(), ex);
         }
     }
 }
Exemplo n.º 17
0
        void IAsyncRelayTransport.EndSendMessageList(IAsyncResult result)
        {
            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            if (result is RoundTripAsyncResult <List <RelayMessage> > )
            {
                if (!result.IsCompleted)
                {
                    result.AsyncWaitHandle.WaitOne();
                    result.AsyncWaitHandle.Close();
                }

                var roundTripResult = (RoundTripAsyncResult <List <RelayMessage> >)result;

                if (roundTripResult.Error != null)
                {
                    throw roundTripResult.Error;
                }

                if (roundTripResult.ResponseMessage != null && roundTripResult.SentMessage != null && roundTripResult.ResponseMessage.Count == roundTripResult.SentMessage.Count)
                {
                    for (int i = 0; i < roundTripResult.SentMessage.Count; i++)
                    {
                        if (roundTripResult.SentMessage[i] != null && roundTripResult.ResponseMessage[i] != null)
                        {
                            roundTripResult.SentMessage[i].ExtractResponse(roundTripResult.ResponseMessage[i]);
                        }
                    }
                }
                else if (roundTripResult.ResponseMessage == null)
                {
                    log.ErrorFormat("Response for async bulk out messages to node {0} was null", _node);
                }
                else if (roundTripResult.SentMessage == null)
                {
                    log.ErrorFormat("List of async out messages sent to {0} was null", _node);
                }
                else                 //message count mismatch
                {
                    log.ErrorFormat("Sent {0} out messages to node {1} but only got {2} back", roundTripResult.SentMessage.Count, _node, roundTripResult.ResponseMessage.Count);
                }
            }
            else if (result is SimpleAsyncResult)
            {
                if (!result.IsCompleted)
                {
                    result.AsyncWaitHandle.WaitOne();
                    result.AsyncWaitHandle.Close();
                }

                var simpleResult = (SimpleAsyncResult)result;

                if (simpleResult.Error != null)
                {
                    throw simpleResult.Error;
                }
            }
            else
            {
                throw new ArgumentException("result did not come from one of the correct SendMessage overloads.", "result");
            }
        }
Exemplo n.º 18
0
        internal SimpleLinkedList <Node> GetNodesForMessage(RelayMessage message)
        {
            SimpleLinkedList <Node> nodes = null;

            if (message == null || message.RelayTTL < 1 || NodeGroups == null)
            {
                return(new SimpleLinkedList <Node>());
            }

            const bool useLegacySerialization = true;

            //commands that, from out of system, route to all groups
            if (message.IsGroupBroadcastMessage)
            {
                message.PrepareMessageToBeSent(useLegacySerialization);
                if (MyNodeGroup == null)                //out of system: all groups
                {
                    nodes = new SimpleLinkedList <Node>();
                    for (int groupIndex = 0; groupIndex < this.NodeGroups.Count; groupIndex++)
                    {
                        nodes.Push(NodeGroups[groupIndex].GetNodesForMessage(message));
                    }
                }
                else                //In system: my group
                {
                    nodes = MyNodeGroup.MyCluster.GetNodesForMessage(message);
                }
            }
            else
            {
                //Commands that always route to a single group
                NodeGroup group = GetNodeGroup(message.TypeId);
                if (group != null)
                {
                    message.PrepareMessageToBeSent(group.GroupDefinition.LegacySerialization);
                    nodes = group.GetNodesForMessage(message);
                }
                else
                {
                    message.PrepareMessageToBeSent(useLegacySerialization);
                    if (_log.IsErrorEnabled)
                    {
                        _log.ErrorFormat("No group found for {0}", message);
                    }
                    nodes = new SimpleLinkedList <Node>();
                }
            }

            if (nodes == null)
            {
                nodes = new SimpleLinkedList <Node>();
            }

            // If no nodes are returned, we predict that the caller
            // will drop the message.  Therefore we call the notification delegate.
            // This is admittedly a kludgy solution, but the only one
            // available without changing this method's signature.
            // A better solution should be adopted. [tchow 01/29/2008]
            if (nodes.Count == 0)
            {
                Forwarder.RaiseMessageDropped(message);
            }

            return(nodes);
        }