示例#1
0
        private void CreateAndRegisterEndpoint(AkkaProtocolHandle handle, int?refuseUid)
        {
            var writing = _settings.UsePassiveConnections && !_endpoints.HasWriteableEndpointFor(handle.RemoteAddress);

            _eventPublisher.NotifyListeners(new AssociatedEvent(handle.LocalAddress, handle.RemoteAddress, true));
            var endpoint = CreateEndpoint(
                handle.RemoteAddress,
                handle.LocalAddress,
                _transportMapping[handle.LocalAddress],
                _settings,
                writing,
                handle,
                refuseUid);

            if (writing)
            {
                _endpoints.RegisterWritableEndpoint(handle.RemoteAddress, endpoint, handle.HandshakeInfo.Uid, refuseUid);
            }
            else
            {
                _endpoints.RegisterReadOnlyEndpoint(handle.RemoteAddress, endpoint, handle.HandshakeInfo.Uid);
                if (!_endpoints.HasWriteableEndpointFor(handle.RemoteAddress))
                {
                    _endpoints.RemovePolicy(handle.RemoteAddress);
                }
            }
        }
示例#2
0
 private void RemovePendingReader(ActorRef takingOverFrom, AkkaProtocolHandle withHandle)
 {
     if (pendingReadHandoffs.ContainsKey(takingOverFrom) &&
         pendingReadHandoffs[takingOverFrom].Equals(withHandle))
     {
         pendingReadHandoffs.Remove(takingOverFrom);
     }
 }
示例#3
0
        private IActorRef CreateEndpoint(
            Address remoteAddress,
            Address localAddress,
            AkkaProtocolTransport transport,
            RemoteSettings endpointSettings,
            bool writing,
            AkkaProtocolHandle handleOption = null,
            int?refuseUid = null)
        {
            System.Diagnostics.Debug.Assert(_transportMapping.ContainsKey(localAddress));
            // refuseUid is ignored for read-only endpoints since the UID of the remote system is already known and has passed
            // quarantine checks

            IActorRef endpointActor;

            if (writing)
            {
                endpointActor =
                    Context.ActorOf(RARP.For(Context.System)
                                    .ConfigureDispatcher(
                                        ReliableDeliverySupervisor.ReliableDeliverySupervisorProps(handleOption, localAddress,
                                                                                                   remoteAddress, refuseUid, transport, endpointSettings, new AkkaPduProtobuffCodec(),
                                                                                                   _receiveBuffers, endpointSettings.Dispatcher)
                                        .WithDeploy(Deploy.Local)),
                                    string.Format("reliableEndpointWriter-{0}-{1}", AddressUrlEncoder.Encode(remoteAddress),
                                                  _endpointId.Next()));
            }
            else
            {
                endpointActor =
                    Context.ActorOf(RARP.For(Context.System)
                                    .ConfigureDispatcher(
                                        EndpointWriter.EndpointWriterProps(handleOption, localAddress, remoteAddress, refuseUid,
                                                                           transport, endpointSettings, new AkkaPduProtobuffCodec(), _receiveBuffers,
                                                                           reliableDeliverySupervisor: null)
                                        .WithDeploy(Deploy.Local)),
                                    string.Format("endpointWriter-{0}-{1}", AddressUrlEncoder.Encode(remoteAddress), _endpointId.Next()));
            }

            Context.Watch(endpointActor);
            return(endpointActor);
        }
示例#4
0
 /// <summary>
 /// Create a new TakeOver command
 /// </summary>
 /// <param name="protocolHandle">The handle of the new association</param>
 /// <param name="replyTo"></param>
 public TakeOver(AkkaProtocolHandle protocolHandle, IActorRef replyTo)
 {
     ProtocolHandle = protocolHandle;
     ReplyTo = replyTo;
 }
示例#5
0
 public static Props EndpointWriterProps(AkkaProtocolHandle handleOrActive, Address localAddress,
     Address remoteAddress, int? refuseUid, AkkaProtocolTransport transport, RemoteSettings settings,
     AkkaPduCodec codec, ConcurrentDictionary<EndpointManager.Link, EndpointManager.ResendState> receiveBuffers, IActorRef reliableDeliverySupervisor = null)
 {
     return Props.Create(
         () =>
             new EndpointWriter(handleOrActive, localAddress, remoteAddress, refuseUid, transport, settings,
                 codec, receiveBuffers, reliableDeliverySupervisor));
 }
示例#6
0
 private IActorRef StartReadEndpoint(AkkaProtocolHandle handle)
 {
     var newReader =
         Context.ActorOf(RARP.For(Context.System)
         .ConfigureDispatcher(
             EndpointReader.ReaderProps(LocalAddress, RemoteAddress, Transport, Settings, _codec, _msgDispatcher,
                 Inbound, (int)handle.HandshakeInfo.Uid, _receiveBuffers, _reliableDeliverySupervisor)
                 .WithDeploy(Deploy.Local)),
             string.Format("endpointReader-{0}-{1}", AddressUrlEncoder.Encode(RemoteAddress), _readerId.Next()));
     Context.Watch(newReader);
     handle.ReadHandlerSource.SetResult(new ActorHandleEventListener(newReader));
     return newReader;
 }
示例#7
0
        public EndpointWriter(
            AkkaProtocolHandle handleOrActive, 
            Address localAddress, 
            Address remoteAddress,
            int? refuseUid, 
            AkkaProtocolTransport transport, 
            RemoteSettings settings,
            AkkaPduCodec codec, 
            ConcurrentDictionary<EndpointManager.Link, EndpointManager.ResendState> receiveBuffers,
            IActorRef reliableDeliverySupervisor = null) :
            base(localAddress, remoteAddress, transport, settings)
        {
            _handleOrActive = handleOrActive;
            _refuseUid = refuseUid;
            _codec = codec;
            _reliableDeliverySupervisor = reliableDeliverySupervisor;
            _system = Context.System;
            _provider = RARP.For(Context.System).Provider;
            _msgDispatcher = new DefaultMessageDispatcher(_system, _provider, _log);
            _receiveBuffers = receiveBuffers;
            Inbound = handleOrActive != null;
            _ackDeadline = NewAckDeadline();
            _handle = handleOrActive;

            if (_handle == null)
            {
                Context.Become(Initializing);
            }
            else
            {
                Context.Become(Writing);
            }
        }
示例#8
0
        protected override void OnReceive(object message)
        {
            message.Match()
                .With<EndpointWriter.FlushAndStop>(flush =>
                {
                    //Trying to serve untilour last breath
                    ResendAll();
                    _writer.Tell(EndpointWriter.FlushAndStop.Instance);
                    Context.Become(FlushWait);
                })
                .With<EndpointManager.Send>(HandleSend)
                .With<Ack>(ack =>
                {
                    if (!UidConfirmed) _pendingAcks.Add(ack);
                    else
                    {
                        try
                        {
                            _resendBuffer = _resendBuffer.Acknowledge(ack);
                        }
                        catch (Exception ex)
                        {
                            throw new InvalidAssociationException(
                                string.Format(
                                    "Error encountered while processing system message acknowledgement {0} {1}",
                                    _resendBuffer, ack), ex);
                        }

                        if (_lastCumulativeAck < ack.CumulativeAck)
                        {
                            _lastCumulativeAck = ack.CumulativeAck;
                            // Cumulative ack is progressing, we might not need to resend non-acked messages yet.
                            // If this progression stops, the timer will eventually kick in, since scheduleAutoResend
                            // does not cancel existing timers (see the "else" case).
                            RescheduleAutoResend();
                        }
                        else
                        {
                            ScheduleAutoResend();
                        }

                        ResendNacked();
                    }
                })
                .With<AttemptSysMsgRedelivery>(sysmsg =>
                {
                    if (UidConfirmed) ResendAll();
                })
                .With<Terminated>(terminated =>
                {
                    _currentHandle = null;
                    Context.Parent.Tell(new EndpointWriter.StoppedReading(Self));
                    if (_resendBuffer.NonAcked.Count > 0 || _resendBuffer.Nacked.Count > 0)
                        Context.System.Scheduler.ScheduleTellOnce(_settings.SysResendTimeout, Self, 
                            new AttemptSysMsgRedelivery(), Self);
                    Context.Become(Idle);
                })
                .With<GotUid>(g =>
                {
                    Context.Parent.Tell(g);
                    //New system that has the same address as the old - need to start from fresh state
                    UidConfirmed = true;
                    if (Uid.HasValue && Uid.Value != g.Uid) Reset();
                    else UnstashAcks();
                    Uid = _refuseUid;
                })
                .With<EndpointWriter.StopReading>(stopped =>
                {
                    _writer.Forward(stopped); //forward the request
                });
        }
示例#9
0
 public ReliableDeliverySupervisor(
     AkkaProtocolHandle handleOrActive, 
     Address localAddress, 
     Address remoteAddress,
     int? refuseUid, 
     AkkaProtocolTransport transport, 
     RemoteSettings settings, 
     AkkaPduCodec codec, 
     ConcurrentDictionary<EndpointManager.Link, EndpointManager.ResendState> receiveBuffers)
 {
     this.handleOrActive = handleOrActive;
     _localAddress = localAddress;
     _remoteAddress = remoteAddress;
     _refuseUid = refuseUid;
     _transport = transport;
     _settings = settings;
     this.codec = codec;
     _currentHandle = handleOrActive;
     _receiveBuffers = receiveBuffers;
     Reset();
     _writer = CreateWriter();
     Uid = handleOrActive != null ? (int?)handleOrActive.HandshakeInfo.Uid : null;
     UidConfirmed = Uid.HasValue;
 }
示例#10
0
        private ActorRef CreateEndpoint(Address remoteAddress, Address localAddress, AkkaProtocolTransport transport,
                                        RemoteSettings endpointSettings, bool writing, AkkaProtocolHandle handleOption = null, int?refuseUid = null)
        {
            System.Diagnostics.Debug.Assert(_transportMapping.ContainsKey(localAddress));
            System.Diagnostics.Debug.Assert(writing || refuseUid == null);

            ActorRef endpointActor;

            if (writing)
            {
                endpointActor =
                    Context.ActorOf(
                        ReliableDeliverySupervisor.ReliableDeliverySupervisorProps(handleOption, localAddress,
                                                                                   remoteAddress, refuseUid, transport, endpointSettings, new AkkaPduProtobuffCodec(),
                                                                                   _receiveBuffers).WithDeploy(Deploy.Local),
                        string.Format("reliableEndpointWriter-{0}-{1}", AddressUrlEncoder.Encode(remoteAddress),
                                      endpointId.Next()));
            }
            else
            {
                endpointActor =
                    Context.ActorOf(
                        EndpointWriter.EndpointWriterProps(handleOption, localAddress, remoteAddress, refuseUid,
                                                           transport, endpointSettings, new AkkaPduProtobuffCodec(), _receiveBuffers,
                                                           reliableDeliverySupervisor: null).WithDeploy(Deploy.Local),
                        string.Format("endpointWriter-{0}-{1}", AddressUrlEncoder.Encode(remoteAddress), endpointId.Next()));
            }

            Context.Watch(endpointActor);
            return(endpointActor);
        }
示例#11
0
 private void Initializing()
 {
     Receive<EndpointManager.Send>(send => EnqueueInBuffer(send));
     Receive<Status.Failure>(failure =>
     {
         if (failure.Cause is InvalidAssociationException)
         {
             PublishAndThrow(new InvalidAssociation(LocalAddress, RemoteAddress, failure.Cause),
                 LogLevel.WarningLevel);
         }
         else
         {
             PublishAndThrow(
                 new EndpointAssociationException(string.Format("Association failed with {0}",
                     RemoteAddress)), LogLevel.DebugLevel);
         }
     });
     Receive<Handle>(handle =>
     {
         // Assert handle == None?
         Context.Parent.Tell(
             new ReliableDeliverySupervisor.GotUid((int)handle.ProtocolHandle.HandshakeInfo.Uid, RemoteAddress));
         _handle = handle.ProtocolHandle;
         _reader = StartReadEndpoint(_handle);
         EventPublisher.NotifyListeners(new AssociatedEvent(LocalAddress, RemoteAddress, Inbound));
         BecomeWritingOrSendBufferedMessages();
     });
 }
示例#12
0
        protected void Receiving()
        {
            Receive<EndpointWriter.FlushAndStop>(flush =>
            {
                //Trying to serve until our last breath
                ResendAll();
                _writer.Tell(EndpointWriter.FlushAndStop.Instance);
                Become(FlushWait);
            });
            Receive<IsIdle>(idle => { }); // Do not reply, we will Terminate soon, or send a GotUid
            Receive<EndpointManager.Send>(send => HandleSend(send));
            Receive<Ack>(ack =>
            {
                // If we are not sure about the UID just ignore the ack. Ignoring is fine.
                if (UidConfirmed)
                {
                    try
                    {
                        _resendBuffer = _resendBuffer.Acknowledge(ack);
                    }
                    catch (Exception ex)
                    {
                        throw new HopelessAssociation(_localAddress, _remoteAddress, Uid,
                            new IllegalStateException($"Error encountered while processing system message acknowledgement buffer: {_resendBuffer} ack: {ack}", ex));
                    }

                    ResendNacked();
                }
            });
            Receive<AttemptSysMsgRedelivery>(sysmsg =>
            {
                if (UidConfirmed) ResendAll();
            });
            Receive<Terminated>(terminated =>
            {
                _currentHandle = null;
                Context.Parent.Tell(new EndpointWriter.StoppedReading(Self));
                if (_resendBuffer.NonAcked.Any() || _resendBuffer.Nacked.Any())
                    Context.System.Scheduler.ScheduleTellOnce(_settings.SysResendTimeout, Self,
                        new AttemptSysMsgRedelivery(), Self);
                GoToIdle();
            });
            Receive<GotUid>(g =>
            {
                _bailoutAt = null;
                Context.Parent.Tell(g);
                //New system that has the same address as the old - need to start from fresh state
                UidConfirmed = true;
                if (Uid.HasValue && Uid.Value != g.Uid) Reset();
                Uid = g.Uid;
                ResendAll();
            });
            Receive<EndpointWriter.StopReading>(stopped =>
            {
                _writer.Forward(stopped); //forward the request
            });
        }
示例#13
0
        protected override SupervisorStrategy SupervisorStrategy()
        {
            return new OneForOneStrategy(ex =>
            {
                if (ex is IAssociationProblem)
                    return Directive.Escalate;

                _log.Warning("Association with remote system {0} has failed; address is now gated for {1} ms. Reason is: [{2}]", _remoteAddress, _settings.RetryGateClosedFor.TotalMilliseconds, ex);
                UidConfirmed = false; // Need confirmation of UID again
                if (_bufferWasInUse)
                {
                    if ((_resendBuffer.Nacked.Any() || _resendBuffer.NonAcked.Any()) && _bailoutAt == null)
                        _bailoutAt = Deadline.Now + _settings.InitialSysMsgDeliveryTimeout;
                    Become(() => Gated(writerTerminated: false, earlyUngateRequested: false));
                    _currentHandle = null;
                    Context.Parent.Tell(new EndpointWriter.StoppedReading(Self));
                    return Directive.Stop;
                }

                return Directive.Escalate;
            });
        }
示例#14
0
 public ReliableDeliverySupervisor(
     AkkaProtocolHandle handleOrActive,
     Address localAddress,
     Address remoteAddress,
     int? refuseUid,
     AkkaProtocolTransport transport,
     RemoteSettings settings,
     AkkaPduCodec codec,
     ConcurrentDictionary<EndpointManager.Link, EndpointManager.ResendState> receiveBuffers)
 {
     _localAddress = localAddress;
     _remoteAddress = remoteAddress;
     _refuseUid = refuseUid;
     _transport = transport;
     _settings = settings;
     _codec = codec;
     _currentHandle = handleOrActive;
     _receiveBuffers = receiveBuffers;
     Reset(); // needs to be called at startup
     _writer = CreateWriter(); // need to create writer at startup
     Uid = handleOrActive != null ? (int?)handleOrActive.HandshakeInfo.Uid : null;
     UidConfirmed = Uid.HasValue;
     Receiving();
     _autoResendTimer = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(_settings.SysResendTimeout, _settings.SysResendTimeout, Self, new AttemptSysMsgRedelivery(),
             Self);
 }
示例#15
0
 public TookOver(IActorRef writer, AkkaProtocolHandle protocolHandle)
 {
     ProtocolHandle = protocolHandle;
     Writer = writer;
 }
示例#16
0
 public Handle(AkkaProtocolHandle protocolHandle)
 {
     ProtocolHandle = protocolHandle;
 }
示例#17
0
 private void RemovePendingReader(IActorRef takingOverFrom, AkkaProtocolHandle withHandle)
 {
     if (_pendingReadHandoffs.ContainsKey(takingOverFrom) &&
         _pendingReadHandoffs[takingOverFrom].Equals(withHandle))
     {
         _pendingReadHandoffs.Remove(takingOverFrom);
     }
 }
示例#18
0
        protected override SupervisorStrategy SupervisorStrategy()
        {
            return new OneForOneStrategy(ex =>
            {
                var directive = Directive.Stop;
                ex.Match()
                    .With<IAssociationProblem>(problem => directive = Directive.Escalate)
                    .Default(e =>
                    {
                        _log.Warning("Association with remote system {0} has failed; address is now gated for {1} ms. Reason is: [{2}]", _remoteAddress, _settings.RetryGateClosedFor.TotalMilliseconds, ex.Message);
                        UidConfirmed = false;
                        Context.Become(Gated);
                        _currentHandle = null;
                        Context.Parent.Tell(new EndpointWriter.StoppedReading(Self));
                        directive = Directive.Stop;
                    });

                return directive;
            });
        }
示例#19
0
        private void CreateAndRegisterEndpoint(AkkaProtocolHandle handle, int? refuseUid)
        {
            var writing = _settings.UsePassiveConnections && !_endpoints.HasWriteableEndpointFor(handle.RemoteAddress);
            _eventPublisher.NotifyListeners(new AssociatedEvent(handle.LocalAddress, handle.RemoteAddress, true));
            var endpoint = CreateEndpoint(
                handle.RemoteAddress,
                handle.LocalAddress,
                _transportMapping[handle.LocalAddress],
                _settings,
                writing,
                handle,
                refuseUid);

            if (writing)
            {
                _endpoints.RegisterWritableEndpoint(handle.RemoteAddress, endpoint, handle.HandshakeInfo.Uid, refuseUid);
            }
            else
            {
                _endpoints.RegisterReadOnlyEndpoint(handle.RemoteAddress, endpoint, handle.HandshakeInfo.Uid);
                if(!_endpoints.HasWriteableEndpointFor(handle.RemoteAddress))
                    _endpoints.RemovePolicy(handle.RemoteAddress);
            }
        }
示例#20
0
 public static Props ReliableDeliverySupervisorProps(
     AkkaProtocolHandle handleOrActive, 
     Address localAddress, 
     Address remoteAddress,
     int? refuseUid, 
     AkkaProtocolTransport transport, 
     RemoteSettings settings, 
     AkkaPduCodec codec, 
     ConcurrentDictionary<EndpointManager.Link, EndpointManager.ResendState> receiveBuffers,
     string dispatcher)
 {
     return
         Props.Create(
             () =>
                 new ReliableDeliverySupervisor(handleOrActive, localAddress, remoteAddress, refuseUid, transport,
                     settings, codec, receiveBuffers))
                     .WithDispatcher(dispatcher);
 }
示例#21
0
        private IActorRef CreateEndpoint(
            Address remoteAddress,
            Address localAddress,
            AkkaProtocolTransport transport,
            RemoteSettings endpointSettings,
            bool writing,
            AkkaProtocolHandle handleOption = null,
            int? refuseUid = null)
        {
            System.Diagnostics.Debug.Assert(_transportMapping.ContainsKey(localAddress));
            System.Diagnostics.Debug.Assert(writing || refuseUid == null);

            IActorRef endpointActor;

            if (writing)
            {
                endpointActor =
                    Context.ActorOf(RARP.For(Context.System)
                    .ConfigureDispatcher(
                        ReliableDeliverySupervisor.ReliableDeliverySupervisorProps(handleOption, localAddress,
                            remoteAddress, refuseUid, transport, endpointSettings, new AkkaPduProtobuffCodec(),
                            _receiveBuffers, endpointSettings.Dispatcher)
                            .WithDeploy(Deploy.Local)),
                        string.Format("reliableEndpointWriter-{0}-{1}", AddressUrlEncoder.Encode(remoteAddress),
                            _endpointId.Next()));
            }
            else
            {
                endpointActor =
                    Context.ActorOf(RARP.For(Context.System)
                    .ConfigureDispatcher(
                        EndpointWriter.EndpointWriterProps(handleOption, localAddress, remoteAddress, refuseUid,
                            transport, endpointSettings, new AkkaPduProtobuffCodec(), _receiveBuffers,
                            reliableDeliverySupervisor: null)
                            .WithDeploy(Deploy.Local)),
                        string.Format("endpointWriter-{0}-{1}", AddressUrlEncoder.Encode(remoteAddress), _endpointId.Next()));
            }

            Context.Watch(endpointActor);
            return endpointActor;
        }
示例#22
0
 private void Initializing(object message)
 {
     if (message is EndpointManager.Send)
     {
         EnqueueInBuffer(message);
     }
     else if (message is Status.Failure)
     {
         var failure = message as Status.Failure;
         if (failure.Cause is InvalidAssociationException)
         {
             PublishAndThrow(new InvalidAssociation(LocalAddress, RemoteAddress, failure.Cause),
                 LogLevel.WarningLevel);
         }
         else
         {
             PublishAndThrow(
                 new EndpointAssociationException(string.Format("Association failed with {0}",
                     RemoteAddress)), LogLevel.DebugLevel);
         }
     }
     else if (message is Handle)
     {
         var inboundHandle = message as Handle;
         Context.Parent.Tell(
             new ReliableDeliverySupervisor.GotUid((int)inboundHandle.ProtocolHandle.HandshakeInfo.Uid));
         _handle = inboundHandle.ProtocolHandle;
         _reader = StartReadEndpoint(_handle);
         BecomeWritingOrSendBufferedMessages();
     }
     else
     {
         Unhandled(message);
     }
 }
示例#23
0
        protected override void Unhandled(object message)
        {
            if (message is Terminated)
            {
                var t = message as Terminated;
                if (_reader == null || t.ActorRef.Equals(_reader))
                {
                    PublishAndThrow(new EndpointDisassociatedException("Disassociated"), LogLevel.DebugLevel);
                }
            }
            else if (message is StopReading)
            {
                var stop = message as StopReading;
                if (_reader != null)
                {
                    _reader.Tell(stop, stop.ReplyTo);
                }
                else
                {
                    // initializing, buffer and take care of it later when buffer is sent
                    EnqueueInBuffer(message);
                }
            }
            else if (message is TakeOver)
            {
                var takeover = message as TakeOver;

                // Shutdown old reader
                _handle.Disassociate();
                _handle = takeover.ProtocolHandle;
                takeover.ReplyTo.Tell(new TookOver(Self, _handle));
                Context.Become(Handoff);
            }
            else if (message is FlushAndStop)
            {
                _stopReason = DisassociateInfo.Shutdown;
                Context.Stop(Self);
            }
            else if (message is OutboundAck)
            {
                var ack = message as OutboundAck;
                _lastAck = ack.Ack;
                if (_ackDeadline.IsOverdue)
                    TrySendPureAck();
            }
            else if (message is AckIdleCheckTimer || message is FlushAndStopTimeout || message is BackoffTimer)
            {
                //ignore
            }
            else
            {
                base.Unhandled(message);
            }
        }