Ejemplo n.º 1
0
        /// <inheritdoc />
        protected override void MessageReceived(Message message)
        {
            if (message.Data is JoinAttempt)
            {
                JoinAttempt attempt = (JoinAttempt)message.Data;
                if (attempt.Type != NodeType.Api)
                {
                    SendMessage(new Message(message, new JoinFailure("Only an API node can send a join attempt to a query node."), false)
                    {
                        SendWithoutConfirmation = true
                    });
                }

                if (attempt.Settings != _settings.ConnectionString)
                {
                    SendMessage(new Message(message, new JoinFailure("The connection strings do not match."), false)
                    {
                        SendWithoutConfirmation = true
                    });
                }

                Connections[message.Address].ConnectionEstablished(message.Address, attempt.Type);
                var response = new Message(message, new JoinSuccess(new Document()), true);
                SendMessage(response);
                response.BlockUntilDone();
            }
            else if (message.Data is PrimaryAnnouncement)
            {
                Logger.Log("Setting the primary controller to " + message.Address.ConnectionName, LogLevel.Info);
                Primary = message.Address;
            }
            else if (message.Data is NodeList)
            {
                lock (_connectedStorageNodes)
                {
                    _connectedStorageNodes.Clear();
                    _connectedStorageNodes.AddRange(((NodeList)message.Data).Nodes.Select(e => new NodeDefinition(e.Split(':')[0], int.Parse(e.Split(':')[1]))));

                    var connections = GetConnectedNodes();
                    foreach (var item in _connectedStorageNodes)
                    {
                        if (!connections.Any(e => Equals(e.Item1, item)))
                        {
                            Message attempt = new Message(item, new JoinAttempt(NodeType.Query, _settings.NodeName, _settings.Port, _settings.ConnectionString), true)
                            {
                                SendWithoutConfirmation = true
                            };

                            SendMessage(attempt);
                            attempt.BlockUntilDone();

                            if (attempt.Success)
                            {
                                if (attempt.Response.Data is JoinFailure)
                                {
                                    Logger.Log("Failed to join storage node: " + ((JoinFailure)attempt.Response.Data).Reason, LogLevel.Error);
                                }
                                else
                                {
                                    Connections[item].ConnectionEstablished(item, NodeType.Storage);
                                    SendMessage(new Message(attempt.Response, new Acknowledgement(), false));
                                }
                            }
                        }
                    }
                }
            }
            else if (message.Data is DataOperation)
            {
                DataOperation op            = (DataOperation)message.Data;
                Document      dataOperation = new Document(op.Json);
                if (!dataOperation.Valid)
                {
                    SendMessage(new Message(message, new DataOperationResult(ErrorCodes.InvalidDocument, "The document is invalid."), false));
                    return;
                }

                try
                {
                    ProcessDataOperation(dataOperation, message);
                }
                catch (Exception e)
                {
                    Logger.Log(e.Message + "\nStackTrace:" + e.StackTrace, LogLevel.Error);
                    SendMessage(new Message(message, new DataOperationResult(ErrorCodes.FailedMessage, "An exception occurred while processing the operation."), false));
                }
            }
            else if (message.Data is ChunkListUpdate)
            {
                _chunkListLock.EnterWriteLock();
                _chunkList = ((ChunkListUpdate)message.Data).ChunkList;
                _chunkListLock.ExitWriteLock();
                SendMessage(new Message(message, new Acknowledgement(), false));
            }
        }
Ejemplo n.º 2
0
        /// <inheritdoc />
        protected override void MessageReceived(Message message)
        {
            if (message.Data is JoinAttempt)
            {
                JoinAttempt attempt = (JoinAttempt)message.Data;
                if (attempt.Type != NodeType.Query && attempt.Type != NodeType.Storage)
                {
                    SendMessage(new Message(message, new JoinFailure("Only a query node can send a join attempt to a storage node."), false)
                    {
                        SendWithoutConfirmation = true
                    });
                }

                if (attempt.Settings != _settings.ConnectionString)
                {
                    SendMessage(new Message(message, new JoinFailure("The connection strings do not match."), false)
                    {
                        SendWithoutConfirmation = true
                    });
                }

                NodeDefinition nodeDef = new NodeDefinition(attempt.Name, attempt.Port);
                RenameConnection(message.Address, nodeDef);
                Connections[nodeDef].ConnectionEstablished(nodeDef, attempt.Type);
                Message response = new Message(message, new JoinSuccess(new Document()), true)
                {
                    Address = nodeDef
                };

                SendMessage(response);
                response.BlockUntilDone();
            }
            else if (message.Data is PrimaryAnnouncement)
            {
                Logger.Log("Setting the primary controller to " + message.Address.ConnectionName, LogLevel.Info);
                Primary = message.Address;
            }
            else if (message.Data is DataOperation)
            {
                DataOperationResult result;
                try
                {
                    result = _database.ProcessOperation((DataOperation)message.Data);
                }
                catch (ChunkMovedException)
                {
                    result = new DataOperationResult(ErrorCodes.ChunkMoved, "The chunk has been moved.");
                }
                catch (Exception e)
                {
                    Logger.Log(e.Message + "\nStackTrace:" + e.StackTrace, LogLevel.Error);
                    result = new DataOperationResult(ErrorCodes.FailedMessage, "An exception occurred while processing the operation.");
                }

                SendMessage(new Message(message, result, false));
            }
            else if (message.Data is DatabaseCreate)
            {
                _database.Create();
                SendMessage(new Message(message, new Acknowledgement(), false));
            }
            else if (message.Data is ChunkTransfer)
            {
                var transfer = (ChunkTransfer)message.Data;
                MessageReceivedThreadPool.QueueWorkItem(TransferChunk, transfer);
            }
            else if (message.Data is ChunkDataRequest)
            {
                _database.ProcessChunkDataRequest((ChunkDataRequest)message.Data, message);
            }
            else if (message.Data is ChunkListRequest)
            {
                _database.ProcessChunkListRequest(message, (ChunkListRequest)message.Data);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Handles a <see cref="JoinAttempt"/> message.
        /// </summary>
        /// <param name="message">The message that was received.</param>
        /// <param name="joinAttemptData">The <see cref="JoinAttempt"/> that was received.</param>
        private void HandleJoinAttemptMessage(Message message, JoinAttempt joinAttemptData)
        {
            switch (joinAttemptData.Type)
            {
            case NodeType.Controller:
                ControllerNodeSettings joinSettings = new ControllerNodeSettings(joinAttemptData.Settings);
                if (joinSettings.ConnectionString != _settings.ConnectionString)
                {
                    SendMessage(new Message(message, new JoinFailure("Connection strings do not match."), false)
                    {
                        SendWithoutConfirmation = true
                    });
                }
                else if (joinSettings.MaxChunkItemCount != _settings.MaxChunkItemCount)
                {
                    SendMessage(new Message(message, new JoinFailure("Max chunk item counts do not match."), false)
                    {
                        SendWithoutConfirmation = true
                    });
                }
                else if (joinSettings.RedundantNodesPerLocation != _settings.RedundantNodesPerLocation)
                {
                    SendMessage(new Message(message, new JoinFailure("Redundent nodes per location do not match."), false)
                    {
                        SendWithoutConfirmation = true
                    });
                }
                else
                {
                    NodeDefinition nodeDef = new NodeDefinition(joinAttemptData.Name, joinAttemptData.Port);
                    if (Equals(message.Address, nodeDef))
                    {
                        Logger.Log("Duplicate connection found. Not recognizing new connection in favor of the old one.", LogLevel.Info);
                    }

                    RenameConnection(message.Address, nodeDef);
                    Connections[nodeDef].ConnectionEstablished(nodeDef, joinAttemptData.Type);
                    Message response = new Message(message, new JoinSuccess(new Document("{\"PrimaryController\":" + Equals(Primary, Self).ToString().ToLower() + "}")), true)
                    {
                        Address = nodeDef
                    };

                    SendMessage(response);
                    response.BlockUntilDone();

                    if (response.Success)
                    {
                        if (joinAttemptData.Primary)
                        {
                            Logger.Log("Connection to primary controller established, setting primary to " + message.Address.ConnectionName, LogLevel.Info);
                            Primary = nodeDef;
                        }

                        SendChunkList();
                    }
                }

                break;

            case NodeType.Query:
                QueryNodeSettings queryJoinSettings = new QueryNodeSettings(joinAttemptData.Settings);
                if (queryJoinSettings.ConnectionString != _settings.ConnectionString)
                {
                    SendMessage(new Message(message, new JoinFailure("Connection strings do not match."), false)
                    {
                        SendWithoutConfirmation = true
                    });
                }
                else
                {
                    NodeDefinition nodeDef = new NodeDefinition(joinAttemptData.Name, joinAttemptData.Port);
                    RenameConnection(message.Address, nodeDef);
                    Connections[nodeDef].ConnectionEstablished(nodeDef, joinAttemptData.Type);
                    Message response = new Message(message, new JoinSuccess(new Document("{\"PrimaryController\":" + Equals(Primary, Self).ToString().ToLower() + "}")),
                                                   true)
                    {
                        Address = nodeDef
                    };

                    SendMessage(response);
                    response.BlockUntilDone();

                    if (response.Success)
                    {
                        SendStorageNodeConnectionMessage();
                        SendQueryNodeConnectionMessage();

                        SendChunkList();
                    }
                }

                break;

            case NodeType.Storage:
                StorageNodeSettings storageJoinSettings = new StorageNodeSettings(joinAttemptData.Settings);
                if (storageJoinSettings.ConnectionString != _settings.ConnectionString)
                {
                    SendMessage(new Message(message, new JoinFailure("Connection strings do not match."), false)
                    {
                        SendWithoutConfirmation = true
                    });
                }
                else
                {
                    NodeDefinition nodeDef = new NodeDefinition(joinAttemptData.Name, joinAttemptData.Port);
                    RenameConnection(message.Address, nodeDef);
                    Connections[nodeDef].ConnectionEstablished(nodeDef, joinAttemptData.Type);

                    var responseData = new Document();
                    responseData["PrimaryController"] = new DocumentEntry("PrimaryController", DocumentEntryType.Boolean, Equals(Primary, Self));
                    responseData["MaxChunkItemCount"] = new DocumentEntry("MaxChunkItemCount", DocumentEntryType.Integer, _settings.MaxChunkItemCount);

                    Message response = new Message(message, new JoinSuccess(responseData), true)
                    {
                        Address = nodeDef
                    };

                    SendMessage(response);
                    response.BlockUntilDone();

                    if (response.Success)
                    {
                        lock (_storageNodes)
                        {
                            _storageNodes.Add(new Tuple <NodeDefinition, int>(nodeDef, storageJoinSettings.Weight));
                        }

                        SendStorageNodeConnectionMessage();

                        TryCreateDatabase();
                    }
                }

                break;

            case NodeType.Api:
                if (joinAttemptData.Settings != _settings.ConnectionString)
                {
                    SendMessage(new Message(message, new JoinFailure("Connection strings do not match."), false)
                    {
                        SendWithoutConfirmation = true
                    });
                }
                else
                {
                    Connections[message.Address].ConnectionEstablished(message.Address, joinAttemptData.Type);
                    var apiResponse = new Message(message, new JoinSuccess(new Document("{\"PrimaryController\":" + Equals(Primary, Self).ToString().ToLower() + "}")), true);
                    SendMessage(apiResponse);
                    apiResponse.BlockUntilDone();

                    if (apiResponse.Success)
                    {
                        SendQueryNodeConnectionMessage();
                    }
                }

                break;
            }
        }