Esempio n. 1
0
        /// <inheritdoc/>
        public override bool Write(ByteString payload)
        {
            var tokens = payload.Length;

            //need to declare recursive delegates first before they can self-reference
            //might want to consider making this consumer function strongly typed: http://blogs.msdn.com/b/wesdyer/archive/2007/02/02/anonymous-recursion-in-c.aspx
            bool TryConsume(ThrottleMode currentBucket)
            {
                var timeOfSend = MonotonicClock.GetNanos();
                var res        = currentBucket.TryConsumeTokens(timeOfSend, tokens);
                var newBucket  = res.Item1;
                var allow      = res.Item2;

                if (allow)
                {
                    return(OutboundThrottleMode.CompareAndSet(currentBucket, newBucket) || TryConsume(OutboundThrottleMode.Value));
                }
                return(false);
            }

            var throttleMode = OutboundThrottleMode.Value;

            if (throttleMode is Blackhole)
            {
                return(true);
            }

            var success = TryConsume(OutboundThrottleMode.Value);

            return(success && WrappedHandle.Write(payload));
        }
        public void A_cluster_must_startup_with_one_dispatcher_thread()
        {
            // This test failed before fixing https://github.com/akkadotnet/akka.net/issues/1959 when adding a sleep before the
            // Await of GetClusterCoreRef in the Cluster extension constructor.
            // The reason was that other cluster actors were started too early and
            // they also tried to get the Cluster extension and thereby blocking
            // dispatcher threads.
            // Note that the Cluster extension is started via ClusterActorRefProvider
            // before ActorSystem.apply returns, i.e. in the constructor of AkkaSpec.
            var totalStartupTime = TimeSpan.FromTicks(MonotonicClock.GetTicks() - _startTime).TotalMilliseconds;

            Assert.True(totalStartupTime < (Sys.Settings.CreationTimeout - TimeSpan.FromSeconds(2)).TotalMilliseconds);
            Sys.ActorOf(TestProps).Tell("hello");
            Sys.ActorOf(TestProps).Tell("hello");
            Sys.ActorOf(TestProps).Tell("hello");

            var cluster = Cluster.Get(Sys);

            totalStartupTime = TimeSpan.FromTicks(MonotonicClock.GetTicks() - _startTime).TotalMilliseconds;
            Assert.True(totalStartupTime < (Sys.Settings.CreationTimeout - TimeSpan.FromSeconds(2)).TotalMilliseconds);

            ExpectMsg("hello");
            ExpectMsg("hello");
            ExpectMsg("hello");
        }
Esempio n. 3
0
 private void ForwardOrDelay(ByteString payload)
 {
     if (InboundThrottleMode is Blackhole)
     {
         // Do nothing
     }
     else
     {
         if (!ThrottledMessages.Any())
         {
             var tokens    = payload.Length;
             var res       = InboundThrottleMode.TryConsumeTokens(MonotonicClock.GetNanos(), tokens);
             var newBucket = res.Item1;
             var success   = res.Item2;
             if (success)
             {
                 InboundThrottleMode = newBucket;
                 UpstreamListener.Notify(new InboundPayload(payload));
             }
             else
             {
                 ThrottledMessages.Enqueue(payload);
                 ScheduleDequeue(InboundThrottleMode.TimeToAvailable(MonotonicClock.GetNanos(), tokens));
             }
         }
         else
         {
             ThrottledMessages.Enqueue(payload);
         }
     }
 }
            public ThrottlingTester(IActorRef remoteRef, IActorRef controller)
            {
                _remoteRef  = remoteRef;
                _controller = controller;

                Receive <string>(s => s.Equals("start"), s =>
                {
                    Self.Tell("sendNext");
                    _startTime = MonotonicClock.GetNanos();
                });

                Receive <string>(s => s.Equals("sendNext") && _messageCount > 0, s =>
                {
                    _remoteRef.Tell("ping");
                    Self.Tell("sendNext");
                    _messageCount--;
                });

                Receive <string>(s => s.Equals("pong"), s =>
                {
                    _received++;
                    if (_received >= MessageCount)
                    {
                        _controller.Tell(MonotonicClock.GetNanos() - _startTime);
                    }
                });
            }
Esempio n. 5
0
        protected void AssertRef(IActorRef actorRef, long suspensions,
                                 long resumes, long registers, long unregisters, long msgsReceived,
                                 long msgsProcessed, long restarts, MessageDispatcher dispatcher = null)
        {
            var deadline = MonotonicClock.GetMilliseconds() + 1000;
            var stats    = StatsFor(actorRef, dispatcher);

            try
            {
                Await(deadline, () => stats.Suspensions.Current == suspensions);
                Await(deadline, () => stats.Resumes.Current == resumes);
                Await(deadline, () => stats.Registers.Current == registers);
                Await(deadline, () => stats.Unregisters.Current == unregisters);
                Await(deadline, () => stats.MsgsReceived.Current == msgsReceived);
                Await(deadline, () => stats.MsgsProcessed.Current == msgsProcessed);
                Await(deadline, () => stats.Restarts.Current == restarts);
            }
            catch (Exception ex)
            {
                Sys.EventStream.Publish(new Error(ex, dispatcher?.ToString(),
                                                  dispatcher?.GetType() ?? this.GetType(),
                                                  $"actual: {stats}, required: InterceptorStats(susp={suspensions}," +
                                                  $"res={resumes}, reg={registers}, unreg={unregisters}, recv={msgsReceived}, " +
                                                  $"proc={msgsProcessed}, restart={restarts})"));
                throw;
            }
        }
Esempio n. 6
0
 private DefaultChannelId()
 {
     unchecked
     {
         _hashCode  = (int)(MonotonicClock.GetTicks() & 0xFFFFFFFF);
         _hashCode *= _hashCode ^ ThreadLocalRandom.Current.Next();
     }
 }
Esempio n. 7
0
        protected void AssertDispatcher(MessageDispatcherInterceptor dispatcher, long stops)
        {
            var deadline = MonotonicClock.GetMilliseconds() + (long)(dispatcher.ShutdownTimeout.TotalMilliseconds * 5);

            try
            {
                Await(deadline, () => stops == dispatcher.Stops.Current);
            }
            catch (Exception ex)
            {
                Sys.EventStream.Publish(new Error(ex, dispatcher.ToString(), dispatcher.GetType(), $"actual: stops={dispatcher.Stops.Current}, required: stops={stops}"));
                throw;
            }
        }
Esempio n. 8
0
        private void FetchFromScheduledTaskQueue()
        {
            if (HasScheduledTasks())
            {
                var tickCount = MonotonicClock.GetTicks();
                while (true)
                {
                    var scheduledTask = PollScheduledTask(tickCount);
                    if (scheduledTask == null)
                    {
                        break;
                    }

                    _taskQueue.Enqueue(scheduledTask);
                }
            }
        }
Esempio n. 9
0
        private static void Await(long until, Func <bool> condition)
        {
            var spinWait = new SpinWait();
            var done     = false;

            while (MonotonicClock.GetMilliseconds() <= until && !done)
            {
                done = condition();
                if (!done)
                {
                    spinWait.SpinOnce();
                }
            }

            if (!done)
            {
                throw new Exception("Await failed");
            }
        }
Esempio n. 10
0
        private void InitializeFSM()
        {
            When(ThrottlerState.WaitExposedHandle, @event =>
            {
                if (@event.FsmEvent is ThrottlerManager.Handle && @event.StateData is Uninitialized)
                {
                    // register to downstream layer and wait for origin
                    OriginalHandle.ReadHandlerSource.SetResult(new ActorHandleEventListener(Self));
                    return
                    (GoTo(ThrottlerState.WaitOrigin)
                     .Using(
                         new ExposedHandle(
                             @event.FsmEvent.AsInstanceOf <ThrottlerManager.Handle>().ThrottlerHandle)));
                }
                return(null);
            });

            When(ThrottlerState.WaitOrigin, @event =>
            {
                if (@event.FsmEvent is InboundPayload && @event.StateData is ExposedHandle)
                {
                    var b = @event.FsmEvent.AsInstanceOf <InboundPayload>().Payload;
                    ThrottledMessages.Enqueue(b);
                    var origin = PeekOrigin(b);
                    if (origin != null)
                    {
                        Manager.Tell(new ThrottlerManager.Checkin(origin, @event.StateData.AsInstanceOf <ExposedHandle>().Handle));
                        return(GoTo(ThrottlerState.WaitMode));
                    }
                    return(Stay());
                }
                return(null);
            });

            When(ThrottlerState.WaitMode, @event =>
            {
                if (@event.FsmEvent is InboundPayload)
                {
                    var b = @event.FsmEvent.AsInstanceOf <InboundPayload>().Payload;
                    ThrottledMessages.Enqueue(b);
                    return(Stay());
                }

                if (@event.FsmEvent is ThrottleMode && @event.StateData is ExposedHandle)
                {
                    var mode            = @event.FsmEvent.AsInstanceOf <ThrottleMode>();
                    var exposedHandle   = @event.StateData.AsInstanceOf <ExposedHandle>().Handle;
                    InboundThrottleMode = mode;
                    try
                    {
                        if (mode is Blackhole)
                        {
                            ThrottledMessages = new Queue <ByteString>();
                            exposedHandle.Disassociate();
                            return(Stop());
                        }
                        else
                        {
                            AssociationHandler.Notify(new InboundAssociation(exposedHandle));
                            var self = Self;
                            exposedHandle.ReadHandlerSource.Task.ContinueWith(
                                r => new ThrottlerManager.Listener(r.Result),
                                TaskContinuationOptions.ExecuteSynchronously)
                            .PipeTo(self);
                            return(GoTo(ThrottlerState.WaitUpstreamListener));
                        }
                    }
                    finally
                    {
                        Sender.Tell(SetThrottleAck.Instance);
                    }
                }

                return(null);
            });

            When(ThrottlerState.WaitUpstreamListener, @event =>
            {
                if (@event.FsmEvent is InboundPayload)
                {
                    var b = @event.FsmEvent.AsInstanceOf <InboundPayload>();
                    ThrottledMessages.Enqueue(b.Payload);
                    return(Stay());
                }

                if (@event.FsmEvent is ThrottlerManager.Listener)
                {
                    UpstreamListener = @event.FsmEvent.AsInstanceOf <ThrottlerManager.Listener>().HandleEventListener;
                    Self.Tell(new Dequeue());
                    return(GoTo(ThrottlerState.Throttling));
                }

                return(null);
            });

            When(ThrottlerState.WaitModeAndUpstreamListener, @event =>
            {
                if (@event.FsmEvent is ThrottlerManager.ListenerAndMode)
                {
                    var listenerAndMode = @event.FsmEvent.AsInstanceOf <ThrottlerManager.ListenerAndMode>();
                    UpstreamListener    = listenerAndMode.HandleEventListener;
                    InboundThrottleMode = listenerAndMode.Mode;
                    Self.Tell(new Dequeue());
                    return(GoTo(ThrottlerState.Throttling));
                }

                if (@event.FsmEvent is InboundPayload)
                {
                    var b = @event.FsmEvent.AsInstanceOf <InboundPayload>();
                    ThrottledMessages.Enqueue(b.Payload);
                    return(Stay());
                }

                return(null);
            });

            When(ThrottlerState.Throttling, @event =>
            {
                if (@event.FsmEvent is ThrottleMode)
                {
                    var mode            = @event.FsmEvent.AsInstanceOf <ThrottleMode>();
                    InboundThrottleMode = mode;
                    if (mode is Blackhole)
                    {
                        ThrottledMessages = new Queue <ByteString>();
                    }
                    CancelTimer(DequeueTimerName);
                    if (ThrottledMessages.Any())
                    {
                        ScheduleDequeue(InboundThrottleMode.TimeToAvailable(MonotonicClock.GetNanos(), ThrottledMessages.Peek().Length));
                    }
                    Sender.Tell(SetThrottleAck.Instance);
                    return(Stay());
                }

                if (@event.FsmEvent is InboundPayload)
                {
                    ForwardOrDelay(@event.FsmEvent.AsInstanceOf <InboundPayload>().Payload);
                    return(Stay());
                }

                if (@event.FsmEvent is Dequeue)
                {
                    if (ThrottledMessages.Any())
                    {
                        var payload = ThrottledMessages.Dequeue();
                        UpstreamListener.Notify(new InboundPayload(payload));
                        InboundThrottleMode = InboundThrottleMode.TryConsumeTokens(MonotonicClock.GetNanos(),
                                                                                   payload.Length).Item1;
                        if (ThrottledMessages.Any())
                        {
                            ScheduleDequeue(InboundThrottleMode.TimeToAvailable(MonotonicClock.GetNanos(), ThrottledMessages.Peek().Length));
                        }
                    }
                    return(Stay());
                }

                return(null);
            });

            WhenUnhandled(@event =>
            {
                // we should always set the throttling mode
                if (@event.FsmEvent is ThrottleMode)
                {
                    InboundThrottleMode = @event.FsmEvent.AsInstanceOf <ThrottleMode>();
                    Sender.Tell(SetThrottleAck.Instance);
                    return(Stay());
                }

                if (@event.FsmEvent is Disassociated)
                {
                    return(Stop()); // not notifying the upstream handler is intentional: we are relying on heartbeating
                }

                if (@event.FsmEvent is FailWith)
                {
                    var reason = @event.FsmEvent.AsInstanceOf <FailWith>().FailReason;
                    if (UpstreamListener != null)
                    {
                        UpstreamListener.Notify(new Disassociated(reason));
                    }
                    return(Stop());
                }

                return(null);
            });

            if (Inbound)
            {
                StartWith(ThrottlerState.WaitExposedHandle, Uninitialized.Instance);
            }
            else
            {
                OriginalHandle.ReadHandlerSource.SetResult(new ActorHandleEventListener(Self));
                StartWith(ThrottlerState.WaitModeAndUpstreamListener, Uninitialized.Instance);
            }
        }
Esempio n. 11
0
 protected static long GetTicks()
 {
     return(MonotonicClock.GetTicks());
 }
Esempio n. 12
0
        private void ProcessMailbox(int left, long deadlineTicks)
        {
            while (ShouldProcessMessage())
            {
                if (!TryDequeue(out var next))
                {
                    return;
                }

                DebugPrint("{0} processing message {1}", Actor.Self, next);

                // not going to bother catching ThreadAbortExceptions here, since they'll get rethrown anyway
                Actor.Invoke(next);
                ProcessAllSystemMessages();
                if (left > 1 && (Dispatcher.ThroughputDeadlineTime.HasValue == false || (MonotonicClock.GetTicks() - deadlineTicks) < 0))
                {
                    left = left - 1;
                    continue;
                }
                break;
            }
        }
 public StartupWithOneThreadSpec() : base(Configuration)
 {
     _startTime = MonotonicClock.GetTicks();
 }
Esempio n. 14
0
 public PreciseDeadline(TimeSpan timespan) : this(timespan.Ticks + MonotonicClock.GetTicks())
 {
 }
Esempio n. 15
0
        private IRunnable PollTask()
        {
            Contract.Assert(InEventLoop);
            IRunnable task;

            if (!_taskQueue.TryDequeue(out task))
            {
                _emptyQueueEvent.Reset();
                if (!_taskQueue.TryDequeue(out task) && !IsShuttingDown)
                // revisit queue as producer might have put a task in meanwhile
                {
                    var nextScheduledTask = ScheduledTaskQueue.Peek();
                    if (nextScheduledTask != null)
                    {
                        var wakeupTimeout = new TimeSpan(nextScheduledTask.Deadline.When - MonotonicClock.GetTicks());
                        if (wakeupTimeout.Ticks > 0)
                        {
                            if (_emptyQueueEvent.Wait(wakeupTimeout))
                            {
                                // woken up before the next scheduled task was due
                                _taskQueue.TryDequeue(out task);
                            }
                        }
                    }
                    else
                    {
                        _emptyQueueEvent.Wait(); // wait until work is put into the queue
                        _taskQueue.TryDequeue(out task);
                    }
                }
            }
            return(task);
        }
Esempio n. 16
0
 private Heartbeat SelfHeartbeat()
 {
     _seqNo += 1;
     return(new Heartbeat(_cluster.SelfAddress, _seqNo, MonotonicClock.GetNanos()));
 }