Skip to content

Commit 47f957a

Browse files
committed
Closes #1: Automatically reload configuration
1 parent 55c9ca3 commit 47f957a

File tree

6 files changed

+135
-82
lines changed

6 files changed

+135
-82
lines changed

xmr-stak-bootstrap/Common/Menu/MenuBuilder.cs

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -84,36 +84,43 @@ private bool IsInputValid(int input)
8484

8585
private int GetInput()
8686
{
87-
Console.Write(@"Select: ");
88-
89-
var knownOptions = _options.Select((_, i) => (i + 1).ToString()).ToList();
90-
91-
ConsoleKeyInfo key;
92-
var input = "";
93-
int index;
94-
do
87+
try
9588
{
96-
key = Console.ReadKey(true);
97-
if (key.Key == ConsoleKey.Backspace && input.Length > 0)
98-
{
99-
input = input.Substring(0, input.Length - 1);
100-
// ReSharper disable once LocalizableElement
101-
Console.Write("\b \b");
102-
}
103-
else if (char.IsNumber(key.KeyChar))
104-
{
105-
input += key.KeyChar;
106-
Console.Write(key.KeyChar);
107-
}
89+
Console.Write(@"Select: ");
90+
91+
var knownOptions = _options.Select((_, i) => (i + 1).ToString()).ToList();
10892

109-
if (int.TryParse(input, out index) && IsInputValid(index))
93+
ConsoleKeyInfo key;
94+
var input = "";
95+
int index;
96+
do
11097
{
111-
var stringInput = index.ToString();
112-
if (knownOptions.Count(x => x.StartsWith(stringInput)) == 1) return index;
98+
key = Console.ReadKey(true);
99+
if (key.Key == ConsoleKey.Backspace && input.Length > 0)
100+
{
101+
input = input.Substring(0, input.Length - 1);
102+
// ReSharper disable once LocalizableElement
103+
Console.Write("\b \b");
104+
}
105+
else if (char.IsNumber(key.KeyChar))
106+
{
107+
input += key.KeyChar;
108+
Console.Write(key.KeyChar);
109+
}
110+
111+
if (int.TryParse(input, out index) && IsInputValid(index))
112+
{
113+
var stringInput = index.ToString();
114+
if (knownOptions.Count(x => x.StartsWith(stringInput)) == 1) return index;
115+
}
113116
}
117+
while (key.Key != ConsoleKey.Enter);
118+
return int.TryParse(input, out index) ? index : -1;
119+
}
120+
finally
121+
{
122+
Console.WriteLine();
114123
}
115-
while (key.Key != ConsoleKey.Enter);
116-
return int.TryParse(input, out index) ? index : -1;
117124
}
118125

119126
private void RenderOptions()
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
using XmrStakBootstrap.MasterConfiguration.Model;
2+
13
namespace XmrStakBootstrap.Core.Job.Miner
24
{
35
public interface IMinerRunner
46
{
5-
void Run();
7+
void Run(MasterConfigurationModel configuration);
68
}
79
}

xmr-stak-bootstrap/Core/Job/Miner/MinerRunner.cs

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,48 +16,45 @@ public class MinerRunner : IMinerRunner
1616
[Dependency]
1717
public IFinalizer Finalizer { get; set; }
1818

19-
[Dependency]
20-
public MasterConfigurationModel MasterConfigurationModel { get; set; }
21-
2219
[Dependency]
2320
public RunConfigurationModel RunConfigurationModel { get; set; }
2421

25-
public void Run()
22+
public void Run(MasterConfigurationModel configuration)
2623
{
27-
var solution = MasterConfigurationModel.SolutionProfiles.GetValue(RunConfigurationModel.ActiveSolutionConfiguration);
28-
var workload = MasterConfigurationModel.WorkloadProfiles.GetValue(RunConfigurationModel.ActiveWorkloadConfiguration);
24+
var solution = configuration.SolutionProfiles.GetValue(RunConfigurationModel.ActiveSolutionConfiguration);
25+
var workload = configuration.WorkloadProfiles.GetValue(RunConfigurationModel.ActiveWorkloadConfiguration);
2926

3027
var i = 0;
3128
foreach (var instances in solution)
3229
{
3330
i++;
34-
var outputPools = GetOutputPools(instances.Pools);
31+
var outputPools = GetOutputPools(configuration.Pools, instances.Pools);
3532

3633
if (outputPools.Count == 0)
3734
{
3835
Console.WriteLine(@"Instance {0}.{1} does not contain any pool bindings.", RunConfigurationModel.ActiveSolutionConfiguration, i);
3936
continue;
4037
}
4138

42-
var configArgument = GetConfigurationArgument(outputPools);
39+
var configArgument = GetConfigurationArgument(configuration.PathsConfiguration.ConfigTemplate, outputPools);
4340
var utilizedHardware = instances.Hardware.Select(x => new UtilizedHardware
4441
{
45-
Hardware = MasterConfigurationModel.Hardware.GetValue(x),
42+
Hardware = configuration.Hardware.GetValue(x),
4643
Profile = workload.GetValue(x)
4744
}).ToList();
4845

49-
var cpuArgument = GetCpuArgument(utilizedHardware.Where(x => x.Hardware.Type == "cpu").ToList());
50-
var amdArgument = GetAmdArgument(utilizedHardware.Where(x => x.Hardware.Type == "amd").ToList());
51-
var nvidiaArgument = GetNvidiaArgument(utilizedHardware.Where(x => x.Hardware.Type == "nvidia").ToList());
46+
var cpuArgument = GetCpuArgument(configuration.PathsConfiguration.CpuTemplate, configuration.CpuProfiles, utilizedHardware.Where(x => x.Hardware.Type == "cpu").ToList());
47+
var amdArgument = GetAmdArgument(configuration.PathsConfiguration.AmdTemplate, configuration.AmdProfiles, utilizedHardware.Where(x => x.Hardware.Type == "amd").ToList());
48+
var nvidiaArgument = GetNvidiaArgument(configuration.PathsConfiguration.NvidiaTemplate, configuration.NvidiaProfiles, utilizedHardware.Where(x => x.Hardware.Type == "nvidia").ToList());
5249

5350
RunMiner($"{configArgument} {cpuArgument} {amdArgument} {nvidiaArgument}");
5451
}
5552
}
5653

57-
private List<PrioritizedPoolEntry> GetOutputPools(IEnumerable<string> pools)
54+
private static List<PrioritizedPoolEntry> GetOutputPools(IDictionary<string, PoolEntry> poolConfiguration, IEnumerable<string> pools)
5855
{
5956
return pools
60-
.Select(x => MasterConfigurationModel.Pools.GetValue(x))
57+
.Select(poolConfiguration.GetValue)
6158
.Reverse()
6259
.Select((x, i) => new PrioritizedPoolEntry
6360
{
@@ -84,29 +81,29 @@ private static void RunMiner(string arguments)
8481
Process.Start(startInfo);
8582
}
8683

87-
private string GetConfigurationArgument(IReadOnlyCollection<PrioritizedPoolEntry> pools)
84+
private string GetConfigurationArgument(string configurationTemplatePath, IReadOnlyCollection<PrioritizedPoolEntry> pools)
8885
{
89-
var configPath = CreateTemporaryConfiguration(MasterConfigurationModel.PathsConfiguration.ConfigTemplate, "config", "%POOLS%", pools);
86+
var configPath = CreateTemporaryConfiguration(configurationTemplatePath, "config", "%POOLS%", pools);
9087
ScheduleFileDelete(configPath);
9188

9289
return $"--config \"{configPath}\"";
9390
}
9491

95-
private string GetCpuArgument(ICollection<UtilizedHardware> entry)
92+
private string GetCpuArgument(string cpuTemplatePath, IDictionary<string, IList<CpuThreadEntry>> cpuConfiguration, ICollection<UtilizedHardware> entry)
9693
{
9794
if (entry.Count == 0)
9895
{
9996
return "--noCPU";
10097
}
10198

102-
var cpuProfile = entry.SelectMany(x => MasterConfigurationModel.CpuProfiles.GetValue(x.Profile)).ToList();
103-
var path = CreateTemporaryConfiguration(MasterConfigurationModel.PathsConfiguration.CpuTemplate, "cpu", "%THREADS%", cpuProfile);
99+
var cpuProfile = entry.SelectMany(x => cpuConfiguration.GetValue(x.Profile)).ToList();
100+
var path = CreateTemporaryConfiguration(cpuTemplatePath, "cpu", "%THREADS%", cpuProfile);
104101
ScheduleFileDelete(path);
105102

106103
return $"--cpu \"{path}\"";
107104
}
108105

109-
private string GetAmdArgument(ICollection<UtilizedHardware> entry)
106+
private string GetAmdArgument(string amdTemplatePath, IDictionary<string, IList<AmdThreadEntry>> amdConfiguration, ICollection<UtilizedHardware> entry)
110107
{
111108
if (entry.Count == 0)
112109
{
@@ -116,7 +113,7 @@ private string GetAmdArgument(ICollection<UtilizedHardware> entry)
116113
var amdProfile = entry
117114
.SelectMany(
118115
x =>
119-
MasterConfigurationModel.AmdProfiles.GetValue(x.Profile)
116+
amdConfiguration.GetValue(x.Profile)
120117
.Select(profile => new IndexedAmdThreadEntry
121118
{
122119
Index = x.Hardware.Index,
@@ -127,13 +124,13 @@ private string GetAmdArgument(ICollection<UtilizedHardware> entry)
127124
}))
128125
.ToList();
129126

130-
var path = CreateTemporaryConfiguration(MasterConfigurationModel.PathsConfiguration.AmdTemplate, "amd", "%THREADS%", amdProfile);
127+
var path = CreateTemporaryConfiguration(amdTemplatePath, "amd", "%THREADS%", amdProfile);
131128
ScheduleFileDelete(path);
132129

133130
return $"--amd \"{path}\"";
134131
}
135132

136-
private string GetNvidiaArgument(ICollection<UtilizedHardware> entry)
133+
private string GetNvidiaArgument(string nvidiaTemplatePath, IDictionary<string, IList<NvidiaThreadEntry>> nvidiaConfiguration, ICollection<UtilizedHardware> entry)
137134
{
138135
if (entry.Count == 0)
139136
{
@@ -143,7 +140,7 @@ private string GetNvidiaArgument(ICollection<UtilizedHardware> entry)
143140
var nvidiaProfile = entry
144141
.SelectMany(
145142
x =>
146-
MasterConfigurationModel.NvidiaProfiles.GetValue(x.Profile)
143+
nvidiaConfiguration.GetValue(x.Profile)
147144
.Select(profile => new IndexedNvidiaThreadEntry
148145
{
149146
Index = x.Hardware.Index,
@@ -156,7 +153,7 @@ private string GetNvidiaArgument(ICollection<UtilizedHardware> entry)
156153
}))
157154
.ToList();
158155

159-
var path = CreateTemporaryConfiguration(MasterConfigurationModel.PathsConfiguration.NvidiaTemplate, "nvidia", "%THREADS%", nvidiaProfile);
156+
var path = CreateTemporaryConfiguration(nvidiaTemplatePath, "nvidia", "%THREADS%", nvidiaProfile);
160157
ScheduleFileDelete(path);
161158

162159
return $"--nvidia \"{path}\"";

xmr-stak-bootstrap/Core/Job/Miner/MinerRunnerMenuJob.cs

Lines changed: 75 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Diagnostics;
33
using System.Threading;
4+
using Newtonsoft.Json;
5+
using Unity;
46
using Unity.Attributes;
57
using XmrStakBootstrap.Common.Helper;
68
using XmrStakBootstrap.Common.Menu;
@@ -14,41 +16,39 @@ public class MinerRunnerMenuJob : IJob
1416
private const bool Continue = true;
1517
private const bool Terminate = false;
1618

17-
[Dependency]
18-
public IFinalizer Finalizer { get; set; }
19+
private MasterConfigurationModel _masterConfigurationModel;
1920

2021
[Dependency]
21-
public RunConfigurationModel RunConfigurationModel { get; set; }
22+
public IUnityContainer UnityContainer { get; set; }
2223

2324
[Dependency]
24-
public MasterConfigurationModel MasterConfigurationModel { get; set; }
25+
public IFinalizer Finalizer { get; set; }
2526

2627
[Dependency]
2728
public IMinerRunner Runner { get; set; }
2829

30+
[Dependency]
31+
public RunConfigurationModel RunConfigurationModel { get; set; }
32+
2933
private bool HasSolution
3034
=>
31-
MasterConfigurationModel.SolutionProfiles.ContainsKey(
35+
GetMasterConfigurationModel().SolutionProfiles.ContainsKey(
3236
RunConfigurationModel.ActiveSolutionConfiguration ?? string.Empty);
3337

3438
private bool HasWorkload
3539
=>
36-
MasterConfigurationModel.WorkloadProfiles.ContainsKey(
40+
GetMasterConfigurationModel().WorkloadProfiles.ContainsKey(
3741
RunConfigurationModel.ActiveWorkloadConfiguration ?? string.Empty);
3842

3943
private bool CanRun => HasSolution && HasWorkload;
4044

4145
public void Execute()
4246
{
43-
if (MasterConfigurationModel == null)
44-
{
45-
Console.WriteLine(@"Master configuration file '{0}' was not loaded. Try running this program with argument --help.", RunConfigurationModel.MasterConfiguration);
46-
return;
47-
}
48-
4947
var @continue = true;
5048
while (@continue)
5149
{
50+
GetMasterConfigurationModel();
51+
5252
Console.Write(@"Active solution: ");
5353
ColorConsole(HasSolution ? ConsoleColor.White : ConsoleColor.DarkGray, () => Console.WriteLine(HasSolution ? RunConfigurationModel.ActiveSolutionConfiguration : "<UNKNOWN>"));
5454
Console.Write(@"Active workload: ");
@@ -63,6 +63,7 @@ public void Execute()
6363
return Continue;
6464
})
6565
.AddConditionalOption(@"Start/restart miners", CanRun, MenuOptionStartMiners)
66+
.AddEnabledOption(@"Reload configuration", MenuOptionReloadConfiguration)
6667
.AddEnabledOption(@"Change solution", MenuOptionChangeSolution)
6768
.AddEnabledOption(@"Change workload", MenuOptionChangeWorkload)
6869
.AddEnabledOption(@"Exit", MenuOptionExit)
@@ -82,20 +83,29 @@ private bool MenuOptionStartMiners()
8283
Thread.Sleep(RunConfigurationModel.MinerStartDelay * 1000);
8384
}
8485
Finalizer.DoFinalize();
85-
Runner.Run(); //TODO: issue #1
86+
Runner.Run(_masterConfigurationModel);
8687
return Terminate;
8788
}
8889

90+
private bool MenuOptionReloadConfiguration()
91+
{
92+
Console.Clear();
93+
InvalidateConfiguration();
94+
return Continue;
95+
}
96+
8997
private bool MenuOptionChangeSolution()
9098
{
91-
SelectSolution(); //TODO: issue #1
99+
InvalidateConfiguration();
100+
SelectSolution();
92101
Console.Clear();
93102
return Continue;
94103
}
95104

96105
private bool MenuOptionChangeWorkload()
97106
{
98-
SelectWorkload(); //TODO: issue #1
107+
InvalidateConfiguration();
108+
SelectWorkload();
99109
Console.Clear();
100110
return Continue;
101111
}
@@ -124,21 +134,69 @@ private static void ColorConsole(ConsoleColor color, Action action)
124134
using (ConsoleColorClosure.ForegroundColor(color)) action();
125135
}
126136

137+
private MasterConfigurationModel GetMasterConfigurationModel()
138+
{
139+
return _masterConfigurationModel ?? (_masterConfigurationModel = LoadConfiguration());
140+
}
141+
142+
private void InvalidateConfiguration()
143+
{
144+
_masterConfigurationModel = null;
145+
}
146+
147+
private MasterConfigurationModel LoadConfiguration()
148+
{
149+
while (true)
150+
{
151+
try
152+
{
153+
var config = UnityContainer.Resolve<MasterConfigurationModel>();
154+
if (config == null)
155+
{
156+
Console.WriteLine(@"Master configuration file '{0}' was not loaded. Try running this program with argument --help.", RunConfigurationModel.MasterConfiguration);
157+
WaitForAnyKeyToReloadConfiguration();
158+
continue;
159+
}
160+
Console.WriteLine(@"Configuration was loaded.");
161+
return config;
162+
}
163+
catch (Exception e)
164+
{
165+
using (ConsoleColorClosure.ForegroundColor(ConsoleColor.Red))
166+
{
167+
Console.WriteLine(@"An error occured while loading master configuration:");
168+
Console.WriteLine((e.InnerException as JsonReaderException)?.Message ?? e.Message);
169+
}
170+
WaitForAnyKeyToReloadConfiguration();
171+
}
172+
}
173+
}
174+
175+
private static void WaitForAnyKeyToReloadConfiguration()
176+
{
177+
Console.WriteLine();
178+
Console.Write(@"Press any key to reload configuration.");
179+
Console.ReadKey(true);
180+
Console.Clear();
181+
}
182+
127183
private void SelectSolution()
128184
{
185+
var configuration = GetMasterConfigurationModel();
129186
Console.WriteLine();
130187
Console.WriteLine(@"Available solutions: ");
131188
RunConfigurationModel.ActiveSolutionConfiguration =
132-
MenuBuilder.CreateTextListMenu(MasterConfigurationModel.SolutionProfiles.Keys)
189+
MenuBuilder.CreateTextListMenu(configuration.SolutionProfiles.Keys)
133190
.Execute();
134191
}
135192

136193
private void SelectWorkload()
137194
{
195+
var configuration = GetMasterConfigurationModel();
138196
Console.WriteLine();
139197
Console.WriteLine(@"Available workloads: ");
140198
RunConfigurationModel.ActiveWorkloadConfiguration =
141-
MenuBuilder.CreateTextListMenu(MasterConfigurationModel.WorkloadProfiles.Keys)
199+
MenuBuilder.CreateTextListMenu(configuration.WorkloadProfiles.Keys)
142200
.Execute();
143201
}
144202

0 commit comments

Comments
 (0)