protected SystemTarget(GrainId grainId, SiloAddress silo, bool lowPriority) { GrainId = grainId; Silo = silo; ActivationId = ActivationId.GetSystemActivation(grainId, silo); SchedulingContext = new SchedulingContext(this, lowPriority); }
/// <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); } }
/// <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); } } }
// 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; } } } } }
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; }