/// <summary> /// Enqueue message for local handling after transaction completes /// </summary> /// <param name="message"></param> /// <param name="targetActivation"></param> private void EnqueueRequest(Message message, ActivationData targetActivation) { var overloadException = targetActivation.CheckOverloaded(logger); if (overloadException != null) { MessagingProcessingStatisticsGroup.OnDispatcherMessageProcessedError(message, "Overload2"); RejectMessage(message, Message.RejectionTypes.Overloaded, overloadException, "Target activation is overloaded " + targetActivation); return; } if (Message.WriteMessagingTraces) { message.AddTimestamp(Message.LifecycleTag.EnqueueWaiting); } bool enqueuedOk = targetActivation.EnqueueMessage(message); if (!enqueuedOk) { ProcessRequestToInvalidActivation(message, targetActivation.Address, targetActivation.ForwardingAddress, "EnqueueRequest"); } // Dont count this as end of processing. The message will come back after queueing via HandleIncomingRequest. #if DEBUG // This is a hot code path, so using #if to remove diags from Release version // Note: Caller already holds lock on activation if (logger.IsVerbose2) { logger.Verbose2(ErrorCode.Dispatcher_EnqueueMessage, "EnqueueMessage for {0}: targetActivation={1}", message.TargetActivation, targetActivation.DumpStatus()); } #endif }
internal void IncrementGrainCounter(string grainTypeName) { if (logger.IsVerbose2) { logger.Verbose2("Increment Grain Counter {0}", grainTypeName); } CounterStatistic ctr = FindGrainCounter(grainTypeName); ctr.Increment(); }
public static Assembly OnReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args) { // loading into the reflection-only context doesn't resolve dependencies automatically. // we're faced with the choice of ignoring arguably false dependency-missing exceptions or // loading the dependent assemblies into the reflection-only context. // // i opted to load dependencies (by implementing OnReflectionOnlyAssemblyResolve) // because it's an opportunity to quickly identify assemblies that wouldn't load under // normal circumstances. try { var name = AppDomain.CurrentDomain.ApplyPolicy(args.Name); return(Assembly.ReflectionOnlyLoad(name)); } catch (IOException) { if (logger.IsVerbose2) { logger.Verbose2(FormatReflectionOnlyAssemblyResolveFailureMessage(sender, args)); } var dirName = Path.GetDirectoryName(args.RequestingAssembly.Location); var assemblyName = new AssemblyName(args.Name); var fileName = string.Format("{0}.dll", assemblyName.Name); var pathName = Path.Combine(dirName, fileName); if (logger.IsVerbose2) { logger.Verbose2("failed to find assembly {0} in {1}; searching for {2} instead.", assemblyName.FullName, dirName, pathName); } try { return(Assembly.ReflectionOnlyLoadFrom(pathName)); } catch (FileNotFoundException) { if (logger.IsVerbose2) { logger.Verbose(FormatReflectionOnlyAssemblyResolveFailureMessage(sender, args)); } throw; } } }
internal void DropExpiredMessage(MessagingStatisticsGroup.Phase phase) { MessagingStatisticsGroup.OnMessageExpired(phase); if (logger.IsVerbose2) { logger.Verbose2("Dropping an expired message: {0}", this); } ReleaseBodyAndHeaderBuffers(); }
public void DoCallback(Message response) { if (alreadyFired) { return; } lock (this) { if (alreadyFired) { return; } if (response.Result == Message.ResponseTypes.Rejection && response.RejectionType == Message.RejectionTypes.Transient) { if (resendFunc(Message)) { return; } } alreadyFired = true; DisposeTimer(); if (StatisticsCollector.CollectApplicationRequestsStats) { timeSinceIssued.Stop(); } if (unregister != null) { unregister(); } } if (Message.WriteMessagingTraces) { response.AddTimestamp(Message.LifecycleTag.InvokeIncoming); } if (logger.IsVerbose2) { logger.Verbose2("Message {0} timestamps: {1}", response, response.GetTimestampString()); } if (StatisticsCollector.CollectApplicationRequestsStats) { ApplicationRequestsStatisticsGroup.OnAppRequestsEnd(timeSinceIssued.Elapsed); } // do callback outside the CallbackData lock. Just not a good practice to hold a lock for this unrelated operation. callback(response, context); }
public void ReceiveResponse(Message message) { if (message.Result == Message.ResponseTypes.Rejection) { if (!message.TargetSilo.Matches(this.CurrentSilo)) { // gatewayed message - gateway back to sender if (logger.IsVerbose2) { logger.Verbose2(ErrorCode.Dispatcher_NoCallbackForRejectionResp, "No callback for rejection response message: {0}", message); } dispatcher.Transport.SendMessage(message); return; } if (logger.IsVerbose) { logger.Verbose(ErrorCode.Dispatcher_HandleMsg, "HandleMessage {0}", message); } switch (message.RejectionType) { case Message.RejectionTypes.DuplicateRequest: // try to remove from callbackData, just in case it is still there. break; case Message.RejectionTypes.Overloaded: break; case Message.RejectionTypes.Unrecoverable: // fall through & reroute case Message.RejectionTypes.Transient: if (!message.ContainsHeader(Message.Header.CACHE_INVALIDATION_HEADER)) { // Remove from local directory cache. Note that SendingGrain is the original target, since message is the rejection response. // If CacheMgmtHeader is present, we already did this. Otherwise, we left this code for backward compatability. // It should be retired as we move to use CacheMgmtHeader in all relevant places. directory.InvalidateCacheEntry(message.SendingAddress); } break; default: logger.Error(ErrorCode.Dispatcher_InvalidEnum_RejectionType, "Missing enum in switch: " + message.RejectionType); break; } } CallbackData callbackData; bool found = callbacks.TryGetValue(message.Id, out callbackData); if (found) { // IMPORTANT: we do not schedule the response callback via the scheduler, since the only thing it does // is to resolve/break the resolver. The continuations/waits that are based on this resolution will be scheduled as work items. callbackData.DoCallback(message); } else { if (logger.IsVerbose) { logger.Verbose(ErrorCode.Dispatcher_NoCallbackForResp, "No callback for response message: " + message); } } }
public void AddTimestamp(LifecycleTag tag) { if (logger.IsVerbose2) { if (LogVerbose(tag)) { logger.Verbose("Message {0} {1}", tag, this); } else if (logger.IsVerbose2) { logger.Verbose2("Message {0} {1}", tag, this); } } if (WriteMessagingTraces) { var now = DateTime.UtcNow; var timestamp = new List <object> { tag, now }; object val; List <object> list = null; if (headers.TryGetValue(Header.TIMESTAMPS, out val)) { list = val as List <object>; } if (list == null) { list = new List <object>(); lock (headers) { headers[Header.TIMESTAMPS] = list; } } else if (list.Count > 0) { var last = list[list.Count - 1] as List <object>; if (last != null) { var context = DebugContext; if (String.IsNullOrEmpty(context)) { context = "Unspecified"; } TransitionStats[,] entry; bool found; lock (lifecycleStatistics) { found = lifecycleStatistics.TryGetValue(context, out entry); } if (!found) { var newEntry = new TransitionStats[32, 32]; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { newEntry[i, j] = new TransitionStats(); } } lock (lifecycleStatistics) { if (!lifecycleStatistics.TryGetValue(context, out entry)) { entry = newEntry; lifecycleStatistics.Add(context, entry); } } } int from = (int)(LifecycleTag)(last[0]); int to = (int)tag; entry[from, to].RecordTransition(now.Subtract((DateTime)last[1])); } } list.Add(timestamp); } if (OnTrace != null) { OnTrace(this, tag); } }