protected override void OnLoad(EventArgs e) { base.OnLoad(e); //// [Optional] Assign the default tracer, to provide system wide tracing functionality. //SystemMonitor.AssignTracer(new Tracer()); //this.tracerControl1.Tracer = SystemMonitor.Tracer; // Create the underlying (server) message bus and put the pool on it. ServerMessageBus messageBus = new ServerMessageBus("Server", null, null); _pool = new Matrix.Framework.SuperPool.Core.SuperPool(messageBus); // Create the client that will server as a connection between this // class and the super pool and add the client to the pool. _poolClient = new SuperPoolClient("Server", this); _pool.AddClient(_poolClient); // Finally subscribe to the event of having a client added to the bus/pool. _pool.MessageBus.ClientAddedEvent += new MessageBus.Core.MessageBusClientUpdateDelegate(MessageBus_ClientAddedEvent); messageBus.ClientRemovedEvent += (bus, id, remove) => { this.Invoke(new GeneralHelper.GenericDelegate <string>(Report), "Client removed " + id.ToString()); }; }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); this.Text += " - " + this.ClientName; // The steps here are exactly the same, as in server side, only difference is the ClientMessageBus // instead of ServerMessageBus. Since this is the only difference, all the remaining source code // is completely independent of whether its a server or a client side. //// Assign the default tracer, to provide system wide tracing functionality. //SystemMonitor.AssignTracer(new Tracer()); //this.tracerControl1.Tracer = SystemMonitor.Tracer; IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, ServerMessageBus.DefaultPort); // Create the underlying (client) message bus, that takes care of transporting the // actual communication messages; the message bus TCP communication is created // at default port, at localhost. ClientMessageBus messageBus = new ClientMessageBus(endPoint, this.ClientName, null); // Initialize the super pool with this message bus. _pool = new Matrix.Framework.SuperPool.Core.SuperPool(messageBus); // Create the client that will server as a connection between this // class and the super pool and add the client to the pool. _poolClient = new SuperPoolClient("Client." + this.ClientName, this); _pool.AddClient(_poolClient); // Use this to assign a specific execution strategy to a given client. // _poolClient.SetupExecutionStrategy(new FrameworkThreadPoolExecutionStrategy()); }
/// <summary> /// Creates a new client, assigns it with a custom execution strategy and adds it to the super pool. /// </summary> /// <param name="superPool"></param> public void Demonstrate(Matrix.Framework.SuperPool.Core.SuperPool superPool) { SuperPoolClient client = new SuperPoolClient("Client", this); client.SetupExecutionStrategy(new CustomExecutionStrategy()); superPool.AddClient(client); }
public void AcceptResponse(SuperPoolClient client, object result, Exception exception) { Response = result; if (AsyncResultDelegate != null) { try { AsyncResultDelegate.Invoke(client, new AsyncResultParams() { Result = result, State = AsyncResultState, Exception = exception }); } catch (Exception ex) { #if Matrix_Diagnostics SystemMonitor.OperationError(string.Format("AcceptReposnse invoke of client [{0}] has caused an exception", client.Name), ex); #endif } } else {// Assign the parameter only in sync calls, since async already consumed it trough async delegate. Exception = exception; } ManualResetEvent eventInstance = Event; if (eventInstance != null) { eventInstance.Set(); } }
/// <summary> /// Constructor. /// </summary> internal CallTestImplementor() { _implementor1 = new InterfaceImplementor("Implementor1"); _implementor2 = new InterfaceImplementor("Implementor2"); Client1 = new SuperPoolClient("client1", _implementor1); Client2 = new SuperPoolClient("client2", _implementor2); }
/// <summary> /// Constructor. /// </summary> public ClientEventsHandler(SuperPoolSubscription owner, SuperPoolClient client) { _owner = owner; if (Initialize(client) == false) { #if Matrix_Diagnostics SystemMonitor.Error("Failed to initialize subscription for client."); SystemMonitor.ErrorIf(Initialize(client) == false, "Failed to initialize subscription for client."); SystemMonitor.ErrorIf(Initialize(client) == false, "Failed to initialize subscription for client."); SystemMonitor.Error("Failed to initialize subscription for client."); #endif } }
/// <summary> /// Perform event subscription (Subscribe), always asynchronous. /// </summary> public bool Subscribe <TType>(SuperPoolClient subscriber, EventSubscriptionRequest request, out TType resultValue) where TType : class { SuperPoolProxyCall call; bool result = Call <TType>(subscriber, out resultValue, out call); call.SubscriptionRequest = request; return(result); }
/// <summary> /// Constructor. /// </summary> public DirectCallSpeedTest() : base(true) { pool = new Matrix.Framework.SuperPool.Core.SuperPool(); client1 = new SuperPoolClient("c1", this); client2 = new SuperPoolClient("c2", this); bool result = pool.AddClient(client1); result = pool.AddClient(client2); }
/// <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> /// /// </summary> public void Dispose() { ReleaseCurrentClientSource(); lock (this) { if (_client != null) { _client.SourceUpdatedEvent -= new SuperPoolSourceUpdateDelegate(_client_SourceChangedEvent); _client = null; } _owner = null; } }
/// <summary> /// Assign and attach to the client. /// </summary> protected bool Initialize(SuperPoolClient client) { lock (this) { if (_client != null) { return(false); } _client = client; _client.SourceUpdatedEvent += new SuperPoolSourceUpdateDelegate(_client_SourceChangedEvent); } AssignClientSource(client.Source); return(true); }
/// <summary> /// Remove a client from the pool. /// </summary> public virtual bool RemoveClient(SuperPoolClient client, bool isPermanent) { IMessageBus messageBus = _messageBus; if (messageBus == null) { return(false); } bool result = messageBus.RemoveClient(client, isPermanent); if (result) { client.ReleaseSuperPool(); } return(result); }
/// <summary> /// Initialize the pool for operation, by supplying it with a message bus. /// </summary> protected virtual bool Initialize(IMessageBus messageBus) { lock (this) { if (_messageBus != null || messageBus == null) { return(false); } _messageBus = messageBus; _messageBus.ClientAddedEvent += new MessageBusClientUpdateDelegate(_messageBus_ClientAddedEvent); _messageBus.ClientRemovedEvent += new MessageBusClientRemovedDelegate(_messageBus_ClientRemovedEvent); _messageBus.ClientUpdateEvent += new MessageBusClientUpdateDelegate(_messageBus_ClientUpdateEvent); // Add a client with self to the message bus. IntercomClient = new SuperPoolClient("SuperPool.Intercom", this); } if (this.AddClient(IntercomClient) == false) { #if Matrix_Diagnostics InstanceMonitor.Fatal("Failed to add super pool main client."); #endif lock (this) { IntercomClient.Dispose(); IntercomClient = null; _messageBus.ClientAddedEvent -= new MessageBusClientUpdateDelegate(_messageBus_ClientAddedEvent); _messageBus.ClientRemovedEvent -= new MessageBusClientRemovedDelegate(_messageBus_ClientRemovedEvent); _messageBus.ClientUpdateEvent -= new MessageBusClientUpdateDelegate(_messageBus_ClientUpdateEvent); _messageBus = null; } return(false); } return(true); }
/// <summary> /// Add a client to the pool. /// </summary> public virtual bool AddClient(SuperPoolClient client) { IMessageBus messageBus = _messageBus; if (messageBus == null) { return(false); } if (client.Source == null) {// TODO: clear this scenario. //System.Diagnostics.Debug.Fail("Warning, adding a client with no source assigned. Make sure to assign source prior to adding client."); } bool result = messageBus.AddClient(client); if (result) { client.AssignSuperPool((SuperPool)this); } return(result); }
/// <summary> /// Initialize the pool for operation, by supplying it with a message bus. /// </summary> protected virtual bool Initialize(IMessageBus messageBus) { lock (this) { if (_messageBus != null || messageBus == null) { return false; } _messageBus = messageBus; _messageBus.ClientAddedEvent += new MessageBusClientUpdateDelegate(_messageBus_ClientAddedEvent); _messageBus.ClientRemovedEvent += new MessageBusClientRemovedDelegate(_messageBus_ClientRemovedEvent); _messageBus.ClientUpdateEvent += new MessageBusClientUpdateDelegate(_messageBus_ClientUpdateEvent); // Add a client with self to the message bus. IntercomClient = new SuperPoolClient("SuperPool.Intercom", this); } if (this.AddClient(IntercomClient) == false) { #if Matrix_Diagnostics InstanceMonitor.Fatal("Failed to add super pool main client."); #endif lock (this) { IntercomClient.Dispose(); IntercomClient = null; _messageBus.ClientAddedEvent -= new MessageBusClientUpdateDelegate(_messageBus_ClientAddedEvent); _messageBus.ClientRemovedEvent -= new MessageBusClientRemovedDelegate(_messageBus_ClientRemovedEvent); _messageBus.ClientUpdateEvent -= new MessageBusClientUpdateDelegate(_messageBus_ClientUpdateEvent); _messageBus = null; } return false; } return true; }
/// <summary> /// Remove a client from the pool. /// </summary> public virtual bool RemoveClient(SuperPoolClient client, bool isPermanent) { IMessageBus messageBus = _messageBus; if (messageBus == null) { return false; } bool result = messageBus.RemoveClient(client, isPermanent); if (result) { client.ReleaseSuperPool(); } return result; }
/// <summary> /// Add a client to the pool. /// </summary> public virtual bool AddClient(SuperPoolClient client) { IMessageBus messageBus = _messageBus; if (messageBus == null) { return false; } if (client.Source == null) {// TODO: clear this scenario. //System.Diagnostics.Debug.Fail("Warning, adding a client with no source assigned. Make sure to assign source prior to adding client."); } bool result = messageBus.AddClient(client); if (result) { client.AssignSuperPool((SuperPool)this); } return result; }
/// <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); }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); //// [Optional] Assign the default tracer, to provide system wide tracing functionality. //SystemMonitor.AssignTracer(new Tracer()); //this.tracerControl1.Tracer = SystemMonitor.Tracer; // Create the underlying (server) message bus and put the pool on it. ServerMessageBus messageBus = new ServerMessageBus("Server", null, null); _pool = new Matrix.Framework.SuperPool.Core.SuperPool(messageBus); // Create the client that will server as a connection between this // class and the super pool and add the client to the pool. _poolClient = new SuperPoolClient("Server", this); _pool.AddClient(_poolClient); // Finally subscribe to the event of having a client added to the bus/pool. _pool.MessageBus.ClientAddedEvent += new MessageBus.Core.MessageBusClientUpdateDelegate(MessageBus_ClientAddedEvent); messageBus.ClientRemovedEvent += (bus, id, remove) => { this.Invoke(new GeneralHelper.GenericDelegate<string>(Report), "Client removed " + id.ToString()); }; }
/// <summary> /// Constructor. /// </summary> public MyComponent() { Client = new SuperPoolClient("MyClient", this); }
/// <summary> /// Contructor. /// </summary> public Component(string name) { client = new SuperPoolClient(name, this); }
/// <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); } }
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); }
protected void AssignClientSource(object source) { SuperPoolClient client = _client; if (client == null) { #if Matrix_Diagnostics SystemMonitor.Error("Failed to add client source, since client not available (possible Dispose)."); #endif return; } SuperPoolSubscription owner = _owner; if (owner == null) { #if Matrix_Diagnostics SystemMonitor.Error("Failed to add client source, since no owner is available (possible Dispose)."); #endif return; } ReleaseCurrentClientSource(); _clientSource = source; if (_clientSource == null) { #if Matrix_Diagnostics SystemMonitor.OperationWarning("Starting a client with no source attached."); #endif return; } foreach (Type interfaceType in ReflectionHelper.GatherTypeAttributeMarkedInterfaces(source.GetType(), typeof(SuperPoolInterfaceAttribute))) {// Gather all events, from interfaces marked with [SuperPoolInterfaceAttribute]. // Make sure to have created the corresponding proxy instance for this interface type. owner.ProxyTypeManager.ObtainInterfaceProxy(interfaceType); foreach (EventInfo eventInfo in interfaceType.GetEvents()) { Type delegateType = eventInfo.EventHandlerType; GeneratedMethodInfo methodInfo = owner.ProxyTypeManager.Builder.GenerateDynamicMethodProxyDelegate(delegateType); // Create delegate can operate in 2 modes: // - create a static delegate like this (requires instnace upon call): info.Method.CreateDelegate(delegateType); // - create an instance delegate like this (can be direct called): info.Method.CreateDelegate(delegateType, instance); Delegate delegateInstance = methodInfo.StandaloneDynamicMethod.CreateDelegate(delegateType, this); eventInfo.AddEventHandler(source, delegateInstance); EventHandlingInformation subscriptionInfo = new EventHandlingInformation() { DelegateInstance = delegateInstance, EventInfo = eventInfo, GeneratedMethodInfo = methodInfo }; lock (this) { _eventsMethods.Add(methodInfo.Id, subscriptionInfo); } } } }
/// <summary> /// Assign and attach to the client. /// </summary> protected bool Initialize(SuperPoolClient client) { lock (this) { if (_client != null) { return false; } _client = client; _client.SourceUpdatedEvent += new SuperPoolSourceUpdateDelegate(_client_SourceChangedEvent); } AssignClientSource(client.Source); return true; }