Пример #1
0
        protected bool DefaultReceive(object message)
        {
            if (message is Subscribe)
            {
                var subscribe = (Subscribe)message;

                Context.Watch(subscribe.Ref);
                Subscribers.Add(subscribe.Ref);
                PruneDeadline = null;
                Context.Parent.Tell(new Subscribed(new SubscribeAck(subscribe), Sender));
            }
            else if (message is Unsubscribe)
            {
                var unsubscribe = (Unsubscribe)message;

                Context.Unwatch(unsubscribe.Ref);
                Remove(unsubscribe.Ref);
                Context.Parent.Tell(new Unsubscribed(new UnsubscribeAck(unsubscribe), Sender));
            }
            else if (message is Terminated)
            {
                var terminated = (Terminated)message;
                Remove(terminated.ActorRef);
            }
            else if (message is Prune)
            {
                if (PruneDeadline != null && PruneDeadline.IsOverdue)
                {
                    PruneDeadline = null;
                    Context.Parent.Tell(NoMoreSubscribers.Instance);
                }
            }
            else if (message is TerminateRequest)
            {
                if (Subscribers.Count == 0 && !Context.GetChildren().Any())
                {
                    Context.Stop(Self);
                }
                else
                {
                    Context.Parent.Tell(NewSubscriberArrived.Instance);
                }
            }
            else
            {
                foreach (var subscriber in Subscribers)
                    subscriber.Forward(message);
            }

            return true;
        }
Пример #2
0
 /// <summary>
 /// Marking an endpoint as failed means that we will not try to connect to the remote system within
 /// the gated period but it is ok for the remote system to try to connect with us (inbound-only.)
 /// </summary>
 /// <param name="endpoint">TBD</param>
 /// <param name="timeOfRelease">TBD</param>
 public void MarkAsFailed(IActorRef endpoint, Deadline timeOfRelease)
 {
     if (IsWritable(endpoint))
     {
         var address = _writableToAddress[endpoint];
         if (_addressToWritable.TryGetValue(address, out var policy))
         {
             if (policy is EndpointManager.Quarantined)
             {
                 // don't overwrite Quarantined with Gated
             }
             else if (policy is EndpointManager.Pass)
             {
                 _addressToWritable[address] = new EndpointManager.Gated(timeOfRelease,
                                                                         policy.AsInstanceOf <EndpointManager.Pass>().RefuseUid);
                 _writableToAddress.Remove(endpoint);
             }
             else if (policy is EndpointManager.WasGated)
             {
                 _addressToWritable[address] = new EndpointManager.Gated(timeOfRelease,
                                                                         policy.AsInstanceOf <EndpointManager.WasGated>().RefuseUid);
                 _writableToAddress.Remove(endpoint);
             }
             else if (policy is EndpointManager.Gated)
             {
                 // already gated
             }
         }
         else
         {
             _addressToWritable[address] = new EndpointManager.Gated(timeOfRelease, null);
             _writableToAddress.Remove(endpoint);
         }
     }
     else if (IsReadOnly(endpoint))
     {
         _addressToReadonly.Remove(_readonlyToAddress[endpoint]);
         _readonlyToAddress.Remove(endpoint);
     }
 }
Пример #3
0
        protected bool DefaultReceive(object message)
        {
            if (message is Subscribe)
            {
                var subscribe = (Subscribe)message;

                Context.Watch(subscribe.Ref);
                Subscribers.Add(subscribe.Ref);
                PruneDeadline = null;
                Context.Parent.Tell(new Subscribed(new SubscribeAck(subscribe), Sender));
            }
            else if (message is Unsubscribe)
            {
                var unsubscribe = (Unsubscribe)message;

                Context.Unwatch(unsubscribe.Ref);
                Remove(unsubscribe.Ref);
                Context.Parent.Tell(new Unsubscribed(new UnsubscribeAck(unsubscribe), Sender));
            }
            else if (message is Terminated)
            {
                var terminated = (Terminated)message;
                Remove(terminated.ActorRef);
            }
            else if (message is Prune)
            {
                if (PruneDeadline != null && PruneDeadline.IsOverdue) Context.Stop(Self);
            }
            else
            {
                foreach (var subscriber in Subscribers)
                    subscriber.Forward(message);
            }

            return true;
        }
Пример #4
0
 private void Reset()
 {
     _resendBuffer = new AckedSendBuffer<EndpointManager.Send>(_settings.SysMsgBufferSize);
     _seqCounter = 0L;
     _bailoutAt = null;
     _bufferWasInUse = false;
 }
Пример #5
0
        private bool WriteSend(EndpointManager.Send send)
        {
            try
            {
                if (_handle == null)
                    throw new EndpointException(
                        "Internal error: Endpoint is in state Writing, but no association handle is present.");
                if (_provider.RemoteSettings.LogSend)
                {
                    var msgLog = string.Format("RemoteMessage: {0} to [{1}]<+[{2}] from [{3}]", send.Message,
                        send.Recipient, send.Recipient.Path, send.SenderOption ?? _system.DeadLetters);
                    _log.Debug(msgLog);
                }

                var pdu = _codec.ConstructMessage(send.Recipient.LocalAddressToUse, send.Recipient,
                    SerializeMessage(send.Message), send.SenderOption, send.Seq, _lastAck);

                //todo: RemoteMetrics https://github.com/akka/akka/blob/dc0547dd73b54b5de9c3e0b45a21aa865c5db8e2/akka-remote/src/main/scala/akka/remote/Endpoint.scala#L742

                //todo: max payload size validation

                var ok = _handle.Write(pdu);

                if (ok)
                {
                    _ackDeadline = NewAckDeadline();
                    _lastAck = null;
                    return true;
                }

                return false;
            }
            catch (SerializationException ex)
            {
                _log.Error(ex, "Transient association error (association remains live)");
                return true;
            }
            catch (EndpointException ex)
            {
                PublishAndThrow(ex, LogLevel.ErrorLevel);
            }
            catch (Exception ex)
            {
                PublishAndThrow(new EndpointException("Failed to write message to the transport", ex),
                    LogLevel.ErrorLevel);
            }

            return false;
        }
Пример #6
0
 public Quarantined(int uid, Deadline deadline)
     : base(true)
 {
     Uid = uid;
     Deadline = deadline;
 }
Пример #7
0
 public Quarantined(long uid, Deadline deadline)
     : base(true)
 {
     Uid      = uid;
     Deadline = deadline;
 }
Пример #8
0
        private void Remove(IActorRef actorRef)
        {
            Subscribers.Remove(actorRef);

            if (Subscribers.Count == 0 && !Context.GetChildren().Any())
            {
                PruneDeadline = Deadline.Now + EmptyTimeToLive;
            }
        }
Пример #9
0
 public void MarkAsQuarantined(Address address, int uid, Deadline timeOfRelease)
 {
     addressToWritable.AddOrSet(address, new EndpointManager.Quarantined(uid, timeOfRelease));
 }
Пример #10
0
        public FirstSeedNodeProcess(ImmutableList<Address> seeds)
        {
            _cluster = Cluster.Get(Context.System);
            _selfAddress = _cluster.SelfAddress;

            if (seeds.Count <= 1 || seeds.Head() != _selfAddress)
                throw new ArgumentException("Join seed node should not be done");

            _remainingSeeds = seeds.Remove(_selfAddress);
            _timeout = Deadline.Now + _cluster.Settings.SeedNodeTimeout;
            _retryTaskToken = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), Self, new InternalClusterAction.JoinSeenNode(), Self);
            Self.Tell(new InternalClusterAction.JoinSeenNode());
        }
Пример #11
0
 /// <summary>
 /// Record a "refused" UID for a remote system that has been quarantined.
 /// </summary>
 /// <param name="remoteAddress">The remote address of the quarantined system.</param>
 /// <param name="refuseUid">The refused UID of the remote system.</param>
 /// <param name="timeOfRelease">The timeframe for releasing quarantine.</param>
 public void RegisterWritableEndpointRefuseUid(Address remoteAddress, int refuseUid, Deadline timeOfRelease)
 {
     _addressToRefuseUid[remoteAddress] = Tuple.Create(refuseUid, timeOfRelease);
 }
Пример #12
0
 /// <summary>
 /// Mark the current remote address as quarantined.
 /// </summary>
 /// <param name="address">The address to quarantine.</param>
 /// <param name="uid">The UID of the current address.</param>
 /// <param name="timeOfRelease">The timeframe to release the quarantine.</param>
 public void MarkAsQuarantined(Address address, int uid, Deadline timeOfRelease)
 {
     _addressToWritable[address]  = new EndpointManager.Quarantined(uid, timeOfRelease);
     _addressToRefuseUid[address] = Tuple.Create(uid, timeOfRelease);
 }
Пример #13
0
 public Quarantined(long uid, Deadline deadline)
 {
     Uid = uid;
     Deadline = deadline;
 }
Пример #14
0
 /// <summary>
 /// Marking an endpoint as failed means that we will not try to connect to the remote system within
 /// the gated period but it is ok for the remote system to try to connect with us (inbound-only.)
 /// </summary>
 public void MarkAsFailed(IActorRef endpoint, Deadline timeOfRelease)
 {
     if (IsWritable(endpoint))
     {
         var address = _writableToAddress[endpoint];
         EndpointManager.EndpointPolicy policy;
         if (_addressToWritable.TryGetValue(address, out policy))
         {
             if (policy is EndpointManager.Quarantined)
             {
             } // don't overwrite Quarantined with Gated
             if (policy is EndpointManager.Pass)
             {
                 _addressToWritable[address] = new EndpointManager.Gated(timeOfRelease,
                     policy.AsInstanceOf<EndpointManager.Pass>().RefuseUid);
                 _writableToAddress.Remove(endpoint);
             }
             else if (policy is EndpointManager.WasGated)
             {
                 _addressToWritable[address] = new EndpointManager.Gated(timeOfRelease,
                     policy.AsInstanceOf<EndpointManager.WasGated>().RefuseUid);
                 _writableToAddress.Remove(endpoint);
             }
             else if (policy is EndpointManager.Gated)
             {
             } // already gated
         }
         else
         {
             _addressToWritable[address] = new EndpointManager.Gated(timeOfRelease, null);
             _writableToAddress.Remove(endpoint);
         }
     }
     else if (IsReadOnly(endpoint))
     {
         _addressToReadonly.Remove(_readonlyToAddress[endpoint]);
         _readonlyToAddress.Remove(endpoint);
     }
 }
Пример #15
0
 public Gated(Deadline deadline, int?refuseUid)
     : base(true)
 {
     TimeOfRelease = deadline;
     RefuseUid     = refuseUid;
 }
Пример #16
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
            });
        }
Пример #17
0
 /// <summary>
 /// Marking an endpoint as failed means that we will not try to connect to the remote system within
 /// the gated period but it is ok for the remote system to try to connect with us (inbound-only.)
 /// </summary>
 public void MarkAsFailed(IActorRef endpoint, Deadline timeOfRelease)
 {
     if (IsWritable(endpoint))
     {
         addressToWritable.AddOrSet(writableToAddress[endpoint], new EndpointManager.Gated(timeOfRelease));
         writableToAddress.Remove(endpoint);
     }
     else if (IsReadOnly(endpoint))
     {
         addressToReadonly.Remove(readonlyToAddress[endpoint]);
         readonlyToAddress.Remove(endpoint);
     }
 }
Пример #18
0
        private void TryingToJoin(object message, Address joinWith, Deadline deadline)
        {
            if (_logInfo && !(message is InternalClusterAction.ITick))
            {
                _log.Debug("[TryingToJoin] Received {0}", message);
            }

            if (message is InternalClusterAction.Welcome)
            {
                var w = message as InternalClusterAction.Welcome;
                Welcome(joinWith, w.From, w.Gossip);
            }
            else if (message is InternalClusterAction.InitJoin)
            {
                Sender.Tell(new InternalClusterAction.InitJoinNack(_cluster.SelfAddress));
            }
            else if (message is ClusterUserAction.JoinTo)
            {
                var jt = message as ClusterUserAction.JoinTo;
                BecomeUninitialized();
                Join(jt.Address);
            }
            else if (message is InternalClusterAction.ISubscriptionMessage)
            {
                var isub = message as InternalClusterAction.ISubscriptionMessage;
                _publisher.Forward(isub);
            }
            else if (message is InternalClusterAction.ITick)
            {
                if (deadline != null && deadline.IsOverdue)
                {
                    BecomeUninitialized();
                    if (_cluster.Settings.SeedNodes.Any()) JoinSeedNodes(_cluster.Settings.SeedNodes);
                    else Join(joinWith);
                }
            }
            else
            {
                Unhandled(message);
            }
        }
Пример #19
0
 /// <summary>
 /// Marking an endpoint as failed means that we will not try to connect to the remote system within
 /// the gated period but it is ok for the remote system to try to connect with us (inbound-only.)
 /// </summary>
 public void MarkAsFailed(IActorRef endpoint, Deadline timeOfRelease)
 {
     if (IsWritable(endpoint))
     {
         _addressToWritable[_writableToAddress[endpoint]] = new EndpointManager.Gated(timeOfRelease);
         _writableToAddress.Remove(endpoint);
     }
     else if (IsReadOnly(endpoint))
     {
         _addressToReadonly.Remove(_readonlyToAddress[endpoint]);
         _readonlyToAddress.Remove(endpoint);
     }
 }
Пример #20
0
 public void MarkAsQuarantined(Address address, int uid, Deadline timeOfRelease)
 {
     _addressToWritable[address] = new EndpointManager.Quarantined(uid, timeOfRelease);
 }
Пример #21
0
 public Gated(Deadline deadline)
     : base(true)
 {
     TimeOfRelease = deadline;
 }
Пример #22
0
 public GossipEnvelope(UniqueAddress from, UniqueAddress to, Gossip gossip, Deadline deadline = null)
 {
     _from = from;
     _to = to;
     Gossip = gossip;
     Deadline = deadline;
 }
Пример #23
0
 public Gated(Deadline deadline)
     : base(true)
 {
     TimeOfRelease = deadline;
 }
Пример #24
0
        private bool WriteSend(EndpointManager.Send send)
        {
            try
            {
                if (_handle == null)
                    throw new EndpointException(
                        "Internal error: Endpoint is in state Writing, but no association handle is present.");
                if (_provider.RemoteSettings.LogSend)
                {
                    _log.Debug("RemoteMessage: {0} to [{1}]<+[{2}] from [{3}]", send.Message,
                        send.Recipient, send.Recipient.Path, send.SenderOption ?? _system.DeadLetters);
                }

                var pdu = _codec.ConstructMessage(send.Recipient.LocalAddressToUse, send.Recipient,
                    SerializeMessage(send.Message), send.SenderOption, send.Seq, _lastAck);

                _remoteMetrics.LogPayloadBytes(send.Message, pdu.Length);

                if (pdu.Length > Transport.MaximumPayloadBytes)
                {
                    var reason = new OversizedPayloadException(
                        string.Format("Discarding oversized payload sent to {0}: max allowed size {1} bytes, actual size of encoded {2} was {3} bytes.",
                            send.Recipient,
                            Transport.MaximumPayloadBytes,
                            send.Message.GetType(),
                            pdu.Length));
                    _log.Error(reason, "Transient association error (association remains live)");
                    return true;
                }
                else
                {
                    var ok = _handle.Write(pdu);

                    if (ok)
                    {
                        _ackDeadline = NewAckDeadline();
                        _lastAck = null;
                        return true;
                    }
                }
                return false;
            }
            catch (SerializationException ex)
            {
                _log.Error(ex, "Transient association error (association remains live)");
                return true;
            }
            catch (EndpointException ex)
            {
                PublishAndThrow(ex, LogLevel.ErrorLevel);
            }
            catch (Exception ex)
            {
                PublishAndThrow(new EndpointException("Failed to write message to the transport", ex),
                    LogLevel.ErrorLevel);
            }

            return false;
        }
Пример #25
0
 private void TrySendPureAck()
 {
     if (_handle != null && _lastAck != null)
     {
         if (_handle.Write(_codec.ConstructPureAck(_lastAck)))
         {
             _ackDeadline = NewAckDeadline();
             _lastAck = null;
         }
     }
 }
Пример #26
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;
            });
        }
Пример #27
0
 public void MarkAsQuarantined(Address address, int uid, Deadline timeOfRelease)
 {
     _addressToWritable.AddOrSet(address, new EndpointManager.Quarantined(uid, timeOfRelease));
 }
Пример #28
0
 private void TryingToJoin(object message, Address joinWith, Deadline deadline)
 {
     message.Match()
         .With<InternalClusterAction.Welcome>(m => Welcome(joinWith, m.From, m.Gossip))
         .With<InternalClusterAction.InitJoin>(
             m => Sender.Tell(new InternalClusterAction.InitJoinAck(_cluster.SelfAddress)))
         .With<ClusterUserAction.JoinTo>(m =>
         {
             BecomeUnitialized();
             Join(m.Address);
         })
         .With<InternalClusterAction.JoinSeedNodes>(m =>
         {
             BecomeUnitialized();
             JoinSeedNodes(m.SeedNodes);
         })
         .With<InternalClusterAction.ISubscriptionMessage>(msg => _publisher.Forward(msg))
         .Default(m =>
         {
             if (deadline != null && deadline.IsOverdue)
             {
                 BecomeUnitialized();
                 if (_cluster.Settings.SeedNodes.Any()) JoinSeedNodes(_cluster.Settings.SeedNodes);
                 else Join(joinWith);
             }
         });
 }