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); } } }
private void RemovePendingReader(ActorRef takingOverFrom, AkkaProtocolHandle withHandle) { if (pendingReadHandoffs.ContainsKey(takingOverFrom) && pendingReadHandoffs[takingOverFrom].Equals(withHandle)) { pendingReadHandoffs.Remove(takingOverFrom); } }
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); }
/// <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; }
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)); }
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; }
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); } }
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 }); }
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; }
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); }
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(); }); }
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 }); }
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; }); }
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); }
public TookOver(IActorRef writer, AkkaProtocolHandle protocolHandle) { ProtocolHandle = protocolHandle; Writer = writer; }
public Handle(AkkaProtocolHandle protocolHandle) { ProtocolHandle = protocolHandle; }
private void RemovePendingReader(IActorRef takingOverFrom, AkkaProtocolHandle withHandle) { if (_pendingReadHandoffs.ContainsKey(takingOverFrom) && _pendingReadHandoffs[takingOverFrom].Equals(withHandle)) { _pendingReadHandoffs.Remove(takingOverFrom); } }
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; }); }
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); } }
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); }
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; }
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); } }
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); } }