Esempio n. 1
0
        /// <summary>
        /// Return 'true' if at least one request has been processed, 'false' otherwise.
        /// </summary>
        public bool HandleRequest()
        {
            if (!_inbox.CanPeek)
            {
                return(false);
            }

            var next = _inbox.Peek().Span;

            try
            {
                var message = new Message(next);
                var kind    = message.Header.MessageKind;
                var mask    = message.Header.ClientId.Mask;

                Span <byte> response;
                switch (kind)
                {
                case MessageKind.OpenBlock:
                    response = OpenBlock(new OpenBlockRequest(message.Span, mask)).Span;
                    break;

                case MessageKind.GetBlockHandle:
                    response = GetBlockHandle(new GetBlockHandleRequest(message.Span, mask)).Span;
                    break;

                case MessageKind.CommitBlock:
                    response = CommitBlock(new CommitBlockRequest(message.Span, mask)).Span;
                    break;

                case MessageKind.GetBlockInfo:
                    response = GetBlockInfo(new GetBlockInfoRequest(message.Span, mask));
                    break;

                default:
                    throw new NotSupportedException();
                }

                while (!_outbox.TryWrite(response))
                {
                    _log?.Log(LogSeverity.Warning, $"ChainController can't write the response to {kind}.");
                    // Pathological situation, we don't want to overflow the logger.
                    Thread.Sleep(1000);
                }
            }
            finally
            {
                _pool.Reset();
                _inbox.Next();
            }

            return(true);
        }
Esempio n. 2
0
        /// <remarks>
        /// Returned <paramref name="value"/> is valid till next call to
        /// TryGet.
        /// </remarks>
        public bool TryGet(T key, out Span <byte> value)
        {
            _pool.Reset(); // clear previous Get result and free some space.
            var keySpan = MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref key, 1));

            using (var tx = _env.BeginTransaction(TransactionBeginFlags.ReadOnly))
                using (var db = tx.OpenDatabase(_dbName))
                {
                    bool result = tx.TryGet(db, keySpan, out var valueSpan);
                    if (result)
                    {
                        value = GetSpan(valueSpan.Length);
                        valueSpan.CopyTo(value);
                    }
                    else
                    {
                        value = Span <byte> .Empty;
                    }

                    return(result);
                }
        }
Esempio n. 3
0
        public bool HandleResponse()
        {
            if (!_outbox.CanPeek)
            {
                return(false);
            }

            var next = _outbox.Peek().Span;

            try
            {
                var message = new Message(next);
                var kind    = message.Header.MessageKind;

                // Remove client ID from message
                message.Header.ClientId = default;

                if (_requestsInProgress >= ResponseBatchSize || _responseCountInPool > 0)
                {
                    var nextResponse = _responsePool.GetSpan(next.Length);
                    next.CopyTo(nextResponse);
                    _responseCountInPool++;

                    if (_responseCountInPool >= ResponseBatchSize)
                    {
                        _socket.Send(_responsePool.Allocated());
                        _responsePool.Reset();
                        _responseCountInPool = 0;
                    }
                }
                else
                {
                    _socket.Send(next);
                }

                Interlocked.Decrement(ref _requestsInProgress);

                // Some responses trigger the termination of the controller.
                if (kind == MessageKind.CloseConnectionResponse ||
                    kind == MessageKind.ProtocolErrorResponse)
                {
                    if (kind == MessageKind.ProtocolErrorResponse)
                    {
                        var protocolResponse = new ProtocolErrorResponse(next);
                        _log?.Log(LogSeverity.Info, $"ConnectionController({ClientId}) on protocol error {protocolResponse.Status}.");
                    }

                    if (_responseCountInPool > 0)
                    {
                        _socket.Send(_responsePool.Allocated());
                        _responsePool.Reset();
                        _responseCountInPool = 0;
                    }

                    _tokenSource.Cancel();
                }
            }
            finally
            {
                _outbox.Next();
            }

            return(true);
        }