Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
s2quake committed Oct 13, 2024
1 parent 9eb1cc9 commit fe44d70
Show file tree
Hide file tree
Showing 14 changed files with 145 additions and 127 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace LibplanetConsole.Console.Executable.EntryCommands;
namespace LibplanetConsole.Common;

public enum PortGenerationMode
{
Expand Down
60 changes: 60 additions & 0 deletions src/common/LibplanetConsole.Common/PortGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Net.Sockets;
using LibplanetConsole.Common.DataAnnotations;

namespace LibplanetConsole.Common;

public sealed class PortGenerator
{
public const int DefaultSpace = 10;
private readonly List<int> _portList = [];

public PortGenerator(int startingPort)
{
_portList.Add(startingPort == 0 ? PortUtility.NextPort() : startingPort);
Current = _portList[0];
}

public int Space { get; init; } = DefaultSpace;

public int Current { get; private set; }

public PortGenerationMode Mode { get; init; } = PortGenerationMode.Random;

public int Next()
{
Current = GetPort(Current);
_portList.Add(Current);
_portList.Sort();
return Current;
}

private int GetPort(int nextPort)
{
if (Mode == PortGenerationMode.Random)
{
var port = PortUtility.NextPort();
while (IsValidRandomPort(port) is false)
{
port = PortUtility.NextPort();
}

return port;
}

return nextPort + Space;
}

private bool IsValidRandomPort(int randomPort)
{
for (var i = 0; i < _portList.Count; i++)
{
var port = _portList[i];
if (Math.Abs(port - randomPort) < Space)
{
return false;
}
}

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,11 @@ internal sealed record class ApplicationSettings

public ApplicationOptions ToOptions()
{
var port = Port == 0 ? PortUtility.NextPort() : Port;
var portGenerator = new PortGenerator(Port);
var port = portGenerator.Current;
var endPoint = GetLocalHost(port);
var nodeOptions = GetNodeOptions(endPoint, GetNodes());
var clientOptions = GetClientOptions(nodeOptions, GetClients());
var nodeOptions = GetNodeOptions(endPoint, GetNodes(), portGenerator);
var clientOptions = GetClientOptions(nodeOptions, GetClients(), portGenerator);
var repository = new Repository(port, nodeOptions, clientOptions);
var genesis = TryGetGenesis(out var g) == true ? g : repository.Genesis;
return new ApplicationOptions(port)
Expand Down Expand Up @@ -130,22 +131,22 @@ public static ApplicationSettings Parse(string[] args)
}

private static NodeOptions[] GetNodeOptions(
EndPoint endPoint, PrivateKey[] nodePrivateKeys)
EndPoint endPoint, PrivateKey[] nodePrivateKeys, PortGenerator portGenerator)
{
return [.. nodePrivateKeys.Select(key => new NodeOptions
{
EndPoint = NextEndPoint(),
EndPoint = GetLocalHost(portGenerator.Next()),
PrivateKey = key,
SeedEndPoint = endPoint,
})];
}

private static ClientOptions[] GetClientOptions(
NodeOptions[] nodeOptions, PrivateKey[] clientPrivateKeys)
NodeOptions[] nodeOptions, PrivateKey[] clientPrivateKeys, PortGenerator portGenerator)
{
return [.. clientPrivateKeys.Select(key => new ClientOptions
{
EndPoint = NextEndPoint(),
EndPoint = GetLocalHost(portGenerator.Next()),
NodeEndPoint = Random(nodeOptions).EndPoint,
PrivateKey = key,
})];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ namespace LibplanetConsole.Console.Executable.EntryCommands;
[CommandSummary("Create a new repository to run Libplanet nodes and clients from the console.")]
internal sealed class InitializeCommand : CommandBase
{
private const int RandomPortSpacing = 10;
private readonly List<int> _portList = [];

public InitializeCommand()
: base("init")
{
Expand Down Expand Up @@ -95,13 +92,13 @@ public InitializeCommand()
[Category("Genesis")]
public string ActionProviderType { get; set; } = string.Empty;

[CommandProperty("port-spacing", InitValue = 2)]
[CommandSummary("Specifies the spacing between ports. Default is 2. " +
[CommandProperty("port-spacing", InitValue = PortGenerator.DefaultSpace)]
[CommandSummary("Specifies the spacing between ports. Default is 10. " +
"This option is only used when --port-generation-mode is set to " +
"'sequential'. If --port-generation-mode is set to 'random', " +
"the value of this option is 5'")]
"the value of this option is 10'")]
[Category("Network")]
[Range(1, 10000)]
[Range(10, 10000)]
public int PortSpacing { get; set; }

[CommandProperty("port-generation-mode")]
Expand All @@ -111,11 +108,11 @@ public InitializeCommand()

protected override void OnExecute()
{
var portGenerator = new PortGenerator(Port);
var genesisKey = PrivateKeyUtility.ParseOrRandom(GenesisKey);
var port = Port == 0 ? PortUtility.NextPort() : Port;
var nextPort = port;
var nodeOptions = GetNodeOptions(ref nextPort);
var clientOptions = GetClientOptions(ref nextPort);
var port = portGenerator.Current;
var nodeOptions = GetNodeOptions(portGenerator);
var clientOptions = GetClientOptions(portGenerator);
var outputPath = Path.GetFullPath(RepositoryPath);
var dateTimeOffset = DateTimeOffset != DateTimeOffset.MinValue
? DateTimeOffset : DateTimeOffset.UtcNow;
Expand Down Expand Up @@ -152,53 +149,15 @@ protected override void OnExecute()
TextWriterExtensions.WriteLineAsJson(writer, info);
}

private int NextPort(ref int nextPort)
{
nextPort = GetPort(nextPort);
_portList.Add(nextPort);
_portList.Sort();
return nextPort;

int GetPort(int nextPort)
{
if (PortGenerationMode == PortGenerationMode.Random)
{
var port = PortUtility.NextPort();
while (IsValidRandomPort(port) is false)
{
port = PortUtility.NextPort();
}

return port;
}

return nextPort + PortSpacing;
}
}

private bool IsValidRandomPort(int randomPort)
{
for (var i = 0; i < _portList.Count; i++)
{
var port = _portList[i];
if (Math.Abs(port - randomPort) < RandomPortSpacing)
{
return false;
}
}

return true;
}

private NodeOptions[] GetNodeOptions(ref int nextPort)
private NodeOptions[] GetNodeOptions(PortGenerator portGenerator)
{
var privateKeys = GetNodes();
var nodeOptionsList = new List<NodeOptions>(privateKeys.Length);
foreach (var privateKey in privateKeys)
{
var nodeOptions = new NodeOptions
{
EndPoint = GetLocalHost(NextPort(ref nextPort)),
EndPoint = GetLocalHost(portGenerator.Next()),
PrivateKey = privateKey,
StorePath = "store",
LogPath = "log",
Expand All @@ -211,15 +170,15 @@ private NodeOptions[] GetNodeOptions(ref int nextPort)
return [.. nodeOptionsList];
}

private ClientOptions[] GetClientOptions(ref int nextPort)
private ClientOptions[] GetClientOptions(PortGenerator portGenerator)
{
var privateKeys = GetClients();
var clientOptionsList = new List<ClientOptions>(privateKeys.Length);
foreach (var privateKey in privateKeys)
{
var clientOptions = new ClientOptions
{
EndPoint = GetLocalHost(NextPort(ref nextPort)),
EndPoint = GetLocalHost(portGenerator.Next()),
PrivateKey = privateKey,
LogPath = "log",
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace LibplanetConsole.Console.Executable.Tracers;
internal sealed class ClientCollectionEventTracer : IHostedService, IDisposable
{
private readonly IClientCollection _clients;
private bool _isDisposed;

public ClientCollectionEventTracer(IClientCollection clients)
{
Expand All @@ -27,12 +28,16 @@ public Task StopAsync(CancellationToken cancellationToken)

void IDisposable.Dispose()
{
foreach (var client in _clients)
if (_isDisposed is false)
{
DetachEvent(client);
}
foreach (var client in _clients)
{
DetachEvent(client);
}

_clients.CollectionChanged -= Clients_CollectionChanged;
_clients.CollectionChanged -= Clients_CollectionChanged;
_isDisposed = true;
}
}

private void AttachEvent(IClient client)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ internal sealed class NodeCollectionEventTracer : IHostedService, IDisposable
private readonly INodeCollection _nodes;
private readonly ILogger<NodeCollectionEventTracer> _logger;
private INode? _current;
private bool _isDisposed;

public NodeCollectionEventTracer(
INodeCollection nodes, ILogger<NodeCollectionEventTracer> logger)
Expand All @@ -34,12 +35,16 @@ public Task StopAsync(CancellationToken cancellationToken)

void IDisposable.Dispose()
{
_nodes.CurrentChanged -= Nodes_CurrentChanged;
_nodes.CollectionChanged -= Nodes_CollectionChanged;
UpdateCurrent(null);
foreach (var node in _nodes)
if (_isDisposed is false)
{
DetachEvent(node);
_nodes.CurrentChanged -= Nodes_CurrentChanged;
_nodes.CollectionChanged -= Nodes_CollectionChanged;
foreach (var node in _nodes)
{
DetachEvent(node);
}

_isDisposed = true;
}
}

Expand All @@ -64,6 +69,7 @@ private void AttachEvent(INode node)
node.Detached += Node_Detached;
node.Started += Node_Started;
node.Stopped += Node_Stopped;
node.Disposed += Node_Disposed;
}

private void DetachEvent(INode node)
Expand All @@ -72,6 +78,7 @@ private void DetachEvent(INode node)
node.Detached -= Node_Detached;
node.Started -= Node_Started;
node.Stopped -= Node_Stopped;
node.Disposed += Node_Disposed;
}

private void Nodes_CurrentChanged(object? sender, EventArgs e)
Expand Down Expand Up @@ -154,4 +161,12 @@ private void Node_Stopped(object? sender, EventArgs e)
System.Console.Out.WriteColoredLine(message, colorType);
}
}

private void Node_Disposed(object? sender, EventArgs e)
{
if (sender is INode node && node == _current)
{
_current = null;
}
}
}
3 changes: 3 additions & 0 deletions src/console/LibplanetConsole.Console/ApplicationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ namespace LibplanetConsole.Console;

public sealed record class ApplicationOptions
{
public const int SeedBlocksyncPortIncrement = 6;
public const int SeedConsensusPortIncrement = 7;

public ApplicationOptions(int port)
{
Port = port;
Expand Down
10 changes: 0 additions & 10 deletions src/console/LibplanetConsole.Console/Node.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ internal sealed partial class Node : INode, IBlockChain
private NodeService? _nodeService;
private BlockChainService? _blockChainService;
private GrpcChannel? _channel;
private EndPoint? _blocksyncEndPoint;
private EndPoint? _consensusEndPoint;
private NodeInfo _nodeInfo;
private bool _isDisposed;
private NodeProcess? _process;
Expand All @@ -52,12 +50,6 @@ public Node(IServiceProvider serviceProvider, NodeOptions nodeOptions)

public event EventHandler? Disposed;

public EndPoint SwarmEndPoint
=> _blocksyncEndPoint ?? throw new InvalidOperationException("Peer is not set.");

public EndPoint ConsensusEndPoint
=> _consensusEndPoint ?? throw new InvalidOperationException("ConsensusPeer is not set.");

public PublicKey PublicKey { get; }

public Address Address => PublicKey.Address;
Expand Down Expand Up @@ -210,8 +202,6 @@ public async Task StartAsync(CancellationToken cancellationToken)
var callOptions = new CallOptions(cancellationToken: cancellationToken);
var response = await _nodeService.StartAsync(request, callOptions);
_nodeInfo = response.NodeInfo;
_blocksyncEndPoint = Parse(_nodeInfo.SwarmEndPoint);
_consensusEndPoint = Parse(_nodeInfo.ConsensusEndPoint);
IsRunning = true;
_logger.LogDebug("Node is started: {Address}", Address);
await Task.WhenAll(Contents.Select(item => item.StartAsync(cancellationToken)));
Expand Down
6 changes: 3 additions & 3 deletions src/console/LibplanetConsole.Console/SeedService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace LibplanetConsole.Console;

internal sealed class SeedService : ISeedService
internal sealed class SeedService(ApplicationOptions options) : ISeedService
{
private readonly PrivateKey _seedNodePrivateKey = new();
private SeedNode? _blocksyncSeedNode;
Expand Down Expand Up @@ -33,12 +33,12 @@ public async Task StartAsync(CancellationToken cancellationToken)
_blocksyncSeedNode = new SeedNode(new()
{
PrivateKey = _seedNodePrivateKey,
Port = PortUtility.NextPort(),
Port = options.Port + ApplicationOptions.SeedBlocksyncPortIncrement,
});
_consensusSeedNode = new SeedNode(new()
{
PrivateKey = _seedNodePrivateKey,
Port = PortUtility.NextPort(),
Port = options.Port + ApplicationOptions.SeedConsensusPortIncrement,
});
await _blocksyncSeedNode.StartAsync(cancellationToken);
await _consensusSeedNode.StartAsync(cancellationToken);
Expand Down
5 changes: 5 additions & 0 deletions src/node/LibplanetConsole.Node/ApplicationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ namespace LibplanetConsole.Node;

public sealed record class ApplicationOptions
{
public const int BlocksyncPortIncrement = 4;
public const int ConsensusPortIncrement = 5;
public const int SeedBlocksyncPortIncrement = 6;
public const int SeedConsensusPortIncrement = 7;

public ApplicationOptions(int port, PrivateKey privateKey, byte[] genesis)
{
Port = port;
Expand Down
Loading

0 comments on commit fe44d70

Please sign in to comment.