Example #1
0
        /// <summary>
        /// Process commands in a single thread, until there are no more queued commands.
        /// Heartbeat is called between every command.
        /// </summary>
        public static void ProcessCommands()
        {
            if ((Core.Flags & StartupFlags.SingleThreaded) != StartupFlags.SingleThreaded)
            {
                throw new InvalidOperationException("ProcessCommands should only be called in single threaded mode.");
            }

            while (PendingCommands.Count > 0 && !ShuttingDown)
            {
                GlobalRules.ConsiderPerformRule("heartbeat");

                Core.SendPendingMessages();

                PendingCommand PendingCommand = null;

                try
                {
                    PendingCommand = PendingCommands.FirstOrDefault();
                    if (PendingCommand != null)
                    {
                        PendingCommands.Remove(PendingCommand);
                    }
                }
                catch (Exception e)
                {
                    LogCommandError(e);
                    PendingCommand = null;
                }

                if (PendingCommand != null)
                {
                    NextCommand = PendingCommand;

                    //Reset flags that the last command may have changed
                    CommandTimeoutEnabled = true;
                    SilentFlag            = false;
                    GlobalRules.LogRules(null);

                    try
                    {
                        var handler = NextCommand.Actor.GetProperty <ClientCommandHandler>("command handler");
                        if (handler != null)
                        {
                            handler.HandleCommand(NextCommand);
                        }
                    }
                    catch (Exception e)
                    {
                        LogCommandError(e);
                        Core.DiscardPendingMessages();
                    }
                    if (PendingCommand.ProcessingCompleteCallback != null)
                    {
                        PendingCommand.ProcessingCompleteCallback();
                    }
                }
            }
        }
Example #2
0
        private static void ProcessThreadedCommands()
        {
            if ((Core.Flags & StartupFlags.SingleThreaded) == StartupFlags.SingleThreaded)
            {
                throw new InvalidOperationException("ProcessThreadedCommands should never be called in single threaded mode.");
            }

            IndividualCommandThread = new Thread(ProcessCommandsWorkerThread);
            IndividualCommandThread.Start();

            while (!ShuttingDown)
            {
                System.Threading.Thread.Sleep(10);
                DatabaseLock.WaitOne();
                Heartbeat();
                DatabaseLock.ReleaseMutex();

                while (PendingCommands.Count > 0 && !ShuttingDown)
                {
                    PendingCommand PendingCommand = null;

                    PendingCommandLock.WaitOne();

                    try
                    {
                        PendingCommand = PendingCommands.FirstOrDefault(pc =>
                        {
                            return(true);
                            //if (pc.Actor.ConnectedClient == null) return true;
                            //else return (DateTime.Now - pc.Actor.ConnectedClient.TimeOfLastCommand).TotalMilliseconds > SettingsObject.AllowedCommandRate;
                        });
                        if (PendingCommand != null)
                        {
                            PendingCommands.Remove(PendingCommand);
                        }
                    }
                    catch (Exception e)
                    {
                        LogCommandError(e);
                        PendingCommand = null;
                    }

                    PendingCommandLock.ReleaseMutex();

                    if (PendingCommand != null)
                    {
                        DatabaseLock.WaitOne();

                        NextCommand = PendingCommand;

                        //Reset flags that the last command may have changed
                        CommandTimeoutEnabled = true;
                        SilentFlag            = false;
                        GlobalRules.LogRules(null);

                        CommandReadyHandle.Set(); //Signal worker thread to proceed.
                        if (!CommandFinishedHandle.WaitOne(SettingsObject.CommandTimeOut))
                        {
                            if (!CommandTimeoutEnabled) //Timeout is disabled, go ahead and wait for infinity.
                            {
                                CommandFinishedHandle.WaitOne();
                            }
                            else
                            {
                                //Kill the command processor thread.
                                IndividualCommandThread.Abort();
                                ClearPendingMessages();
                                if (PendingCommand.Actor.ConnectedClient != null)
                                {
                                    PendingCommand.Actor.ConnectedClient.Send("Command timeout.\r\n");
                                    LogError(String.Format("Command timeout. {0} - {1}", PendingCommand.Actor.ConnectedClient.ConnectionDescription, PendingCommand.RawCommand));
                                }
                                else
                                {
                                    LogError(String.Format("Command timeout [No client] - {1}", PendingCommand.RawCommand));
                                }
                                IndividualCommandThread = new Thread(ProcessCommandsWorkerThread);
                                IndividualCommandThread.Start();
                            }
                        }

                        if (PendingCommand.ProcessingCompleteCallback != null)
                        {
                            PendingCommand.ProcessingCompleteCallback();
                        }

                        DatabaseLock.ReleaseMutex();
                    }
                }
            }

            IndividualCommandThread.Abort();
            if (Core.OnShutDown != null)
            {
                Core.OnShutDown();
            }
        }