/// <summary> /// Obtain the next execution entity and remove it from pending. /// Children to override to manage the way operations are performed, if they need to. /// This is where currently the MultiThreads per client protection is performed. /// </summary> protected virtual ExecutionEntity PopNextExecutionEntity() { lock (this) { // Check total executioners count. if (_threadPool.FreeThreadsCount < 2) { //if ((DateTime.Now - _executionersBusyWarningShownTime) >= _warningsTimeSpan) { SystemMonitor.OperationError("All of the [" + _threadPool.MaximumSimultaniouslyRunningThreadsAllowed + "] arbiter [" + _arbiter.Name + "] executioners are busy, entity execution delayed.", TracerItem.PriorityEnum.Medium); //_executionersBusyWarningShownTime = DateTime.Now; } return(null); } // Try looking for a new entity. for (int i = 0; i < _pendingEntities.Count; i++) {// Look for an entity that we are allowed to execute now. ExecutionEntity entity = _pendingEntities[i]; IArbiterClient iClient = _arbiter.GetClientByID(entity.ReceiverID); bool isTransportResponceMessage = (entity.Message is TransportMessage && ((TransportMessage)(entity.Message)).IsRequest == false); int runningOnClient = 0; if (_clientsRunningExecutioners.ContainsKey(entity.ReceiverID)) { runningOnClient = _clientsRunningExecutioners[entity.ReceiverID]; } if (isTransportResponceMessage == false && iClient != null && iClient.SingleThreadMode && runningOnClient > 0 /*_executionersAndClientIDs.ContainsValue(entity.ReceiverID)*/) {// We are not allowed to run this, as there is already an executioner there. // And it is not a responce requestMessage. continue; } if (runningOnClient >= _maxExecutionersPerEntity) {// This entity is already consuming too many threads. It must release some before using more. //if ((DateTime.Now - _executionersBusyWarningShownTime) >= _warningsTimeSpan) { //_executionersBusyWarningShownTime = DateTime.Now; SystemMonitor.OperationError("An entity [" + entity.ReceiverID.Id.Name + "] is using all its threads allowed. Further entity executions will be delayed.", TracerItem.PriorityEnum.Medium); } continue; } //TraceHelper.Trace("PopNextExecutionEntity [" + iClient.ToString() + "][" + iClient.SingleThreadMode + "," + _executionersAndClientIDs.ContainsValue(entity.ReceiverID) + "][" + entity.Message.ToString() + "]"); _pendingEntities.Remove(entity); // OK, this entity is good to go. return(entity); } return(null); } }
/// <summary> /// Constructor. /// </summary> public ArbiterSlimActiveClientStub(IArbiterClient client, ArbiterSlimExecutionStrategy executionStrategy) { _client = client; _executionStrategy = executionStrategy; SystemMonitor.CheckThrow(executionStrategy != null, "Execution strategy not assigned."); Construct(); }
/// <summary> /// Constructor. /// </summary> public ArbiterSlimActiveClientStub(IArbiterClient client) { _client = client; //_executionStrategy = new FrameworkThreadPoolExecutionStrategy(this); _executionStrategy = new ThreadPoolFastExecutionStrategy(this, true); Construct(); }
/// <summary> /// Default constructor. /// </summary> public ArbiterClientId(string name, Type identifiedType, IArbiterClient optionalReference) { _optionalReference = optionalReference; _sessionTag = string.Empty; _id = new ComponentId() { Guid = Guid.NewGuid(), Name = name, IdentifiedComponentType = identifiedType }; }
/// <summary> /// /// </summary> /// <param name="parameter0"></param> protected void _timeOutMonitor_EntityTimedOutEvent(TimeOutable parameter0) { Conversation conversation = (Conversation)parameter0; IArbiterClient client = GetClientByID(conversation.OwnerID, false); if (client != null) { client.ReceiveConversationTimedOut(conversation); } }
/// <summary> /// /// </summary> /// <param name="client"></param> /// <returns></returns> public bool RemoveClient(IArbiterClient client) { if (_isDisposed) {// Possible to get disposed while operating here. return(false); } lock (_clientsAndFilters) { client.ArbiterUnInitialize(); return(_clientsAndFilters.Remove(client) && _clientsIdsAndClients.Remove(client.SubscriptionClientID)); } }
/// <summary> /// Add a client to the arbiter, will raise the ClientAddedEvent if successful. /// </summary> public bool AddClient(IArbiterClient client) { if (client == null || GetClientByID(client.SubscriptionClientID, false) != null) { return(false); } if (_isDisposed) {// Possible to get disposed while operating here. return(false); } lock (_clientsAndFilters) { if (_clientsAndFilters.ContainsKey(client)) { return(false); } _clientsAndFilters.Add(client, client.SubscriptionMessageFilter); } lock (_clientsIdsAndClients) { _clientsIdsAndClients.Add(client.SubscriptionClientID, client); } if (client.ArbiterInitialize(this) == false || _isDisposed) { lock (_clientsAndFilters) { _clientsAndFilters.Remove(client); } lock (_clientsIdsAndClients) { _clientsIdsAndClients.Remove(client.SubscriptionClientID); } SystemMonitor.OperationError("Client failed arbiter initialialization [" + client.Name + "]"); return(false); } ClientManagerClientUpdateDelegate clientAddedDelegate = ClientAddedEvent; if (clientAddedDelegate != null) { clientAddedDelegate(this, client); } return(true); }
/// <summary> /// The direct call allows to circumvent the many steps (incl serialization) of typical message sending /// and make a direct call to another Arbiter member; thus making a much faster delivery. This path /// has a maximum optimization for speed, so tracing etc. are disabled. /// /// Also this mechanism only works for TransportClients currently. /// /// The mechanism does not utilize any new threads, and the execution is performed on the calling thread. /// /// Direct calls can only be made to participants on the same arbiter, and no addressing is applied /// for the messages. /// </summary> public Message DirectCall(ArbiterClientId senderID, ArbiterClientId receiverID, Message message) { IArbiterClient receiver = GetClientByID(receiverID, true); if (receiver == null || receiver is TransportClient == false) { SystemMonitor.OperationWarning("Sender [" + senderID.Id.Print() + "] creating conversation message [" + message.GetType().Name + " ] by not present receiver [" + receiverID.Id.Print() + "] or receiver not a TransportClient"); return(null); } Message response = receiver.ReceiveDirectCall(message); return(response); }
/// <summary> /// Add a client to the arbiter, will raise the ClientAddedEvent if successful. /// </summary> public bool AddClient(IArbiterClient client) { if (client == null || GetClientByID(client.SubscriptionClientID, false) != null) { return false; } if (_isDisposed) {// Possible to get disposed while operating here. return false; } lock (_clientsAndFilters) { if (_clientsAndFilters.ContainsKey(client)) { return false; } _clientsAndFilters.Add(client, client.SubscriptionMessageFilter); } lock (_clientsIdsAndClients) { _clientsIdsAndClients.Add(client.SubscriptionClientID, client); } if (client.ArbiterInitialize(this) == false || _isDisposed) { lock (_clientsAndFilters) { _clientsAndFilters.Remove(client); } lock (_clientsIdsAndClients) { _clientsIdsAndClients.Remove(client.SubscriptionClientID); } SystemMonitor.OperationError("Client failed arbiter initialialization [" + client.Name + "]"); return false; } ClientManagerClientUpdateDelegate clientAddedDelegate = ClientAddedEvent; if (clientAddedDelegate != null) { clientAddedDelegate(this, client); } return true; }
/// <summary> /// Remove the client from the arbiter (will raise the ClientRemovedEvent if successful). /// </summary> public bool RemoveClient(IArbiterClient client) { if (_isDisposed) {// Possible to get disposed while operating here. return(false); } bool result = false; lock (_clientsAndFilters) { client.ArbiterUnInitialize(); result = _clientsAndFilters.Remove(client) && _clientsIdsAndClients.Remove(client.SubscriptionClientID); } ClientManagerClientUpdateDelegate clientRemovedDelegate = ClientRemovedEvent; if (result && clientRemovedDelegate != null) { clientRemovedDelegate(this, client); } return(result); }
void arbiter_ClientRemovedEvent(IArbiterClientManager manager, IArbiterClient client) { RemoveClient(client.Slim); }
void arbiter_ClientAddedEvent(IArbiterClientManager manager, IArbiterClient client) { AddClient(client.Slim); }
/// <summary> /// /// </summary> void worker_DoWork(ExecutionEntity entity) { lock (this) { if (_clientsRunningExecutioners.ContainsKey(entity.ReceiverID) == false) { _clientsRunningExecutioners[entity.ReceiverID] = 1; } else { _clientsRunningExecutioners[entity.ReceiverID] = _clientsRunningExecutioners[entity.ReceiverID] + 1; } } TracerHelper.Trace(" Enlisted entity at [" + entity.ReceiverID.Id.Name + "]"); DateTime startTime = DateTime.Now; TracerHelper.TraceEntry("entity starting [" + entity.Message.GetType().Name + ", " + entity.ReceiverID.Id.Name + "], total count [" + _threadPool.ActiveRunningThreadsCount.ToString() + "]"); // Notify executor we are running this entity. entity.Conversation.EntityExecutionStarted(entity); try { IArbiterClient receiver = _arbiter.GetClientByID(entity.ReceiverID); if (receiver != null) { SystemMonitor.CheckError(((TransportMessage)entity.Message).TransportInfo.TransportInfoCount > 0); // Do the entity. if (entity is ExecutionEntityWithReply) { ExecutionEntityWithReply replyEntity = (ExecutionEntityWithReply)entity; SystemMonitor.CheckError(replyEntity.ReplyMessage == null && replyEntity.ReplyTimeOut == TimeSpan.Zero); receiver.ReceiveExecutionWithReply(replyEntity); } else { SystemMonitor.CheckError(entity.GetType() == typeof(ExecutionEntity)); receiver.ReceiveExecution(entity); } entity.Conversation.EntityExecutionFinished(entity); } } catch (TargetInvocationException exception) { if (exception.InnerException is ThreadInterruptedException) {// ThreadInterruptedException's are OK, since we use them to awake sleeping threads when closing down. SystemMonitor.Report(exception.ToString() + "[" + exception.InnerException.Message + "]"); entity.Conversation.EntityExecutionFailed(entity, exception); } else { SystemMonitor.OperationError(exception.ToString() + "[" + exception.InnerException.Message + "]"); entity.Conversation.EntityExecutionFailed(entity, exception); } } catch (ThreadInterruptedException exception) { // ThreadInterruptedException's are OK, since we use them to awake sleeping threads when closing down. SystemMonitor.Report(exception.ToString() + "[" + exception.Message + "]"); entity.Conversation.EntityExecutionFailed(entity, exception); } catch (Exception exception) { SystemMonitor.Error(exception.ToString()); entity.Conversation.EntityExecutionFailed(entity, exception); } finally { entity.Die(); } lock (this) { if (_clientsRunningExecutioners.ContainsKey(entity.ReceiverID)) { int newClientsValue = _clientsRunningExecutioners[entity.ReceiverID] - 1; if (newClientsValue <= 0) { _clientsRunningExecutioners.Remove(entity.ReceiverID); } else { _clientsRunningExecutioners[entity.ReceiverID] = newClientsValue; } } else { if (IsDisposed == false) { SystemMonitor.Error("ClientsRunningExecutioners not properly maintained."); } } TracerHelper.TraceExit("entity finished for [" + (DateTime.Now - startTime).Milliseconds + "]ms [" + entity.Message.GetType().Name + ", " + entity.ReceiverID.Id.Name + "], total count [" + _threadPool.ActiveRunningThreadsCount.ToString() + "]"); } // Continue execution chain. UpdatePendingExecution(); }
/// <summary> /// Remove the client from the arbiter (will raise the ClientRemovedEvent if successful). /// </summary> public bool RemoveClient(IArbiterClient client) { if (_isDisposed) {// Possible to get disposed while operating here. return false; } bool result = false; lock (_clientsAndFilters) { client.ArbiterUnInitialize(); result = _clientsAndFilters.Remove(client) && _clientsIdsAndClients.Remove(client.SubscriptionClientID); } ClientManagerClientUpdateDelegate clientRemovedDelegate = ClientRemovedEvent; if (result && clientRemovedDelegate != null) { clientRemovedDelegate(this, client); } return result; }
/// <summary> /// /// </summary> /// <param name="client"></param> /// <returns></returns> public bool RemoveClient(IArbiterClient client) { if (_isDisposed) {// Possible to get disposed while operating here. return false; } lock (_clientsAndFilters) { client.ArbiterUnInitialize(); return _clientsAndFilters.Remove(client) && _clientsIdsAndClients.Remove(client.SubscriptionClientID); } }