예제 #1
0
        private static bool CheckIfShouldMine(double currentProfit, bool log = true)
        {
            var isProfitable = CheckIfProfitable(currentProfit, log);

            ApplicationStateManager.SetProfitableState(isProfitable);
            ApplicationStateManager.DisplayNoInternetConnection(!_isConnectedToInternet);

            if (!_isConnectedToInternet && log)
            {
                Logger.Info(Tag, $"No internet connection! Not able to mine.");
            }

            AvailableNotifications.CreateNotProfitableInfo(isProfitable);

            // if profitable and connected to internet mine
            var shouldMine = isProfitable && _isConnectedToInternet;

            return(shouldMine);
        }
예제 #2
0
        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;
                }
            }
        }
예제 #3
0
        private async Task RunMinerWatchDogLoop(TaskCompletionSource <object> tsc, CancellationToken stop, string username)
        {
            // if we fail 3 times in a row under certain conditions mark on of them
            const int maxRestartCount         = 3;
            int       restartCount            = 0;
            const int minRestartTimeInSeconds = 240;

            try
            {
                var firstStart = true;
                using (_endMiner = new CancellationTokenSource())
                    using (var linkedEndMiner = CancellationTokenSource.CreateLinkedTokenSource(stop, _endMiner.Token))
                    {
                        Logger.Info(MinerTag(), $"Starting miner watchdog task");
                        while (!linkedEndMiner.IsCancellationRequested && (restartCount < maxRestartCount))
                        {
                            var startTime = DateTime.UtcNow;
                            try
                            {
                                if (!firstStart)
                                {
                                    Logger.Info(MinerTag(), $"Restart Mining in {MiningSettings.Instance.MinerRestartDelayMS}ms");
                                    AvailableNotifications.CreateRestartedMinerInfo(DateTime.UtcNow.ToLocalTime(), _plugin.Name);
                                    await TaskHelpers.TryDelay(MiningSettings.Instance.MinerRestartDelayMS, linkedEndMiner.Token);
                                }
                                var result = await StartAsync(linkedEndMiner.Token, username);

                                if (firstStart)
                                {
                                    firstStart = false;
                                    tsc.SetResult(result);
                                }
                                if (result is bool ok && ok)
                                {
                                    var runningMinerTask = _miner.MinerProcessTask;
                                    if (_algos.Any(a => a.AlgorithmName == "RandomXmonero"))
                                    {
                                        _ = XMRingStartedWaitTime(runningMinerTask, linkedEndMiner.Token);
                                    }
                                    _ = MinerStatsLoop(runningMinerTask, linkedEndMiner.Token);
                                    await runningMinerTask;
                                    // TODO log something here
                                    Logger.Info(MinerTag(), $"Running Miner Task Completed");
                                }
                                else
                                {
                                    // TODO check if the miner file is missing or locked and blacklist the algorithm for a certain period of time
                                    Logger.Error(MinerTag(), $"StartAsync result: {result}");
                                }
                            }
                            catch (TaskCanceledException e)
                            {
                                Logger.Debug(MinerTag(), $"RunMinerWatchDogLoop TaskCanceledException: {e.Message}");
                                return;
                            }
                            catch (Exception e)
                            {
                                Logger.Error(MinerTag(), $"RunMinerWatchDogLoop Exception: {e.Message}");
                            }
                            finally
                            {
                                var endTime        = DateTime.UtcNow;
                                var elapsedSeconds = (endTime - startTime).TotalSeconds - (MiningSettings.Instance.MinerRestartDelayMS / 1000);
                                if (elapsedSeconds < minRestartTimeInSeconds)
                                {
                                    restartCount++;
                                }
                                else
                                {
                                    restartCount = 0;
                                }
                                if (restartCount >= maxRestartCount)
                                {
                                    var    firstAlgo = _algos.FirstOrDefault();
                                    Random randWait  = new Random();
                                    firstAlgo.IgnoreUntil = DateTime.UtcNow.AddMinutes(randWait.Next(20, 30));
                                    await MiningManager.MinerRestartLoopNotify();
                                }
                            }
                        }
예제 #4
0
        //private static async Task ResumeAllMiners()
        //{
        //    foreach (var groupMiner in _runningMiners.Values)
        //    {
        //        await groupMiner.StartMinerTask(stopMiningManager, _username);
        //    }
        //    // TODO resume devices to Mining state
        //}

        private static async Task CheckGroupingAndUpdateMiners(MainCommand command)
        {
            // #1 parse the command
            var commandType = command.GetType().Name;

            Logger.Debug(Tag, $"Command type {commandType}");
            if (command is NormalizedProfitsUpdateCommand normalizedProfitsUpdateCommand)
            {
                _normalizedProfits = normalizedProfitsUpdateCommand.normalizedProfits;
            }
            else if (command is UsernameChangedCommand usernameChangedCommand)
            {
                _username = usernameChangedCommand.username;
            }
            else if (command is PauseMiningWhenGamingModeSettingsChangedCommand pauseMiningWhenGamingModeSettingsChangedCommand)
            {
                _isPauseMiningWhenGamingEnabled = pauseMiningWhenGamingModeSettingsChangedCommand.isPauseMiningWhenGamingModeSettingEnabled;
                if (!_isPauseMiningWhenGamingEnabled)
                {
                    var dev = AvailableDevices.Devices.FirstOrDefault(d => d.IsGaming == true);
                    if (dev != null)
                    {
                        dev.IsGaming = false;
                    }
                }
            }
            else if (command is IsSteamGameRunningChangedCommand isSteamGameRunningChangedCommand)
            {
                _isGameRunning = isSteamGameRunningChangedCommand.isSteamGameRunning;
            }
            else if (command is GPUToPauseChangedCommand gpuToPauseChangedCommand)
            {
                _deviceToPauseUuid = gpuToPauseChangedCommand.gpuUuid;

                // unpause device if not mining and not selected
                var devToUnpause = AvailableDevices.Devices.FirstOrDefault(d => d.Uuid != _deviceToPauseUuid && d.IsGaming == true);
                if (devToUnpause != null)
                {
                    devToUnpause.IsGaming = false;
                }

                // set new selected gpu to true
                var newSelectedDev = AvailableDevices.GetDeviceWithUuid(_deviceToPauseUuid);
                if (newSelectedDev != null)
                {
                    newSelectedDev.PauseMiningWhenGamingMode = true;
                    ConfigManager.DeviceConfigFileCommit(newSelectedDev);
                }

                // set previous selected gpu to false
                var oldSelectedDev = AvailableDevices.Devices.FirstOrDefault(d => d.Uuid != _deviceToPauseUuid && d.PauseMiningWhenGamingMode);
                if (oldSelectedDev != null)
                {
                    oldSelectedDev.PauseMiningWhenGamingMode = false;
                    ConfigManager.DeviceConfigFileCommit(oldSelectedDev);
                }
            }

            bool isRestartMinersCommand(Command command) =>
            command switch
            {
                UsernameChangedCommand => true,
                UseOptimizationProfilesChangedCommand => true,
                DNSQChangedCommand => true,
                SSLMiningChangedCommand => true,
                _ => false,
            };
            // here we do the deciding
            // to mine we need to have the username mining location set and ofc device to mine with
            if (_username == null || _normalizedProfits == null)
            {
                if (_username == null)
                {
                    Logger.Error(Tag, "_username is null");
                }
                if (_normalizedProfits == null)
                {
                    Logger.Error(Tag, "_normalizedProfits is null");
                }
                await PauseAllMiners();
            }
            else if (isRestartMinersCommand(command))
            {
                // RESTART-STOP-START
                // STOP
                foreach (var miner in _runningMiners.Values)
                {
                    await miner.StopTask();
                }
                // START
                foreach (var miner in _runningMiners.Values)
                {
                    await miner.StartMinerTask(_stopMiningManager, _username);
                }
            }
            else if (_miningDevices.Count == 0)
            {
                await StopAllMinersTask();

                ApplicationStateManager.StopMining();
            }
            else if (_isGameRunning && _isPauseMiningWhenGamingEnabled && _deviceToPauseUuid != null)
            {
                AvailableNotifications.CreateGamingStarted();
                var dev = AvailableDevices.Devices.FirstOrDefault(d => d.Uuid == _deviceToPauseUuid);
                dev.IsGaming = true;
                bool skipProfitsThreshold = CheckIfShouldSkipProfitsThreshold(command);
                await SwichMostProfitableGroupUpMethodTask(_normalizedProfits, skipProfitsThreshold);
            }
            else if (!_isGameRunning && _isPauseMiningWhenGamingEnabled && command is IsSteamGameRunningChangedCommand)
            {
                AvailableNotifications.CreateGamingFinished();
                var dev = AvailableDevices.Devices.FirstOrDefault(d => d.Uuid == _deviceToPauseUuid);
                dev.IsGaming = false;
                bool skipProfitsThreshold = CheckIfShouldSkipProfitsThreshold(command);
                await SwichMostProfitableGroupUpMethodTask(_normalizedProfits, skipProfitsThreshold);
            }
            else
            {
                ApplicationStateManager.StartMining();
                bool skipProfitsThreshold = CheckIfShouldSkipProfitsThreshold(command);
                await SwichMostProfitableGroupUpMethodTask(_normalizedProfits, skipProfitsThreshold);
            }
        }