diff --git a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt index c06404e477b..7354240f61d 100644 --- a/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt +++ b/src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt @@ -55,7 +55,6 @@ namespace Akka.Actor { public const int UndefinedUid = 0; public ActorCell(Akka.Actor.Internal.ActorSystemImpl system, Akka.Actor.IInternalActorRef self, Akka.Actor.Props props, Akka.Dispatch.MessageDispatcher dispatcher, Akka.Actor.IInternalActorRef parent) { } - protected Akka.Actor.ActorBase Actor { get; } public Akka.Actor.Internal.IChildrenContainer ChildrenContainer { get; } public int CurrentEnvelopeId { get; } public object CurrentMessage { get; } @@ -709,6 +708,7 @@ namespace Akka.Actor public abstract Akka.Actor.IActorRefProvider Provider { get; } public abstract Akka.Actor.IInternalActorRef SystemGuardian { get; } public abstract void Abort(); + public abstract string PrintTree(); public abstract Akka.Actor.IActorRef SystemActorOf(Akka.Actor.Props props, string name = null); public abstract Akka.Actor.IActorRef SystemActorOf(string name = null) where TActor : Akka.Actor.ActorBase, new (); @@ -1941,6 +1941,7 @@ namespace Akka.Actor.Internal public override bool HasExtension(System.Type type) { } public override bool HasExtension() where T : class, Akka.Actor.IExtension { } + public override string PrintTree() { } public override object RegisterExtension(Akka.Actor.IExtensionId extension) { } public override void RegisterOnTermination(System.Action code) { } public void Start() { } @@ -2091,6 +2092,7 @@ namespace Akka.Actor.Internal public override bool IsNormal { get; } public override bool IsTerminating { get; } public Akka.Actor.Internal.SuspendReason Reason { get; } + public System.Collections.Immutable.ImmutableHashSet ToDie { get; } public override Akka.Actor.Internal.IChildrenContainer Add(string name, Akka.Actor.Internal.ChildRestartStats stats) { } public Akka.Actor.Internal.IChildrenContainer CreateCopyWithReason(Akka.Actor.Internal.SuspendReason reason) { } public override Akka.Actor.Internal.IChildrenContainer Remove(Akka.Actor.IActorRef child) { } diff --git a/src/core/Akka/Actor/ActorCell.cs b/src/core/Akka/Actor/ActorCell.cs index d8eabb6c149..0e629a0246f 100644 --- a/src/core/Akka/Actor/ActorCell.cs +++ b/src/core/Akka/Actor/ActorCell.cs @@ -104,7 +104,7 @@ public ActorCell(ActorSystemImpl system, IInternalActorRef self, Props props, Me /// /// TBD /// - protected ActorBase Actor { get { return _actor; } } + internal ActorBase Actor { get { return _actor; } } /// /// TBD /// diff --git a/src/core/Akka/Actor/ChildrenContainer/Internal/TerminatingChildrenContainer.cs b/src/core/Akka/Actor/ChildrenContainer/Internal/TerminatingChildrenContainer.cs index 6ee965c155e..b562a5e186b 100644 --- a/src/core/Akka/Actor/ChildrenContainer/Internal/TerminatingChildrenContainer.cs +++ b/src/core/Akka/Actor/ChildrenContainer/Internal/TerminatingChildrenContainer.cs @@ -51,6 +51,8 @@ public TerminatingChildrenContainer(IImmutableDictionary ch _reason = reason; } + public ImmutableHashSet ToDie => _toDie; + /// /// TBD /// diff --git a/src/core/Akka/Actor/ExtendedActorSystem.cs b/src/core/Akka/Actor/ExtendedActorSystem.cs index e2563954fdb..97b0f7f06dd 100644 --- a/src/core/Akka/Actor/ExtendedActorSystem.cs +++ b/src/core/Akka/Actor/ExtendedActorSystem.cs @@ -71,6 +71,8 @@ public abstract class ExtendedActorSystem : ActorSystem /// public abstract void Abort(); + public abstract string PrintTree(); + //TODO: Missing threadFactory, dynamicAccess, printTree // /** // * A ThreadFactory that can be used if the transport needs to create any Threads diff --git a/src/core/Akka/Actor/Internal/ActorSystemImpl.cs b/src/core/Akka/Actor/Internal/ActorSystemImpl.cs index f7540c33f04..7699a81e9e3 100644 --- a/src/core/Akka/Actor/Internal/ActorSystemImpl.cs +++ b/src/core/Akka/Actor/Internal/ActorSystemImpl.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -16,6 +17,7 @@ using Akka.Dispatch.SysMsg; using Akka.Event; using System.Reflection; +using System.Text; using Akka.Actor.Setup; using Akka.Serialization; using Akka.Util; @@ -569,6 +571,78 @@ public override string ToString() { return LookupRoot.Path.Root.Address.ToString(); } + + public override string PrintTree() + { + string PrintNode(IActorRef node, string indent) + { + var sb = new StringBuilder(); + if (node is ActorRefWithCell wc) + { + const string space = " "; + var cell = wc.Underlying; + sb.Append(string.IsNullOrEmpty(indent) ? "-> " : indent.Remove(indent.Length-1) + "L-> ") + .Append($"{node.Path.Name} {Logging.SimpleName(node)} "); + + if (cell is ActorCell real) + { + var realActor = real.Actor; + sb.Append(realActor is null ? "null" : realActor.GetType().ToString()) + .Append($" status={real.Mailbox.CurrentStatus()}"); + } + else + { + sb.Append(Logging.SimpleName(cell)); + } + sb.Append(space); + + switch (cell.ChildrenContainer) + { + case TerminatingChildrenContainer t: + var toDie = t.ToDie.ToList(); + toDie.Sort(); + var reason = t.Reason; + sb.Append($"Terminating({reason})") + .Append($"\n{indent} | toDie: ") + .Append(string.Join($"\n{indent} | ", toDie)); + break; + case TerminatedChildrenContainer x: + sb.Append(x); + break; + case EmptyChildrenContainer x: + sb.Append(x); + break; + case NormalChildrenContainer n: + sb.Append($"{n.Children.Count} children"); + break; + case var x: + sb.Append(Logging.SimpleName(x)); + break; + } + + if (cell.ChildrenContainer.Children.Count > 0) + { + sb.Append("\n"); + + var children = cell.ChildrenContainer.Children.ToList(); + children.Sort(); + var childStrings = children.Select((t, i) => i == 0 + ? PrintNode(t, $"{indent} |") + : PrintNode(t, $"{indent} ")); + + sb.Append(string.Join("\n", childStrings)); + } + } + else + { + sb.Append($"{indent}{node.Path.Name} {Logging.SimpleName(node)}"); + } + + return sb.ToString(); + } + + return PrintNode(LookupRoot, ""); + } } /// diff --git a/src/core/Akka/Akka.csproj b/src/core/Akka/Akka.csproj index 4114dbbd706..46d74c6fcee 100644 --- a/src/core/Akka/Akka.csproj +++ b/src/core/Akka/Akka.csproj @@ -4,10 +4,10 @@ Akka Akka.NET is a port of the popular Java/Scala framework Akka to .NET - $(NetStandardLibVersion) + $(NetStandardLibVersion) $(AkkaPackageTags) true - 7.2 + 8.0