Exemple #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Message"/> class.
 /// </summary>
 /// <param name="address">The address the message is to be sent to.</param>
 /// <param name="data">The data to be sent in the message.</param>
 /// <param name="waitingForResponse">Whether the message is waiting for a response.</param>
 public Message(NodeDefinition address, BaseMessageData data, bool waitingForResponse)
 {
     _address            = address;
     _data               = data;
     _status             = MessageStatus.Created;
     _id                 = GetNextId();
     _waitingForResponse = waitingForResponse;
 }
Exemple #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Message"/> class.
 /// </summary>
 /// <param name="responseTo">The message this is in response to.</param>
 /// <param name="data">The data to be sent in the message.</param>
 /// <param name="waitingForResponse">Whether the message is waiting for a response.</param>
 public Message(Message responseTo, BaseMessageData data, bool waitingForResponse)
 {
     _address            = responseTo.Address;
     _inResponseTo       = responseTo._id;
     _data               = data;
     _status             = MessageStatus.Created;
     _id                 = GetNextId();
     _waitingForResponse = waitingForResponse;
 }
Exemple #3
0
        /// <summary>
        /// Decodes the received message.
        /// </summary>
        /// <param name="data">The data to be decoded.</param>
        private void DecodeMessage(byte[] data)
        {
            int index = 0;

            _id                 = ByteArrayHelper.ToUInt32(data, ref index);
            _inResponseTo       = ByteArrayHelper.ToUInt32(data, ref index);
            _waitingForResponse = ByteArrayHelper.ToBoolean(data, ref index);
            _data               = BaseMessageData.Decode(data, index);
        }
Exemple #4
0
        /// <summary>
        /// Attempts to merge the database chunks.
        /// </summary>
        private void AttemptMerge()
        {
            BaseMessageData message = null;

            _checkForMerge = false;

            _lock.EnterUpgradeableReadLock();

            for (int i = 0; i < _chunks.Count - 1; ++i)
            {
                if (_chunks[i].Count + _chunks[i + 1].Count < _maxChunkItemCount / 2 &&
                    Equals(_chunks[i].End, _chunks[i + 1].Start))
                {
                    _checkForMerge = true;

                    if (_node.Primary == null)
                    {
                        break;
                    }

                    Message canMerge = new Message(_node.Primary, new ChunkManagementRequest(), true);
                    _node.SendDatabaseMessage(canMerge);
                    canMerge.BlockUntilDone();
                    if (canMerge.Success && ((ChunkManagementResponse)canMerge.Response.Data).Result)
                    {
                        _lock.EnterWriteLock();

                        // Merging two chunks, do the merge and then alert the primary controller before doing anything else.
                        _chunks[i].Merge(_chunks[i + 1]);
                        _chunks.RemoveAt(i + 1);
                        message = new ChunkMerge(_chunks[i].Start, _chunks[i].End);

                        _lock.ExitWriteLock();
                    }

                    break;
                }
            }

            _lock.ExitUpgradeableReadLock();

            if (message != null)
            {
                Message sentMessage = new Message(_node.Primary, message, true);
                _node.SendDatabaseMessage(sentMessage);
                sentMessage.BlockUntilDone();
            }
        }
Exemple #5
0
        /// <summary>
        /// Attempts to split the database chunks.
        /// </summary>
        private void AttemptSplit()
        {
            BaseMessageData message = null;

            _checkForSplit = false;

            _lock.EnterUpgradeableReadLock();

            for (int i = 0; i < _chunks.Count; ++i)
            {
                if (_chunks[i].Count > _maxChunkItemCount)
                {
                    _checkForSplit = true;
                    if (_node.Primary == null)
                    {
                        break;
                    }

                    Message canSplit = new Message(_node.Primary, new ChunkManagementRequest(), true);
                    _node.SendDatabaseMessage(canSplit);
                    canSplit.BlockUntilDone();
                    if (canSplit.Success && ((ChunkManagementResponse)canSplit.Response.Data).Result)
                    {
                        _lock.EnterWriteLock();

                        // Spliting a chunk, do the split and then alert the primary controller before doing anything else.
                        _chunks.Insert(i + 1, _chunks[i].Split());
                        message = new ChunkSplit(_chunks[i].Start, _chunks[i].End, _chunks[i + 1].Start, _chunks[i + 1].End);

                        _lock.ExitWriteLock();
                    }

                    break;
                }
            }

            _lock.ExitUpgradeableReadLock();

            if (message != null)
            {
                Message sentMessage = new Message(_node.Primary, message, true);
                _node.SendDatabaseMessage(sentMessage);
                sentMessage.BlockUntilDone();
            }
        }
Exemple #6
0
        private async void ReadMessages()
        {
            WebSocketReceiveResult webSocketReceiveResult = null;
            string lastMessage = null;

            try
            {
                readers.AddCount();

                while (true)
                {
                    await CheckConnectionOrWait();

                    bool readCompleted = false;

                    try
                    {
                        webSocketReceiveResult = await clientWebSocket.ReceiveAsync(incomingData, readerTokenSource.Token);

                        readCompleted = true;
                    }
                    catch (TaskCanceledException) { /* swallow */ }
                    catch (ThreadAbortException) { /* swallow */ }
                    catch (ObjectDisposedException) { /* swallow */ }
                    catch (OperationCanceledException) { /* swallow */ }
                    catch (WebSocketException)
                    {
                        communication.SendWarningMessage($"PubSub Websocket closed unexpectedly.");
                    }
                    catch (Exception ex)
                    {
                        communication.SendErrorMessage($"PubSub Exception: {ex.GetType().Name}");
                        errorHandler.LogMessageException(ex, "");
                    }

                    if (generalTokenSource.IsCancellationRequested)
                    {
                        //We are quitting
                        break;
                    }

                    if ((readerTokenSource?.IsCancellationRequested ?? true) || !readCompleted)
                    {
                        //We are just restarting reader, since it was intercepted with an exception or the reader token source was cancelled
                        continue;
                    }

                    if (webSocketReceiveResult.Count < 1)
                    {
                        await Task.Delay(100, generalTokenSource.Token);

                        continue;
                    }

                    lastMessage = Encoding.UTF8.GetString(incomingData, 0, webSocketReceiveResult.Count);

                    while (!webSocketReceiveResult.EndOfMessage)
                    {
                        readCompleted = false;
                        try
                        {
                            webSocketReceiveResult = await clientWebSocket.ReceiveAsync(incomingData, readerTokenSource.Token);

                            readCompleted = true;
                        }
                        catch (TaskCanceledException) { /* swallow */ }
                        catch (ThreadAbortException) { /* swallow */ }
                        catch (ObjectDisposedException) { /* swallow */ }
                        catch (OperationCanceledException) { /* swallow */ }
                        catch (WebSocketException)
                        {
                            communication.SendWarningMessage($"PubSub Websocket closed unexpectedly.");
                        }
                        catch (Exception ex)
                        {
                            communication.SendErrorMessage($"PubSub Exception: {ex.GetType().Name}");
                            errorHandler.LogMessageException(ex, "");
                        }

                        if (generalTokenSource.IsCancellationRequested)
                        {
                            //We are quitting
                            break;
                        }

                        if ((readerTokenSource?.IsCancellationRequested ?? true) || !readCompleted)
                        {
                            //We are just restarting reader, since it was intercepted with an exception or the reader token source was cancelled
                            break;
                        }

                        if (webSocketReceiveResult.Count < 1)
                        {
                            communication.SendWarningMessage($"WebSocketMessage returned no characters despite not being at end.  {lastMessage}");
                            break;
                        }

                        lastMessage += Encoding.UTF8.GetString(incomingData, 0, webSocketReceiveResult.Count);
                    }


                    if (generalTokenSource.IsCancellationRequested)
                    {
                        //We are quitting
                        break;
                    }

                    if ((readerTokenSource?.IsCancellationRequested ?? true) || !readCompleted)
                    {
                        //We are just restarting reader, since it was intercepted with an exception or the reader token source was cancelled
                        continue;
                    }

                    BasicPubSubMessage message = JsonSerializer.Deserialize <BasicPubSubMessage>(lastMessage);

                    switch (message.TypeString)
                    {
                    case "PONG":
                        pongReceived = true;
                        break;

                    case "PING":
                        await SendMessage(pongMessage);

                        break;

                    case "RECONNECT":
                        communication.SendDebugMessage($"PubSub Reconnect Message Received");
                        breakConnection = true;
                        break;

                    case "RESPONSE":
                    {
                        PubSubResponseMessage response    = JsonSerializer.Deserialize <PubSubResponseMessage>(lastMessage);
                        PubSubMessage         sentMessage = sentMessages.Where(x => x.Nonce == response.Nonce).FirstOrDefault();

                        if (!string.IsNullOrEmpty(response.ErrorString))
                        {
                            if (sentMessage is not null)
                            {
                                communication.SendErrorMessage($"Error with message {JsonSerializer.Serialize(sentMessage)}: {response.ErrorString}");
                            }
                            else
                            {
                                communication.SendErrorMessage($"Error with message <Unable To Locate>: {response.ErrorString}");
                            }
                        }

                        if (sentMessage is not null)
                        {
                            sentMessages.Remove(sentMessage);
                        }
                    }
                    break;

                    case "MESSAGE":
                    {
                        ListenResponse listenResponse = JsonSerializer.Deserialize <ListenResponse>(lastMessage);

                        BaseMessageData messageData = JsonSerializer.Deserialize <BaseMessageData>(listenResponse.Data.Message);

                        switch (messageData.TypeString)
                        {
                        case "reward-redeemed":
                            ChannelPointMessageData channelPointMessageData = JsonSerializer.Deserialize <ChannelPointMessageData>(listenResponse.Data.Message);
                            redemptionHandler.HandleRedemption(channelPointMessageData.Data);
                            break;

                        default:
                            communication.SendErrorMessage($"Unsupported PubSub Message: {messageData.TypeString} - {listenResponse.Data.Message}");
                            break;
                        }
                    }
                    break;

                    default:
                        communication.SendErrorMessage($"Unsupported PubSub Message Type: {message.TypeString} - {lastMessage}");
                        break;
                    }
                }
            }
            catch (TaskCanceledException) { /* swallow */ }
            catch (ThreadAbortException) { /* swallow */ }
            catch (ObjectDisposedException) { /* swallow */ }
            catch (OperationCanceledException) { /* swallow */ }
            catch (Exception ex)
            {
                communication.SendErrorMessage($"PubSub Exception: {ex.GetType().Name}");
                if (lastMessage is not null)
                {
                    communication.SendErrorMessage($"Last PubSub Message: {lastMessage}");
                }

                errorHandler.LogMessageException(ex, "");
            }
            finally
            {
                readers.Signal();
            }
        }