/// <summary> /// The main method of the program. /// </summary> private static void Main() { AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; StorageNodeSettings settings; if (File.Exists("config.xml")) { settings = new StorageNodeSettings(File.ReadAllText("config.xml")); } else { Logger.Log("\"config.xml\" not found, creating with the defaults.", LogLevel.Warning); settings = new StorageNodeSettings(); File.WriteAllText("config.xml", settings.ToString()); } Logger.Init(string.Empty, "Storage", settings.LogLevel, true); _node = new StorageNode(settings); _node.Run(); Logger.Shutdown(); }
/// <summary> /// Initializes a new instance of the <see cref="StorageNode"/> class. /// </summary> /// <param name="settings">The settings to use.</param> public StorageNode(StorageNodeSettings settings) : base(settings.Port) { _settings = settings; _database = new Database(this); }
/// <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; } }