439{
441
443
444 std::string default_db_type = "lmdb";
445
447 available_dbs = "available: " + available_dbs;
448
450
452
453 boost::filesystem::path output_file_path;
454
455 po::options_description desc_cmd_only("Command line options");
456 po::options_description desc_cmd_sett("Command line options and settings options");
459 "database", available_dbs.c_str(), default_db_type
460 };
462 "db-sync-mode"
463 , "Specify sync option, using format [safe|fast|fastest]:[nrecords_per_sync]."
464 , "fast:1000"
465 };
467
476
477 po::options_description desc_options("Allowed options");
478 desc_options.add(desc_cmd_only).add(desc_cmd_sett);
479
480 po::variables_map vm;
482 {
483 auto parser = po::command_line_parser(argc, argv).options(desc_options);
484 po::store(parser.run(), vm);
485 po::notify(vm);
486 return true;
487 });
488 if (! r)
489 return 1;
490
492 {
494 std::cout << desc_options << std::endl;
495 return 1;
496 }
497
501 else
502 mlog_set_log(std::string(std::to_string(log_level) +
",bcutil:INFO").c_str());
503
504 MINFO(
"Starting...");
505
511 while (boost::ends_with(data_dir, "/") || boost::ends_with(data_dir, "\\"))
513
516 {
517 MERROR(
"Invalid database type: " << db_type);
518 return 1;
519 }
520 if (db_type != "lmdb")
521 {
522 MERROR(
"Unsupported database type: " << db_type <<
". Only lmdb is supported");
523 return 1;
524 }
525
528 if (!parse_db_sync_mode(db_sync_mode, db_flags))
529 {
530 MERROR(
"Invalid db sync mode: " << db_sync_mode);
531 return 1;
532 }
533
534
535
536
537
538
539
540
541
542
543
544
545 MINFO(
"Initializing source blockchain (BlockchainDB)");
546 std::array<std::unique_ptr<Blockchain>, 2> core_storage;
549 boost::filesystem::path paths[2];
550 bool already_pruned = false;
551 for (size_t n = 0; n < core_storage.size(); ++n)
552 {
553 core_storage[n].reset(
new Blockchain(m_mempool));
554
556 if (db == NULL)
557 {
558 MERROR(
"Attempted to use non-existent database type: " << db_type);
559 throw std::runtime_error("Attempting to use non-existent database type");
560 }
561 MDEBUG(
"database: " << db_type);
562
563 if (n == 1)
564 {
565 paths[1] = boost::filesystem::path(data_dir) / (db->
get_db_name() +
"-pruned");
566 if (boost::filesystem::exists(paths[1]))
567 {
568 if (!boost::filesystem::is_directory(paths[1]))
569 {
570 MERROR(
"LMDB needs a directory path, but a file was passed: " << paths[1].
string());
571 return 1;
572 }
573 }
574 else
575 {
576 if (!boost::filesystem::create_directories(paths[1]))
577 {
578 MERROR(
"Failed to create directory: " << paths[1].
string());
579 return 1;
580 }
581 }
582 db_path = paths[1].string();
583 }
584 else
585 {
586 paths[0] = boost::filesystem::path(data_dir) / db->
get_db_name();
587 }
588
589 MINFO(
"Loading blockchain from folder " << paths[n] <<
" ...");
590
591 try
592 {
594 }
595 catch (const std::exception& e)
596 {
597 MERROR(
"Error opening database: " << e.what());
598 return 1;
599 }
600 r = core_storage[n]->init(db, net_type);
601
602 std::string source_dest = n == 0 ? "source" : "pruned";
604 MINFO(source_dest <<
" blockchain storage initialized OK");
605 if (n == 0 && core_storage[0]->get_blockchain_pruning_seed())
606 {
607 if (!opt_copy_pruned_database)
608 {
609 MERROR(
"Blockchain is already pruned, use --" << arg_copy_pruned_database.name <<
" to copy it anyway");
610 return 1;
611 }
612 already_pruned = true;
613 }
614 }
615 core_storage[0]->deinit();
616 core_storage[0].reset(NULL);
617 core_storage[1]->deinit();
618 core_storage[1].reset(NULL);
619
621 MDB_env *env0 = NULL, *env1 = NULL;
622 open(env0, paths[0], db_flags, true);
623 open(env1, paths[1], db_flags, false);
627
630
640 if (already_pruned)
641 {
644 }
645 else
646 {
647 prune(env0, env1);
648 }
649 close(env1);
650 close(env0);
651
652 MINFO(
"Swapping databases, pre-pruning blockchain will be left in " << paths[0].
string() +
"-old and can be removed if desired");
653 if (replace_file(paths[0].string(), paths[0].string() + "-old") || replace_file(paths[1].string(), paths[0].string()))
654 {
655 MERROR(
"Blockchain pruned OK, but renaming failed");
656 return 1;
657 }
658
659 MINFO(
"Blockchain pruned OK");
660 return 0;
661
663}
The BlockchainDB backing store interface declaration/contract.
virtual std::string get_db_name() const =0
gets the name of the folder the BlockchainDB's file(s) should be in
virtual void open(const std::string &filename, const int db_flags=0)=0
open a db, or create it if necessary.
static int compare_string(const MDB_val *a, const MDB_val *b)
static int compare_hash32(const MDB_val *a, const MDB_val *b)
static int compare_uint64(const MDB_val *a, const MDB_val *b)
Transaction pool, handles transactions which are not part of a block.
struct MDB_env MDB_env
Opaque structure for a database environment.
void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size=MAX_LOG_FILE_SIZE, const std::size_t max_log_files=MAX_LOG_FILES)
#define CATCH_ENTRY(location, return_val)
std::string mlog_get_default_log_path(const char *default_filename)
void mlog_set_log(const char *log)
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
void add_arg(boost::program_options::options_description &description, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg, bool unique=true)
const arg_descriptor< bool > arg_help
bool is_arg_defaulted(const boost::program_options::variables_map &vm, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg)
bool handle_error_helper(const boost::program_options::options_description &desc, F parser)
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
const command_line::arg_descriptor< std::string, false, true, 2 > arg_data_dir
const command_line::arg_descriptor< bool, false > arg_testnet_on
BlockchainDB * new_db(const std::string &db_type)
bool blockchain_valid_db_type(const std::string &db_type)
const command_line::arg_descriptor< bool, false > arg_stagenet_on
std::string blockchain_db_types(const std::string &sep)
const command_line::arg_descriptor< std::string > arg_db_sync_mode
const command_line::arg_descriptor< std::string > arg_log_level
boost::filesystem::path data_dir
unsigned __int64 uint64_t
const char *const ELECTRONEUM_RELEASE_NAME
const char *const ELECTRONEUM_VERSION_FULL