public async Task StartAsync(CancellationToken cancel) { var ptcv = PrintToConsole ? 1 : 0; using var process = Start($"{NetworkTranslator.GetCommandLineArguments(Network)} -datadir=\"{DataDir}\" -printtoconsole={ptcv}", false); await PidFile.WriteFileAsync(process.Id).ConfigureAwait(false); CachedPid = process.Id; string latestFailureMessage = null; while (true) { var ex = await RpcClient.TestAsync().ConfigureAwait(false); if (ex is null) { Logger.LogInfo($"RPC connection is successfully established."); break; } else if (latestFailureMessage != ex.Message) { latestFailureMessage = ex.Message; Logger.LogInfo($"{Constants.BuiltinBitcoinNodeName} is not yet ready... Reason: {latestFailureMessage}"); } if (process is null || process.HasExited) { throw new BitcoindException($"Failed to start daemon, location: '{process?.StartInfo.FileName} {process?.StartInfo.Arguments}'", ex); } if (cancel.IsCancellationRequested) { await StopAsync(true).ConfigureAwait(false); cancel.ThrowIfCancellationRequested(); } await Task.Delay(100).ConfigureAwait(false); // So to leave some breathing room before the next check. } }
/// <summary> /// This method can be called only once. /// </summary> public async Task StartAsync(CancellationToken cancel) { int ptcv = PrintToConsole ? 1 : 0; string processPath = MicroserviceHelpers.GetBinaryPath("bitcoind"); string networkArgument = NetworkTranslator.GetCommandLineArguments(Network); string args = $"{networkArgument} -datadir=\"{DataDir}\" -printtoconsole={ptcv}"; // Start bitcoind process. Process = new ProcessAsync(ProcessStartInfoFactory.Make(processPath, args)); Process.Start(); // Store PID in PID file. await PidFile.WriteFileAsync(Process.Id).ConfigureAwait(false); CachedPid = Process.Id; try { var exceptionTracker = new LastExceptionTracker(); // Try to connect to bitcoin daemon RPC until we succeed. while (true) { try { TimeSpan timeSpan = await RpcClient.UptimeAsync(cancel).ConfigureAwait(false); Logger.LogInfo("RPC connection is successfully established."); Logger.LogDebug($"RPC uptime is: {timeSpan}."); // Bitcoin daemon is started. We are done. break; } catch (Exception ex) { ExceptionInfo exceptionInfo = exceptionTracker.Process(ex); // Don't log extensively. if (exceptionInfo.IsFirst) { Logger.LogInfo($"{Constants.BuiltinBitcoinNodeName} is not yet ready... Reason: {exceptionInfo.Exception.Message}"); } if (Process is { } p&& p.HasExited) { throw new BitcoindException($"Failed to start daemon, location: '{p.StartInfo.FileName} {p.StartInfo.Arguments}'", ex); } } if (cancel.IsCancellationRequested) { Logger.LogDebug("Bitcoin daemon was not started yet and user requested to cancel the operation."); await StopAsync(onlyOwned : true).ConfigureAwait(false); cancel.ThrowIfCancellationRequested(); } // Wait a moment before the next check. await Task.Delay(100, cancel).ConfigureAwait(false); } } catch (Exception) { Process?.Dispose(); throw; } }