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> /// 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)); }
protected override bool HandleClientAdded(IMessageBus messageBus, ClientId clientId) { // Make sure to have this done first, since it will send notifications of clients, and we // may need those for the establishment of events. if (base.HandleClientAdded(messageBus, clientId) == false || messageBus == null || clientId == null) { return(false); } MessageBusClient clientInstance = messageBus.GetLocalClientInstance(clientId); // Will only work for local AND MessageSuperPoolClient typed clients. if (clientInstance is SuperPoolClient) { lock (_syncRoot) { if (_clients.ContainsKey(clientInstance.Id)) {// Already added. return(false); } ClientEventsHandler subscription = new ClientEventsHandler(this, (SuperPoolClient)clientInstance); _clients.Add(clientInstance.Id, subscription); } } else { List <string> sourceTypeNames = messageBus.GetClientSourceTypes(clientId); if (sourceTypeNames == null) { #if Matrix_Diagnostics InstanceMonitor.Error("Failed to obtain client [" + clientId.ToString() + "] source type."); #endif return(false); } SuperPoolClient intercomClient = IntercomClient; if (intercomClient == null) { #if Matrix_Diagnostics InstanceMonitor.Error("Failed to obtain super pool main intercom client, so new client handling has failed."); #endif return(false); } List <EventSubscriptionRequest> totalRequests = new List <EventSubscriptionRequest>(); if (clientId.IsLocalClientId == false) { // Gather all the Super Pool related interfaces and their events, and send global updates for those // so that any pending subscriptions may be restored. // This is only done where the client is a remote client instance, since local ones we already know // of them. This eventing information must be at the local pool for the client, since it is the one // handling the event and sending it to all interested parties. foreach (Type interfaceType in ReflectionHelper.GetKnownTypes(sourceTypeNames)) { if (interfaceType.IsInterface && ReflectionHelper.TypeHasCustomAttribute(interfaceType, typeof(SuperPoolInterfaceAttribute), false) == false) {// Interface type not marked as super pool. continue; } foreach (EventInfo info in interfaceType.GetEvents()) { string eventName = GeneralHelper.GetEventMethodExtendedName(info, false); EventSubscriptionInfo eventInfo; if (_eventSubscriptions.TryGetValue(eventName, out eventInfo)) { totalRequests.AddRange(eventInfo.GatherSourceRelatedUpdates(clientId)); } } } } // Send updates for the newly connected client, so that it can obtain any subscription information // regarding it, it case it has missed some. foreach (EventSubscriptionRequest request in totalRequests) { // 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* intercomClient.CallAll <ISuperPoolIntercom>().ProcessSubscriptionUpdate(request); } } return(true); }