/// <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> /// An envelope has arrived from the messaging infrastructure. /// </summary> protected override void OnPerformExecution(Envelope envelope) { object messageConsumer = Source; if (messageConsumer == null || envelope.Message.GetType() != typeof(SuperPoolCall)) {// This is a not a super pool call, or no message consumer. base.OnPerformExecution(envelope); return; } try { SuperPoolCall call = envelope.Message as SuperPoolCall; if (call.State == SuperPoolCall.StateEnum.Responding) {// Response. object response = call.Parameters.Length > 0 ? call.Parameters[0] : null; Exception exception = call.Parameters.Length > 1 ? call.Parameters[1] as Exception : null; long callId = call.Id; SyncCallInfo syncCallInfo = null; lock (_syncCalls) { if (_syncCalls.TryGetValue(callId, out syncCallInfo)) { if (syncCallInfo.IsMultiResponse == false) {// Only remove single response ones, since we have 1 for sure. _syncCalls.Remove(callId); } } else { syncCallInfo = null; } } if (syncCallInfo != null) { syncCallInfo.AcceptResponse(this, response, exception); if (syncCallInfo.IsMultiResponse && syncCallInfo.IsMultiResponseComplete) { lock (_syncCalls) { _syncCalls.Remove(callId); } } } } else if (call.State == SuperPoolCall.StateEnum.Requesting) {// Call (Request). if (_consumerInterfacesHotSwap.Contains(call.MethodInfoLocal.ReflectedType)) { object result = null; Exception exception = null; result = PerformCall(call, messageConsumer, out exception); if (call.RequestResponse) { call.State = SuperPoolCall.StateEnum.Responding; if (exception == null) { call.Parameters = new object[] { result }; } else {// Also transport the exception. call.Parameters = new object[] { result, exception }; } Matrix.Framework.SuperPool.Core.SuperPool pool = _superPool; if (pool == null) { #if Matrix_Diagnostics SystemMonitor.Error(this.GetType().Name + " has failed to find super pool instance, execution failed."); #endif return; } IMessageBus messageBus = pool.MessageBus; if (messageBus == null) { #if Matrix_Diagnostics SystemMonitor.Error(this.GetType().Name + " has failed to find super pool's message bus instance, execution failed."); #endif return; } messageBus.Respond(envelope, new Envelope(call) { DuplicationMode = EnvelopeDuplicationMode }); } else { call.State = SuperPoolCall.StateEnum.Finished; } } else { if (call.MethodInfoLocal == null) { #if Matrix_Diagnostics SystemMonitor.OperationError(string.Format("Call with no method info assigned ignored.")); #endif } else { #if Matrix_Diagnostics SystemMonitor.OperationError(string.Format("Call to [{0}] not recognized.", call.MethodInfoLocal.ToString())); #endif } } } else if (call.State == SuperPoolCall.StateEnum.EventRaise) { Exception exception; object result = PerformCall(call, messageConsumer, out exception); call.State = SuperPoolCall.StateEnum.Finished; } } catch (Exception ex) {// It is possible we encounter some invocation error (for ex. source type changed while call travelling) // so gracefully handle these here. #if Matrix_Diagnostics SystemMonitor.OperationError("Execution failed", ex); #endif } }
protected override void OnPerformExecution(Envelope envelope) { object source = this.Source; if (source == null || envelope.Message.GetType() != typeof(SuperPoolCall)) { base.OnPerformExecution(envelope); } else { try { SuperPoolCall call = envelope.Message as SuperPoolCall; object obj1; if (call.State == SuperPoolCall.StateEnum.Responding) { object result = call.Parameters.Length > 0 ? call.Parameters[0] : (object)null; Exception exception = call.Parameters.Length > 1 ? call.Parameters[1] as Exception : (Exception)null; long id = call.Id; SyncCallInfo syncCallInfo = (SyncCallInfo)null; lock (this._syncCalls) { if (this._syncCalls.TryGetValue(id, out syncCallInfo)) { if (!syncCallInfo.IsMultiResponse) { this._syncCalls.Remove(id); } } else { syncCallInfo = (SyncCallInfo)null; } } if (syncCallInfo != null) { syncCallInfo.AcceptResponse(this, result, exception); if (syncCallInfo.IsMultiResponse && syncCallInfo.IsMultiResponseComplete) { lock (this._syncCalls) this._syncCalls.Remove(id); } } } else if (call.State == SuperPoolCall.StateEnum.Requesting) { if (this._consumerInterfacesHotSwap.Contains(call.MethodInfoLocal.ReflectedType)) { obj1 = (object)null; Exception exception = (Exception)null; object obj2 = this.PerformCall(call, source, out exception); if (call.RequestResponse) { call.State = SuperPoolCall.StateEnum.Responding; if (exception == null) { call.Parameters = new object[1] { obj2 } } ; else { call.Parameters = new object[2] { obj2, (object)exception } }; SuperPool superPool = this._superPool; if (superPool == null) { return; } IMessageBus messageBus = superPool.MessageBus; if (messageBus == null) { return; } int num = (int)messageBus.Respond(envelope, new Envelope((object)call) { DuplicationMode = this.EnvelopeDuplicationMode }); } else { call.State = SuperPoolCall.StateEnum.Finished; } } else if (call.MethodInfoLocal != null) { ; } } else if (call.State == SuperPoolCall.StateEnum.EventRaise) { Exception exception; obj1 = this.PerformCall(call, source, out exception); call.State = SuperPoolCall.StateEnum.Finished; } } catch (Exception ex) { } } }