Example #1
0
        void IProxyTypeSink.ReceivePropertySet(int methodId, object value)
        {
            SuperPoolProxyCall pendingCall = null;

            if (_pendingThreadsCalls.TryGetValue(Thread.CurrentThread.ManagedThreadId, out pendingCall) == false)
            {
#if Matrix_Diagnostics
                InstanceMonitor.OperationError("Failed to find corresponding thread proxy call information.");
#endif
                return;
            }

            pendingCall.Parameters = new object[] { value };
            pendingCall.ReturnType = null;

            ProxyTypeBuilder builder = ProxyTypeBuilder;
            if (builder == null)
            {
#if Matrix_Diagnostics
                InstanceMonitor.OperationError("Failed to find proxy type builder.");
#endif
                return;
            }

            pendingCall.MethodInfo = builder.GetMethodInfoById(methodId);
            if (pendingCall.MethodInfo == null)
            {
#if Matrix_Diagnostics
                InstanceMonitor.OperationError("Failed to find method [" + methodId + "] info.");
#endif
                return;
            }

            pendingCall.Sender.ProcessCall(pendingCall);
        }
Example #2
0
        /// <summary>
        /// Process a pool call.
        /// </summary>
        object ProcessReceiveCall(int methodId, Type returnType, object[] parameters)
        {
            SuperPoolProxyCall pendingCall = null;

            if (_pendingThreadsCalls.TryGetValue(Thread.CurrentThread.ManagedThreadId, out pendingCall) == false)
            {
#if Matrix_Diagnostics
                InstanceMonitor.OperationError("Failed to find corresponding thread proxy call information.");
#endif
                return(null);
            }

            pendingCall.Parameters = parameters;
            pendingCall.ReturnType = returnType;

            ProxyTypeBuilder builder = ProxyTypeBuilder;
            if (builder == null)
            {
#if Matrix_Diagnostics
                InstanceMonitor.OperationError("Failed to find proxy type builder.");
#endif
                return(ProxyTypeManager.GetTypeDefaultValue(returnType));
            }

            pendingCall.MethodInfo = builder.GetMethodInfoById(methodId);
            if (pendingCall.MethodInfo == null)
            {
#if Matrix_Diagnostics
                InstanceMonitor.OperationError("Failed to find method [" + methodId + "] info.");
#endif
                return(ProxyTypeManager.GetTypeDefaultValue(returnType));
            }

            return(pendingCall.Sender.ProcessCall(pendingCall));
        }
Example #3
0
 /// <summary>
 ///
 /// </summary>
 internal bool Call <InterfaceType>(SuperPoolClient sender, ComponentId receiversIds,
                                    out InterfaceType result, out SuperPoolProxyCall call)
     where InterfaceType : class
 {
     if (receiversIds == null)
     {
         return(Call <InterfaceType>(sender, (IEnumerable <ComponentId>)null, out result, out call));
     }
     else
     {
         return(Call <InterfaceType>(sender, new ComponentId[] { receiversIds }, out result, out call));
     }
 }
Example #4
0
 /// <summary>
 /// Helper version of the call, with no receiver speicified.
 /// This is utilized in events calls.
 /// </summary>
 internal bool Call <InterfaceType>(SuperPoolClient sender, out InterfaceType result, out SuperPoolProxyCall call)
     where InterfaceType : class
 {
     return(Call <InterfaceType>(sender, (IEnumerable <ComponentId>)null, out result, out call));
 }
Example #5
0
        /// <summary>
        /// Basic asynchronous call operation.
        /// </summary>
        /// <param name="receiverId">The value of the receiver, null means call all.</param>
        internal bool Call <InterfaceType>(SuperPoolClient sender, IEnumerable <ComponentId> receiversIds,
                                           out InterfaceType result, out SuperPoolProxyCall call)
            where InterfaceType : class
        {
            call   = null;
            result = null;

            // SLOW.
            //if (_messageBus.ContainsClient(sender.Id) == false)
            //{
            //    SystemMonitor.OperationError("Client not a member of message bus (and super pool).");
            //    return false;
            //}

            if (typeof(InterfaceType).IsInterface == false)
            {
                throw new Exception("Type provided not an interface.");
            }

            // Very slow !!
            //object[] attributes = typeof(InterfaceType).GetCustomAttributes(typeof(SuperPoolInterfaceAttribute), false);
            //if (attributes == null || attributes.Length == 0)
            //{
            //    SystemMonitor.Throw("Interface type [" + typeof(InterfaceType).Name + "] not marked as super pool interface.");
            //    return false;
            //}

            ProxyTypeManager typeManager = _proxyTypeManager;

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

            if (_pendingThreadsCalls.TryGetValue(Thread.CurrentThread.ManagedThreadId, out call) == false)
            {// We are safe from danger of someone else already adding the value with this id,
                // since we are the only thread with this id.
                call = new SuperPoolProxyCall();
                // This is slow, but very rarely executed, since thread ids are reused.
                _pendingThreadsCalls.Add(Thread.CurrentThread.ManagedThreadId, call);
            }
            else
            {
                // Since we reuse the call, clean it up before usage.
                call.Clear();
            }

            call.Processed = false;
            if (receiversIds != null)
            {// Extract the Indeces from the Ids.
                List <ClientId> receiversIndeces = new List <ClientId>();
                foreach (ComponentId id in receiversIds)
                {
                    receiversIndeces.Add((ClientId)id);
                }

                call.ReceiversIds = receiversIndeces;
            }
            else
            {
                call.ReceiversIds = null;
            }

            call.Sender = sender;

            result = (InterfaceType)typeManager.ObtainInterfaceProxy(typeof(InterfaceType));

            return(true);
        }
Example #6
0
        /// <summary>
        /// A call has been made from us trough the proxy object.
        /// </summary>
        internal object ProcessCall(SuperPoolProxyCall proxyCall)
        {
            SuperPoolInvocation superPool = _superPool;

            if (superPool == null)
            {
#if Matrix_Diagnostics
                SystemMonitor.OperationError("Failed to find super pool (possible dispose).");
#endif
                return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
            }

            IMessageBus messageBus = superPool.MessageBus;
            if (messageBus == null)
            {
#if Matrix_Diagnostics
                SystemMonitor.OperationError("Failed to find message bus (possible dispose).");
#endif
                return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
            }

            if (proxyCall.Processed)
            {
#if Matrix_Diagnostics
                SystemMonitor.OperationError("Proxy call already processed.");
#endif
                return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
            }

            if (proxyCall.Mode == SuperPoolProxyCall.ModeEnum.DirectCall)
            {
                MessageBusClient clientInstance = messageBus.GetLocalClientInstance(proxyCall.ReceiversIds[0]);
                if (clientInstance == null || clientInstance is SuperPoolClient == false)
                {
#if Matrix_Diagnostics
                    SystemMonitor.OperationError("Direct call failed, due to client not found or corresponding.");
#endif
                    return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
                }
                else
                {// Perform the direct call.
                    // This is still fast, since caching is used.
                    FastInvokeHelper.FastInvokeHandlerDelegate delegateInstance = FastInvokeHelper.GetMethodInvoker(proxyCall.MethodInfo.ProxyMethodInfo, true, true);
                    return(delegateInstance.Invoke(((SuperPoolClient)clientInstance).Source, proxyCall.Parameters));
                }
            }
            else if (proxyCall.Mode == SuperPoolProxyCall.ModeEnum.CallFirst)
            {
                ClientId firstId = this.Resolve(proxyCall.MethodInfo.ProxyMethodInfo.DeclaringType);
                if (firstId == null)
                {
#if Matrix_Diagnostics
                    SystemMonitor.OperationError("Call first failed, no client found for [" + proxyCall.MethodInfo.ProxyMethodInfo.DeclaringType.Name + "] interface.");
#endif

                    return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
                }

                proxyCall.ReceiversIds = new List <ClientId>()
                {
                    firstId
                };
            }

            SuperPoolCall call = new SuperPoolCall(superPool.GetUniqueCallId());

            call.Parameters      = proxyCall.Parameters;
            call.MethodInfoLocal = proxyCall.MethodInfo.ProxyMethodInfo;

            call.State = SuperPoolCall.StateEnum.Requesting;
            //SuperPoolProxyCall.ModeEnum.Default ? SuperPoolCall.StateEnum.Requesting : SuperPoolCall.StateEnum.RequestingDirectCall;

            call.RequestResponse = proxyCall.IsSynchronous || proxyCall.IsAsyncResultExpecting;

            proxyCall.Processed = true;

            foreach (ParameterInfo info in call.MethodInfoLocal.GetParameters())
            {// Filter out ref, out and optional parameters.
                if (/*info.IsOptional ||*/ info.IsOut || info.IsRetval || info.IsOut || info.ParameterType.IsByRef)
                {
                    throw new NotImplementedException("Super pool calls do not support optional, out and ref parameters");
                }
            }

            // Prepare the synchronous structure (also handles waiting for the async results).
            SyncCallInfo syncCall = null;
            if (proxyCall.IsSynchronous || proxyCall.IsAsyncResultExpecting)
            {
                syncCall = new SyncCallInfo(call.Id)
                {
                    AsyncResultState    = proxyCall.AsyncResultState,
                    AsyncResultDelegate = proxyCall.AsyncResultDelegate,
                    AsyncResultTimeout  = proxyCall.AsyncResultTimeout,
                };

                lock (_syncCalls)
                {
                    _syncCalls[call.Id] = syncCall;
                }
            }

            List <ClientId> receiversIndeces = null;
            if (proxyCall.ReceiversIds == null)
            {// No receiver indicates send to all, so that is what we do.
                if (proxyCall.MethodInfo == null || proxyCall.MethodInfo.ProxyOwnerType == null)
                {
#if Matrix_Diagnostics
                    SystemMonitor.Error("Failed to establish the required proxy call parameters.");
#endif
                    return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
                }

                Type interfaceType = proxyCall.MethodInfo.GetBaseInterfaceType();
                if (interfaceType == null)
                {
#if Matrix_Diagnostics
                    SystemMonitor.Error("Failed to establish the base interface type.");
#endif
                    return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
                }

                receiversIndeces = new List <ClientId>();
                foreach (ComponentId receiverId in superPool.GetInterfaceImplementors(interfaceType))
                {
                    if (receiverId != proxyCall.Sender.Id)
                    {
                        receiversIndeces.Add((ClientId)receiverId);
                    }

                    if (proxyCall.IsSynchronous && receiversIndeces.Count > 0)
                    {// Synchronous inadressed calls only execute agains a max of one provider.
                        break;
                    }
                }
            }
            else
            {
                receiversIndeces = proxyCall.ReceiversIds;
            }

            if (receiversIndeces.Count > 0)
            {
                if (syncCall != null && proxyCall.IsSynchronous)
                {// Prepare the event.
                    syncCall.Event = new ManualResetEvent(false);
                }

                Outcomes sendResult = messageBus.Send(this.Id, receiversIndeces, new Envelope(call)
                {
                    DuplicationMode = EnvelopeDuplicationMode
                }, proxyCall.RequestConfirmTimeout, false);

                if (proxyCall.Outcome != null)
                {
                    proxyCall.Outcome.Result = sendResult;
                }

                if (sendResult != Outcomes.Success)
                {
#if Matrix_Diagnostics
                    SystemMonitor.OperationError(string.Format("Failed to send proxy call [{0}].", proxyCall.ToString()));
#endif
                    return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
                }

                if (syncCall != null && proxyCall.IsSynchronous)
                {     // Wait for response.
                    if (syncCall.Event.WaitOne(proxyCall.Timeout.Value) == false)
                    { // Time out.
#if Matrix_Diagnostics
                        SystemMonitor.OperationWarning(string.Format("Proxy call timed out [{0}].", proxyCall.ToString()));
#endif
                        return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
                    }
                    else
                    {// Waited and awaken.
                        return(syncCall.Response);
                    }
                }
            }
            else
            {
#if Matrix_Diagnostics
                SystemMonitor.OperationWarning(string.Format("Failed to find invocation recipients for call [{0}].", proxyCall.ToString()));
#endif
            }

            return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
        }
Example #7
0
        internal object ProcessCall(SuperPoolProxyCall proxyCall)
        {
            SuperPoolInvocation superPoolInvocation = (SuperPoolInvocation)this._superPool;

            if (superPoolInvocation == null)
            {
                return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
            }
            IMessageBus messageBus = superPoolInvocation.MessageBus;

            if (messageBus == null || proxyCall.Processed)
            {
                return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
            }
            if (proxyCall.Mode == SuperPoolProxyCall.ModeEnum.DirectCall)
            {
                MessageBusClient localClientInstance = messageBus.GetLocalClientInstance(proxyCall.ReceiversIds[0]);
                if (localClientInstance == null || !(localClientInstance is SuperPoolClient))
                {
                    return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
                }
                else
                {
                    return(FastInvokeHelper.GetMethodInvoker(proxyCall.MethodInfo.ProxyMethodInfo, true, true)(((ActiveInvocatorClient)localClientInstance).Source, proxyCall.Parameters));
                }
            }
            else
            {
                if (proxyCall.Mode == SuperPoolProxyCall.ModeEnum.CallFirst)
                {
                    ClientId clientId = this.Resolve(proxyCall.MethodInfo.ProxyMethodInfo.DeclaringType);
                    if ((ComponentId)clientId == (ComponentId)null)
                    {
                        return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
                    }
                    proxyCall.ReceiversIds = new List <ClientId>()
                    {
                        clientId
                    };
                }
                SuperPoolCall superPoolCall = new SuperPoolCall(superPoolInvocation.GetUniqueCallId());
                superPoolCall.Parameters      = proxyCall.Parameters;
                superPoolCall.MethodInfoLocal = proxyCall.MethodInfo.ProxyMethodInfo;
                superPoolCall.State           = SuperPoolCall.StateEnum.Requesting;
                superPoolCall.RequestResponse = proxyCall.IsSynchronous || proxyCall.IsAsyncResultExpecting;
                proxyCall.Processed           = true;
                foreach (ParameterInfo parameterInfo in superPoolCall.MethodInfoLocal.GetParameters())
                {
                    if (parameterInfo.IsOut || parameterInfo.IsRetval || parameterInfo.IsOut || parameterInfo.ParameterType.IsByRef)
                    {
                        throw new NotImplementedException("Super pool calls do not support optional, out and ref parameters");
                    }
                }
                SyncCallInfo syncCallInfo = (SyncCallInfo)null;
                if (proxyCall.IsSynchronous || proxyCall.IsAsyncResultExpecting)
                {
                    syncCallInfo = new SyncCallInfo(superPoolCall.Id)
                    {
                        AsyncResultState    = proxyCall.AsyncResultState,
                        AsyncResultDelegate = proxyCall.AsyncResultDelegate,
                        AsyncResultTimeout  = proxyCall.AsyncResultTimeout
                    };
                    lock (this._syncCalls)
                        this._syncCalls[superPoolCall.Id] = syncCallInfo;
                }
                List <ClientId> list;
                if (proxyCall.ReceiversIds == null)
                {
                    if (proxyCall.MethodInfo == null || proxyCall.MethodInfo.ProxyOwnerType == null)
                    {
                        return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
                    }
                    Type baseInterfaceType = proxyCall.MethodInfo.GetBaseInterfaceType();
                    if (baseInterfaceType == null)
                    {
                        return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
                    }
                    list = new List <ClientId>();
                    foreach (ComponentId componentId in superPoolInvocation.GetInterfaceImplementors(baseInterfaceType))
                    {
                        if (componentId != (ComponentId)proxyCall.Sender.Id)
                        {
                            list.Add((ClientId)componentId);
                        }
                        if (proxyCall.IsSynchronous && list.Count > 0)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    list = proxyCall.ReceiversIds;
                }
                if (list.Count <= 0)
                {
                    return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
                }
                if (syncCallInfo != null && proxyCall.IsSynchronous)
                {
                    syncCallInfo.Event = new ManualResetEvent(false);
                }
                Outcomes outcomes = messageBus.Send(this.Id, (IEnumerable <ClientId>)list, new Envelope((object)superPoolCall)
                {
                    DuplicationMode = this.EnvelopeDuplicationMode
                }, proxyCall.RequestConfirmTimeout, 0 != 0);
                if (proxyCall.Outcome != null)
                {
                    proxyCall.Outcome.Result = outcomes;
                }
                if (outcomes != Outcomes.Success || (syncCallInfo == null || !proxyCall.IsSynchronous || !syncCallInfo.Event.WaitOne(proxyCall.Timeout.Value)))
                {
                    return(ProxyTypeManager.GetTypeDefaultValue(proxyCall.ReturnType));
                }
                else
                {
                    return(syncCallInfo.Response);
                }
            }
        }
        /// <summary>
        /// Handle event subscription (Proxy.Event.Subscribe)
        /// </summary>
        protected override void ProcessReceiveEventSubscription(int methodId, Delegate delegateInstance, bool isAdd)
        {
            SuperPoolProxyCall pendingCall = null;

            if (_pendingThreadsCalls.TryGetValue(Thread.CurrentThread.ManagedThreadId, out pendingCall) == false)
            {
#if Matrix_Diagnostics
                InstanceMonitor.OperationError("Failed to find corresponding thread proxy call information.");
#endif
                return;
            }

            EventSubscriptionRequest subscriptionRequest = pendingCall.SubscriptionRequest;
            if (subscriptionRequest == null)
            {
#if Matrix_Diagnostics
                InstanceMonitor.OperationError("Failed to find corresponding subscription requests, event subscription failed.");
#endif
                return;
            }

            if (pendingCall.Sender == null || pendingCall.Sender.Id == null)
            {
#if Matrix_Diagnostics
                InstanceMonitor.OperationError("Failed to establish subscription sender information, subscription failed.");
#endif
                return;
            }

            if (delegateInstance.Target != pendingCall.Sender.Source)
            {
#if Matrix_Diagnostics
                InstanceMonitor.Error("Only a message super pool client source can subscribe to events.");
#endif
                return;
            }

            ProxyTypeBuilder builder = ProxyTypeBuilder;
            if (builder == null)
            {
#if Matrix_Diagnostics
                InstanceMonitor.OperationError("Failed to find proxy type builder, event subscription failed.");
#endif
                return;
            }

            GeneratedMethodInfo generatedMethodInfo = builder.GetMethodInfoById(methodId);
            if (generatedMethodInfo == null)
            {
#if Matrix_Diagnostics
                InstanceMonitor.OperationError("Failed to find method [id, " + methodId + "] info, event subscription failed.");
#endif
                return;
            }

            if (string.IsNullOrEmpty(generatedMethodInfo.EventName))
            {
                generatedMethodInfo.EventName = GeneralHelper.GetEventExtendedNameByMethod(generatedMethodInfo.GetMethodInfo(), false, true);
            }

            // generatedMethodInfo.GetMethodInfo() >> I2.add_AEVent
            string     extendedEventName  = generatedMethodInfo.EventName;
            MethodInfo eventAddMethodInfo = generatedMethodInfo.GetMethodInfo();

            // *IMPORTANT* the Call<> will cause the currently used pendingCall to be repopulated with information,
            // so we ned to extract the *sender id* BEFORE calling the actual Call(), since it will change the
            // pendingCall instance immediately.
            subscriptionRequest.SenderId          = pendingCall.Sender.Id;
            subscriptionRequest.ExtendedEventName = extendedEventName;
            subscriptionRequest.IsAdd             = isAdd;
            //subscriptionRequest.EventAddMethodInfo = eventAddMethodInfo;
            subscriptionRequest.DelegateInstanceMethodInfo = delegateInstance.Method;

            // Process locally.
            ((ISuperPoolIntercom)this).ProcessSubscriptionUpdate(subscriptionRequest);

            SuperPoolClient mainClient = IntercomClient;
            if (mainClient == null)
            {
#if Matrix_Diagnostics
                InstanceMonitor.Error("Failed to obtain super pool main intercom client, so new client handling has failed.");
#endif
            }
            else
            {
                // Notify other connected super pools of this subcription,
                // since the subscribee(s) may be attached on them.
                // *pendingCall swap done here, make sure to not use it on or after this line*
                mainClient.CallAll <ISuperPoolIntercom>().ProcessSubscriptionUpdate(subscriptionRequest);
            }
        }