| 1440 | }; |
| 1441 | |
| 1442 | bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) |
| 1443 | { |
| 1444 | const ArgsManager& args = *Assert(node.args); |
| 1445 | const CChainParams& chainparams = Params(); |
| 1446 | |
| 1447 | auto opt_max_upload = ParseByteUnits(args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET), ByteUnit::M); |
| 1448 | if (!opt_max_upload) { |
| 1449 | return InitError(strprintf(_("Unable to parse -maxuploadtarget: '%s'"), args.GetArg("-maxuploadtarget", ""))); |
| 1450 | } |
| 1451 | |
| 1452 | // ********************************************************* Step 4a: application initialization |
| 1453 | if (!CreatePidFile(args)) { |
| 1454 | // Detailed error printed inside CreatePidFile(). |
| 1455 | return false; |
| 1456 | } |
| 1457 | if (!init::StartLogging(args)) { |
| 1458 | // Detailed error printed inside StartLogging(). |
| 1459 | return false; |
| 1460 | } |
| 1461 | |
| 1462 | LogInfo("Using at most %i automatic connections (%i file descriptors available)", nMaxConnections, available_fds); |
| 1463 | |
| 1464 | // Warn about relative -datadir path. |
| 1465 | if (args.IsArgSet("-datadir") && !args.GetPathArg("-datadir").is_absolute()) { |
| 1466 | LogWarning("Relative datadir option '%s' specified, which will be interpreted relative to the " |
| 1467 | "current working directory '%s'. This is fragile, because if bitcoin is started in the future " |
| 1468 | "from a different location, it will be unable to locate the current data files. There could " |
| 1469 | "also be data loss if bitcoin is started while in a temporary directory.", |
| 1470 | args.GetArg("-datadir", ""), fs::PathToString(fs::current_path())); |
| 1471 | } |
| 1472 | |
| 1473 | assert(!node.scheduler); |
| 1474 | node.scheduler = std::make_unique<CScheduler>(); |
| 1475 | auto& scheduler = *node.scheduler; |
| 1476 | |
| 1477 | // Start the lightweight task scheduler thread |
| 1478 | scheduler.m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { scheduler.serviceQueue(); }); |
| 1479 | |
| 1480 | // Gather some entropy once per minute. |
| 1481 | scheduler.scheduleEvery([]{ |
| 1482 | RandAddPeriodic(); |
| 1483 | }, std::chrono::minutes{1}); |
| 1484 | |
| 1485 | // Check disk space every 5 minutes to avoid db corruption. |
| 1486 | scheduler.scheduleEvery([&args, &node]{ |
| 1487 | constexpr uint64_t min_disk_space{50_MiB}; |
| 1488 | if (!CheckDiskSpace(args.GetBlocksDirPath(), min_disk_space)) { |
| 1489 | LogError("Shutting down due to lack of disk space!\n"); |
| 1490 | if (!(Assert(node.shutdown_request))()) { |
| 1491 | LogError("Failed to send shutdown signal after disk space check\n"); |
| 1492 | } |
| 1493 | } |
| 1494 | }, std::chrono::minutes{5}); |
| 1495 | |
| 1496 | if (args.GetBoolArg("-logratelimit", BCLog::DEFAULT_LOGRATELIMIT)) { |
| 1497 | LogInstance().SetRateLimiting(BCLog::LogRateLimiter::Create( |
| 1498 | [&scheduler](auto func, auto window) { scheduler.scheduleEvery(std::move(func), window); }, |
| 1499 | BCLog::RATELIMIT_MAX_BYTES, |