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); }
/// <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)); }
/// <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)); } }
/// <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)); }
/// <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); }
/// <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)); }
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); } }