/// <summary> /// The Activate method is invoked to instruct the IPC module /// to start asynchronously processing IO. /// </summary> public void Activate() { if (_moduleState == ModuleStates.Module_State_Shutdown) { _moduleState = ModuleStates.Module_State_Active; // REC: Disable the Nagle algorithm: _socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); // REC: Dispatch the Event_Opened event to the // module's owner: EventHandler <VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { tmp(this, new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Opened)); } // REC: Initiate the first receive operation against the // socket associated with the module. As receive operations // complete, the completion handler will take care of all the // subsequent IO context generation / management: IoContext rxContext = new IoContext(_socket, new VfxMsgBlock(8192)); InitiateRecv(rxContext); } }
/// <summary> /// The Shutdown method is invoked to instruct the module /// to terminate the connection to the peer system. If the /// graceful flag is set to true, then the module will wait /// until all pending I/O operations are completed before /// </summary> /// <param name="graceful"></param> public void Shutdown(bool graceful) { if (_moduleState == ModuleStates.Module_State_Active) { _moduleState = ModuleStates.Module_State_Closing; if (graceful == false) { // REC: Remove all pending send operations // from the queue and return their buffers // to the buffer pool: lock (_synchTxContextQueue) { while (_txContextQueue.Count > 0) { IoContext txContext = _txContextQueue.Dequeue(); txContext._ipcBuffer.RdIndex = 0; txContext._ipcBuffer.WrIndex = 0; lock (_synchIoContextQueue) { _ioContextQueue.Enqueue(txContext); } } } // REC: Close the socket that is being // used to send data to the client: _socket.Close(); } else { } } }
private OneStateTransition GetOneChangeTransition(SystemState anotherSystemState) { var transitionPairs = ModuleStates .Zip(anotherSystemState.ModuleStates, (from, to) => new OneStateTransition(from, to)) .ToList(); var notEqualPairs = transitionPairs.Where(pair => !pair.From.Equals(pair.To)).ToList(); if (notEqualPairs.Count != 1) { return(null); } var transition = notEqualPairs.Single(); return(transition.From.IsValidStateChangeTo(transition.To) ? transition : null); }
public ModuleInfo(string name, string installedVersion, string currentVersion, Guid?moduleId = null) { _name = name; _installedVersion = installedVersion; _currentVersion = currentVersion; _moduleId = moduleId; if (installedVersion == null) { _status = ModuleStates.NotYetInstalled; } else if (_currentVersion == null) { _status = ModuleStates.Unreferenced; } else if (installedVersion == _currentVersion) { _status = ModuleStates.UpToDate; } else { _status = ModuleStates.ToBeUpdated; } }
public override string ToString() => $"[{string.Join("", ModuleStates.Select(state => state.ToString()))}]";
/// <summary> /// The CompleteRecv method is invoked in response to /// an asynchronous receive operation completing. /// </summary> /// <param name="ar"></param> private void CompleteRecv(IAsyncResult ar) { // REC: Retrieve the IO context that is associated with the // original asynchronous receive operation. IoContext rxContext = ar.AsyncState as IoContext; if (rxContext != null) { try { // REC: Get the total number of bytes that were read // from the peer system by this operation: int rxBytes = rxContext._ipcSocket.EndReceive(ar); if (rxBytes > 0) { // REC: Adjust the write index in the message block: rxContext._ipcBuffer.WrIndex = rxContext._ipcBuffer.WrIndex + rxBytes; // REC: Offload the received data onto a separate thread: if (this._rxBuffering == true) { Socket rxSocket = rxContext._ipcSocket; lock (this._synchRxPendingQueue) { // REC: Push the received data onto the queue so that // it can be picked up by the secondary receive thread // for further processing: this._rxPendingQueue.Enqueue(rxContext); // REC: If the queue was empty prior to this context // being added to it, we need to signal the secondary // receive thread so that it can start processing the // data again: if (this._rxPendingQueue.Count == 1) { this._eventRxBuffer.Set(); } } // REC: Attempt to pull another context from the context // queue so that we can receive more data: IoContext rxNext; if (this._rxContextQueue.Count > 0) { rxNext = this._rxContextQueue.Dequeue(); } else { // REC: Note that this is BAD and will result in the // exhaustion of all the system's memory if there is a // continuous problem with the speed at which messages // are being consumed on the receive thread... rxNext = new IoContext(rxSocket, new VfxMsgBlock(8192)); } // REC: Initiate a new receive operation, using the next // available receive context: InitiateRecv(rxNext); } else { // REC: If receive buffering has not been enabled then the // data is dispatched directly to the module's owner: EventHandler <VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { tmp(this, new VfxIpcEventArgs(rxContext._ipcBuffer)); // REC: Adjust the buffer to take into consideration // any data that was read by the module's owner: rxContext._ipcBuffer.Crunch(); // REC: Initiate another receive operation using the // same receive buffer that was just processed: InitiateRecv(rxContext); } } } else { _moduleState = ModuleStates.Module_State_Shutdown; // REC: This might happen as the result of the // user closing the session down. EventHandler <VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { VfxIpcEventArgs dxArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Closed); tmp(this, dxArgs); } } } catch (SocketException) { _moduleState = ModuleStates.Module_State_Shutdown; // REC: This might happen as the result of the // user closing the session down. EventHandler <VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { VfxIpcEventArgs dxArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Closed); tmp(this, dxArgs); } } catch (ObjectDisposedException) { _moduleState = ModuleStates.Module_State_Shutdown; // REC: This happens if the socket gets closed // locally rather than being closed by the peer. EventHandler <VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { VfxIpcEventArgs dxArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Closed); tmp(this, dxArgs); } } } }
/// <summary> /// The CompleteSend event handler is invoked in response to an /// asynchronous send operation being completed. The system reacts /// to the completion by finalizing the asynchronous operation and /// then starting a new one. /// </summary> /// <param name="ar"></param> private void CompleteSend(IAsyncResult ar) { IoContext ctx = ar.AsyncState as IoContext; if (ctx != null) { int txBytes = ctx._ipcSocket.EndSend(ar); if (txBytes > 0) { // REC: If the system did not transmit all of the data // that was in the IO context buffer then it initiates // a new send operation against the residual content: if (txBytes < ctx._ipcBuffer.Length()) { // REC: Adjust the read index... ctx._ipcBuffer.RdIndex += txBytes; ctx._ipcBuffer.Crunch(); // REC: and try to send it again... InitiateSend(ctx, true); } else { lock (_synchIoContextQueue) { // REC: Reset the message block's // read and write indices: ctx._ipcBuffer.RdIndex = 0; ctx._ipcBuffer.WrIndex = 0; // REC: Return the buffer to the // pool so it can be used again: _ioContextQueue.Enqueue(ctx); // REC: If there were no contexts remaining // in the transmit queue when this one was // returned to it, trigger the buffer event // so that HandleTx can acquire one: if (_ioContextQueue.Count == 1) { _eventTxBuffer.Set(); } } lock (_synchTxContextQueue) { if (_txContextQueue.Count > 0) { IoContext next = _txContextQueue.Dequeue(); InitiateSend(next, true); } else { _txPending = false; // REC: If the module is being shutdown // and there are no further pending sends // left to process, generate the shutdown // event to notify the module's owner: if (_moduleState == ModuleStates.Module_State_Closing) { _moduleState = ModuleStates.Module_State_Shutdown; // REC: Close the socket to ensure that the // disconnect event is triggered: _socket.Close(); } } } } } } }
/// <summary> /// The CompleteRecv method is invoked in response to /// an asynchronous receive operation completing. /// </summary> /// <param name="ar"></param> private void CompleteRecv(IAsyncResult ar) { // REC: Retrieve the IO context that is associated with the // original asynchronous receive operation. IoContext rxContext = ar.AsyncState as IoContext; if (rxContext != null) { try { // REC: Get the total number of bytes that were read // from the peer system by this operation: int rxBytes = rxContext._ipcSocket.EndReceive(ar); if (rxBytes > 0) { // REC: Adjust the write index in the message block: rxContext._ipcBuffer.WrIndex = rxContext._ipcBuffer.WrIndex + rxBytes; // REC: Offload the received data onto a separate thread: if (this._rxBuffering == true) { Socket rxSocket = rxContext._ipcSocket; lock (this._synchRxPendingQueue) { // REC: Push the received data onto the queue so that // it can be picked up by the secondary receive thread // for further processing: this._rxPendingQueue.Enqueue(rxContext); // REC: If the queue was empty prior to this context // being added to it, we need to signal the secondary // receive thread so that it can start processing the // data again: if (this._rxPendingQueue.Count == 1) { this._eventRxBuffer.Set(); } } // REC: Attempt to pull another context from the context // queue so that we can receive more data: IoContext rxNext; if (this._rxContextQueue.Count > 0) { rxNext = this._rxContextQueue.Dequeue(); } else { // REC: Note that this is BAD and will result in the // exhaustion of all the system's memory if there is a // continuous problem with the speed at which messages // are being consumed on the receive thread... rxNext = new IoContext(rxSocket, new VfxMsgBlock(8192)); } // REC: Initiate a new receive operation, using the next // available receive context: InitiateRecv(rxNext); } else { // REC: If receive buffering has not been enabled then the // data is dispatched directly to the module's owner: EventHandler<VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { tmp(this, new VfxIpcEventArgs(rxContext._ipcBuffer)); // REC: Adjust the buffer to take into consideration // any data that was read by the module's owner: rxContext._ipcBuffer.Crunch(); // REC: Initiate another receive operation using the // same receive buffer that was just processed: InitiateRecv(rxContext); } } } else { _moduleState = ModuleStates.Module_State_Shutdown; // REC: This might happen as the result of the // user closing the session down. EventHandler<VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { VfxIpcEventArgs dxArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Closed); tmp(this, dxArgs); } } } catch (SocketException) { _moduleState = ModuleStates.Module_State_Shutdown; // REC: This might happen as the result of the // user closing the session down. EventHandler<VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { VfxIpcEventArgs dxArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Closed); tmp(this, dxArgs); } } catch (ObjectDisposedException) { _moduleState = ModuleStates.Module_State_Shutdown; // REC: This happens if the socket gets closed // locally rather than being closed by the peer. EventHandler<VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { VfxIpcEventArgs dxArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Closed); tmp(this, dxArgs); } } } }
/// <summary> /// The Activate method is invoked to instruct the IPC module /// to start asynchronously processing IO. /// </summary> public void Activate() { if (_moduleState == ModuleStates.Module_State_Shutdown) { _moduleState = ModuleStates.Module_State_Active; // REC: Disable the Nagle algorithm: _socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); // REC: Dispatch the Event_Opened event to the // module's owner: EventHandler<VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { tmp(this, new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Opened)); } // REC: Initiate the first receive operation against the // socket associated with the module. As receive operations // complete, the completion handler will take care of all the // subsequent IO context generation / management: IoContext rxContext = new IoContext(_socket, new VfxMsgBlock(8192)); InitiateRecv(rxContext); } }