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(); }
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); } }