public virtual void InitMiningPairs(IEnumerable <MiningPair> miningPairs) { // now should be ordered _miningPairs = GetSortedMiningPairs(miningPairs); // update log group try { var devs = _miningPairs.Select(pair => $"{pair.Device.DeviceType}:{pair.Device.ID}"); var devsTag = $"devs({string.Join(",", devs)})"; var algo = _miningPairs.First().Algorithm.AlgorithmName; var algoTag = $"algo({algo})"; _logGroup = $"{_baseTag}-{algoTag}-{devsTag}"; } catch (Exception e) { Logger.Error(_logGroup, $"Error while setting _logGroup: {e.Message}"); } // init algo, ELP and finally miner specific init // init algo var singleType = MinerToolkit.GetAlgorithmSingleType(_miningPairs); _algorithmType = singleType.Item1; bool ok = singleType.Item2; if (!ok) { Logger.Info(_logGroup, "Initialization of miner failed. Algorithm not found!"); throw new InvalidOperationException("Invalid mining initialization"); } // init ELP, _miningPairs are ordered and ELP parsing keeps ordering if (MinerOptionsPackage != null) { var miningPairsList = _miningPairs.ToList(); var ignoreDefaults = MinerOptionsPackage.IgnoreDefaultValueOptions; var generalParams = ExtraLaunchParametersParser.Parse(miningPairsList, MinerOptionsPackage.GeneralOptions, ignoreDefaults); var temperatureParams = ExtraLaunchParametersParser.Parse(miningPairsList, MinerOptionsPackage.TemperatureOptions, ignoreDefaults); _extraLaunchParameters = $"{generalParams} {temperatureParams}".Trim(); } // miner specific init Init(); }
/// <summary> /// Provides available port for miner API binding /// </summary> public int GetAvaliablePort() { Dictionary <string, List <int> > reservedPorts = null; if (MinerReservedApiPorts != null && MinerReservedApiPorts.UseUserSettings) { reservedPorts = MinerReservedApiPorts.AlgorithmReservedPorts; } var reservedPortsKey = MinerToolkit.GetAlgorithmPortsKey(_miningPairs); if (reservedPorts != null && reservedPorts.ContainsKey(reservedPortsKey) && reservedPorts[reservedPortsKey] != null) { var reservedPortsRange = reservedPorts[reservedPortsKey]; var port = FreePortsCheckerManager.GetAvaliablePortInRange(reservedPortsRange); // retrive custom user port if (port > -1) { return(port); } } // if no custom port return a port in the default range return(FreePortsCheckerManager.GetAvaliablePortFromSettings()); // use the default range }
// TODO check mining pairs /// <summary> /// Sets <see cref="DesiredRunningState"/> to Start if not already so. Then creates a miningProcess and awaits for stop token. Also handles restarts of miningProcess in case of errors. /// </summary> public void StartMining() { lock (_lock) { if (_desiredState == DesiredRunningState.Start) { Logger.Error(_logGroup, $"Trying to start an already started miner"); return; } Logger.Info(_logGroup, $"Starting miner watchdog task"); _desiredState = DesiredRunningState.Start; } //const int ERROR_FILE_NOT_FOUND = 0x2; //const int ERROR_ACCESS_DENIED = 0x5; Task.Run(() => { using (var stopMiner = new CancellationTokenSource()) { lock (_lock) { _stopMiners.Add(stopMiner); } var run = IsStart() && stopMiner.IsCancellationRequested == false; while (run) { var binPathBinCwdPair = GetBinAndCwdPaths(); var binPath = binPathBinCwdPair.Item1; var binCwd = binPathBinCwdPair.Item2; var commandLine = MiningCreateCommandLine(); var environmentVariables = GetEnvironmentVariables(); using (var miningProcess = MinerToolkit.CreateMiningProcess(binPath, binCwd, commandLine, environmentVariables)) { lock (_lock) { _miningProcess = miningProcess; } var quitMiningProcess = stopMiner.Token.Register(() => { try { var pid = miningProcess?.Id ?? -1; miningProcess?.CloseMainWindow(); // 5 seconds wait for shutdown var hasExited = !miningProcess?.WaitForExit(5 * 1000) ?? false; var stillRunning = pid > -1 ? Process.GetProcessById(pid) != null : false; if (!hasExited || stillRunning) { miningProcess?.Kill(); // TODO look for another gracefull shutdown } } catch (Exception e) { Logger.Info(_logGroup, $"Error occured while stopping the process: {e.Message}"); } }); try { // mandatory 500ms delay Task.Delay(500).Wait(); // BEFORE ThrowIfIsStop(stopMiner.IsCancellationRequested); if (this is IBeforeStartMining bsm) { bsm.BeforeStartMining(); } ThrowIfIsStop(stopMiner.IsCancellationRequested); // Logging Logger.Info(_logGroup, $"Starting miner binPath='{binPath}'"); Logger.Info(_logGroup, $"Starting miner binCwd='{binCwd}'"); Logger.Info(_logGroup, $"Starting miner commandLine='{commandLine}'"); // TODO this will not print content var environmentVariablesLog = environmentVariables == null ? "<null>" : string.Join(";", environmentVariables.Select(x => x.Key + "=" + x.Value)); Logger.Info(_logGroup, $"Starting miner environmentVariables='{environmentVariablesLog}'"); // TODO log or debug??? ThrowIfIsStop(stopMiner.IsCancellationRequested); //_stopMiner = new CancellationTokenSource(); { if (!miningProcess.Start()) { Logger.Info(_logGroup, $"Error occured while starting a new process: {miningProcess.ToString()}"); throw new InvalidOperationException("Could not start process: " + miningProcess); } ThrowIfIsStop(stopMiner.IsCancellationRequested); if (this is IAfterStartMining asm) { asm.AfterStartMining(); } ThrowIfIsStop(stopMiner.IsCancellationRequested); // block loop until process is running miningProcess.WaitForExit(); } } //catch (Win32Exception ex2) //{ // ////if (ex2.NativeErrorCode == ERROR_FILE_NOT_FOUND) throw ex2; // //Logger.Info(_logGroup, $"Win32Exception Error occured in StartMining : {ex2.ToString()}"); // //Task.Delay(MinerToolkit.MinerRestartDelayMS, _stopMiner.Token).Wait(); //} catch (StopMinerWatchdogException) { Logger.Info(_logGroup, $"Watchdog stopped in StartMining"); } catch (Exception e) { Logger.Error(_logGroup, $"Error occured in StartMining : {e.Message}"); } finally { quitMiningProcess.Dispose(); // delay restart run = IsStart() && stopMiner.IsCancellationRequested == false; if (run) { Logger.Info(_logGroup, $"Restart Mining in {MinerToolkit.MinerRestartDelayMS}ms"); Task.Delay(MinerToolkit.MinerRestartDelayMS).Wait(); } } } } Logger.Info(_logGroup, $"Exited miner watchdog"); lock (_lock) { _stopMiners.Remove(stopMiner); } } }); }
public Task <object> StartMiningTask(CancellationToken stop) { //const int ERROR_FILE_NOT_FOUND = 0x2; //const int ERROR_ACCESS_DENIED = 0x5; // tsc for started process var startProcessTaskCompletionSource = new TaskCompletionSource <object>(); var binPathBinCwdPair = GetBinAndCwdPaths(); var binPath = binPathBinCwdPair.Item1; var binCwd = binPathBinCwdPair.Item2; var commandLine = MiningCreateCommandLine(); var environmentVariables = GetEnvironmentVariables(); var stopActionExec = false; _miningProcessTask = Task.Run(() => { using (_stopMinerTaskSource = new CancellationTokenSource()) using (var stopMinerTask = CancellationTokenSource.CreateLinkedTokenSource(stop, _stopMinerTaskSource.Token)) using (var miningProcess = MinerToolkit.CreateMiningProcess(binPath, binCwd, commandLine, environmentVariables)) using (var quitMiningProcess = stopMinerTask.Token.Register(() => ExitMiningProcess(miningProcess))) { lock (_lock) { _miningProcess = miningProcess; } try { // BEFORE ThrowIfIsStop(stopMinerTask.IsCancellationRequested); if (this is IBeforeStartMining bsm) { bsm.BeforeStartMining(); } ThrowIfIsStop(stopMinerTask.IsCancellationRequested); // Logging Logger.Info(_logGroup, $"Starting miner binPath='{binPath}'"); Logger.Info(_logGroup, $"Starting miner binCwd='{binCwd}'"); Logger.Info(_logGroup, $"Starting miner commandLine='{commandLine}'"); var environmentVariablesLog = environmentVariables == null ? "<null>" : string.Join(";", environmentVariables.Select(x => x.Key + "=" + x.Value)); Logger.Info(_logGroup, $"Starting miner environmentVariables='{environmentVariablesLog}'"); ThrowIfIsStop(stopMinerTask.IsCancellationRequested); // exec START custom scripts if any, must be here if blocking ExecMinerCustomActionSettings(true); if (!miningProcess.Start()) { Logger.Info(_logGroup, $"Error occured while starting a new process: {miningProcess.ToString()}"); startProcessTaskCompletionSource.SetResult(new InvalidOperationException("Could not start process: " + miningProcess)); return; } startProcessTaskCompletionSource.SetResult(true); ThrowIfIsStop(stopMinerTask.IsCancellationRequested); if (this is IAfterStartMining asm) { asm.AfterStartMining(); } ThrowIfIsStop(stopMinerTask.IsCancellationRequested); // block while process is running miningProcess.WaitForExit(); // exec STOP custom scripts if any, must be here if blocking stopActionExec = true; ExecMinerCustomActionSettings(false); } //catch (Win32Exception ex2) //{ // ////if (ex2.NativeErrorCode == ERROR_FILE_NOT_FOUND) throw ex2; // //Logger.Info(_logGroup, $"Win32Exception Error occured in StartMining : {ex2.ToString()}"); // //Task.Delay(MinerToolkit.MinerRestartDelayMS, _stopMiner.Token).Wait(); //} catch (StopMinerWatchdogException) { Logger.Info(_logGroup, $"Watchdog stopped in StartMining"); startProcessTaskCompletionSource.SetResult(false); } catch (Exception e) { Logger.Error(_logGroup, $"Error occured in StartMining : {e.Message}"); startProcessTaskCompletionSource.SetResult(e); } finally { if (!stopActionExec) { // exec STOP custom scripts if any, last resort it will not block but it is a fallback option ExecMinerCustomActionSettings(false); } } } }); return(startProcessTaskCompletionSource.Task); }
public BenchmarkProcess(string binPath, string workingDir, string commandLine, Dictionary <string, string> environmentVariables = null) { Handle = MinerToolkit.CreateBenchmarkProcess(binPath, workingDir, commandLine, environmentVariables); }