Example #1
0
        internal static async Task <(bool started, string failReason)> StartDeviceTask(ComputeDevice device)
        {
            device.StartState = true;
            // we can only start a device it is already stopped
            if (device.State == DeviceState.Disabled)
            {
                return(false, "Device is disabled");
            }

            if (device.State != DeviceState.Stopped && device.State != DeviceState.Error)
            {
                return(false, "Device already started");
            }

            var started               = true;
            var failReason            = "";
            var allAlgorithmsDisabled = !device.AnyAlgorithmEnabled();
            var isAllZeroPayingState  = device.AllEnabledAlgorithmsZeroPaying();
            // check if device has any benchmakrs
            var needBenchmarkOrRebench = device.AnyEnabledAlgorithmsNeedBenchmarking();

            if (allAlgorithmsDisabled)
            {
                device.State = DeviceState.Error;
                started      = false;
                failReason   = "Cannot start a device with all disabled algoirhtms";
            }
            else if (isAllZeroPayingState && !needBenchmarkOrRebench)
            {
                device.State = DeviceState.Error;
                started      = false;
                failReason   = "No enabled algorithm is profitable";
            }
            else
            {
                await MiningManager.StartDevice(device);
            }

            return(started, failReason);
        }
        private async Task Benchmark()
        {
            bool showFailed  = false;
            bool startMining = false;

            _stopBenchmark = CancellationTokenSource.CreateLinkedTokenSource(ApplicationStateManager.ExitApplication.Token);
            try
            {
                foreach (var a in _algorithms)
                {
                    a.SetBenchmarkPending();
                }
                var benchAlgos = new Queue <AlgorithmContainer>(_algorithms);
                //BenchmarkingHandlers.TryAdd(Device, this);
                // whole benchmark scope
                var commandTask = GetCommand(_stopBenchmark.Token);
                // Until container is not empty
                while (benchAlgos.Any() && !_stopBenchmark.IsCancellationRequested)
                {
                    // per algo benchmark scope
                    bool?benchmarkSuccess = null;
                    _stopCurrentAlgorithmBenchmark = CancellationTokenSource.CreateLinkedTokenSource(_stopBenchmark.Token);
                    try
                    {
                        var nextAlgo      = benchAlgos.Dequeue();
                        var benchmark     = BenchmarkAlgorithm(nextAlgo, _stopCurrentAlgorithmBenchmark.Token);
                        var firstFinished = await Task.WhenAny(new Task <object>[] { commandTask, benchmark });

                        var ret = await firstFinished;
                        if (ret is IReadOnlyList <AlgorithmContainer> updatedAlgorithms)
                        {
                            commandTask = GetCommand(_stopBenchmark.Token);
                            var stop           = _algorithms.Except(updatedAlgorithms).Any(algo => algo == nextAlgo);
                            var restAlgorithms = updatedAlgorithms.Where(algo => algo != nextAlgo).ToArray();
                            // update Algorithms
                            _algorithms = restAlgorithms;
                            foreach (var a in _algorithms)
                            {
                                a.SetBenchmarkPending();
                            }
                            // updated
                            benchAlgos = new Queue <AlgorithmContainer>(_algorithms);
                            if (stop)
                            {
                                // THIS Throws
                                _stopCurrentAlgorithmBenchmark.Cancel();
                            }
                            else
                            {
                                // wait for the current benchmark to finish
                                ret = await benchmark;
                            }
                        }
                        if (ret is bool success)
                        {
                            benchmarkSuccess = success;
                        }
                        // this will drain the container
                        await Task.Delay(MiningSettings.Instance.MinerRestartDelayMS, _stopCurrentAlgorithmBenchmark.Token);
                    }
                    catch (TaskCanceledException e)
                    {
                        Logger.Debug("BenchmarkingDevice", $"TaskCanceledException occurred in benchmark task: {e.Message}");
                    }
                    catch (Exception e)
                    {
                        Logger.Error("BenchmarkingDevice", $"Exception occurred in benchmark task: {e.Message}");
                    }
                    finally
                    {
                        _stopCurrentAlgorithmBenchmark.Dispose();
                        if (!_stopCurrentAlgorithmBenchmark.IsCancellationRequested && benchmarkSuccess.HasValue && !benchmarkSuccess.Value)
                        {
                            showFailed = true;
                        }
                    }
                }
                startMining = !_stopBenchmark.IsCancellationRequested;
                // clear what we didn't benchmark
                while (benchAlgos.Any())
                {
                    var nextAlgo = benchAlgos.Dequeue();
                    nextAlgo.ClearBenchmarkPending();
                }
                if (showFailed)
                {
                    AvailableNotifications.CreateFailedBenchmarksInfo(Device);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("BenchmarkingDevice2", $"Exception occurred in benchmark task: {ex.Message}");
            }
            finally
            {
                _stopBenchmark.Dispose();
                if (startMining)
                {
                    _ = MiningManager.StartDevice(Device); // important do not await
                }
                else
                {
                    Device.State = DeviceState.Stopped;
                }
            }
        }