public static MasterConfiguration FromMessage(Message msg) { if (!msg.Header.StartsWith("master", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException("Message is not a 'master' message"); } var ret = new MasterConfiguration(); using (var reader = msg.GetContentReader()) { string line; while((line = reader.ReadLine()) != null) { var nvp = line.Split(':'); if (nvp.Length == 2) { switch (nvp[0].ToLowerInvariant()) { case "writequorum": ret.WriteQuorum = Int32.Parse(nvp[1]); break; } } } } return ret; }
public override Message AsMessage() { const string header = "spu"; var args = String.Join(" ", StoreId, JobId, PrevTxnId); var msg = new Message(header, args); using(var writer = msg.GetContentWriter()) { if (!String.IsNullOrEmpty(Expression)) { writer.WriteLine(Expression); } } return msg; }
public static ClusterSparqlTransaction FromMessage(Message msg) { var args = msg.Args.Split(' '); var txn = new ClusterSparqlTransaction { StoreId = args[0], JobId = Guid.Parse(args[1]), PrevTxnId = Guid.Parse(args[2]), }; using(var reader = msg.GetContentReader()) { txn.Expression = ReadSection(reader); } return txn; }
private bool SendMasterMessage(NodeConfiguration master) { var socket = AssertConnection(master); if (socket == null) return false; var msg = new Message("master", String.Empty); using(var writer = msg.GetContentWriter()) { _config.MasterConfiguration.WriteTo(writer); } bool masterIsSet = SendMessageAndWaitForAck(socket,msg); if (masterIsSet) { _master = master; } return masterIsSet; }
public static ClusterUpdateTransaction FromMessage(Message msg) { var args = msg.Args.Split(' '); var txn = new ClusterUpdateTransaction { StoreId = args[0], JobId = Guid.Parse(args[1]), PrevTxnId = Guid.Parse(args[2]), }; using(var reader = msg.GetContentReader()) { txn.Preconditions = ReadSection(reader); txn.Deletes = ReadSection(reader); txn.Inserts = ReadSection(reader); } return txn; }
public override Message AsMessage() { const string header = "txn"; var args = String.Join(" ", StoreId, JobId, PrevTxnId); var msg = new Message(header, args); using(var writer = msg.GetContentWriter()) { if (!String.IsNullOrEmpty(Preconditions)) { writer.WriteLine(Preconditions); } writer.WriteLine("||"); if (!String.IsNullOrEmpty(Deletes)) { writer.WriteLine(Deletes); } writer.WriteLine("||"); if (!String.IsNullOrEmpty(Inserts)) { writer.WriteLine(Inserts); } } return msg; }
private void HandleClientRequest(object client) { var tcpClient = (TcpClient)client; var clientStream = tcpClient.GetStream(); // all message have a single line header and then data. var msg = Message.Read(clientStream); switch (msg.Header.ToLowerInvariant()) { case "ping": SendMessage(clientStream, new Message("pong", String.Empty)); break; case "master": { var configuration = MasterConfiguration.FromMessage(msg); bool handledOk = _requestHandler.SetMaster(configuration); SendMessage(clientStream, handledOk ? Message.ACK : Message.NAK); break; } case "slaveof": { var args = msg.Args.Split(' '); bool handledOk = _requestHandler.SlaveOf(args[0], Int32.Parse(args[1])); SendMessage(clientStream, handledOk ? Message.ACK : Message.NAK); break; } case "sync": { var dict = new Dictionary<string, string>(); using (var reader = msg.GetContentReader()) { string line; while ((line = reader.ReadLine()) != null) { var args = line.Split('|'); var storeName = args[0]; var txnId = args[1]; dict.Add(storeName, txnId); } } var syncOk = _requestHandler.SyncSlave( dict, new SyncContext {Connection = tcpClient}, (context, message) => SendMessageAndWaitForAck(context.Connection, message)); // Send endsync message var endsync = new Message("endsync", new[] { syncOk ? "OK" : "FAIL" }); // TODO: Body could provide some check - e.g. # messages sent in sync ? SendMessage(clientStream, endsync); break; } case "listen": { AddSlave(tcpClient); break; } } }
private Response HandleTransactionMessage(Message txnMessage) { bool handledOk = false; switch (txnMessage.Header.ToLowerInvariant()) { case "txn": var updateTransaction = ClusterUpdateTransaction.FromMessage(txnMessage); handledOk = _requestHandler.ProcessSlaveTransaction(updateTransaction); break; case "spu": var sparqlTransaction = ClusterSparqlTransaction.FromMessage(txnMessage); handledOk = _requestHandler.ProcessSlaveTransaction(sparqlTransaction); break; case "+store": handledOk = _requestHandler.CreateStore(txnMessage.Args); break; case "-store": handledOk = _requestHandler.DeleteStore(txnMessage.Args); break; } return new Response(handledOk ? Message.ACK : Message.NAK); }
/// <summary> /// Create a channel to the master for receiving new transactions /// </summary> /// <param name="masterAddress"></param> public void OpenTransactionChannel(EndpointAddress masterAddress) { var tcpClient = new TcpClient(masterAddress.Uri.Host, masterAddress.Uri.Port); var msg = new Message("listen", String.Empty); var stream = tcpClient.GetStream(); msg.WriteTo(stream); stream.Flush(); _transactionMessageReader = new MessageReader(tcpClient, HandleTransactionMessage); _transactionMessageReader.Start(); }
/// <summary> /// Handler function for messages that can be received by the slave /// through the initial sync connection with the master /// </summary> /// <param name="msg">The message received</param> /// <returns>The response to send to the message</returns> private Response HandleSyncMessage(Message msg) { bool handledOk = false; switch (msg.Header.ToLowerInvariant()) { case "txn": var txn = ClusterUpdateTransaction.FromMessage(msg); handledOk = _requestHandler.ProcessSyncTransaction(txn); break; case "+store": handledOk = _requestHandler.CreateStore(msg.Args); break; case "-store": handledOk = _requestHandler.DeleteStore(msg.Args); break; case "endsync": var syncStatus = msg.Args.Split(' ')[0]; _requestHandler.SlaveSyncCompleted(syncStatus); handledOk = true; break; } if (handledOk) { return new Response(Message.ACK); } return new Response(Message.NAK, true); }
/// <summary> /// Construct a sync message that lists all the stores we have and the last commited transaction id for each one /// then start a reader to process the updates the master will send to us /// </summary> /// <param name="masterAddress"></param> /// <param name="lastTxn"></param> public void SendSyncToMaster(EndpointAddress masterAddress, Dictionary<string, string> lastTxn) { var msg = new Message("sync", String.Empty); using(var writer = msg.GetContentWriter()) { foreach (var entry in lastTxn) { writer.WriteLine("{0}|{1}", entry.Key, entry.Value); } } var socket = new TcpClient(masterAddress.Uri.Host, masterAddress.Uri.Port); var socketStream = socket.GetStream(); msg.WriteTo(socketStream); socketStream.Flush(); var messageReader = new MessageReader(socket, HandleSyncMessage); messageReader.Start(); }
private bool SendMessageAndWaitForAck(TcpClient socket, Message messageToSend) { var stream = socket.GetStream(); messageToSend.WriteTo(stream); stream.Flush(); var message = Message.Read(stream); return message.Header.Equals("ACK", StringComparison.OrdinalIgnoreCase); }
private void SendMessage(Stream networkStream, Message messageToSend) { messageToSend.WriteTo(networkStream); networkStream.Flush(); }
public bool SyncSlave(Dictionary<string, string> lastTxn, SyncContext context, Func<SyncContext, Message, bool> messageSink ) { bool syncOk = true; // Push existing transactions down the pipe foreach(var storeId in _stores) { IEnumerable<ITransactionInfo> transactionsToSend; if (lastTxn.ContainsKey(storeId)) { Guid lastJobId = Guid.Parse(lastTxn[storeId]); transactionsToSend = _serverCore.GetTransactions(storeId).SkipWhile(t => !t.JobId.Equals(lastJobId)).Skip(1); syncOk &= SendTransactions(context, messageSink, transactionsToSend, storeId, lastJobId); } else { // For all stores that aren't listed in the lastTxn dictionary // Send a create store message followed byt all transactions var createMessage = new Message("+store", storeId); if (messageSink(context, createMessage)) { syncOk &= SendTransactions(context, messageSink, _serverCore.GetTransactions(storeId), storeId, Guid.Empty); } else { syncOk = false; } } } // For all stores that are listed in lastTxn dictionary and not in our store list // send a delete store message foreach (var storeId in lastTxn.Keys.Where(s=>!_stores.Contains(s))) { var deleteMessage = new Message("-store", storeId); messageSink(context, deleteMessage); } return syncOk; }