/// <summary>
 /// Maps the interfaces of the provided <paramref name="implementationType"/>.
 /// </summary>
 /// <param name="implementationType">The implementation type.</param>
 /// <param name="invoker">The grain method invoker.</param>
 /// <returns>The mapped interface.</returns>
 private static Dictionary<int, InterceptedMethodInvoker> CreateInterfaceToImplementationMap(
     Type implementationType,
     IGrainMethodInvoker invoker)
 {
     if (implementationType.IsConstructedGenericType) return CreateMapForConstructedGeneric(implementationType, invoker);
     return CreateMapForNonGeneric(implementationType, invoker);
 }
예제 #2
0
 internal LocalObjectData(IAddressable obj, GuidId observerId, IGrainMethodInvoker invoker)
 {
     LocalObject = new WeakReference(obj);
     ObserverId  = observerId;
     Invoker     = invoker;
     Messages    = new Queue <Message>();
     Running     = false;
 }
예제 #3
0
 public GrainReference CreateObjectReference(IAddressable obj, IGrainMethodInvoker invoker)
 {
     if (RuntimeContext.Current == null)
     {
         return(this.HostedClient.CreateObjectReference(obj, invoker));
     }
     throw new InvalidOperationException("Cannot create a local object reference from a grain.");
 }
예제 #4
0
 internal LocalObjectData(IAddressable obj, GrainId grain, IGrainMethodInvoker invoker)
 {
     LocalObject = new WeakReference(obj);
     Grain       = grain;
     Invoker     = invoker;
     Messages    = new Queue <Message>();
     Running     = false;
 }
예제 #5
0
 public async static System.Threading.Tasks.Task <IClientObserver> CreateObjectReference(IClientObserver obj)
 {
     if (methodInvoker == null)
     {
         methodInvoker = new ClientObserverMethodInvoker();
     }
     return(ClientObserverFactory.Cast(await GrainReference.CreateObjectReference(obj, methodInvoker)));
 }
예제 #6
0
 internal LocalObjectData(IAddressable obj, ObserverGrainId observerId, IGrainMethodInvoker invoker)
 {
     this.LocalObject = new WeakReference(obj);
     this.ObserverId  = observerId;
     this.Invoker     = invoker;
     this.Messages    = new Queue <Message>();
     this.Running     = false;
 }
예제 #7
0
        internal bool TryAddExtension(IGrainExtensionMethodInvoker invoker, IGrainExtension extension)
        {
            this.lastInvoker = null;
            if (extensionInvoker == null)
            {
                extensionInvoker = new ExtensionInvoker();
            }

            return(extensionInvoker.TryAddExtension(invoker, extension));
        }
예제 #8
0
 /// <summary>
 /// Maps the interfaces of the provided <paramref name="implementationType"/>.
 /// </summary>
 /// <param name="implementationType">The implementation type.</param>
 /// <param name="invoker">The grain method invoker.</param>
 /// <returns>The mapped interface.</returns>
 private static Dictionary <int, InterceptedMethodInvoker> CreateInterfaceToImplementationMap(
     Type implementationType,
     IGrainMethodInvoker invoker)
 {
     if (implementationType.IsConstructedGenericType)
     {
         return(CreateMapForConstructedGeneric(implementationType, invoker));
     }
     return(CreateMapForNonGeneric(implementationType, invoker));
 }
예제 #9
0
        public IGrainMethodInvoker GetInvoker(GrainTypeManager typeManager, int interfaceId, string genericGrainType = null)
        {
            if (lastInvoker != null && interfaceId == lastInvoker.InterfaceId)
                return lastInvoker;

            var invoker = typeManager.GetInvoker(interfaceId);
            lastInvoker = invoker;
            
            return lastInvoker;
        }
예제 #10
0
 /// <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>
 public GrainMethodInvoker(
     IAddressable grain,
     InvokeMethodRequest request,
     IGrainMethodInvoker rootInvoker,
     List <IIncomingGrainCallFilter> filters,
     InterfaceToImplementationMappingCache interfaceToImplementationMapping)
 {
     this.request     = request;
     this.rootInvoker = rootInvoker;
     this.Grain       = grain;
     this.filters     = filters;
     this.interfaceToImplementationMapping = interfaceToImplementationMapping;
 }
예제 #11
0
        public IGrainMethodInvoker GetInvoker(GrainTypeManager typeManager, int interfaceId, string genericGrainType = null)
        {
            if (lastInvoker != null && interfaceId == lastInvoker.InterfaceId)
            {
                return(lastInvoker);
            }

            var invoker = typeManager.GetInvoker(interfaceId);

            lastInvoker = invoker;

            return(lastInvoker);
        }
예제 #12
0
        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;
        }
예제 #13
0
 internal void RemoveExtension(IGrainExtension extension)
 {
     this.lastInvoker = null;
     if (extensionInvoker != null)
     {
         if (extensionInvoker.Remove(extension))
         {
             extensionInvoker = null;
         }
     }
     else
     {
         throw new InvalidOperationException("Grain extensions not installed.");
     }
 }
예제 #14
0
        public GrainReference CreateObjectReference(IAddressable obj, IGrainMethodInvoker invoker)
        {
            if (obj is GrainReference)
            {
                throw new ArgumentException("Argument obj is already a grain reference.");
            }

            GrainReference gr = GrainReference.NewObserverGrainReference(clientId, GuidId.GetNewGuidId());

            if (!localObjects.TryAdd(gr.ObserverId, new LocalObjectData(obj, gr.ObserverId, invoker)))
            {
                throw new ArgumentException(String.Format("Failed to add new observer {0} to localObjects collection.", gr), "gr");
            }
            return(gr);
        }
예제 #15
0
        public async Task <GrainReference> CreateObjectReference(IAddressable obj, IGrainMethodInvoker invoker)
        {
            if (obj is GrainReference)
            {
                throw new ArgumentException("Argument obj is already a grain reference.");
            }

            GrainId target = GrainId.NewClientAddressableGrainId();
            await transport.RegisterObserver(target);

            lock (localObjects)
            {
                localObjects.Add(target, new LocalObjectData(obj, target, invoker));
            }
            return(GrainReference.FromGrainId(target));
        }
        /// <summary>
        /// Returns a grain method invoker which calls the grain's implementation of <see cref="IGrainInvokeInterceptor"/>
        /// if it exists, otherwise calling the provided <paramref name="invoker"/> directly.
        /// </summary>
        /// <param name="implementationType">The grain type.</param>
        /// <param name="interfaceId">The interface id.</param>
        /// <param name="invoker">
        /// The underlying invoker, which will be passed to the grain's <see cref="IGrainInvokeInterceptor.Invoke"/>
        /// method.
        /// </param>
        /// <returns>
        /// A grain method invoker which calls the grain's implementation of <see cref="IGrainInvokeInterceptor"/>.
        /// </returns>
        public InterceptedMethodInvoker GetOrCreate(Type implementationType, int interfaceId, IGrainMethodInvoker invoker)
        {
            var implementation = invokers.GetOrAdd(
                implementationType,
                _ => new ConcurrentDictionary<int, InterceptedMethodInvoker>());

            InterceptedMethodInvoker interceptedMethodInvoker;
            if (implementation.TryGetValue(interfaceId, out interceptedMethodInvoker))
            {
                return interceptedMethodInvoker;
            }

            // Create a mapping between the interface and the implementation.
            return implementation.GetOrAdd(
                interfaceId,
                _ => CreateInterceptedMethodInvoker(implementationType, interfaceId, invoker));
        }
        /// <summary>
        /// Creates and returns a map from interface id to intercepted invoker for non-generic or open-generic types.
        /// </summary>
        /// <param name="implementationType">The implementation type.</param>
        /// <param name="invoker">The underlying invoker.</param>
        /// <returns>A map from interface id to intercepted invoker.</returns>
        private static Dictionary<int, InterceptedMethodInvoker> CreateMapForNonGeneric(Type implementationType, IGrainMethodInvoker invoker)
        {
            if (implementationType.IsConstructedGenericType)
            {
                throw new InvalidOperationException(
                    $"Type {implementationType} passed to {nameof(CreateMapForNonGeneric)} is a constructed generic type.");
            }

            var implementationTypeInfo = implementationType.GetTypeInfo();
            var interfaces = implementationType.GetInterfaces();

            // Create an invoker for every interface on the provided type.
            var result = new Dictionary<int, InterceptedMethodInvoker>(interfaces.Length);
            foreach (var iface in interfaces)
            {
                var methods = GrainInterfaceUtils.GetMethods(iface);

                // Map every method on this interface from the definition interface onto the implementation class.
                var methodMap = new Dictionary<int, MethodInfo>(methods.Length);
                var mapping = default(InterfaceMapping);
                foreach (var method in methods)
                {
                    // If this method is not from the expected interface (eg, because it's from a parent interface), then
                    // get the mapping for the interface which it does belong to.
                    if (mapping.InterfaceType != method.DeclaringType)
                    {
                        mapping = implementationTypeInfo.GetRuntimeInterfaceMap(method.DeclaringType);
                    }

                    // Find the index of the interface method and then get the implementation method at that position.
                    for (var k = 0; k < mapping.InterfaceMethods.Length; k++)
                    {
                        if (mapping.InterfaceMethods[k] != method) continue;
                        methodMap[GrainInterfaceUtils.ComputeMethodId(method)] = mapping.TargetMethods[k];
                        break;
                    }
                }

                // Add the resulting map of methodId -> method to the interface map.
                var interfaceId = GrainInterfaceUtils.GetGrainInterfaceId(iface);
                result[interfaceId] = new InterceptedMethodInvoker(invoker, methodMap);
            }

            return result;
        }
예제 #18
0
        /// <inheritdoc />
        public GrainReference CreateObjectReference(IAddressable obj, IGrainMethodInvoker invoker)
        {
            if (obj is GrainReference)
            {
                throw new ArgumentException("Argument obj is already a grain reference.");
            }

            var grainReference = GrainReference.NewObserverGrainReference(this.ClientAddress.Grain, GuidId.GetNewGuidId(), this.grainReferenceRuntime);

            if (!this.invokableObjects.TryRegister(obj, grainReference.ObserverId, invoker))
            {
                throw new ArgumentException(
                          string.Format("Failed to add new observer {0} to localObjects collection.", grainReference),
                          nameof(grainReference));
            }

            return(grainReference);
        }
 public OrleansRequesterMiddleware(OcelotRequestDelegate next,
                                   IClusterClientBuilder clusterClientBuilder,
                                   IGrainReference grainReference,
                                   IGrainMethodInvoker grainInvoker,
                                   IRouteValuesBuilder routeValuesBuilder,
                                   IOptions <OrleansRequesterConfiguration> config,
                                   IOrleansAuthorisation authorisation,
                                   IOcelotLoggerFactory loggerFactory)
     : base(loggerFactory.CreateLogger <OrleansRequesterMiddleware>())
 {
     this._clusterClientBuilder = clusterClientBuilder;
     this._grainReference       = grainReference;
     this._grainInvoker         = grainInvoker;
     this._routeValuesBuilder   = routeValuesBuilder;
     this._logger        = loggerFactory.CreateLogger <OrleansRequesterMiddleware>();
     this._config        = config?.Value;
     this._authorisation = authorisation;
     this._next          = next;
 }
예제 #20
0
            public IGrainMethodInvoker GetInvoker(string genericGrainType = null)
            {
                if (String.IsNullOrEmpty(genericGrainType))
                {
                    return(invoker ?? (invoker = (IGrainMethodInvoker)Activator.CreateInstance(baseInvokerType)));
                }

                if (cachedGenericInvokers.ContainsKey(genericGrainType))
                {
                    return(cachedGenericInvokers[genericGrainType]);
                }

                var typeArgs     = TypeUtils.GenericTypeArgs(genericGrainType);
                var concreteType = baseInvokerType.MakeGenericType(typeArgs);
                var inv          = (IGrainMethodInvoker)Activator.CreateInstance(concreteType);

                cachedGenericInvokers[genericGrainType] = inv;
                return(inv);
            }
예제 #21
0
        // 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>
        /// Returns a new <see cref="InterceptedMethodInvoker"/> for the provided values.
        /// </summary>
        /// <param name="implementationType">The grain type.</param>
        /// <param name="interfaceId">The interface id.</param>
        /// <param name="invoker">The invoker.</param>
        /// <returns>A new <see cref="InterceptedMethodInvoker"/> for the provided values.</returns>
        private static InterceptedMethodInvoker CreateInterceptedMethodInvoker(
            Type implementationType,
            int interfaceId,
            IGrainMethodInvoker invoker)
        {
            // If a grain extension is being invoked, the implementation map must match the methods on the extension
            // and not the grain implementation.
            var extensionMap = invoker as IGrainExtensionMap;
            if (extensionMap != null)
            {
                IGrainExtension extension;
                if (extensionMap.TryGetExtension(interfaceId, out extension))
                {
                    implementationType = extension.GetType();
                }
            }

            var implementationMap = GetInterfaceToImplementationMap(interfaceId, implementationType);
            return new InterceptedMethodInvoker(invoker, implementationMap);
        }
        /// <summary>
        /// Returns a grain method invoker which calls the grain's implementation of <see cref="IGrainInvokeInterceptor"/>
        /// if it exists, otherwise calling the provided <paramref name="invoker"/> directly.
        /// </summary>
        /// <param name="implementationType">The grain type.</param>
        /// <param name="interfaceId">The interface id.</param>
        /// <param name="invoker">
        /// The underlying invoker, which will be passed to the grain's <see cref="IGrainInvokeInterceptor.Invoke"/>
        /// method.
        /// </param>
        /// <returns>
        /// A grain method invoker which calls the grain's implementation of <see cref="IGrainInvokeInterceptor"/>.
        /// </returns>
        public InterceptedMethodInvoker GetOrCreate(Type implementationType, int interfaceId, IGrainMethodInvoker invoker)
        {
            // Get or create the mapping between interfaceId and invoker for the provided type.
            Dictionary<int, InterceptedMethodInvoker> invokerMap;
            if (!this.invokers.TryGetValue(implementationType, out invokerMap))
            {
                // Generate an the invoker mapping using the provided invoker.
                this.invokers[implementationType] = invokerMap = CreateInterfaceToImplementationMap(implementationType, invoker);
            }

            // Attempt to get the invoker for the provided interfaceId.
            InterceptedMethodInvoker interceptedMethodInvoker;
            if (!invokerMap.TryGetValue(interfaceId, out interceptedMethodInvoker))
            {
                throw new InvalidOperationException(
                    $"Type {implementationType} does not implement interface with id {interfaceId} ({interfaceId:X}).");
            }

            return interceptedMethodInvoker;
        }
예제 #24
0
        public GrainReference CreateObjectReference(IAddressable obj, IGrainMethodInvoker invoker)
        {
            if (obj is GrainReference)
            {
                throw new ArgumentException("Argument obj is already a grain reference.", nameof(obj));
            }

            if (obj is Grain)
            {
                throw new ArgumentException("Argument must not be a grain class.", nameof(obj));
            }

            GrainReference gr = GrainReference.NewObserverGrainReference(clientId, GuidId.GetNewGuidId(), this.GrainReferenceRuntime);

            if (!localObjects.TryRegister(obj, gr.ObserverId, invoker))
            {
                throw new ArgumentException(String.Format("Failed to add new observer {0} to localObjects collection.", gr), "gr");
            }
            return(gr);
        }
예제 #25
0
        public IGrainMethodInvoker GetInvoker(int interfaceId, string genericGrainType = null)
        {
            // Return previous cached invoker, if applicable
            if (lastInvoker != null && interfaceId == lastInvoker.InterfaceId) // extension invoker returns InterfaceId==0, so this condition will never be true if an extension is installed
            {
                return(lastInvoker);
            }

            if (extensionInvoker != null && extensionInvoker.IsExtensionInstalled(interfaceId)) // HasExtensionInstalled(interfaceId)
            // Shared invoker for all extensions installed on this grain
            {
                lastInvoker = extensionInvoker;
            }
            else
            {
                // Find the specific invoker for this interface / grain type
                lastInvoker = RuntimeClient.Current.GetInvoker(interfaceId, genericGrainType);
            }

            return(lastInvoker);
        }
예제 #26
0
        public GrainReference CreateObjectReference(IAddressable obj, IGrainMethodInvoker invoker)
        {
            if (obj is GrainReference)
            {
                throw new ArgumentException("Argument obj is already a grain reference.", nameof(obj));
            }

            if (obj is Grain)
            {
                throw new ArgumentException("Argument must not be a grain class.", nameof(obj));
            }

            var            observerId = ObserverGrainId.Create(this.clientId);
            GrainReference reference  = GrainReference.NewObserverGrainReference(observerId, this.GrainReferenceRuntime);

            if (!localObjects.TryRegister(obj, observerId, invoker))
            {
                throw new ArgumentException($"Failed to add new observer {reference} to localObjects collection.", "reference");
            }
            return(reference);
        }
예제 #27
0
        public async Task<object> Invoke(MethodInfo methodInfo, InvokeMethodRequest request, IGrainMethodInvoker invoker)
        {
            if (methodInfo.Name == "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;
        }
예제 #28
0
        IGrainMethodInvoker IInvokable.GetInvoker(GrainTypeManager typeManager, int interfaceId, string genericGrainType)
        {
            // Return previous cached invoker, if applicable
            if (lastInvoker != null && interfaceId == lastInvoker.InterfaceId) // extension invoker returns InterfaceId==0, so this condition will never be true if an extension is installed
            {
                return(lastInvoker);
            }

            if (extensionInvoker != null && extensionInvoker.IsExtensionInstalled(interfaceId))
            {
                // Shared invoker for all extensions installed on this target
                lastInvoker = extensionInvoker;
            }
            else
            {
                // Find the specific invoker for this interface / grain type
                lastInvoker = typeManager.GetInvoker(interfaceId, genericGrainType);
            }

            return(lastInvoker);
        }
예제 #29
0
            public IGrainMethodInvoker GetInvoker(string genericGrainType = null)
            {
                // if the grain class is non-generic
                if (!this.isGeneric)
                {
                    return(invoker ?? (invoker = (IGrainMethodInvoker)Activator.CreateInstance(baseInvokerType)));
                }

                if (this.cachedGenericInvokers.TryGetValue(genericGrainType, out IGrainMethodInvoker result))
                {
                    return(result);
                }

                var typeArgs     = TypeUtils.GenericTypeArgsFromArgsString(genericGrainType);
                var concreteType = this.baseInvokerType.MakeGenericType(typeArgs);
                var inv          = (IGrainMethodInvoker)Activator.CreateInstance(concreteType);

                this.cachedGenericInvokers.TryAdd(genericGrainType, inv);

                return(inv);
            }
예제 #30
0
        public OrleansHttpGatewayMiddleware(RequestDelegate next,
                                            IOptions <OrleansHttpGatewayOptions> config,
                                            JsonSerializer serializer,
                                            IGrainBuilder grainBuilder,
                                            IGrainMethodInvoker grainMethodInvoker,
                                            IRouteDataResolve routeDataResolve,
                                            ILogger <OrleansHttpGatewayMiddleware> logger)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            this._routeDataResolve = routeDataResolve;
            this._options          = config.Value;
            this._grainBuilder     = grainBuilder ?? throw new ArgumentNullException(nameof(grainBuilder));
            this._grainInvoker     = grainMethodInvoker;
            this._logger           = logger;
            _serializer            = serializer;
            _next = next;
        }
        /// <summary>
        /// Returns a new <see cref="InterceptedMethodInvoker"/> for the provided values.
        /// </summary>
        /// <param name="implementationType">The grain type.</param>
        /// <param name="interfaceId">The interface id.</param>
        /// <param name="invoker">The invoker.</param>
        /// <returns>A new <see cref="InterceptedMethodInvoker"/> for the provided values.</returns>
        private static InterceptedMethodInvoker CreateInterceptedMethodInvoker(
            Type implementationType,
            int interfaceId,
            IGrainMethodInvoker invoker)
        {
            // If a grain extension is being invoked, the implementation map must match the methods on the extension
            // and not the grain implementation.
            var extensionMap = invoker as IGrainExtensionMap;

            if (extensionMap != null)
            {
                IGrainExtension extension;
                if (extensionMap.TryGetExtension(interfaceId, out extension))
                {
                    implementationType = extension.GetType();
                }
            }

            var implementationMap = GetInterfaceToImplementationMap(interfaceId, implementationType);

            return(new InterceptedMethodInvoker(invoker, implementationMap));
        }
예제 #32
0
 public async static System.Threading.Tasks.Task<IClientObserver> CreateObjectReference(IClientObserver obj)
 {
     if (methodInvoker == null) methodInvoker = new ClientObserverMethodInvoker();
     return ClientObserverFactory.Cast(await GrainReference.CreateObjectReference(obj, methodInvoker));
 }
예제 #33
0
        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);
        }
예제 #34
0
 public async static System.Threading.Tasks.Task<IObserve> CreateObjectReference(IObserve obj)
 {
     if (methodInvoker == null) methodInvoker = new ObserveMethodInvoker();
     return ObserveFactory.Cast(await GrainReference.CreateObjectReference(obj, methodInvoker));
 }
예제 #35
0
 public GrainReference CreateObjectReference(IAddressable obj, IGrainMethodInvoker invoker)
 {
     throw new InvalidOperationException("Cannot create a local object reference from a grain.");
 }
예제 #36
0
            public IGrainMethodInvoker GetInvoker(string genericGrainType = null)
            {
                // if the grain class is non-generic
                if (cachedGenericInvokersLockObj == null)
                {
                    return invoker ?? (invoker = (IGrainMethodInvoker)Activator.CreateInstance(baseInvokerType));
                }
                else
                {
                    lock (cachedGenericInvokersLockObj)
                    {
                        if (cachedGenericInvokers.ContainsKey(genericGrainType))
                            return cachedGenericInvokers[genericGrainType];
                    }
                    var typeArgs = TypeUtils.GenericTypeArgsFromArgsString(genericGrainType);
                    var concreteType = baseInvokerType.MakeGenericType(typeArgs);
                    var inv = (IGrainMethodInvoker)Activator.CreateInstance(concreteType);

                    lock (cachedGenericInvokersLockObj)
                    {
                        if (!cachedGenericInvokers.ContainsKey(genericGrainType))
                            cachedGenericInvokers[genericGrainType] = inv;
                    }

                    return inv;
                }
            }
예제 #37
0
        public Task <object> Invoke(MethodInfo methodInfo, InvokeMethodRequest request, IGrainMethodInvoker invoker)
        {
            if (methodInfo.Name == nameof(GetInputAsString))
            {
                return(Task.FromResult <object>($"Hah! You wanted {request.Arguments[0]}, but you got me!"));
            }

            return(invoker.Invoke(this, request));
        }
예제 #38
0
        public GrainReference CreateObjectReference(IAddressable obj, IGrainMethodInvoker invoker)
        {
            if (obj is GrainReference)
                throw new ArgumentException("Argument obj is already a grain reference.");

            GrainReference gr = GrainReference.NewObserverGrainReference(clientId, GuidId.GetNewGuidId());
            if (!localObjects.TryAdd(gr.ObserverId, new LocalObjectData(obj, gr.ObserverId, invoker)))
            {
                throw new ArgumentException(String.Format("Failed to add new observer {0} to localObjects collection.", gr), "gr");
            }
            return gr;
        }
        // capture stats
        async Task<object> InvokeInterceptor(MethodInfo targetMethod, InvokeMethodRequest request, IGrain grain, IGrainMethodInvoker invoker)
        {
            var grainName = grain.GetType().FullName;
            var stopwatch = Stopwatch.StartNew();

            // invoke grain
            object result = null;
            var isException = false;

            try
            {
                if (this.innerInterceptor != null)
                {
                    result = await this.innerInterceptor(targetMethod, request, grain, invoker);
                }
                else
                {
                    result = await invoker.Invoke(grain, request);
                }
            }
            catch (Exception ex)
            {
                isException = true;
                throw;
            }
            finally
            {

                try
                {
                    stopwatch.Stop();

                    var elapsedMs = (double)stopwatch.ElapsedTicks / TimeSpan.TicksPerMillisecond;

                    var key = string.Format("{0}.{1}", grainName, targetMethod?.Name ?? "Unknown");

                    grainTrace.AddOrUpdate(key, _ =>
                    {
                        return new GrainTraceEntry
                        {
                            Count = 1,
                            ExceptionCount = (isException ? 1 : 0),
                            SiloAddress = siloAddress,
                            ElapsedTime = elapsedMs,
                            Grain = grainName ,
                            Method = targetMethod?.Name ?? "Unknown",
                            Period = DateTime.UtcNow
                        };
                    },
                    (_, last) =>
                    {
                        last.Count += 1;
                        last.ElapsedTime += elapsedMs;
                        if (isException) last.ExceptionCount += 1;
                        return last;
                    });
                }
                catch (Exception ex)
                {
                    this.Logger.Error(100002, "error recording results for grain", ex);
                }
            }

            return result;
        }
예제 #40
0
 public InterceptedMethodInvoker(IGrainMethodInvoker invoker, IReadOnlyDictionary<int, MethodInfo> methodInfos)
 {
     this.invoker = invoker;
     this.methodInfos = methodInfos;
 }
예제 #41
0
        // capture stats
        async Task <object> InvokeInterceptor(MethodInfo targetMethod, InvokeMethodRequest request, IGrain grain, IGrainMethodInvoker invoker)
        {
            var grainName = grain.GetType().FullName;
            var stopwatch = Stopwatch.StartNew();

            // invoke grain
            object result      = null;
            var    isException = false;

            try
            {
                if (this.innerInterceptor != null)
                {
                    result = await this.innerInterceptor(targetMethod, request, grain, invoker).ConfigureAwait(false);
                }
                else
                {
                    result = await invoker.Invoke(grain, request).ConfigureAwait(false);
                }
            }
            catch (Exception)
            {
                isException = true;
                throw;
            }
            finally
            {
                try
                {
                    stopwatch.Stop();

                    var elapsedMs = (double)stopwatch.ElapsedTicks / TimeSpan.TicksPerMillisecond;

                    var key = string.Format("{0}.{1}", grainName, formatMethodName(targetMethod, request, grain));

                    grainTrace.AddOrUpdate(key, _ =>
                    {
                        return(new GrainTraceEntry
                        {
                            Count = 1,
                            ExceptionCount = (isException ? 1 : 0),
                            SiloAddress = siloAddress,
                            ElapsedTime = elapsedMs,
                            Grain = grainName,
                            Method = formatMethodName(targetMethod, request, grain),
                            Period = DateTime.UtcNow
                        });
                    },
                                           (_, last) =>
                    {
                        last.Count       += 1;
                        last.ElapsedTime += elapsedMs;
                        if (isException)
                        {
                            last.ExceptionCount += 1;
                        }
                        return(last);
                    });
                }
                catch (Exception ex)
                {
                    this.Logger.Error(100002, "error recording results for grain", ex);
                }
            }

            return(result);
        }
예제 #42
0
        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  = this.CurrentStreamProviderRuntime.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));
            }

            // If the request is intended for an extension object, use that as the implementation type, otherwise use
            // the target object.
            Type            implementationType;
            var             extensionMap = invoker as IGrainExtensionMap;
            IGrainExtension extension;

            if (extensionMap != null && extensionMap.TryGetExtension(request.InterfaceId, out extension))
            {
                implementationType = extension.GetType();
            }
            else
            {
                implementationType = target.GetType();
            }

            // 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(
                implementationType,
                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));
        }
예제 #43
0
 public GrainReference CreateObjectReference(IAddressable obj, IGrainMethodInvoker invoker)
 {
     throw new InvalidOperationException("Cannot create a local object reference from a grain.");
 }
예제 #44
0
 /// <summary>
 /// Called from generated code.
 /// </summary>
 public static Task <GrainReference> CreateObjectReference(IAddressable o, IGrainMethodInvoker invoker)
 {
     return(Task.FromResult(RuntimeClient.Current.CreateObjectReference(o, invoker)));
 }
예제 #45
0
        public IGrainMethodInvoker GetInvoker(int interfaceId, string genericGrainType=null)
        {
            // Return previous cached invoker, if applicable
            if (lastInvoker != null && interfaceId == lastInvoker.InterfaceId) // extension invoker returns InterfaceId==0, so this condition will never be true if an extension is installed
                return lastInvoker;

            if (extensionInvoker != null && extensionInvoker.IsExtensionInstalled(interfaceId)) // HasExtensionInstalled(interfaceId)
                // Shared invoker for all extensions installed on this grain
                lastInvoker = extensionInvoker;
            else
                // Find the specific invoker for this interface / grain type
                lastInvoker = RuntimeClient.Current.GetInvoker(interfaceId, genericGrainType);

            return lastInvoker;
        }
예제 #46
0
 internal LocalObjectData(IAddressable obj, GuidId observerId, IGrainMethodInvoker invoker)
 {
     LocalObject = new WeakReference(obj);
     ObserverId = observerId;
     Invoker = invoker;
     Messages = new Queue<Message>();
     Running = false;
 }
예제 #47
0
            public IGrainMethodInvoker GetInvoker(string genericGrainType = null)
            {
                if (String.IsNullOrEmpty(genericGrainType))
                    return invoker ?? (invoker = (IGrainMethodInvoker) Activator.CreateInstance(baseInvokerType));
                lock (cachedGenericInvokersLockObj)
                {
                    if (cachedGenericInvokers.ContainsKey(genericGrainType))
                        return cachedGenericInvokers[genericGrainType];
                }

                var typeArgs = TypeUtils.GenericTypeArgs(genericGrainType);
                var concreteType = baseInvokerType.MakeGenericType(typeArgs);
                var inv = (IGrainMethodInvoker) Activator.CreateInstance(concreteType);
                lock (cachedGenericInvokersLockObj)
                {
                    if (!cachedGenericInvokers.ContainsKey(genericGrainType))
                        cachedGenericInvokers[genericGrainType] = inv;
                }

                return inv;
            }
예제 #48
0
        private bool TryInstallExtension(int interfaceId, IInvokable invokable, string genericGrainType, ref IGrainMethodInvoker invoker)
        {
            IGrainExtension extension = TryGetCurrentActivationData(out ActivationData activationData)
                ? activationData.ActivationServices.GetServiceByKey <int, IGrainExtension>(interfaceId)
                : this.ServiceProvider.GetServiceByKey <int, IGrainExtension>(interfaceId);

            if (extension == null)
            {
                return(false);
            }

            if (!TryAddExtension(extension))
            {
                return(false);
            }

            // Get the newly installed invoker for the grain extension.
            invoker = invokable.GetInvoker(typeManager, interfaceId, genericGrainType);
            return(true);
        }
        /// <summary>
        /// Creates and returns a map from interface id to intercepted invoker for constructed generic types.
        /// </summary>
        /// <param name="implementationType">The implementation type.</param>
        /// <param name="invoker">The underlying invoker.</param>
        /// <returns>A map from interface id to intercepted invoker.</returns>
        private static Dictionary<int, InterceptedMethodInvoker> CreateMapForConstructedGeneric(
            Type implementationType,
            IGrainMethodInvoker invoker)
        {
            // It is important to note that the interfaceId and methodId are computed based upon the non-concrete
            // version of the implementation type. During code generation, the concrete type would not be available
            // and therefore the generic type definition is used.
            if (!implementationType.IsConstructedGenericType)
            {
                throw new InvalidOperationException(
                    $"Type {implementationType} passed to {nameof(CreateMapForConstructedGeneric)} is not a constructed generic type");
            }

            var genericClass = implementationType.GetGenericTypeDefinition();
            var genericClassTypeInfo = genericClass.GetTypeInfo();
            var implementationTypeInfo = implementationType.GetTypeInfo();

            var genericInterfaces = genericClass.GetInterfaces();
            var concreteInterfaces = implementationType.GetInterfaces();

            // Create an invoker for every interface on the provided type.
            var result = new Dictionary<int, InterceptedMethodInvoker>(genericInterfaces.Length);
            for (var i = 0; i < genericInterfaces.Length; i++)
            {
                // Because these methods are identical except for type parameters, their methods should also be identical except
                // for type parameters, including identical ordering. That is the assumption.
                var genericMethods = GrainInterfaceUtils.GetMethods(genericInterfaces[i]);
                var concreteInterfaceMethods = GrainInterfaceUtils.GetMethods(concreteInterfaces[i]);

                // Map every method on this interface from the definition interface onto the implementation class.
                var methodMap = new Dictionary<int, MethodInfo>(genericMethods.Length);
                var genericMap = default(InterfaceMapping);
                var concreteMap = default(InterfaceMapping);
                for (var j = 0; j < genericMethods.Length; j++)
                {
                    // If this method is not from the expected interface (eg, because it's from a parent interface), then
                    // get the mapping for the interface which it does belong to.
                    var genericInterfaceMethod = genericMethods[j];
                    if (genericMap.InterfaceType != genericInterfaceMethod.DeclaringType)
                    {
                        genericMap = genericClassTypeInfo.GetRuntimeInterfaceMap(genericInterfaceMethod.DeclaringType);
                        concreteMap = implementationTypeInfo.GetRuntimeInterfaceMap(concreteInterfaceMethods[j].DeclaringType);
                    }

                    // Determine the position in the definition's map which the target method belongs to and take the implementation
                    // from the same position on the implementation's map.
                    for (var k = 0; k < genericMap.InterfaceMethods.Length; k++)
                    {
                        if (genericMap.InterfaceMethods[k] != genericInterfaceMethod) continue;
                        methodMap[GrainInterfaceUtils.ComputeMethodId(genericInterfaceMethod)] = concreteMap.TargetMethods[k];
                        break;
                    }
                }

                // Add the resulting map of methodId -> method to the interface map.
                var interfaceId = GrainInterfaceUtils.GetGrainInterfaceId(genericInterfaces[i]);
                result[interfaceId] = new InterceptedMethodInvoker(invoker, methodMap);
            }

            return result;
        }
예제 #50
0
        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();

                if (target.GetPrimaryKeyString() != null)
                {
                    grainEvent.GrainKeyString = target.GetPrimaryKeyString();
                }
                else if (target.IsPrimaryKeyBasedOnLong())
                {
                    grainEvent.GrainKeyLong      = target.GetPrimaryKeyLong(out var keyExt);
                    grainEvent.GrainKeyExtention = keyExt;
                }
                else
                {
                    grainEvent.GrainKeyGuid      = target.GetPrimaryKey(out var keyExt);
                    grainEvent.GrainKeyExtention = keyExt;
                }

                if (target is Grain grainTarget)
                {
                    grainEvent.SiloAddress = grainTarget.RuntimeIdentity;
                }

                grainEvent.SiloDeploymentId = ConfigBuilder.ClusterConfiguration.Globals.DeploymentId;


                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();
                }
            }
        }
예제 #51
0
 /// <summary>
 /// Constructs a new instance of the <see cref="InterceptedMethodInvoker"/> class.
 /// </summary>
 /// <param name="invoker">The underlying method invoker.</param>
 /// <param name="methodInfos">
 /// The mapping between method id and <see cref="MethodInfo"/> for each of the grain's methods.
 /// </param>
 public InterceptedMethodInvoker(IGrainMethodInvoker invoker, Dictionary <int, MethodInfo> methodInfos)
 {
     this.invoker     = invoker;
     this.methodInfos = methodInfos;
 }