in src/runtime/service_api_c.cpp [380:580]
bool run(const char *config_file,
const char *config_arguments,
bool is_server,
std::string &app_list)
{
// We put the loading of configuration at the beginning of this func.
// Because in dsn_global_init(), it calls perf_counters::instance(), which calls
// shared_io_service::instance(). And in the cstor of shared_io_service, it calls
// dsn_config_get_value_uint64() to load the corresponding configs. That will make
// dsn_config_get_value_uint64() get wrong value if we put dsn_config_load at behind of
// dsn_global_init()
if (!dsn_config_load(config_file, config_arguments)) {
printf("Fail to load config file %s\n", config_file);
return false;
}
dsn::flags_initialize();
dsn_global_init();
dsn_core_init();
::dsn::task::set_tls_dsn_context(nullptr, nullptr);
dsn_all.engine_ready = false;
dsn_all.config_completed = false;
dsn_all.tool = nullptr;
dsn_all.engine = &::dsn::service_engine::instance();
dsn_all.magic = 0xdeadbeef;
// pause when necessary
if (FLAGS_pause_on_start) {
printf("\nPause for debugging (pid = %d)...\n", static_cast<int>(getpid()));
getchar();
}
for (int i = 0; i <= dsn::task_code::max(); i++) {
dsn_all.task_specs.push_back(::dsn::task_spec::get(i));
}
// initialize global specification from config file
::dsn::service_spec spec;
if (!spec.init()) {
printf("error in config file %s, exit ...\n", config_file);
return false;
}
dsn_all.config_completed = true;
// setup data dir
auto &data_dir = spec.data_dir;
CHECK(!dsn::utils::filesystem::file_exists(data_dir), "{} should not be a file.", data_dir);
if (!dsn::utils::filesystem::directory_exists(data_dir)) {
CHECK(dsn::utils::filesystem::create_directory(data_dir), "Fail to create {}", data_dir);
}
std::string cdir;
CHECK(dsn::utils::filesystem::get_absolute_path(data_dir, cdir),
"Fail to get absolute path from {}",
data_dir);
spec.data_dir = cdir;
::dsn::utils::coredump::init();
// setup log dir
spec.dir_log = ::dsn::utils::filesystem::path_combine(cdir, "log");
dsn::utils::filesystem::create_directory(spec.dir_log);
// init tools
dsn_all.tool.reset(::dsn::utils::factory_store<::dsn::tools::tool_app>::create(
spec.tool.c_str(), ::dsn::PROVIDER_TYPE_MAIN, spec.tool.c_str()));
dsn_all.tool->install(spec);
// init app specs
if (!spec.init_app_specs()) {
printf("error in config file %s, exit ...\n", config_file);
return false;
}
#ifdef DSN_ENABLE_GPERF
::MallocExtension::instance()->SetMemoryReleaseRate(FLAGS_tcmalloc_release_rate);
#endif
// init logging
dsn_log_init(spec.logging_factory_name, spec.dir_log, dsn_log_prefixed_message_func);
// prepare minimum necessary
::dsn::service_engine::instance().init_before_toollets(spec);
LOG_INFO("process({}) start: {}, date: {}",
getpid(),
dsn::utils::process_start_millis(),
dsn::utils::process_start_date_time_mills());
// init toollets
for (auto it = spec.toollets.begin(); it != spec.toollets.end(); ++it) {
auto tlet =
dsn::tools::internal_use_only::get_toollet(it->c_str(), ::dsn::PROVIDER_TYPE_MAIN);
CHECK_NOTNULL(tlet, "toolet not found");
tlet->install(spec);
}
// init provider specific system inits
dsn::tools::sys_init_before_app_created.execute();
// TODO: register sys_exit execution
// init runtime
::dsn::service_engine::instance().init_after_toollets();
dsn_all.engine_ready = true;
// init security if FLAGS_enable_auth == true
if (dsn::security::FLAGS_enable_auth) {
if (!dsn::security::init(is_server)) {
return false;
}
// if FLAGS_enable_auth is false but FLAGS_enable_zookeeper_kerberos, we should init
// kerberos for it separately
// include two steps:
// 1) apply kerberos ticket and keep it valid
// 2) complete sasl init for client(use FLAGS_sasl_plugin_path)
} else if (dsn::security::FLAGS_enable_zookeeper_kerberos && app_list == "meta") {
if (!dsn::security::init_for_zookeeper_client()) {
return false;
}
}
// split app_name and app_index
std::list<std::string> applistkvs;
::dsn::utils::split_args(app_list.c_str(), applistkvs, ';');
// init apps
for (auto &sp : spec.app_specs) {
if (!sp.run)
continue;
bool create_it = false;
// create all apps
if (app_list == "") {
create_it = true;
} else {
for (auto &kv : applistkvs) {
std::list<std::string> argskvs;
::dsn::utils::split_args(kv.c_str(), argskvs, '@');
if (std::string("apps.") + argskvs.front() == sp.config_section) {
if (argskvs.size() < 2)
create_it = true;
else
create_it = (std::stoi(argskvs.back()) == sp.index);
break;
}
}
}
if (create_it) {
::dsn::service_engine::instance().start_node(sp);
}
}
if (dsn::service_engine::instance().get_all_nodes().size() == 0) {
printf("no app are created, usually because \n"
"app_name is not specified correctly, should be 'xxx' in [apps.xxx]\n"
"or app_index (1-based) is greater than specified count in config file\n");
exit(1);
}
dump_log_cmd =
dsn::command_manager::instance().register_command({"config-dump"},
"config-dump - dump configuration",
"config-dump [to-this-config-file]",
[](const std::vector<std::string> &args) {
std::ostringstream oss;
std::ofstream off;
std::ostream *os = &oss;
if (args.size() > 0) {
off.open(args[0]);
os = &off;
oss << "config dump to file "
<< args[0] << std::endl;
}
dsn_config_dump(*os);
return oss.str();
});
// invoke customized init after apps are created
dsn::tools::sys_init_after_app_created.execute();
// start the tool
dsn_all.tool->run();
if (is_server) {
while (true) {
std::this_thread::sleep_for(std::chrono::hours(1));
}
}
// add this to allow mimic app call from this thread.
memset((void *)&dsn::tls_dsn, 0, sizeof(dsn::tls_dsn));
return true;
}