Esempio n. 1
0
        public void ReceiveResponse(Message response)
        {
            EventSourceUtils.EmitEvent(response, OrleansOutsideRuntimeClientEvent.ReceiveResponseAction);

            if (logger.IsEnabled(LogLevel.Trace))
            {
                logger.Trace("Received {0}", response);
            }

            // ignore duplicate requests
            if (response.Result == Message.ResponseTypes.Rejection &&
                (response.RejectionType == Message.RejectionTypes.DuplicateRequest ||
                 response.RejectionType == Message.RejectionTypes.CacheInvalidation))
            {
                return;
            }

            CallbackData callbackData;
            var          found = callbacks.TryRemove(response.Id, out callbackData);

            if (found)
            {
                // We need to import the RequestContext here as well.
                // Unfortunately, it is not enough, since CallContext.LogicalGetData will not flow "up" from task completion source into the resolved task.
                // RequestContextExtensions.Import(response.RequestContextData);
                callbackData.DoCallback(response);
            }
            else
            {
                logger.Warn(ErrorCode.Runtime_Error_100011, "No callback for response message: " + response);
            }
        }
Esempio n. 2
0
        public void SendRequest(GrainReference target, InvokeMethodRequest request, TaskCompletionSource <object> context, string debugContext = null, InvokeMethodOptions options = InvokeMethodOptions.None, string genericArguments = null)
        {
            var message = this.messageFactory.CreateMessage(request, options);

            EventSourceUtils.EmitEvent(message, OrleansOutsideRuntimeClientEvent.SendRequestAction);
            SendRequestMessage(target, message, context, debugContext, options, genericArguments);
        }
Esempio n. 3
0
        /// <summary>
        /// Handles an incoming (proxied) message by rerouting it immediately and unconditionally,
        /// after some header massaging.
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="receivedOnSocket"></param>
        protected override void HandleMessage(Message msg, Socket receivedOnSocket)
        {
            EventSourceUtils.EmitEvent(msg, OrleansGatewayAcceptorEvent.HandleMessageAction);
            // Don't process messages that have already timed out
            if (msg.IsExpired)
            {
                msg.DropExpiredMessage(MessagingStatisticsGroup.Phase.Receive);
                return;
            }

            gatewayTrafficCounter.Increment();

            // return address translation for geo clients (replace sending address cli/* with gcl/*)
            if (this.multiClusterOptions.HasMultiClusterNetwork && msg.SendingAddress.Grain.Category != UniqueKey.Category.GeoClient)
            {
                msg.SendingGrain = GrainId.NewClientId(msg.SendingAddress.Grain.PrimaryKey, this.siloDetails.ClusterId);
            }

            // Are we overloaded?
            if (this.overloadDetector.Overloaded)
            {
                MessagingStatisticsGroup.OnRejectedMessage(msg);
                Message rejection = this.MessageFactory.CreateRejectionResponse(msg, Message.RejectionTypes.GatewayTooBusy, "Shedding load");
                MessageCenter.TryDeliverToProxy(rejection);
                if (Log.IsEnabled(LogLevel.Debug))
                {
                    Log.Debug("Rejecting a request due to overloading: {0}", msg.ToString());
                }
                loadSheddingCounter.Increment();
                return;
            }

            SiloAddress targetAddress = gateway.TryToReroute(msg);

            msg.SendingSilo = MessageCenter.MyAddress;

            if (targetAddress == null)
            {
                // reroute via Dispatcher
                msg.TargetSilo       = null;
                msg.TargetActivation = null;
                msg.ClearTargetAddress();

                if (msg.TargetGrain.IsSystemTarget)
                {
                    msg.TargetSilo       = MessageCenter.MyAddress;
                    msg.TargetActivation = ActivationId.GetSystemActivation(msg.TargetGrain, MessageCenter.MyAddress);
                }

                MessagingStatisticsGroup.OnMessageReRoute(msg);
                MessageCenter.RerouteMessage(msg);
            }
            else
            {
                // send directly
                msg.TargetSilo = targetAddress;
                MessageCenter.SendMessage(msg);
            }
        }
Esempio n. 4
0
        public void SendResponse(Message request, Response response)
        {
            var message = this.messageFactory.CreateResponseMessage(request);

            EventSourceUtils.EmitEvent(message, OrleansOutsideRuntimeClientEvent.SendResponseAction);
            message.BodyObject = response;

            transport.SendMessage(message);
        }
        private void ReceiveMessage(Message msg)
        {
            EventSourceUtils.EmitEvent(msg, OrleansIncomingMessageAgentEvent.ReceiverMessageAction);
            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 = this.messageFactory.CreateRejectionResponse(msg, 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 == ActivationState.Valid)
                        {
                            // Response messages are not subject to overload checks.
                            if (msg.Direction != Message.Directions.Response)
                            {
                                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 = target.SchedulingContext;
                        }
                        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);
                }
            }
        }
Esempio n. 6
0
        protected virtual void HandleMessage(Message msg, Socket receivedOnSocket)
        {
            EventSourceUtils.EmitEvent(msg, OrleansIncomingMessageAcceptorEvent.HandleMessageAction);
            // See it's a Ping message, and if so, short-circuit it
            object pingObj;
            var    requestContext = msg.RequestContextData;

            if (requestContext != null &&
                requestContext.TryGetValue(RequestContext.PING_APPLICATION_HEADER, out pingObj) &&
                pingObj is bool &&
                (bool)pingObj)
            {
                MessagingStatisticsGroup.OnPingReceive(msg.SendingSilo);

                if (Log.IsEnabled(LogLevel.Trace))
                {
                    Log.Trace("Responding to Ping from {0}", msg.SendingSilo);
                }

                if (!msg.TargetSilo.Equals(MessageCenter.MyAddress)) // got ping that is not destined to me. For example, got a ping to my older incarnation.
                {
                    MessagingStatisticsGroup.OnRejectedMessage(msg);
                    Message rejection = this.MessageFactory.CreateRejectionResponse(msg, Message.RejectionTypes.Unrecoverable,
                                                                                    $"The target silo is no longer active: target was {msg.TargetSilo.ToLongString()}, but this silo is {MessageCenter.MyAddress.ToLongString()}. " +
                                                                                    $"The rejected ping message is {msg}.");
                    MessageCenter.OutboundQueue.SendMessage(rejection);
                }
                else
                {
                    var response = this.MessageFactory.CreateResponseMessage(msg);
                    response.BodyObject = Response.Done;
                    MessageCenter.SendMessage(response);
                }
                return;
            }

            // sniff message headers for directory cache management
            sniffIncomingMessageHandler?.Invoke(msg);

            // Don't process messages that have already timed out
            if (msg.IsExpired)
            {
                msg.DropExpiredMessage(MessagingStatisticsGroup.Phase.Receive);
                return;
            }

            // If we've stopped application message processing, then filter those out now
            // Note that if we identify or add other grains that are required for proper stopping, we will need to treat them as we do the membership table grain here.
            if (MessageCenter.IsBlockingApplicationMessages && (msg.Category == Message.Categories.Application) && !Constants.SystemMembershipTableId.Equals(msg.SendingGrain))
            {
                // We reject new requests, and drop all other messages
                if (msg.Direction != Message.Directions.Request)
                {
                    return;
                }

                MessagingStatisticsGroup.OnRejectedMessage(msg);
                var reject = this.MessageFactory.CreateRejectionResponse(msg, Message.RejectionTypes.Unrecoverable, "Silo stopping");
                MessageCenter.SendMessage(reject);
                return;
            }

            // Make sure the message is for us. Note that some control messages may have no target
            // information, so a null target silo is OK.
            if ((msg.TargetSilo == null) || msg.TargetSilo.Matches(MessageCenter.MyAddress))
            {
                // See if it's a message for a client we're proxying.
                if (MessageCenter.IsProxying && MessageCenter.TryDeliverToProxy(msg))
                {
                    return;
                }

                // Nope, it's for us
                MessageCenter.InboundQueue.PostMessage(msg);
                return;
            }

            if (!msg.TargetSilo.Endpoint.Equals(MessageCenter.MyAddress.Endpoint))
            {
                // If the message is for some other silo altogether, then we need to forward it.
                if (Log.IsEnabled(LogLevel.Trace))
                {
                    Log.Trace("Forwarding message {0} from {1} to silo {2}", msg.Id, msg.SendingSilo, msg.TargetSilo);
                }
                MessageCenter.OutboundQueue.SendMessage(msg);
                return;
            }

            // If the message was for this endpoint but an older epoch, then reject the message
            // (if it was a request), or drop it on the floor if it was a response or one-way.
            if (msg.Direction == Message.Directions.Request)
            {
                MessagingStatisticsGroup.OnRejectedMessage(msg);
                Message rejection = this.MessageFactory.CreateRejectionResponse(msg, Message.RejectionTypes.Transient,
                                                                                string.Format("The target silo is no longer active: target was {0}, but this silo is {1}. The rejected message is {2}.",
                                                                                              msg.TargetSilo.ToLongString(), MessageCenter.MyAddress.ToLongString(), msg));

                // Invalidate the remote caller's activation cache entry.
                if (msg.TargetAddress != null)
                {
                    rejection.AddToCacheInvalidationHeader(msg.TargetAddress);
                }

                MessageCenter.OutboundQueue.SendMessage(rejection);
                if (Log.IsEnabled(LogLevel.Debug))
                {
                    Log.Debug("Rejecting an obsolete request; target was {0}, but this silo is {1}. The rejected message is {2}.",
                              msg.TargetSilo.ToLongString(), MessageCenter.MyAddress.ToLongString(), msg);
                }
            }
        }