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;
 }
Example #7
0
        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;
                    }
            }
        }
Example #8
0
 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);
 }
Example #9
0
        /// <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();
        }
Example #10
0
        /// <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);
        }
Example #11
0
        /// <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();
        }
Example #12
0
        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);
        }
Example #13
0
 private void SendMessage(Stream networkStream, Message messageToSend)
 {
     messageToSend.WriteTo(networkStream);
     networkStream.Flush();
 }
Example #14
0
        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;
        }