public void SendRequest( GrainReference target, InvokeMethodRequest request, TaskCompletionSource <object> context, Action <Message, TaskCompletionSource <object> > callback, string debugContext, InvokeMethodOptions options, string genericArguments = null) { var message = this.messageFactory.CreateMessage(request, options); SendRequestMessage(target, message, context, callback, debugContext, options, genericArguments); }
private void ValidateArguments(IAddressable grain, InvokeMethodRequest invokeMethodRequest) { if (!Equals(this.Grain, grain)) { throw new ArgumentException($"Provided {nameof(IAddressable)} differs from expected value", nameof(grain)); } if (!Equals(this.request, invokeMethodRequest)) { throw new ArgumentException($"Provided {nameof(InvokeMethodRequest)} differs from expected value", nameof(invokeMethodRequest)); } }
public async Task <object> Invoke(MethodInfo method, InvokeMethodRequest request, IGrainMethodInvoker invoker) { try { return(await invoker.Invoke(this, request)); } catch (Exception e) { PrettyConsole.Line("Exception in interceptor"); DeactivateOnIdle(); throw; } }
/// <summary> /// Initializes a new instance of the <see cref="GrainMethodInvoker"/> class. /// </summary> /// <param name="grainContext">The grain.</param> /// <param name="request">The request.</param> /// <param name="rootInvoker">The generated invoker.</param> /// <param name="filters">The invocation interceptors.</param> /// <param name="interfaceToImplementationMapping">The implementation map.</param> public GrainMethodInvoker( IGrainContext grainContext, InvokeMethodRequest request, IGrainMethodInvoker rootInvoker, List <IIncomingGrainCallFilter> filters, InterfaceToImplementationMappingCache interfaceToImplementationMapping) { this.request = request; this.rootInvoker = rootInvoker; this.grainContext = grainContext; this.filters = filters; this.interfaceToImplementationMapping = interfaceToImplementationMapping; }
public async Task MessageTest_TtlUpdatedOnSerialization() { var request = new InvokeMethodRequest(0, 0, 0, null); var message = this.messageFactory.CreateMessage(request, InvokeMethodOptions.None); message.TimeToLive = TimeSpan.FromSeconds(1); await Task.Delay(TimeSpan.FromMilliseconds(500)); var deserializedMessage = RoundTripMessage(message); Assert.NotNull(deserializedMessage.TimeToLive); Assert.InRange(message.TimeToLive.Value, TimeSpan.FromMilliseconds(-1000), TimeSpan.FromMilliseconds(900)); }
/// <summary> /// Invokes the appropriate grain or extension method for the request interface ID and method ID. /// First each extension invoker is tried; if no extension handles the request, then the base /// invoker is used to handle the request. /// The base invoker will throw an appropriate exception if the request is not recognized. /// </summary> /// <param name="grain"></param> /// <param name="request"></param> /// <returns></returns> public Task <object> Invoke(IAddressable grain, InvokeMethodRequest request) { if (extensionMap == null || !extensionMap.ContainsKey(request.InterfaceId)) { throw new InvalidOperationException( String.Format("Extension invoker invoked with an unknown interface ID:{0}.", request.InterfaceId)); } var invoker = extensionMap[request.InterfaceId].Item2; var extension = extensionMap[request.InterfaceId].Item1; return(invoker.Invoke(extension, request)); }
public void SendRequest( GrainReference target, InvokeMethodRequest request, TaskCompletionSource <object> context, string debugContext, InvokeMethodOptions options, string genericArguments = null) { var message = this.messageFactory.CreateMessage(request, options); EventSourceUtils.EmitEvent(message, OrleansInsideRuntimeClientEvent.SendRequestAction); SendRequestMessage(target, message, context, debugContext, options, genericArguments); }
public async Task <object> Invoke(MethodInfo methodInfo, InvokeMethodRequest request, IGrainMethodInvoker invoker) { var initialLastStreamValue = this.lastStreamValue; var result = await invoker.Invoke(this, request); // If the last stream value changed after the invoke, then the stream must have produced a value, double // it for testing purposes. if (this.lastStreamValue != initialLastStreamValue) { this.lastStreamValue *= 2; } return(result); }
public void SendRcRequest( GrainReference target, InvokeMethodRequest request, TaskCompletionSource <object> context, Action <Message, TaskCompletionSource <object> > callback, bool refresh, string debugContext, InvokeMethodOptions options = InvokeMethodOptions.None, string genericArguments = null) { var message = Message.CreateRcRequest(request, refresh); SendRequestMessage(target, message, context, callback, debugContext, InvokeMethodOptions.OneWay, genericArguments); }
public void Message_SerializeBodyTooBig() { var maxBodySize = this.fixture.Services.GetService <IOptions <SiloMessagingOptions> >().Value.MaxMessageBodySize; // Create a request with a ridiculously big argument var arg = new byte[maxBodySize + 1]; var request = new InvokeMethodRequest(0, 0, 0, new[] { arg }); var message = this.messageFactory.CreateMessage(request, InvokeMethodOptions.None); var pipe = new Pipe(new PipeOptions(pauseWriterThreshold: 0)); var writer = pipe.Writer; Assert.Throws <OrleansException>(() => this.messageSerializer.Write(ref writer, message)); }
private async Task <object> Interceptor(MethodInfo targetMethod, InvokeMethodRequest request, IGrain target, IGrainMethodInvoker invoker) { if (targetMethod == null) { throw new ArgumentNullException(nameof(targetMethod)); } var declaringNameSpace = targetMethod.DeclaringType?.Namespace; // Do not intercept Orleans grains or other grains which should not be included in statistics. if (targetMethod.DeclaringType.GetCustomAttribute <ExcludeGrainFromStatisticsAttribute>() != null || declaringNameSpace?.StartsWith("Orleans") == true) { return(await invoker.Invoke(target, request)); } RequestTimings.GetOrCreate(); // Ensure request timings is created here and not in the grain call. RequestTimings.Current.Request.Start(); Exception ex = null; try { return(await invoker.Invoke(target, request)); } catch (Exception e) { ex = e; throw; } finally { RequestTimings.Current.Request.Stop(); var grainEvent = EventPublisher.CreateEvent(); grainEvent.TargetType = targetMethod.DeclaringType?.FullName; grainEvent.TargetMethod = targetMethod.Name; grainEvent.Exception = ex; grainEvent.ErrCode = ex != null ? null : (int?)0; try { EventPublisher.TryPublish(grainEvent); } catch (Exception) { EventsDiscarded.Increment(); } } }
private void RunTest(int numItems) { InvokeMethodRequest request = new InvokeMethodRequest(0, 2, 0, null); Message resp = this.messageFactory.CreateMessage(request, InvokeMethodOptions.None); resp.Id = new CorrelationId(); resp.SendingSilo = SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 200), 0); resp.TargetSilo = SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 300), 0); resp.SendingGrain = GrainId.NewId(); resp.TargetGrain = GrainId.NewId(); resp.IsAlwaysInterleave = true; Assert.True(resp.IsUsingInterfaceVersions); List <object> requestBody = new List <object>(); for (int k = 0; k < numItems; k++) { requestBody.Add(k + ": test line"); } resp.BodyObject = requestBody; string s = resp.ToString(); output.WriteLine(s); var resp1 = RoundTripMessage(resp); //byte[] serialized = resp.FormatForSending(); //Message resp1 = new Message(serialized, serialized.Length); Assert.Equal(resp.Category, resp1.Category); //Category is incorrect" Assert.Equal(resp.Direction, resp1.Direction); //Direction is incorrect Assert.Equal(resp.Id, resp1.Id); //Correlation ID is incorrect Assert.Equal(resp.IsAlwaysInterleave, resp1.IsAlwaysInterleave); //Foo Boolean is incorrect Assert.Equal(resp.CacheInvalidationHeader, resp1.CacheInvalidationHeader); //Bar string is incorrect Assert.True(resp.TargetSilo.Equals(resp1.TargetSilo)); Assert.True(resp.TargetGrain.Equals(resp1.TargetGrain)); Assert.True(resp.SendingGrain.Equals(resp1.SendingGrain)); Assert.True(resp.SendingSilo.Equals(resp1.SendingSilo)); //SendingSilo is incorrect Assert.True(resp1.IsUsingInterfaceVersions); List <object> responseList = Assert.IsAssignableFrom <List <object> >(resp1.BodyObject); Assert.Equal <int>(numItems, responseList.Count); //Body list has wrong number of entries for (int k = 0; k < numItems; k++) { Assert.IsAssignableFrom <string>(responseList[k]); //Body list item " + k + " has wrong type Assert.Equal((string)(requestBody[k]), (string)(responseList[k])); //Body list item " + k + " is incorrect } }
/// <summary> /// Invoke a grain method. /// Invoker classes in generated code implement this method to provide a method call jump-table to map invoke /// data to a strongly typed call to the correct method on the correct interface. /// </summary> /// <param name="grain">Reference to the grain to be invoked.</param> /// <param name="request">The request being invoked.</param> /// <returns>Value promise for the result of the method invoke.</returns> public Task <object> Invoke(IAddressable grain, InvokeMethodRequest request) { // If the grain implements IGrainInvokeInterceptor then call its implementation, passing // the underlying invoker so that the grain can easily dispatch invocation to the correct method. var interceptor = grain as IGrainInvokeInterceptor; if (interceptor != null) { var methodInfo = this.GetMethodInfo(request.MethodId); return(interceptor.Invoke(methodInfo, request, this.invoker)); } // Otherwise, call the underlying invoker directly. return(this.invoker.Invoke(grain, request)); }
/// <summary> /// Initializes a new instance of the <see cref="OutgoingCallInvoker"/> class. /// </summary> /// <param name="grain">The grain reference.</param> /// <param name="request">The request.</param> /// <param name="options"></param> /// <param name="sendRequest"></param> /// <param name="filters">The invocation interceptors.</param> /// <param name="mapping">The implementation map.</param> public OutgoingCallInvoker( GrainReference grain, InvokeMethodRequest request, InvokeMethodOptions options, Func <GrainReference, InvokeMethodRequest, InvokeMethodOptions, Task <object> > sendRequest, InterfaceToImplementationMappingCache mapping, IOutgoingGrainCallFilter[] filters) { this.request = request; this.options = options; this.sendRequest = sendRequest; this.mapping = mapping; this.grainReference = grain; this.filters = filters; }
/// <summary> /// Initializes a new instance of the <see cref="GrainMethodInvoker"/> class. /// </summary> /// <param name="grain">The grain.</param> /// <param name="request">The request.</param> /// <param name="rootInvoker">The generated invoker.</param> /// <param name="filters">The invocation interceptors.</param> /// <param name="interfaceToImplementationMapping">The implementation map.</param> /// <param name="invokeInterceptor">The deprecated silo-wide interceptor.</param> public GrainMethodInvoker( IAddressable grain, InvokeMethodRequest request, IGrainMethodInvoker rootInvoker, List <IGrainCallFilter> filters, InterfaceToImplementationMappingCache interfaceToImplementationMapping, InvokeInterceptor invokeInterceptor) { this.request = request; this.rootInvoker = rootInvoker; this.Grain = grain; this.filters = filters; this.deprecatedInvokeInterceptor = invokeInterceptor; this.interfaceToImplementationMapping = interfaceToImplementationMapping; }
public string Format(MethodInfo targetMethod, InvokeMethodRequest request, IGrain grain) { if (targetMethod == null) { return("Unknown"); } if (grain is TestMessageBasedGrain) { var arg = request.Arguments[0]; return(arg?.GetType().Name ?? $"{targetMethod.Name}(NULL)"); } return(targetMethod.Name); }
public static void Intercept(InvokeMethodRequest request, IGrain grain) { // flow activity.current Activity currentActivity = Activity.Current; if (currentActivity != null) { RequestContext.Set(DiagnosticsLoggingStrings.RequestIdHeaderName, currentActivity.Id); // we expect baggage to be empty or contain a few items var baggage = currentActivity.Baggage.ToArray(); if (baggage.Length > 0) { RequestContext.Set(DiagnosticsLoggingStrings.CorrelationContextHeaderName, baggage); } } }
private Task <object> InvokeMethod_Impl(InvokeMethodRequest request, string debugContext, InvokeMethodOptions options) { if (debugContext == null && USE_DEBUG_CONTEXT) { debugContext = GetDebugContext(this.InterfaceName, GetMethodName(this.InterfaceId, request.MethodId), request.Arguments); } // Call any registered client pre-call interceptor function. CallClientInvokeCallback(request); bool isOneWayCall = ((options & InvokeMethodOptions.OneWay) != 0); var resolver = isOneWayCall ? null : new TaskCompletionSource <object>(); RuntimeClient.Current.SendRequest(this, request, resolver, ResponseCallback, debugContext, options, genericArguments); return(isOneWayCall ? null : resolver.Task); }
public static object Message(this InvokeMethodRequest request) { if (request?.Arguments == null) { return(null); } var receiveMessage = request.Arguments.Length == 1; if (receiveMessage) { return(UnwrapImmutable(request.Arguments[0])); } var streamMessage = request.Arguments.Length == 5; return(streamMessage ? UnwrapImmutable(request.Arguments[2]) : null); }
internal bool MayInterleave(InvokeMethodRequest request) { if (request?.Arguments == null) { return(false); } var receiveMessage = request.Arguments.Length == 1; if (receiveMessage) { return(interleavePredicate(UnwrapImmutable(request.Arguments[0]))); } var streamMessage = request.Arguments.Length == 4; return(streamMessage && interleavePredicate(UnwrapImmutable(request.Arguments[1]))); }
internal static Message CreateRcRequest(InvokeMethodRequest request, bool refresh) { var message = new Message( Categories.Application, Directions.OneWay) { Id = CorrelationId.GetNext(), BodyObject = request, IsAlwaysInterleave = true }; message.SetHeader(Header.RC_MSG, refresh ? ReactiveComputationTypes.KeepAlive : ReactiveComputationTypes.Execute); var contextData = RequestContext.Export(); message.RequestContextData = contextData; return(message); }
// capture stats async Task <object> InvokeInterceptor(MethodInfo targetMethod, InvokeMethodRequest request, IGrain grain, IGrainMethodInvoker invoker) { // round down to nearest 10 seconds to group results var grainName = grain.GetType().FullName; var stopwatch = Stopwatch.StartNew(); // invoke grain object result = null; if (this.innerInterceptor != null) { result = await this.innerInterceptor(targetMethod, request, grain, invoker); } else { result = await invoker.Invoke(grain, request); } stopwatch.Stop(); var elapsedMs = (double)stopwatch.ElapsedTicks / TimeSpan.TicksPerMillisecond; var key = $"{grainName}.{targetMethod?.Name ?? "Unknown"}"; grainTrace.AddOrUpdate(key, _ => { return(new GrainTraceEntry { Count = 1, SiloAddress = siloAddress, ElapsedTime = elapsedMs, Grain = grainName, Method = targetMethod?.Name ?? "Unknown", Period = DateTime.UtcNow }); }, (_, last) => { last.Count += 1; last.ElapsedTime += elapsedMs; return(last); }); return(result); }
/// <summary> /// Adds CancellationToken to the grain extension /// so that it can be canceled through remote call to the CancellationSourcesExtension. /// </summary> /// <param name="target"></param> /// <param name="request"></param> internal static void RegisterCancellationTokens( IGrainContext target, InvokeMethodRequest request) { for (var i = 0; i < request.Arguments.Length; i++) { var arg = request.Arguments[i]; if (!(arg is GrainCancellationToken)) { continue; } var grainToken = ((GrainCancellationToken)request.Arguments[i]); var cancellationExtension = (CancellationSourcesExtension)target.GetGrainExtension <ICancellationSourcesExtension>(); // Replacing the half baked GrainCancellationToken that came from the wire with locally fully created one. request.Arguments[i] = cancellationExtension.RecordCancellationToken(grainToken.Id, grainToken.IsCancellationRequested); } }
private Task <object> InvokeWithInterceptors(IAddressable target, InvokeMethodRequest request, IGrainMethodInvoker invoker) { // If the target has a grain-level interceptor or there is a silo-level interceptor, intercept the // call. var siloWideInterceptor = SiloProviderRuntime.Instance.GetInvokeInterceptor(); var grainWithInterceptor = target as IGrainInvokeInterceptor; // Silo-wide interceptors do not operate on system targets. var hasSiloWideInterceptor = siloWideInterceptor != null && target is IGrain; var hasGrainLevelInterceptor = grainWithInterceptor != null; if (!hasGrainLevelInterceptor && !hasSiloWideInterceptor) { // The call is not intercepted at either the silo or the grain level, so call the invoker // directly. return(invoker.Invoke(target, request)); } // Get an invoker which delegates to the grain's IGrainInvocationInterceptor implementation. // If the grain does not implement IGrainInvocationInterceptor, then the invoker simply delegates // calls to the provided invoker. var interceptedMethodInvoker = interceptedMethodInvokerCache.GetOrCreate( target.GetType(), request.InterfaceId, invoker); var methodInfo = interceptedMethodInvoker.GetMethodInfo(request.MethodId); if (hasSiloWideInterceptor) { // There is a silo-level interceptor and possibly a grain-level interceptor. // As a minor optimization, only pass the intercepted invoker if there is a grain-level // interceptor. return(siloWideInterceptor( methodInfo, request, (IGrain)target, hasGrainLevelInterceptor ? interceptedMethodInvoker : invoker)); } // The grain has an invoke method, but there is no silo-wide interceptor. return(grainWithInterceptor.Invoke(methodInfo, request, invoker)); }
private void HandleReactiveComputationExecute(IAddressable target, InvokeMethodRequest request, Message message, IGrainMethodInvoker invoker, bool refresh = false) { // Fetch the method info for the intercepted call. var interceptedMethodInvoker = interceptedMethodInvokerCache.GetOrCreate( target.GetType(), request.InterfaceId, invoker); var methodInfo = interceptedMethodInvoker.GetMethodInfo(request.MethodId); Type arg_type = methodInfo.ReturnType.GenericTypeArguments[0]; Type class_type = typeof(InsideRuntimeClient); MethodInfo mi = class_type.GetMethod("StartQuery"); MethodInfo mi2 = mi.MakeGenericMethod(new Type[] { arg_type }); logger.Info("{0} # Received Summary Initiation/Subscription for {1} from {2}", CurrentActivationAddress, request, message.SendingActivation); var activationKey = RcUtils.GetRawActivationKey(CurrentGrain); mi2.Invoke(this, new object[] { activationKey, target, request, invoker, message, refresh }); }
public void Message_SerializeHeaderTooBig() { try { // Create a ridiculously big RequestContext var maxHeaderSize = this.fixture.Services.GetService <IOptions <SiloMessagingOptions> >().Value.MaxMessageHeaderSize; RequestContext.Set("big_object", new byte[maxHeaderSize + 1]); var request = new InvokeMethodRequest(0, 0, 0, null); var message = this.messageFactory.CreateMessage(request, InvokeMethodOptions.None); var pipe = new Pipe(new PipeOptions(pauseWriterThreshold: 0)); var writer = pipe.Writer; Assert.Throws <OrleansException>(() => this.messageSerializer.Write(ref writer, message)); } finally { RequestContext.Clear(); } }
public static string Format(MethodInfo method, InvokeMethodRequest request, IGrain grain) { if (method == null) { return("Unknown"); } if (!(grain is IActorEndpoint)) { return(method.Name); } if (method.Name != nameof(IActorEndpoint.Receive) && method.Name != nameof(IActorEndpoint.ReceiveVoid) && method.Name != nameof(IActorEndpoint.Notify)) { return(method.Name); } return(request.Arguments[0]?.GetType().Name ?? $"{method.Name}(NULL)"); }
public Message CreateMessage(InvokeMethodRequest request, InvokeMethodOptions options) { var direction = (options & InvokeMethodOptions.OneWay) != 0 ? Message.Directions.OneWay : Message.Directions.Request; var message = new Message { Category = Message.Categories.Application, Direction = direction, Id = CorrelationId.GetNext(), IsReadOnly = (options & InvokeMethodOptions.ReadOnly) != 0, IsUnordered = (options & InvokeMethodOptions.Unordered) != 0, BodyObject = request }; if ((options & InvokeMethodOptions.AlwaysInterleave) != 0) { message.IsAlwaysInterleave = true; } message.RequestContextData = RequestContext.Export(); return(message); }
public async Task <object> Invoke(MethodInfo methodInfo, InvokeMethodRequest request, IGrainMethodInvoker invoker) { if (methodInfo.Name == nameof(One) && methodInfo.GetParameters().Length == 0) { return("intercepted one with no args"); } var result = await invoker.Invoke(this, request); // To prove that the MethodInfo is from the implementation and not the interface, // we check for this attribute which is only present on the implementation. This could be // done in a simpler fashion, but this demonstrates a potential usage scenario. var shouldMessWithResult = methodInfo.GetCustomAttribute <MessWithResultAttribute>(); var resultString = result as string; if (shouldMessWithResult != null && resultString != null) { result = string.Concat(resultString.Reverse()); } return(result); }
/// <summary> /// Called from generated code. /// </summary> protected async Task <T> InvokeMethodAsync <T>(int methodId, object[] arguments, InvokeMethodOptions options = InvokeMethodOptions.None, SiloAddress silo = null) { CheckForGrainArguments(arguments); var argsDeepCopy = (object[])SerializationManager.DeepCopy(arguments); var request = new InvokeMethodRequest(this.InterfaceId, methodId, argsDeepCopy); if (IsUnordered) { options |= InvokeMethodOptions.Unordered; } Task <object> resultTask = InvokeMethod_Impl(request, null, options); if (resultTask == null) { return(default(T)); } resultTask = OrleansTaskExtentions.ConvertTaskViaTcs(resultTask); return((T)await resultTask); }