예제 #1
0
        public void TestMessageChecksum()
        {
            byte[] bytes = new byte[] {
                4, 6, 4, 6, 6, 46, 6, 34, 64, 2, 64, 62, 47, 27, 247,
                4, 6, 4, 6, 6, 46, 6, 34, 64, 2, 64, 62, 47, 27, 247
            };

            byte[] bigBytes = new byte[8 * 1024];
            Array.Copy(bytes, bigBytes, bytes.Length);

            var calculatedChecksum = CoderHelper.CalculateChecksum(bytes, 0, bytes.Length);

            var newLength = CoderHelper.AddChecksum(bigBytes, 0, bytes.Length) + bytes.Length;

            byte checksumInBigBytes = bigBytes[bytes.Length];

            Assert.AreEqual(checksumInBigBytes, calculatedChecksum);

            var writer = new MessageStreamWriter();
            var reader = new MessageStreamReader();

            var loginRequest = new LoginRequest()
            {
                accessToken = "alsdjflakjsdf", username = "******"
            };
            var matchRequest = new MatchRequest()
            {
                value1 = 1, value2 = 2, value3 = 3, value4 = 4
            };

            writer.Write(loginRequest);
            writer.Write(matchRequest);
            writer.Use((buffer, len) => {
                reader.Add(buffer, len);
                var message = reader.Decode();
                Assert.IsTrue(message.Value.Is(200));
                Assert.AreEqual(loginRequest, message.Value.Parse <LoginRequest>());
                message = reader.Decode();
                Assert.IsTrue(message.Value.Is(201));
                Assert.AreEqual(matchRequest, message.Value.Parse <MatchRequest>());
                writer.DidWrite(len);
            });

            writer.Write(loginRequest);
            writer.Write(matchRequest);
            writer.currentBuffer[0] = 23;
            writer.Use((buffer, len) => {
                reader.Add(buffer, len);
                var message = reader.Decode();
                Assert.IsFalse(message.HasValue);
                Assert.IsTrue(message == null);
                message = reader.Decode();
                Assert.IsTrue(message.Value.Is(201));
                Assert.AreEqual(matchRequest, message.Value.Parse <MatchRequest>());
                writer.DidWrite(len);
            });
        }
예제 #2
0
            public void Serialize(MessageStreamWriter w, Hash value, int rank)
            {
                if (rank > 256)
                {
                    throw new FormatException();
                }

                w.Write((ulong)value.Algorithm);
                w.Write(value.Value);
            }
예제 #3
0
        private void Cancel(int id)
        {
            var messageStream = new RecyclableMemoryStream(_bufferManager);
            var writer        = new MessageStreamWriter(messageStream, _bufferManager);

            writer.Write((ulong)AmoebaFunctionType.Cancel);
            writer.Write((ulong)id);

            messageStream.Seek(0, SeekOrigin.Begin);
            _messagingManager.Send(messageStream);
        }
예제 #4
0
        public void TestMultithreadReadAndWrite()
        {
            var loginRequest = new LoginRequest()
            {
                accessToken = "askldfaljksdf", username = "******"
            };

            var reader = new MessageStreamReader();
            var writer = new MessageStreamWriter();

            for (int reading = 0; reading < 50; reading++)
            {
                for (int write = 0; write < 2; write++)
                {
                    writer.Write(loginRequest);
                    Logger.Log($"Did Write loginRequest {write * reading}");
                }

                writer.Use((buffer, len) => {
                    Logger.Log($"Using buffer with len: {len}");
                    reader.Add(buffer, len);
                    MessageContainer?message = null;
                    while ((message = reader.Decode()).HasValue)
                    {
                        Logger.Log($"Decoded message: {message.Value.type}");
                        Assert.AreEqual(loginRequest, message.Value.Parse <LoginRequest>());
                    }
                    writer.DidWrite(len);
                    Logger.Log($"Did Write len: {len}");
                });
            }

            Assert.AreEqual(0, writer.currentBufferLength);
            Assert.AreEqual(0, reader.currentBufferLength);
        }
        public void ManyMessagesShouldNotTriggerSizeAlert()
        {
            int messageSize = TestUtil.GetAllSet().SerializedSize;
              // Enough messages to trigger the alert unless we've reset the size
              // Note that currently we need to make this big enough to copy two whole buffers,
              // as otherwise when we refill the buffer the second type, the alert triggers instantly.
              int correctCount = (CodedInputStream.BufferSize * 2) / messageSize + 1;
              using (MemoryStream stream = new MemoryStream()) {
            MessageStreamWriter<TestAllTypes> writer = new MessageStreamWriter<TestAllTypes>(stream);
            for (int i = 0; i < correctCount; i++) {
              writer.Write(TestUtil.GetAllSet());
            }
            writer.Flush();

            stream.Position = 0;

            int count = 0;
            foreach (var message in MessageStreamIterator<TestAllTypes>.FromStreamProvider(() => stream)
              .WithSizeLimit(CodedInputStream.BufferSize * 2)) {
              count++;
              TestUtil.AssertAllFieldsSet(message);
            }
            Assert.AreEqual(correctCount, count);
              }
        }
        private void PersistTopology()
        {
            byte[] buffer;
            var    topology = master.Topology.GetTopology();

            using (var stream = new MemoryStream())
            {
                var writer = new MessageStreamWriter <TopologyResultMessage>(stream);
                writer.Write(topology);
                writer.Flush();
                buffer = stream.ToArray();
            }

            hashTable.Batch(actions =>
            {
                var values = actions.Get(new GetRequest
                {
                    Key = Constants.Topology
                });
                actions.Put(new PutRequest
                {
                    Key            = Constants.Topology,
                    ParentVersions = values.Select(x => x.Version).ToArray(),
                    Bytes          = buffer,
                    IsReadOnly     = true
                });

                actions.Commit();
            });
        }
        private void HandleReplicateNextPage(StorageMessageUnion wrapper,
                                             MessageStreamWriter <StorageMessageUnion> writer)
        {
            var replicationResult = replication.ReplicateNextPage(
                wrapper.ReplicateNextPageRequest.ReplicationEndpoint.GetNodeEndpoint(),
                wrapper.ReplicateNextPageRequest.Type == ReplicationType.Backup ? Internal.ReplicationType.Backup : Internal.ReplicationType.Ownership,
                wrapper.ReplicateNextPageRequest.Segment
                );

            writer.Write(new StorageMessageUnion.Builder
            {
                Type = StorageMessageType.ReplicateNextPageResponse,
                ReplicateNextPageResponse = new ReplicateNextPageResponseMessage.Builder()
                {
                    Done = replicationResult.Done,
                    RemoveRequestsList =
                    {
                        replicationResult.RemoveRequests.Select(x => x.GetRemoveRequest()),
                    },
                    PutRequestsList =
                    {
                        replicationResult.PutRequests.Select(x => x.GetPutRequest())
                    }
                }.Build()
            }.Build());
        }
예제 #8
0
    public void ThreeMessages() {
      NestedMessage message1 = new NestedMessage.Builder { Bb = 5 }.Build();
      NestedMessage message2 = new NestedMessage.Builder { Bb = 1500 }.Build();
      NestedMessage message3 = new NestedMessage.Builder().Build();

      byte[] data;
      using (MemoryStream stream = new MemoryStream()) {
        MessageStreamWriter<NestedMessage> writer = new MessageStreamWriter<NestedMessage>(stream);
        writer.Write(message1);
        writer.Write(message2);
        writer.Write(message3);
        writer.Flush();
        data = stream.ToArray();
      }

      TestUtil.AssertEqualBytes(ThreeMessageData, data);
    }
 private void HandleTopologyUpdate(MessageStreamWriter <StorageMessageUnion> writer)
 {
     node.UpdateTopology();
     writer.Write(new StorageMessageUnion.Builder
     {
         Type = StorageMessageType.TopologyUpdated
     }.Build());
 }
예제 #10
0
        public Stream GetCashStream(string signature)
        {
            var bufferManager = BufferManager.Instance;

            var signatureStream = new RecyclableMemoryStream(bufferManager);
            {
                var writer = new MessageStreamWriter(signatureStream, bufferManager);
                writer.Write((ulong)5);
                writer.Write(signature);

                signatureStream.Seek(0, SeekOrigin.Begin);
            }

            var target = new MulticastMetadata(this.Type, this.Tag, this.CreationTime, this.Metadata, (Cash)null, (Certificate)null);

            return(new UniteStream(target.Export(bufferManager), signatureStream));
        }
        private void HandleGetToplogy(MessageStreamWriter <MasterMessageUnion> writer)
        {
            var topology = master.GetTopology();

            writer.Write(new MasterMessageUnion.Builder
            {
                Type     = MasterMessageType.GetTopologyResult,
                Topology = topology.GetTopology()
            }.Build());
        }
        public PutResult[] Put(int topologyVersion,
                               params ExtendedPutRequest[] valuesToAdd)
        {
            writer.Write(new StorageMessageUnion.Builder
            {
                Type            = StorageMessageType.PutRequests,
                TopologyVersion = topologyVersion,
                PutRequestsList =
                {
                    valuesToAdd.Select(x => x.GetPutRequest())
                }
            }.Build());
            writer.Flush();
            stream.Flush();

            var union = ReadReply(StorageMessageType.PutResponses);

            return(union.PutResponsesList.Select(x => new PutResult
            {
                ConflictExists = x.ConflictExists,
                Version = new PersistentHashTable.ValueVersion
                {
                    InstanceId = new Guid(x.Version.InstanceId.ToByteArray()),
                    Number = x.Version.Number
                }
            }).ToArray());
        }
예제 #13
0
        private (int, WaitQueue <ResponseInfo>) Send <TArgument>(AmoebaFunctionType type, TArgument argument)
        {
            int id    = this.CreateId();
            var queue = new WaitQueue <ResponseInfo>();

            _queueMap.Add(id, queue);

            var messageStream = new RecyclableMemoryStream(_bufferManager);
            var writer        = new MessageStreamWriter(messageStream, _bufferManager);

            writer.Write((ulong)type);
            writer.Write((ulong)id);

            Stream valueStream = null;

            if (argument != null)
            {
                try
                {
                    valueStream = new RecyclableMemoryStream(_bufferManager);
                    JsonUtils.Save(valueStream, argument);
                }
                catch (Exception)
                {
                    if (valueStream != null)
                    {
                        valueStream.Dispose();
                        valueStream = null;
                    }

                    throw;
                }
            }

            messageStream.Seek(0, SeekOrigin.Begin);
            _messagingManager.Send(new UniteStream(messageStream, valueStream));

            return(id, queue);
        }
 private void HandleGaveUp(MasterMessageUnion wrapper,
                           MessageStreamWriter <MasterMessageUnion> writer)
 {
     master.GaveUp(new NodeEndpoint
     {
         Async = new Uri(wrapper.GaveUp.Endpoint.Async),
         Sync  = new Uri(wrapper.GaveUp.Endpoint.Sync)
     },
                   wrapper.GaveUp.Type == ReplicationType.Backup ? Internal.ReplicationType.Backup : Internal.ReplicationType.Ownership,
                   wrapper.GaveUp.GaveUpSegmentsList.ToArray());
     writer.Write(new MasterMessageUnion.Builder
     {
         Type = MasterMessageType.GaveUpResponse
     }.Build());
 }
        private void HandlePut(StorageMessageUnion wrapper,
                               int topologyVersion,
                               MessageStreamWriter <StorageMessageUnion> writer)
        {
            var puts    = wrapper.PutRequestsList.Select(x => x.GetPutRequest()).ToArray();
            var results = storage.Put(topologyVersion, puts);

            writer.Write(new StorageMessageUnion.Builder
            {
                Type             = StorageMessageType.PutResponses,
                TopologyVersion  = topologyVersion,
                PutResponsesList =
                {
                    results.Select(x => x.GetPutResponse())
                }
            }.Build());
        }
        private void HandleAssignEmpty(StorageMessageUnion wrapper,
                                       MessageStreamWriter <StorageMessageUnion> writer)
        {
            var segments = replication.AssignAllEmptySegments(
                wrapper.AssignAllEmptySegmentsRequest.ReplicationEndpoint.GetNodeEndpoint(),
                wrapper.AssignAllEmptySegmentsRequest.Type == ReplicationType.Backup ? Internal.ReplicationType.Backup : Internal.ReplicationType.Ownership,
                wrapper.AssignAllEmptySegmentsRequest.SegmentsList.ToArray()
                );

            writer.Write(new StorageMessageUnion.Builder
            {
                Type = StorageMessageType.AssignAllEmptySegmentsResponse,
                AssignAllEmptySegmentsResponse = new AssignAllEmptySegmentsResponseMessage.Builder
                {
                    AssignedSegmentsList = { segments }
                }.Build()
            }.Build());
        }
        private void HandleGet(StorageMessageUnion wrapper,
                               int topologyVersion,
                               MessageStreamWriter <StorageMessageUnion> writer)
        {
            var values = storage.Get(topologyVersion,
                                     wrapper.GetRequestsList.Select(x => x.GetGetRequest()).ToArray()
                                     );
            var reply = new StorageMessageUnion.Builder
            {
                Type             = StorageMessageType.GetResponses,
                TopologyVersion  = wrapper.TopologyVersion,
                GetResponsesList =
                {
                    values.Select(x => x.GetGetResponse())
                }
            };

            writer.Write(reply.Build());
        }
        private void HandleJoin(MasterMessageUnion wrapper,
                                MessageStreamWriter <MasterMessageUnion> writer)
        {
            var endpoint = wrapper.JoinRequest.EndpointJoining;
            var segments = master.Join(new NodeEndpoint
            {
                Async = new Uri(endpoint.Async),
                Sync  = new Uri(endpoint.Sync)
            });
            var joinResponse = new JoinResponseMessage.Builder
            {
                SegmentsList = { segments.Select(x => x.GetSegment()) }
            };

            writer.Write(new MasterMessageUnion.Builder
            {
                Type         = MasterMessageType.JoinResult,
                JoinResponse = joinResponse.Build()
            }.Build());
        }
        private void HandleRemove(StorageMessageUnion wrapper,
                                  int topologyVersion,
                                  MessageStreamWriter <StorageMessageUnion> writer)
        {
            var requests = wrapper.RemoveRequestsList.Select(x => x.GetRemoveRequest()).ToArray();
            var removed  = storage.Remove(topologyVersion, requests);

            writer.Write(new StorageMessageUnion.Builder
            {
                Type               = StorageMessageType.RemoveResponses,
                TopologyVersion    = topologyVersion,
                RemoveResponesList =
                {
                    removed.Select(x => new RemoveResponseMessage.Builder
                    {
                        WasRemoved = x
                    }.Build())
                }
            }.Build());
        }
 private void HandlePut(StorageMessageUnion wrapper,
     int topologyVersion,
     MessageStreamWriter<StorageMessageUnion> writer)
 {
     var puts = wrapper.PutRequestsList.Select(x => x.GetPutRequest()).ToArray();
     var results = storage.Put(topologyVersion, puts);
     writer.Write(new StorageMessageUnion.Builder
     {
         Type = StorageMessageType.PutResponses,
         TopologyVersion = topologyVersion,
         PutResponsesList =
             {
                 results.Select(x=>x.GetPutResponse())
             }
     }.Build());
 }
 private void HandleGet(StorageMessageUnion wrapper,
     int topologyVersion,
     MessageStreamWriter<StorageMessageUnion> writer)
 {
     var values = storage.Get(topologyVersion,
         wrapper.GetRequestsList.Select(x => x.GetGetRequest()).ToArray()
         );
     var reply = new StorageMessageUnion.Builder
     {
         Type = StorageMessageType.GetResponses,
         TopologyVersion = wrapper.TopologyVersion,
         GetResponsesList =
             {
                 values.Select(x=> x.GetGetResponse())
             }
     };
     writer.Write(reply.Build());
 }
 private void HandleAssignEmpty(StorageMessageUnion wrapper,
     MessageStreamWriter<StorageMessageUnion> writer)
 {
     var segments = replication.AssignAllEmptySegments(
         wrapper.AssignAllEmptySegmentsRequest.ReplicationEndpoint.GetNodeEndpoint(),
         wrapper.AssignAllEmptySegmentsRequest.Type == ReplicationType.Backup ? Internal.ReplicationType.Backup : Internal.ReplicationType.Ownership,
         wrapper.AssignAllEmptySegmentsRequest.SegmentsList.ToArray()
         );
     writer.Write(new StorageMessageUnion.Builder
     {
         Type = StorageMessageType.AssignAllEmptySegmentsResponse,
         AssignAllEmptySegmentsResponse = new AssignAllEmptySegmentsResponseMessage.Builder
         {
             AssignedSegmentsList = { segments }
         }.Build()
     }.Build());
 }
예제 #23
0
        public void TestPartialStreamingDecoding()
        {
            var firstToken  = "asldkfjalksdjfalkjsdf";
            var username    = "******";
            var secondToken = "asdlkfalksjdgklashdioohweg";
            var ip          = "10.0.0.1";
            var port        = (short)6109;


            var loginRequest = new LoginRequest {
                accessToken = firstToken,
                username    = username
            };

            var matchRequest = new MatchRequest();

            var connectRequest = new ConnectGameInstanceResponse {
                token = secondToken,
                ip    = ip,
                port  = port
            };

            var         encoder = new MessageStreamWriter();
            List <byte> data    = new List <byte>();

            encoder.Write(loginRequest);
            encoder.Use((buffer, count) => data.AddRange(buffer, count));
            encoder.Write(matchRequest);
            encoder.Use((buffer, count) => data.AddRange(buffer, count));
            encoder.Write(connectRequest);
            encoder.Use((buffer, count) => data.AddRange(buffer, count));

            var decoder = new MessageStreamReader();

            this.Measure(() => {
                var position = 0;
                do
                {
                    var x = data.GetRange(position, 1).ToArray();
                    decoder.Add(x, x.Length);
                    var container = decoder.Decode();
                    if (container.HasValue)
                    {
                        if (container.Value.Is(200))   // LoginRequest
                        {
                            var message = container.Value.Parse <LoginRequest>();
                            Assert.AreEqual(message.accessToken, firstToken);
                            Assert.AreEqual(message.username, username);
                        }
                        else if (container.Value.Is(201))     // MatchRequest
                        {
                            var message = container.Value.Parse <MatchRequest>();
                            Assert.AreNotEqual(message, null);
                        }
                        else if (container.Value.Is(202))     // ConnectGameInstanceResponse
                        {
                            var message = container.Value.Parse <ConnectGameInstanceResponse>();
                            Assert.AreEqual(message.ip, ip);
                            Assert.AreEqual(message.port, port);
                            Assert.AreEqual(message.token, secondToken);
                        }
                    }
                    position += 1;
                } while (position < data.Count);
            }, "Partial Stream Decoding");
        }
        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);
            }
        }
        private void _messagingManager_ReceiveEvent(Stream requestStream)
        {
            var reader = new MessageStreamReader(new WrapperStream(requestStream), _bufferManager);

            {
                var type = (AmoebaFunctionType)reader.GetUInt64();
                int id   = (int)reader.GetUInt64();

                if (type == AmoebaFunctionType.Exit)
                {
                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                    _tokenSource.Cancel();
                }
                else if (type == AmoebaFunctionType.Cancel)
                {
                    if (_tasks.TryGetValue(id, out var responseTask))
                    {
                        responseTask.Stop();
                    }
                }
                else
                {
                    var responseTask = ResponseTask.Create((token) =>
                    {
                        try
                        {
                            switch (type)
                            {
                            case AmoebaFunctionType.GetReport:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.Report);
                                    break;
                                }

                            case AmoebaFunctionType.GetNetworkConnectionReports:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.GetNetworkConnectionReports());
                                    break;
                                }

                            case AmoebaFunctionType.GetCacheContentReports:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.GetCacheContentReports());
                                    break;
                                }

                            case AmoebaFunctionType.GetDownloadContentReports:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.GetDownloadContentReports());
                                    break;
                                }

                            case AmoebaFunctionType.GetConfig:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.Config);
                                    break;
                                }

                            case AmoebaFunctionType.SetConfig:
                                {
                                    var config = JsonUtils.Load <ServiceConfig>(requestStream);
                                    _serviceManager.SetConfig(config);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.SetCloudLocations:
                                {
                                    var cloudLocations = JsonUtils.Load <Location[]>(requestStream);
                                    _serviceManager.SetCloudLocations(cloudLocations);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.GetSize:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.Size);
                                    break;
                                }

                            case AmoebaFunctionType.Resize:
                                {
                                    long size = JsonUtils.Load <long>(requestStream);
                                    _serviceManager.Resize(size);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.CheckBlocks:
                                {
                                    _serviceManager.CheckBlocks(new Action <CheckBlocksProgressReport>((report) =>
                                    {
                                        SendResponse(AmoebaFunctionResponseType.Output, id, report);
                                    }), token).Wait();

                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.AddContent:
                                {
                                    var arguments = JsonUtils.Load <(string, DateTime)>(requestStream);
                                    var result    = _serviceManager.AddContent(arguments.Item1, arguments.Item2, token).Result;
                                    SendResponse(AmoebaFunctionResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaFunctionType.RemoveContent:
                                {
                                    string path = JsonUtils.Load <string>(requestStream);
                                    _serviceManager.RemoveContent(path);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.Diffusion:
                                {
                                    string path = JsonUtils.Load <string>(requestStream);
                                    _serviceManager.DiffuseContent(path);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.AddDownload:
                                {
                                    var arguments = JsonUtils.Load <(Metadata, string, long)>(requestStream);
                                    _serviceManager.AddDownload(arguments.Item1, arguments.Item2, arguments.Item3);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.RemoveDownload:
                                {
                                    var arguments = JsonUtils.Load <(Metadata, string)>(requestStream);
                                    _serviceManager.RemoveDownload(arguments.Item1, arguments.Item2);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.ResetDownload:
                                {
                                    var arguments = JsonUtils.Load <(Metadata, string)>(requestStream);
                                    _serviceManager.ResetDownload(arguments.Item1, arguments.Item2);
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.SetProfile:
                                {
                                    var arguments = JsonUtils.Load <(ProfileContent, DigitalSignature)>(requestStream);
                                    _serviceManager.SetProfile(arguments.Item1, arguments.Item2, token).Wait();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.SetStore:
                                {
                                    var arguments = JsonUtils.Load <(StoreContent, DigitalSignature)>(requestStream);
                                    _serviceManager.SetStore(arguments.Item1, arguments.Item2, token).Wait();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.SetUnicastCommentMessage:
                                {
                                    var arguments = JsonUtils.Load <(Signature, CommentContent, AgreementPublicKey, DigitalSignature)>(requestStream);
                                    _serviceManager.SetUnicastCommentMessage(arguments.Item1, arguments.Item2, arguments.Item3, arguments.Item4, token).Wait();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.SetMulticastCommentMessage:
                                {
                                    var arguments = JsonUtils.Load <(Tag, CommentContent, DigitalSignature, TimeSpan)>(requestStream);
                                    _serviceManager.SetMulticastCommentMessage(arguments.Item1, arguments.Item2, arguments.Item3, arguments.Item4, token).Wait();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.GetProfile:
                                {
                                    var signature = JsonUtils.Load <Signature>(requestStream);
                                    var result    = _serviceManager.GetProfile(signature, token).Result;
                                    SendResponse(AmoebaFunctionResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaFunctionType.GetStore:
                                {
                                    var signature = JsonUtils.Load <Signature>(requestStream);
                                    var result    = _serviceManager.GetStore(signature, token).Result;
                                    SendResponse(AmoebaFunctionResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaFunctionType.GetUnicastCommentMessages:
                                {
                                    var arguments = JsonUtils.Load <(Signature, AgreementPrivateKey)>(requestStream);
                                    var result    = _serviceManager.GetUnicastCommentMessages(arguments.Item1, arguments.Item2, token).Result;
                                    SendResponse(AmoebaFunctionResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaFunctionType.GetMulticastCommentMessages:
                                {
                                    var tag    = JsonUtils.Load <Tag>(requestStream);
                                    var result = _serviceManager.GetMulticastCommentMessages(tag, token).Result;
                                    SendResponse(AmoebaFunctionResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaFunctionType.GetState:
                                {
                                    SendResponse(AmoebaFunctionResponseType.Result, id, _serviceManager.State);
                                    break;
                                }

                            case AmoebaFunctionType.Start:
                                {
                                    _serviceManager.Start();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.Stop:
                                {
                                    _serviceManager.Stop();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.Load:
                                {
                                    _serviceManager.Load();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaFunctionType.Save:
                                {
                                    _serviceManager.Save();
                                    SendResponse(AmoebaFunctionResponseType.Result, id, (object)null);
                                    break;
                                }
                            }
                        }
                        catch (OperationCanceledException)
                        {
                            SendResponse(AmoebaFunctionResponseType.Cancel, id, (object)null);
                        }
                        catch (Exception e)
                        {
                            Log.Error(string.Format("Rpc Error: {0}", type.ToString()));
                            Log.Error(e);

                            var argument = new AmoebaErrorMessage(e.GetType().ToString(), e.Message, e.StackTrace?.ToString());
                            SendResponse(AmoebaFunctionResponseType.Error, id, argument);
                        }
                        finally
                        {
                            requestStream.Dispose();
                            _tasks.Remove(id);
                        }
                    });

                    _tasks.Add(id, responseTask);
                    responseTask.Start();
                }
            }

            void SendResponse <T>(AmoebaFunctionResponseType type, int id, T value)
            {
                var messageStream = new RecyclableMemoryStream(_bufferManager);
                var writer        = new MessageStreamWriter(messageStream, _bufferManager);

                writer.Write((ulong)type);
                writer.Write((ulong)id);

                Stream valueStream = null;

                if (value != null)
                {
                    try
                    {
                        valueStream = new RecyclableMemoryStream(_bufferManager);
                        JsonUtils.Save(valueStream, value);
                    }
                    catch (Exception)
                    {
                        if (valueStream != null)
                        {
                            valueStream.Dispose();
                            valueStream = null;
                        }

                        return;
                    }
                }

                messageStream.Seek(0, SeekOrigin.Begin);
                _messagingManager.Send(new UniteStream(messageStream, valueStream));
            }
        }
        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 HandleCatchUp(MasterMessageUnion wrapper,
     MessageStreamWriter<MasterMessageUnion> writer)
 {
     master.CaughtUp(new NodeEndpoint
     {
         Async = new Uri(wrapper.CaughtUp.Endpoint.Async),
         Sync = new Uri(wrapper.CaughtUp.Endpoint.Sync)
     },
     wrapper.CaughtUp.Type == ReplicationType.Backup ? Internal.ReplicationType.Backup : Internal.ReplicationType.Ownership,
     wrapper.CaughtUp.CaughtUpSegmentsList.ToArray());
     writer.Write(new MasterMessageUnion.Builder
     {
         Type = MasterMessageType.CaughtUpResponse
     }.Build());
 }
        private void PersistTopology()
        {
            byte[] buffer;
            var topology = master.Topology.GetTopology();
            using (var stream = new MemoryStream())
            {
                var writer = new MessageStreamWriter<TopologyResultMessage>(stream);
                writer.Write(topology);
                writer.Flush();
                buffer = stream.ToArray();
            }

            hashTable.Batch(actions =>
            {
                var values = actions.Get(new GetRequest
                {
                    Key = Constants.Topology
                });
                actions.Put(new PutRequest
                {
                    Key = Constants.Topology,
                    ParentVersions = values.Select(x => x.Version).ToArray(),
                    Bytes = buffer,
                    IsReadOnly = true
                });

                actions.Commit();
            });
        }
        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 HandleTopologyUpdate(MessageStreamWriter<StorageMessageUnion> writer)
 {
     node.UpdateTopology();
     writer.Write(new StorageMessageUnion.Builder
     {
         Type = StorageMessageType.TopologyUpdated
     }.Build());
 }
 private void HandleRemove(StorageMessageUnion wrapper,
     int topologyVersion,
     MessageStreamWriter<StorageMessageUnion> writer)
 {
     var requests = wrapper.RemoveRequestsList.Select(x => x.GetRemoveRequest()).ToArray();
     var removed = storage.Remove(topologyVersion, requests);
     writer.Write(new StorageMessageUnion.Builder
     {
         Type = StorageMessageType.RemoveResponses,
         TopologyVersion = topologyVersion,
         RemoveResponesList =
             {
                 removed.Select(x => new RemoveResponseMessage.Builder
                 {
                     WasRemoved = x
                 }.Build())
             }
     }.Build());
 }
 private void HandleReplicateNextPage(StorageMessageUnion wrapper,
     MessageStreamWriter<StorageMessageUnion> writer)
 {
     var replicationResult = replication.ReplicateNextPage(
         wrapper.ReplicateNextPageRequest.ReplicationEndpoint.GetNodeEndpoint(),
         wrapper.ReplicateNextPageRequest.Type == ReplicationType.Backup ? Internal.ReplicationType.Backup : Internal.ReplicationType.Ownership,
         wrapper.ReplicateNextPageRequest.Segment
         );
     writer.Write(new StorageMessageUnion.Builder
     {
         Type = StorageMessageType.ReplicateNextPageResponse,
         ReplicateNextPageResponse = new ReplicateNextPageResponseMessage.Builder()
         {
             Done = replicationResult.Done,
             RemoveRequestsList =
                 {
                     replicationResult.RemoveRequests.Select(x=>x.GetRemoveRequest()),
                 },
             PutRequestsList =
                 {
                     replicationResult.PutRequests.Select(x=>x.GetPutRequest())
                 }
         }.Build()
     }.Build());
 }
 private void HandleGetToplogy(MessageStreamWriter<MasterMessageUnion> writer)
 {
     var topology = master.GetTopology();
     writer.Write(new MasterMessageUnion.Builder
     {
         Type = MasterMessageType.GetTopologyResult,
         Topology = topology.GetTopology()
     }.Build());
 }
 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);
     }
 }
 private void HandleJoin(MasterMessageUnion wrapper,
     MessageStreamWriter<MasterMessageUnion> writer)
 {
     var endpoint = wrapper.JoinRequest.EndpointJoining;
     var segments = master.Join(new NodeEndpoint
     {
         Async = new Uri(endpoint.Async),
         Sync = new Uri(endpoint.Sync)
     });
     var joinResponse = new JoinResponseMessage.Builder
     {
         SegmentsList = { segments.Select(x => x.GetSegment()) }
     };
     writer.Write(new MasterMessageUnion.Builder
     {
         Type = MasterMessageType.JoinResult,
         JoinResponse = joinResponse.Build()
     }.Build());
 }