/// <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"); }
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); } }); }
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; } }
private DefaultChannelId() { unchecked { _hashCode = (int)(MonotonicClock.GetTicks() & 0xFFFFFFFF); _hashCode *= _hashCode ^ ThreadLocalRandom.Current.Next(); } }
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; } }
private void FetchFromScheduledTaskQueue() { if (HasScheduledTasks()) { var tickCount = MonotonicClock.GetTicks(); while (true) { var scheduledTask = PollScheduledTask(tickCount); if (scheduledTask == null) { break; } _taskQueue.Enqueue(scheduledTask); } } }
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"); } }
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); } }
protected static long GetTicks() { return(MonotonicClock.GetTicks()); }
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(); }
public PreciseDeadline(TimeSpan timespan) : this(timespan.Ticks + MonotonicClock.GetTicks()) { }
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); }
private Heartbeat SelfHeartbeat() { _seqNo += 1; return(new Heartbeat(_cluster.SelfAddress, _seqNo, MonotonicClock.GetNanos())); }