Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New default config file #422

Merged
merged 4 commits into from
Oct 16, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 110 additions & 66 deletions programs/witness_node/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,113 @@ namespace bpo = boost::program_options;
void write_default_logging_config_to_stream(std::ostream& out);
fc::optional<fc::logging_config> load_logging_config_from_ini_file(const fc::path& config_ini_filename);

class deduplicator
{
public:
deduplicator() : modifier(nullptr) {}

deduplicator(const boost::shared_ptr<bpo::option_description> (*mod_fn)(const boost::shared_ptr<bpo::option_description>&))
: modifier(mod_fn) {}

const boost::shared_ptr<bpo::option_description> next(const boost::shared_ptr<bpo::option_description>& o)
{
const std::string name = o->long_name();
if( seen.find( name ) != seen.end() )
return nullptr;
seen.insert(name);
return modifier ? modifier(o) : o;
}

private:
boost::container::flat_set<std::string> seen;
const boost::shared_ptr<bpo::option_description> (*modifier)(const boost::shared_ptr<bpo::option_description>&);
};

static void load_config_file( const fc::path& config_ini_path, const bpo::options_description& cfg_options,
bpo::variables_map& options )
{
deduplicator dedup;
bpo::options_description unique_options("Graphene Witness Node");
for( const boost::shared_ptr<bpo::option_description> opt : cfg_options.options() )
{
const boost::shared_ptr<bpo::option_description> od = dedup.next(opt);
if( !od ) continue;
unique_options.add( od );
}

// get the basic options
bpo::store(bpo::parse_config_file<char>(config_ini_path.preferred_string().c_str(),
unique_options, true), options);

// try to get logging options from the config file.
try
{
fc::optional<fc::logging_config> logging_config = load_logging_config_from_ini_file(config_ini_path);
if (logging_config)
fc::configure_logging(*logging_config);
}
catch (const fc::exception&)
{
wlog("Error parsing logging config from config file ${config}, using default config", ("config", config_ini_path.preferred_string()));
}
}

const boost::shared_ptr<bpo::option_description> new_option_description( const std::string& name, const bpo::value_semantic* value, const std::string& description )
{
bpo::options_description helper("");
helper.add_options()( name.c_str(), value, description.c_str() );
return helper.options()[0];
}

static void create_new_config_file( const fc::path& config_ini_path, const fc::path& data_dir,
const bpo::options_description& cfg_options )
{
ilog("Writing new config file at ${path}", ("path", config_ini_path));
if( !fc::exists(data_dir) )
fc::create_directories(data_dir);

auto modify_option_defaults = [](const boost::shared_ptr<bpo::option_description>& o) -> const boost::shared_ptr<bpo::option_description> {
const std::string& name = o->long_name();
if( name == "partial-operations" )
return new_option_description( name, bpo::value<bool>()->default_value(true), o->description() );
if( name == "max-ops-per-account" )
return new_option_description( name, bpo::value<int>()->default_value(1000), o->description() );
return o;
};
deduplicator dedup(modify_option_defaults);
std::ofstream out_cfg(config_ini_path.preferred_string());
for( const boost::shared_ptr<bpo::option_description> opt : cfg_options.options() )
{
const boost::shared_ptr<bpo::option_description> od = dedup.next(opt);
if( !od ) continue;

if( !od->description().empty() )
out_cfg << "# " << od->description() << "\n";
boost::any store;
if( !od->semantic()->apply_default(store) )
out_cfg << "# " << od->long_name() << " = \n";
else {
auto example = od->format_parameter();
if( example.empty() )
// This is a boolean switch
out_cfg << od->long_name() << " = " << "false\n";
else {
// The string is formatted "arg (=<interesting part>)"
example.erase(0, 6);
example.erase(example.length()-1);
out_cfg << od->long_name() << " = " << example << "\n";
}
}
out_cfg << "\n";
}
write_default_logging_config_to_stream(out_cfg);
out_cfg.close();
// read the default logging config we just wrote out to the file and start using it
fc::optional<fc::logging_config> logging_config = load_logging_config_from_ini_file(config_ini_path);
if (logging_config)
fc::configure_logging(*logging_config);
}

int main(int argc, char** argv) {
app::application* node = new app::application();
fc::oexception unhandled_exception;
Expand Down Expand Up @@ -109,72 +216,9 @@ int main(int argc, char** argv) {
}

fc::path config_ini_path = data_dir / "config.ini";
if( fc::exists(config_ini_path) )
{
boost::container::flat_set<std::string> seen;
bpo::options_description unique_options("Graphene Witness Node");
for( const boost::shared_ptr<bpo::option_description> od : cfg_options.options() )
{
const std::string name = od->long_name();
if( seen.find(name) != seen.end() ) continue;
seen.insert(name);
unique_options.add( od );
}

// get the basic options
bpo::store(bpo::parse_config_file<char>(config_ini_path.preferred_string().c_str(), unique_options, true), options);

// try to get logging options from the config file.
try
{
fc::optional<fc::logging_config> logging_config = load_logging_config_from_ini_file(config_ini_path);
if (logging_config)
fc::configure_logging(*logging_config);
}
catch (const fc::exception&)
{
wlog("Error parsing logging config from config file ${config}, using default config", ("config", config_ini_path.preferred_string()));
}
}
else
{
ilog("Writing new config file at ${path}", ("path", config_ini_path));
if( !fc::exists(data_dir) )
fc::create_directories(data_dir);

boost::container::flat_set<std::string> seen;
std::ofstream out_cfg(config_ini_path.preferred_string());
for( const boost::shared_ptr<bpo::option_description> od : cfg_options.options() )
{
if( !od->description().empty() )
out_cfg << "# " << od->description() << "\n";
boost::any store;
if( !od->semantic()->apply_default(store) )
out_cfg << "# " << od->long_name() << " = \n";
else {
const std::string name = od->long_name();
if( seen.find(name) != seen.end() ) continue;
seen.insert(name);
auto example = od->format_parameter();
if( example.empty() )
// This is a boolean switch
out_cfg << od->long_name() << " = " << "false\n";
else {
// The string is formatted "arg (=<interesting part>)"
example.erase(0, 6);
example.erase(example.length()-1);
out_cfg << od->long_name() << " = " << example << "\n";
}
}
out_cfg << "\n";
}
write_default_logging_config_to_stream(out_cfg);
out_cfg.close();
// read the default logging config we just wrote out to the file and start using it
fc::optional<fc::logging_config> logging_config = load_logging_config_from_ini_file(config_ini_path);
if (logging_config)
fc::configure_logging(*logging_config);
}
if( !fc::exists(config_ini_path) )
create_new_config_file( config_ini_path, data_dir, cfg_options );
load_config_file( config_ini_path, cfg_options, options );

bpo::notify(options);
node->initialize(data_dir, options);
Expand Down