private StorageMessageUnion ReadReply(StorageMessageType responses)
        {
            var iterator = MessageStreamIterator <StorageMessageUnion> .FromStreamProvider(() => new UndisposableStream(stream));

            var union = iterator.First();

            if (union.Type == StorageMessageType.TopologyChangedError)
            {
                throw new TopologyVersionDoesNotMatchException();
            }
            if (union.Type == StorageMessageType.SeeOtherError)
            {
                throw new SeeOtherException
                      {
                          Endpoint = union.SeeOtherError.Other.GetNodeEndpoint()
                      };
            }
            if (union.Type == StorageMessageType.StorageErrorResult)
            {
                throw new RemoteNodeException(union.Exception.Message);
            }
            if (union.Type != responses)
            {
                throw new UnexpectedReplyException("Got reply " + union.Type + " but expected " + responses);
            }

            return(union);
        }
        public void Start()
        {
            hashTable.Initialize();
            hashTable.Batch(actions =>
            {
                var value = actions.Get(new GetRequest {
                    Key = Constants.Topology
                }).LastOrDefault();

                if (value != null)
                {
                    var topology = MessageStreamIterator <TopologyResultMessage>
                                   .FromStreamProvider(() => new MemoryStream(value.Data))
                                   .First();

                    master.Topology = topology.GetTopology();
                    master.RefreshEndpoints();
                }
                actions.Commit();
            });

            listener.Start();
            listener.BeginAcceptTcpClient(OnAcceptTcpClient, null);
            OnTopologyChanged();
        }
示例#3
0
        private static MasterMessageUnion ReadReply(MasterMessageType responses, Stream stream)
        {
            var iterator = MessageStreamIterator <MasterMessageUnion> .FromStreamProvider(() => new UndisposableStream(stream));

            var union = iterator.First();

            if (union.Type == MasterMessageType.MasterErrorResult)
            {
                throw new RemoteNodeException(union.Exception.Message);
            }
            if (union.Type != responses)
            {
                throw new UnexpectedReplyException("Got reply " + union.Type + " but expected " + responses);
            }

            return(union);
        }
        private void OnAcceptTcpClient(IAsyncResult result)
        {
            TcpClient client;

            try
            {
                client = listener.EndAcceptTcpClient(result);
            }
            catch (ObjectDisposedException)
            {
                return;
            }

            //this is done intentionally in a single threaded fashion
            //the master is not a hot spot and it drastically simplify our life
            //to avoid having to do multi threaded stuff here
            //all calls to the master are also very short

            try
            {
                using (client)
                    using (var stream = client.GetStream())
                    {
                        var writer = new MessageStreamWriter <MasterMessageUnion>(stream);
                        foreach (var wrapper in MessageStreamIterator <MasterMessageUnion> .FromStreamProvider(() => stream))
                        {
                            try
                            {
                                log.DebugFormat("Accepting message from {0} - {1}",
                                                client.Client.RemoteEndPoint,
                                                wrapper.Type);
                                switch (wrapper.Type)
                                {
                                case MasterMessageType.GetTopologyRequest:
                                    HandleGetToplogy(writer);
                                    break;

                                case MasterMessageType.JoinRequest:
                                    HandleJoin(wrapper, writer);
                                    break;

                                case MasterMessageType.CaughtUpRequest:
                                    HandleCatchUp(wrapper, writer);
                                    break;

                                case MasterMessageType.GaveUpRequest:
                                    HandleGaveUp(wrapper, writer);
                                    break;

                                default:
                                    throw new ArgumentOutOfRangeException();
                                }
                                writer.Flush();
                                stream.Flush();
                            }
                            catch (Exception e)
                            {
                                log.Warn("Error performing request", e);
                                writer.Write(new MasterMessageUnion.Builder
                                {
                                    Type      = MasterMessageType.MasterErrorResult,
                                    Exception = new ErrorMessage.Builder
                                    {
                                        Message = e.ToString()
                                    }.Build()
                                }.Build());
                                writer.Flush();
                                stream.Flush();
                            }
                        }
                    }
            }
            catch (Exception e)
            {
                log.Warn("Error when dealing with a request (or could not send error details)", e);
            }
            finally
            {
                try
                {
                    listener.BeginAcceptTcpClient(OnAcceptTcpClient, null);
                }
                catch (InvalidOperationException)
                {
                    //the listener was closed
                }
            }
        }
        private void OnBeginAcceptTcpClient(IAsyncResult result)
        {
            TcpClient client;

            try
            {
                client = listener.EndAcceptTcpClient(result);
                listener.BeginAcceptTcpClient(OnBeginAcceptTcpClient, null);
            }
            catch (ObjectDisposedException)
            {
                return;
            }
            catch (InvalidOperationException)
            {
                return;
            }
            try
            {
                using (client)
                    using (var stream = client.GetStream())
                    {
                        var writer = new MessageStreamWriter <StorageMessageUnion>(stream);
                        try
                        {
                            foreach (var wrapper in MessageStreamIterator <StorageMessageUnion> .FromStreamProvider(() => new UndisposableStream(stream)))
                            {
                                log.DebugFormat("Got message {0}", wrapper.Type);
                                switch (wrapper.Type)
                                {
                                case StorageMessageType.GetRequests:
                                    HandleGet(wrapper, wrapper.TopologyVersion.Value, writer);
                                    break;

                                case StorageMessageType.PutRequests:
                                    HandlePut(wrapper, wrapper.TopologyVersion.Value, writer);
                                    break;

                                case StorageMessageType.RemoveRequests:
                                    HandleRemove(wrapper, wrapper.TopologyVersion.Value, writer);
                                    break;

                                case StorageMessageType.AssignAllEmptySegmentsRequest:
                                    HandleAssignEmpty(wrapper, writer);
                                    break;

                                case StorageMessageType.ReplicateNextPageRequest:
                                    HandleReplicateNextPage(wrapper, writer);
                                    break;

                                case StorageMessageType.UpdateTopology:
                                    HandleTopologyUpdate(writer);
                                    break;

                                default:
                                    throw new InvalidOperationException("Message type was not understood: " + wrapper.Type);
                                }
                                writer.Flush();
                                stream.Flush();
                            }
                        }
                        catch (IOException)
                        {
                            // disconnected, so nothing else to do
                        }
                        catch (SeeOtherException e)
                        {
                            writer.Write(new StorageMessageUnion.Builder
                            {
                                Type          = StorageMessageType.SeeOtherError,
                                SeeOtherError = new SeeOtherErrorMessage.Builder
                                {
                                    Other = e.Endpoint.GetNodeEndpoint()
                                }.Build()
                            }.Build());
                            writer.Flush();
                            stream.Flush();
                        }
                        catch (TopologyVersionDoesNotMatchException)
                        {
                            writer.Write(new StorageMessageUnion.Builder
                            {
                                Type = StorageMessageType.TopologyChangedError,
                            }.Build());
                            writer.Flush();
                            stream.Flush();
                        }
                        catch (Exception e)
                        {
                            log.Warn("Error performing request", e);
                            writer.Write(new StorageMessageUnion.Builder
                            {
                                Type      = StorageMessageType.StorageErrorResult,
                                Exception = new ErrorMessage.Builder
                                {
                                    Message = e.ToString()
                                }.Build()
                            }.Build());
                            writer.Flush();
                            stream.Flush();
                        }
                    }
            }
            catch (Exception e)
            {
                log.Warn("Error when processing request to storage", e);
            }
        }