Example #1
0
 protected SystemTarget(GrainId grainId, SiloAddress silo, bool lowPriority)
 {
     GrainId = grainId;
     Silo = silo;
     ActivationId = ActivationId.GetSystemActivation(grainId, silo);
     SchedulingContext = new SchedulingContext(this, lowPriority);
 }
Example #2
0
        /// <summary>
        /// Handle an incoming message and queue/invoke appropriate handler
        /// </summary>
        /// <param name="message"></param>
        /// <param name="targetActivation"></param>
        public void HandleIncomingRequest(Message message, ActivationData targetActivation)
        {
            lock (targetActivation)
            {
                if (targetActivation.State == ActivationState.Invalid)
                {
                    ProcessRequestToInvalidActivation(message, targetActivation.Address, targetActivation.ForwardingAddress, "HandleIncomingRequest");
                    return;
                }

                // Now we can actually scheduler processing of this request
                targetActivation.RecordRunning(message);
                var context = new SchedulingContext(targetActivation);

                MessagingProcessingStatisticsGroup.OnDispatcherMessageProcessedOk(message);
                Scheduler.QueueWorkItem(new InvokeWorkItem(targetActivation, message, context), context);
            }
        }
Example #3
0
 /// <summary>
 /// Register a new object to which messages can be delivered with the local lookup table and scheduler.
 /// </summary>
 /// <param name="activation"></param>
 public void RegisterMessageTarget(ActivationData activation)
 {
     var context = new SchedulingContext(activation);
     scheduler.RegisterWorkContext(context);
     activations.RecordNewTarget(activation);
     activationsCreated.Increment();
 }
        private void ReceiveMessage(Message msg)
        {
            MessagingProcessingStatisticsGroup.OnImaMessageReceived(msg);

            ISchedulingContext context;
            // Find the activation it targets; first check for a system activation, then an app activation
            if (msg.TargetGrain.IsSystemTarget)
            {
                SystemTarget target = directory.FindSystemTarget(msg.TargetActivation);
                if (target == null)
                {
                    MessagingStatisticsGroup.OnRejectedMessage(msg);
                    Message response = msg.CreateRejectionResponse(Message.RejectionTypes.Unrecoverable,
                        String.Format("SystemTarget {0} not active on this silo. Msg={1}", msg.TargetGrain, msg));
                    messageCenter.SendMessage(response);
                    Log.Warn(ErrorCode.MessagingMessageFromUnknownActivation, "Received a message {0} for an unknown SystemTarget: {1}", msg, msg.TargetAddress);
                    return;
                }
                context = target.SchedulingContext;
                switch (msg.Direction)
                {
                    case Message.Directions.Request:
                        MessagingProcessingStatisticsGroup.OnImaMessageEnqueued(context);
                        scheduler.QueueWorkItem(new RequestWorkItem(target, msg), context);
                        break;

                    case Message.Directions.Response:
                        MessagingProcessingStatisticsGroup.OnImaMessageEnqueued(context);
                        scheduler.QueueWorkItem(new ResponseWorkItem(target, msg), context);
                        break;

                    default:
                        Log.Error(ErrorCode.Runtime_Error_100097, "Invalid message: " + msg);
                        break;
                }
            }
            else
            {
                // Run this code on the target activation's context, if it already exists
                ActivationData targetActivation = directory.FindTarget(msg.TargetActivation);
                if (targetActivation != null)
                {
                    lock (targetActivation)
                    {
                        var target = targetActivation; // to avoid a warning about nulling targetActivation under a lock on it
                        if (target.State.Equals(ActivationState.Valid))
                        {
                            var overloadException = target.CheckOverloaded(Log);
                            if (overloadException != null)
                            {
                                // Send rejection as soon as we can, to avoid creating additional work for runtime
                                dispatcher.RejectMessage(msg, Message.RejectionTypes.Overloaded, overloadException, "Target activation is overloaded " + target);
                                return;
                            }

                            // Run ReceiveMessage in context of target activation
                            context = new SchedulingContext(target);
                        }
                        else
                        {
                            // Can't use this activation - will queue for another activation
                            target = null;
                            context = null;
                        }

                        EnqueueReceiveMessage(msg, target, context);
                    }
                }
                else
                {
                    // No usable target activation currently, so run ReceiveMessage in system context
                    EnqueueReceiveMessage(msg, null, null);
                }
            }
        }
Example #5
0
        // Execute one or more turns for this activation.
        // This method is always called in a single-threaded environment -- that is, no more than one
        // thread will be in this method at once -- but other asynch threads may still be queueing tasks, etc.
        public void Execute()
        {
            lock (lockable)
            {
                if (state == WorkGroupStatus.Shutdown)
                {
                    if (!IsActive)
                    {
                        return;             // Don't mind if no work has been queued to this work group yet.
                    }
                    ReportWorkGroupProblemWithBacktrace(
                        "Cannot execute work items in a work item group that is in a shutdown state.",
                        ErrorCode.SchedulerNotExecuteWhenShutdown); // Throws InvalidOperationException
                    return;
                }
                state = WorkGroupStatus.Running;
            }

            var thread = WorkerPoolThread.CurrentWorkerThread;

            try
            {
                // Process multiple items -- drain the applicationMessageQueue (up to max items) for this physical activation
                int count     = 0;
                var stopwatch = new Stopwatch();
                stopwatch.Start();
                do
                {
                    lock (lockable)
                    {
                        if (state == WorkGroupStatus.Shutdown)
                        {
                            if (WorkItemCount > 0)
                            {
                                log.Warn(ErrorCode.SchedulerSkipWorkStopping, "Thread {0} is exiting work loop due to Shutdown state {1} while still having {2} work items in the queue.",
                                         thread.ToString(), this.ToString(), WorkItemCount);
                            }
                            else
                            if (log.IsVerbose)
                            {
                                log.Verbose("Thread {0} is exiting work loop due to Shutdown state {1}. Has {2} work items in the queue.",
                                            thread.ToString(), this.ToString(), WorkItemCount);
                            }

                            break;
                        }

                        // Check the cancellation token (means that the silo is stopping)
                        if (thread.CancelToken.IsCancellationRequested)
                        {
                            log.Warn(ErrorCode.SchedulerSkipWorkCancelled, "Thread {0} is exiting work loop due to cancellation token. WorkItemGroup: {1}, Have {2} work items in the queue.",
                                     thread.ToString(), this.ToString(), WorkItemCount);
                            break;
                        }
                    }

                    // Get the first Work Item on the list
                    Task task;
                    lock (lockable)
                    {
                        if (workItems.Count > 0)
                        {
                            task = workItems.Dequeue();
                        }
                        else // If the list is empty, then we're done
                        {
                            break;
                        }
                    }

#if TRACK_DETAILED_STATS
                    if (StatisticsCollector.CollectGlobalShedulerStats)
                    {
                        SchedulerStatisticsGroup.OnWorkItemDequeue();
                    }
#endif

#if DEBUG
                    if (log.IsVerbose2)
                    {
                        log.Verbose2("About to execute task {0} in SchedulingContext={1}", task, SchedulingContext);
                    }
#endif
                    var taskStart = stopwatch.Elapsed;

                    try
                    {
                        thread.CurrentTask = task;
#if TRACK_DETAILED_STATS
                        if (StatisticsCollector.CollectTurnsStats)
                        {
                            SchedulerStatisticsGroup.OnTurnExecutionStartsByWorkGroup(workItemGroupStatisticsNumber, thread.WorkerThreadStatisticsNumber, SchedulingContext);
                        }
#endif
                        TaskRunner.RunTask(task);
                    }
                    catch (Exception ex)
                    {
                        log.Error(ErrorCode.SchedulerExceptionFromExecute, String.Format("Worker thread caught an exception thrown from Execute by task {0}", task), ex);
                        throw;
                    }
                    finally
                    {
#if TRACK_DETAILED_STATS
                        if (StatisticsCollector.CollectTurnsStats)
                        {
                            SchedulerStatisticsGroup.OnTurnExecutionEnd(Utils.Since(thread.CurrentStateStarted));
                        }

                        if (StatisticsCollector.CollectThreadTimeTrackingStats)
                        {
                            thread.threadTracking.IncrementNumberOfProcessed();
                        }
#endif
                        totalItemsProcessed++;
                        var taskLength = stopwatch.Elapsed - taskStart;
                        if (taskLength > OrleansTaskScheduler.TurnWarningLengthThreshold)
                        {
                            SchedulerStatisticsGroup.NumLongRunningTurns.Increment();
                            log.Warn(ErrorCode.SchedulerTurnTooLong3, "Task {0} in WorkGroup {1} took elapsed time {2:g} for execution, which is longer than {3}. Running on thread {4}",
                                     OrleansTaskExtentions.ToString(task), SchedulingContext.ToString(), taskLength, OrleansTaskScheduler.TurnWarningLengthThreshold, thread.ToString());
                        }
                        thread.CurrentTask = null;
                    }
                    count++;
                }while (((MaxWorkItemsPerTurn <= 0) || (count <= MaxWorkItemsPerTurn)) &&
                        ((ActivationSchedulingQuantum <= TimeSpan.Zero) || (stopwatch.Elapsed < ActivationSchedulingQuantum)));
                stopwatch.Stop();
            }
            catch (Exception ex)
            {
                log.Error(ErrorCode.Runtime_Error_100032, String.Format("Worker thread {0} caught an exception thrown from IWorkItem.Execute", thread), ex);
            }
            finally
            {
                // Now we're not Running anymore.
                // If we left work items on our run list, we're Runnable, and need to go back on the silo run queue;
                // If our run list is empty, then we're waiting.
                lock (lockable)
                {
                    if (state != WorkGroupStatus.Shutdown)
                    {
                        if (WorkItemCount > 0)
                        {
                            state = WorkGroupStatus.Runnable;
                            masterScheduler.RunQueue.Add(this);
                        }
                        else
                        {
                            state = WorkGroupStatus.Waiting;
                        }
                    }
                }
            }
        }
Example #6
0
 public Task Init(string name, IProviderRuntime providerRuntime, IProviderConfiguration config)
 {
     Name = name;
     this.logger = providerRuntime.GetLogger("MockStatsSiloCollector");
     this.grain = providerRuntime.GrainFactory.GetGrain<IStatsCollectorGrain>(0);
     this.taskScheduler = Silo.CurrentSilo.LocalScheduler;
     this.schedulingContext = Silo.CurrentSilo.testHook.SchedulingContext;
     logger.Info("{0} Init called", GetType().Name);
     return TaskDone.Done;
 }