Пример #1
0
int Config::initialize(int argc, char* argv[])
{
    Config* c = Config::getInstance();

    std::vector< std::string > nodes;
    std::vector< std::string > hostnames;
    std::vector< std::string > box_strings;
    std::string                configfile;
    std::string                keystore_file;
    std::string                private_key_file;

    // parsing program options using boost::program_options
    namespace po = boost::program_options;

    po::options_description cmdline_options("Generic options");
    cmdline_options.add_options()
        ("help,h", "Produce this help message")
        ("config,c", po::value<std::string>(&configfile),
            "Use supplied config file instead of default one")
        ("keystore", po::value<std::string>(&keystore_file),
            "Use supplied keystore file instead of default one")
        ("privatekey", po::value<std::string>(&private_key_file),
            "Use supplied privatekey file instead of default one")
        ("create-private-key", "Create new keypair for hostnames")
    ;

    po::options_description generic_options("Allowed options");
    generic_options.add_options()
        ("node,n", po::value<std::vector< std::string >>(&nodes), 
            "Add node location to listen to (multiple arguments allowed)")
        ("box,b", po::value<std::vector <std::string> >(&box_strings), 
            "Add path of a directory to watch (multiple arguments allowed)")
        ("hostname,p", po::value<std::vector <std::string> >(&hostnames),
            "Add a name for this machine under which other nodes can reach it (multiple arguments allowed)")
    ;

    po::options_description options;
    options.add(cmdline_options).add(generic_options);


    // BUG we cannot ADD nodes/boxes through the cli,
    //     it takes either the config file or the command line...
    // parse command line arguments
    po::store(po::parse_command_line( argc, argv, options ), c->vm_);
    po::notify(c->vm_);

    // parse config file, if any
    wordexp_t expanded_config_file_path;
    if (configfile.empty()) {
        wordexp( F_CONFIG_FILE, &expanded_config_file_path, 0 );
    } else {
        wordexp( configfile.c_str(), &expanded_config_file_path, 0 );
    }
    std::ifstream ifs( expanded_config_file_path.we_wordv[0] );
    wordfree(&expanded_config_file_path);
    if ( !ifs ) {
        if (F_MSG_DEBUG) printf("config: no config file found\n");
    } else {
        po::store(po::parse_config_file(ifs, generic_options), c->vm_);
        po::notify(c->vm_);
        ifs.close();
    }

    // parse keystore file
    wordexp_t expanded_keystore_file_path;
    if (keystore_file.empty()) {
        wordexp( F_KEYSTORE_FILE, &expanded_keystore_file_path, 0 );
    } else {
        wordexp( keystore_file.c_str(), &expanded_keystore_file_path, 0 );
    }
    keystore_file = expanded_keystore_file_path.we_wordv[0];
    wordfree(&expanded_keystore_file_path);

    // parse privatekey file
    wordexp_t expanded_privatekey_file_path;
    if (private_key_file.empty()) {
        wordexp( F_PRIVATEKEY_FILE, &expanded_privatekey_file_path, 0 );
    } else {
        wordexp( private_key_file.c_str(), &expanded_privatekey_file_path, 0 );
    }
    private_key_file = expanded_privatekey_file_path.we_wordv[0];
    wordfree(&expanded_privatekey_file_path);

    int return_val;
    return_val = c->doSanityCheck( &options, &nodes, &hostnames, &box_strings );
    if ( return_val != 0 ) return return_val;
    return_val = c->synchronizeKeystore( &keystore_file, &private_key_file );
    return return_val;
}
return_code
ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config)
{
    // declare a group of options that will be allowed only on command line
    boost::program_options::options_description generic_options("Options");
    generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
        "config,c", boost::program_options::value<boost::filesystem::path>(
                        &extractor_config.config_file_path)->default_value("extractor.ini"),
        "Path to a configuration file.");

    // declare a group of options that will be allowed both on command line and in config file
    boost::program_options::options_description config_options("Configuration");
    config_options.add_options()("profile,p",
                                 boost::program_options::value<boost::filesystem::path>(
                                     &extractor_config.profile_path)->default_value("profile.lua"),
                                 "Path to LUA routing profile")(
        "threads,t",
        boost::program_options::value<unsigned int>(&extractor_config.requested_num_threads)
            ->default_value(tbb::task_scheduler_init::default_num_threads()),
        "Number of threads to use");

    // hidden options, will be allowed both on command line and in config file, but will not be
    // shown to the user
    boost::program_options::options_description hidden_options("Hidden options");
    hidden_options.add_options()("input,i", boost::program_options::value<boost::filesystem::path>(
                                                &extractor_config.input_path),
                                 "Input file in .osm, .osm.bz2 or .osm.pbf format");

    // positional option
    boost::program_options::positional_options_description positional_options;
    positional_options.add("input", 1);

    // combine above options for parsing
    boost::program_options::options_description cmdline_options;
    cmdline_options.add(generic_options).add(config_options).add(hidden_options);

    boost::program_options::options_description config_file_options;
    config_file_options.add(config_options).add(hidden_options);

    boost::program_options::options_description visible_options(
        boost::filesystem::basename(argv[0]) + " <input.osm/.osm.bz2/.osm.pbf> [options]");
    visible_options.add(generic_options).add(config_options);

    // parse command line options
    try
    {
        boost::program_options::variables_map option_variables;
        boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
                                          .options(cmdline_options)
                                          .positional(positional_options)
                                          .run(),
                                      option_variables);
        if (option_variables.count("version"))
        {
            SimpleLogger().Write() << g_GIT_DESCRIPTION;
            return return_code::exit;
        }

        if (option_variables.count("help"))
        {
            SimpleLogger().Write() << visible_options;
            return return_code::exit;
        }

        boost::program_options::notify(option_variables);

        // parse config file
        if (boost::filesystem::is_regular_file(extractor_config.config_file_path))
        {
            SimpleLogger().Write()
                << "Reading options from: " << extractor_config.config_file_path.string();
            std::string ini_file_contents =
                read_file_lower_content(extractor_config.config_file_path);
            std::stringstream config_stream(ini_file_contents);
            boost::program_options::store(parse_config_file(config_stream, config_file_options),
                                          option_variables);
            boost::program_options::notify(option_variables);
        }

        if (!option_variables.count("input"))
        {
            SimpleLogger().Write() << visible_options;
            return return_code::exit;
        }
    }
    catch (std::exception &e)
    {
        SimpleLogger().Write(logWARNING) << e.what();
        return return_code::fail;
    }

    return return_code::ok;
}
Пример #3
0
bool Config::init_with_args(int ac, char** av, const std::vector<std::string>& customized, WorkerInfo* worker_info) {
    namespace po = boost::program_options;

    po::options_description generic_options("Generic options");
    generic_options.add_options()("help,H", "print help message");

    std::string config_file_path;
    po::options_description config_file_options("Configuration File");
    config_file_options.add_options()("conf,C", po::value<std::string>(&config_file_path), "Configure file Path");

    std::string master_host;
    int master_port;
    int comm_port;
    std::string log_dir;
    po::options_description required_options("Required options");
    required_options.add_options()("master_host", po::value<std::string>(&master_host), "Master hostname")(
        "master_port", po::value<int>(&master_port), "Master port")(
        "comm_port", po::value<int>(&comm_port), "Communication port")("log_dir", po::value<std::string>(&log_dir),
                                                                       "Log directory");

    po::options_description worker_info_options("Worker Info options");
    worker_info_options.add_options()("worker.info", po::value<std::vector<std::string>>()->multitoken(),
                                      "Worker information.\nFormat is '%worker_hostname:%thread_number'.\nUse "
                                      "colon ':' as separator.");

    po::options_description worker_info_config("Worker Info from config");
    worker_info_config.add_options()("worker.info", po::value<std::vector<std::string>>()->multitoken(),
                                     "Worker information.\nFormat is '%worker_hostname:%thread_number'.\nUse "
                                     "colon ':' as separator.");

    po::options_description customized_options("Customized options");
    if (!customized.empty())
        for (auto& arg : customized)
            customized_options.add_options()(arg.c_str(), po::value<std::string>(), "");

    po::options_description cmdline_options;
    cmdline_options.add(generic_options).add(config_file_options).add(required_options).add(worker_info_options);
    po::options_description config_options;
    config_options.add(required_options).add(worker_info_config);
    if (!customized_options.options().empty()) {
        cmdline_options.add(customized_options);
        config_options.add(customized_options);
    }

    po::variables_map vm;
    po::store(po::command_line_parser(ac, av).options(cmdline_options).run(), vm);
    po::notify(vm);

    if (ac == 1 || vm.count("help")) {
        std::cout << "Usage:" << std::endl;
        std::cout << cmdline_options << std::endl;
        return false;
    }

    if (vm.count("conf")) {
        std::ifstream config_file(config_file_path.c_str());
        if (!config_file) {
            LOG_E << "Can not open config file: " << config_file_path;
            return false;
        }
        // The configure in config_file would be overwritten by cmdline as parsing order.
        // For details, the interface is:
        //     parse_config_file(const char * filename, const options_description &,
        //                       bool allow_unregistered = false)
        auto parsed_config_options = po::parse_config_file(config_file, config_options, true);
        po::store(parsed_config_options, vm);
        po::notify(vm);

        // Store what is not registered in customized_options.
        for (const auto& o : parsed_config_options.options)
            if (vm.find(o.string_key) == vm.end())
                set_param(o.string_key, o.value.front());  // Only accept `key=value`.
    }

    int setup_all = 0;

    if (vm.count("master_host")) {
        set_master_host(master_host);
        setup_all += 1;
    } else {
        LOG_E << "arg master_host is needed";
    }

    if (vm.count("master_port")) {
        set_master_port(master_port);
        setup_all += 1;
    } else {
        LOG_E << "arg master_port is needed";
    }

    if (vm.count("comm_port")) {
        set_comm_port(comm_port);
        setup_all += 1;
    } else {
        LOG_E << "arg comm_port is needed";
    }

    if (vm.count("log_dir"))
        set_log_dir(log_dir);

    if (vm.count("worker.info")) {
        std::string hostname = get_hostname();
        int proc_id = -1;
        int num_workers = 0;
        int num_local_threads = 0;
        int num_global_threads = 0;
        std::vector<std::string> workers_info = vm["worker.info"].as<std::vector<std::string>>();
        for (auto& w : workers_info) {
            std::size_t colon_pos = w.find(':');
            if (colon_pos == std::string::npos || colon_pos == w.size() - 1) {
                // Cannot find colon ':' or lack number of threads.
                LOG_E << "arg worker.info '" + w + "' not match the format";
                return false;
            }
            std::string worker_hostname = w.substr(0, colon_pos);
            machines_.insert(worker_hostname);
            int num_threads = std::stoi(w.substr(colon_pos + 1, w.size() - colon_pos - 1));
            if (is_local(worker_hostname)) {
                num_local_threads = num_threads;
                proc_id = num_workers;
            }
            if (worker_info != nullptr)
                worker_info->set_hostname(num_workers, worker_hostname);
            for (int i = 0; i < num_threads; i++) {
                if (worker_info != nullptr)
                    worker_info->add_worker(num_workers, num_global_threads, i);
                ++num_global_threads;
            }
            num_workers += 1;
        }
        if (worker_info != nullptr)
            worker_info->set_process_id(proc_id);
        set_param("hostname", hostname);
        setup_all += 1;
    } else {
        LOG_E << "arg worker.info is needed";
    }

    if (!customized.empty()) {
        for (auto& arg : customized)
            if (vm.count(arg.c_str())) {
                set_param(arg, vm[arg.c_str()].as<std::string>());
                setup_all += 1;
            } else {
                LOG_E << "arg " << arg << " is needed";
            }
    }

    if (setup_all != customized.size() + 4) {
        LOG_E << "Please provide all necessary args!";
        return false;
    }

    return true;
}
return_code
ContractorOptions::ParseArguments(int argc, char *argv[], ContractorConfig &contractor_config)
{
    // declare a group of options that will be allowed only on command line
    boost::program_options::options_description generic_options("Options");
    generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
        "config,c", boost::program_options::value<boost::filesystem::path>(&contractor_config.config_file_path)
                        ->default_value("contractor.ini"),
        "Path to a configuration file.");

    // declare a group of options that will be allowed both on command line and in config file
    boost::program_options::options_description config_options("Configuration");
    config_options.add_options()(
        "restrictions,r",
        boost::program_options::value<boost::filesystem::path>(&contractor_config.restrictions_path),
        "Restrictions file in .osrm.restrictions format")(
        "profile,p", boost::program_options::value<boost::filesystem::path>(&contractor_config.profile_path)
                         ->default_value("profile.lua"),
        "Path to LUA routing profile")(
        "threads,t", boost::program_options::value<unsigned int>(&contractor_config.requested_num_threads)
                         ->default_value(tbb::task_scheduler_init::default_num_threads()),
        "Number of threads to use");

    // hidden options, will be allowed both on command line and in config file, but will not be
    // shown to the user
    boost::program_options::options_description hidden_options("Hidden options");
    hidden_options.add_options()(
        "input,i", boost::program_options::value<boost::filesystem::path>(&contractor_config.osrm_input_path),
        "Input file in .osm, .osm.bz2 or .osm.pbf format");

    // positional option
    boost::program_options::positional_options_description positional_options;
    positional_options.add("input", 1);

    // combine above options for parsing
    boost::program_options::options_description cmdline_options;
    cmdline_options.add(generic_options).add(config_options).add(hidden_options);

    boost::program_options::options_description config_file_options;
    config_file_options.add(config_options).add(hidden_options);

    boost::program_options::options_description visible_options(
        "Usage: " + boost::filesystem::basename(argv[0]) + " <input.osrm> [options]");
    visible_options.add(generic_options).add(config_options);

    // parse command line options
    boost::program_options::variables_map option_variables;
    boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
                                      .options(cmdline_options)
                                      .positional(positional_options)
                                      .run(),
                                  option_variables);

    const auto &temp_config_path = option_variables["config"].as<boost::filesystem::path>();
    if (boost::filesystem::is_regular_file(temp_config_path))
    {
        boost::program_options::store(boost::program_options::parse_config_file<char>(
                                          temp_config_path.string().c_str(), cmdline_options, true),
                                      option_variables);
    }

    if (option_variables.count("version"))
    {
        SimpleLogger().Write() << g_GIT_DESCRIPTION;
        return return_code::exit;
    }

    if (option_variables.count("help"))
    {
        SimpleLogger().Write() << "\n" << visible_options;
        return return_code::exit;
    }

    boost::program_options::notify(option_variables);

    if (!option_variables.count("restrictions"))
    {
        contractor_config.restrictions_path = contractor_config.osrm_input_path.string() + ".restrictions";
    }

    if (!option_variables.count("input"))
    {
        SimpleLogger().Write() << "\n" << visible_options;
        return return_code::fail;
    }

    return return_code::ok;
}
Пример #5
0
bool parse_options(fscp::logger& logger, int argc, char** argv, cli_configuration& configuration)
{
	namespace po = boost::program_options;

	po::options_description visible_options;
	po::options_description all_options;

	po::options_description generic_options("Generic options");
	generic_options.add_options()
	("help,h", "Produce help message.")
	("version,v", "Get the program version.")
	("debug,d", "Enables debug output.")
	("threads,t", po::value<unsigned int>(&configuration.thread_count)->default_value(0), "The number of threads to use.")
	("configuration_file,c", po::value<std::string>(), "The configuration file to use.")
	;

	visible_options.add(generic_options);
	all_options.add(generic_options);

	po::options_description configuration_options("Configuration");
	configuration_options.add(get_server_options());
	configuration_options.add(get_client_options());
	configuration_options.add(get_fscp_options());
	configuration_options.add(get_security_options());
	configuration_options.add(get_tap_adapter_options());
	configuration_options.add(get_switch_options());
	configuration_options.add(get_router_options());

	visible_options.add(configuration_options);
	all_options.add(configuration_options);

#ifdef WINDOWS
	po::options_description service_options("Service");
	service_options.add_options()
	("install", "Install the service.")
	("uninstall", "Uninstall the service.")
	("reinstall", "Reinstall the service.")
	;

	visible_options.add(service_options);
	all_options.add(service_options);
#else
	po::options_description daemon_options("Daemon");
	daemon_options.add_options()
	("foreground,f", "Do not run as a daemon.")
	("pid_file,p", po::value<std::string>(), "A pid file to use.")
	;

	visible_options.add(daemon_options);
	all_options.add(daemon_options);

	po::options_description misc_options("Miscellaneous");
	misc_options.add_options()
	("nocolor", "Disable color output.")
	;

	visible_options.add(misc_options);
	all_options.add(misc_options);
#endif

	po::variables_map vm;
	po::store(po::parse_command_line(argc, argv, all_options), vm);
	make_paths_absolute(vm, fs::current_path());

	if (vm.count("help"))
	{
		std::cout << visible_options << std::endl;

		return false;
	}

	if (vm.count("version"))
	{
		std::cout << FREELAN_NAME << " " << FREELAN_VERSION_STRING << " " << FREELAN_DATE << std::endl;

		return false;
	}

#ifdef WINDOWS
	if (vm.count("install"))
	{
		if (vm.count("uninstall"))
		{
			throw std::runtime_error("Cannot specify both --install and --uninstall options. Use --reinstall instead.");
		}
		else
		{
			if (windows::install_service())
			{
				logger(fscp::log_level::important) << "Service installed.";
			}
			else
			{
				logger(fscp::log_level::error) << "The service was already installed.";
			}

			return false;
		}
	}
	else if (vm.count("uninstall"))
	{
		if (windows::uninstall_service())
		{
			logger(fscp::log_level::important) << "Service uninstalled.";
		}
		else
		{
			logger(fscp::log_level::error) << "The service has already been deleted.";
		}

		return false;
	}
	else if (vm.count("reinstall"))
	{
		if (windows::uninstall_service())
		{
			logger(fscp::log_level::important) << "Service uninstalled.";
		}
		else
		{
			logger(fscp::log_level::error) << "The service has already been deleted.";
		}

		if (windows::install_service())
		{
			logger(fscp::log_level::important) << "Service installed.";
		}
		else
		{
			logger(fscp::log_level::error) << "The service was already installed.";
		}

		return false;
	}
#else
	configuration.foreground = (vm.count("foreground") > 0);

	if (vm.count("nocolor") > 0)
	{
		// This is a global variable. Not really nice but does its job in this case.
		DISABLE_COLOR = true;
	}

	if (vm.count("pid_file"))
	{
		configuration.pid_file = fs::absolute(vm["pid_file"].as<std::string>());
	}
	else
	{
		char* val = getenv("FREELAN_PID_FILE");

		if (val)
		{
			configuration.pid_file = fs::absolute(std::string(val));
		}
	}
#endif

	fs::path configuration_file;

	if (vm.count("configuration_file"))
	{
		configuration_file = fs::absolute(vm["configuration_file"].as<std::string>());
	}
	else
	{
#ifdef _MSC_VER
#ifdef UNICODE
		std::wstring value(4096, L'\0');

		const DWORD value_size = GetEnvironmentVariable(L"FREELAN_CONFIGURATION_FILE", &value[0], static_cast<DWORD>(value.size()));
#else
		std::string value(4096, '\0');

		const DWORD value_size = GetEnvironmentVariable("FREELAN_CONFIGURATION_FILE", &value[0], static_cast<DWORD>(value.size()));
#endif

		if (value_size > 0)
		{
			value.resize(value_size);

			configuration_file = fs::absolute(value);
		}
#else
		const char* val = getenv("FREELAN_CONFIGURATION_FILE");

		if (val)
		{
			configuration_file = fs::absolute(std::string(val));
		}
#endif
	}

	if (!configuration_file.empty())
	{
		logger(fscp::log_level::information) << "Reading configuration file at: " << configuration_file;

		fs::basic_ifstream<char> ifs(configuration_file);

		if (!ifs)
		{
			throw po::reading_file(configuration_file.string().c_str());
		}

		po::store(po::parse_config_file(ifs, configuration_options, true), vm);
	}
	else
	{
		bool configuration_read = false;

		const std::vector<fs::path> configuration_files = get_configuration_files();

		BOOST_FOREACH(const fs::path& conf, configuration_files)
		{
			fs::basic_ifstream<char> ifs(conf);

			if (ifs)
			{
				logger(fscp::log_level::information) << "Reading configuration file at: " << conf << std::endl;

				po::store(po::parse_config_file(ifs, configuration_options, true), vm);

				configuration_file = fs::absolute(conf);

				configuration_read = true;

				break;
			}
		}

		if (!configuration_read)
		{
			logger(fscp::log_level::warning) << "Warning ! No configuration file specified and none found in the environment.";
			logger(fscp::log_level::warning) << "Looked up locations were:";

			for (auto&& conf : configuration_files)
			{
				logger(fscp::log_level::warning) << "- "  << conf;
			}
		}
	}
Пример #6
0
int main (int argc, char *argv[]) {
    try {
        LogPolicy::GetInstance().Unmute();
        double startup_time = get_timestamp();

        boost::filesystem::path config_file_path, input_path, profile_path;
        int requested_num_threads;

        // declare a group of options that will be allowed only on command line
        boost::program_options::options_description generic_options("Options");
        generic_options.add_options()
            ("version,v", "Show version")
            ("help,h", "Show this help message")
            ("config,c", boost::program_options::value<boost::filesystem::path>(&config_file_path)->default_value("extractor.ini"),
                  "Path to a configuration file.");

        // declare a group of options that will be allowed both on command line and in config file
        boost::program_options::options_description config_options("Configuration");
        config_options.add_options()
            ("profile,p", boost::program_options::value<boost::filesystem::path>(&profile_path)->default_value("profile.lua"),
                "Path to LUA routing profile")
            ("threads,t", boost::program_options::value<int>(&requested_num_threads)->default_value(8),
                "Number of threads to use");

        // hidden options, will be allowed both on command line and in config file, but will not be shown to the user
        boost::program_options::options_description hidden_options("Hidden options");
        hidden_options.add_options()
            ("input,i", boost::program_options::value<boost::filesystem::path>(&input_path),
                "Input file in .osm, .osm.bz2 or .osm.pbf format");

        // positional option
        boost::program_options::positional_options_description positional_options;
        positional_options.add("input", 1);

        // combine above options for parsing
        boost::program_options::options_description cmdline_options;
        cmdline_options.add(generic_options).add(config_options).add(hidden_options);

        boost::program_options::options_description config_file_options;
        config_file_options.add(config_options).add(hidden_options);

        boost::program_options::options_description visible_options(boost::filesystem::basename(argv[0]) + " <input.osm/.osm.bz2/.osm.pbf> [options]");
        visible_options.add(generic_options).add(config_options);

        // parse command line options
        boost::program_options::variables_map option_variables;
        boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
            options(cmdline_options).positional(positional_options).run(), option_variables);

        if(option_variables.count("version")) {
            SimpleLogger().Write() << g_GIT_DESCRIPTION;
            return 0;
        }

        if(option_variables.count("help")) {
            SimpleLogger().Write() << visible_options;
            return 0;
        }

        boost::program_options::notify(option_variables);

        // parse config file
        if(boost::filesystem::is_regular_file(config_file_path)) {
            SimpleLogger().Write() << "Reading options from: " << config_file_path.c_str();
            std::string config_str;
            PrepareConfigFile( config_file_path.c_str(), config_str );
            std::stringstream config_stream( config_str );
            boost::program_options::store(parse_config_file(config_stream, config_file_options), option_variables);
            boost::program_options::notify(option_variables);
        }

        if(!option_variables.count("input")) {
            SimpleLogger().Write(logWARNING) << "No input file specified";
            SimpleLogger().Write() << visible_options;
            return -1;
        }

        if(1 > requested_num_threads) {
            SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
            return -1;
        }

        SimpleLogger().Write() << "Input file: " << input_path.filename().string();
        SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
        SimpleLogger().Write() << "Threads: " << requested_num_threads;

        /*** Setup Scripting Environment ***/
        ScriptingEnvironment scriptingEnvironment(profile_path.c_str());

        omp_set_num_threads( std::min( omp_get_num_procs(), requested_num_threads) );

        bool file_has_pbf_format(false);
        std::string output_file_name(input_path.c_str());
        std::string restrictionsFileName(input_path.c_str());
        std::string::size_type pos = output_file_name.find(".osm.bz2");
        if(pos==std::string::npos) {
            pos = output_file_name.find(".osm.pbf");
            if(pos!=std::string::npos) {
                file_has_pbf_format = true;
            }
        }
        if(pos==std::string::npos) {
            pos = output_file_name.find(".pbf");
            if(pos!=std::string::npos) {
                file_has_pbf_format = true;
            }
        }
        if(pos!=std::string::npos) {
            output_file_name.replace(pos, 8, ".osrm");
            restrictionsFileName.replace(pos, 8, ".osrm.restrictions");
        } else {
            pos=output_file_name.find(".osm");
            if(pos!=std::string::npos) {
                output_file_name.replace(pos, 5, ".osrm");
                restrictionsFileName.replace(pos, 5, ".osrm.restrictions");
            } else {
                output_file_name.append(".osrm");
                restrictionsFileName.append(".osrm.restrictions");
            }
        }

        StringMap stringMap;
        ExtractionContainers externalMemory;

        stringMap[""] = 0;
        extractCallBacks = new ExtractorCallbacks(&externalMemory, &stringMap);
        BaseParser* parser;
        if(file_has_pbf_format) {
            parser = new PBFParser(input_path.c_str(), extractCallBacks, scriptingEnvironment);
        } else {
            parser = new XMLParser(input_path.c_str(), extractCallBacks, scriptingEnvironment);
        }

        if(!parser->ReadHeader()) {
            throw OSRMException("Parser not initialized!");
        }
        SimpleLogger().Write() << "Parsing in progress..";
        double parsing_start_time = get_timestamp();
        parser->Parse();
        SimpleLogger().Write() << "Parsing finished after " <<
            (get_timestamp() - parsing_start_time) <<
            " seconds";

        if( externalMemory.all_edges_list.empty() ) {
            SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
            return -1;
        }

        externalMemory.PrepareData(output_file_name, restrictionsFileName);

        delete parser;
        delete extractCallBacks;

        SimpleLogger().Write() <<
            "extraction finished after " << get_timestamp() - startup_time <<
            "s";

         SimpleLogger().Write() << "To prepare the data for routing, run: "
            << "./osrm-prepare " << output_file_name << std::endl;

    } catch(boost::program_options::too_many_positional_options_error& e) {
        SimpleLogger().Write(logWARNING) << "Only one input file can be specified";
        return -1;
    } catch(boost::program_options::error& e) {
        SimpleLogger().Write(logWARNING) << e.what();
        return -1;
    } catch(std::exception & e) {
        SimpleLogger().Write(logWARNING) << "Unhandled exception: " << e.what();
        return -1;
    }
    return 0;
}
Пример #7
0
bool parse_options(int argc, char** argv, cli_configuration& configuration)
{
	namespace po = boost::program_options;

	po::options_description visible_options;
	po::options_description all_options;

	po::options_description generic_options("Generic options");
	generic_options.add_options()
	("help,h", "Produce help message.")
	("debug,d", "Enables debug output.")
	("configuration_file,c", po::value<std::string>(), "The configuration file to use")
	;

	visible_options.add(generic_options);
	all_options.add(generic_options);

	po::options_description configuration_options("Configuration");
	configuration_options.add(get_server_options());
	configuration_options.add(get_fscp_options());
	configuration_options.add(get_security_options());
	configuration_options.add(get_tap_adapter_options());
	configuration_options.add(get_switch_options());

	visible_options.add(configuration_options);
	all_options.add(configuration_options);

#ifdef WINDOWS
	po::options_description service_options("Service");
	service_options.add_options()
	("install", "Install the service.")
	("uninstall", "Uninstall the service.")
	("reinstall", "Reinstall the service.")
	;

	visible_options.add(service_options);
	all_options.add(service_options);
#else
	po::options_description daemon_options("Daemon");
	daemon_options.add_options()
	("foreground,f", "Do not run as a daemon.")
	("pid_file,p", po::value<std::string>(), "A pid file to use.")
	;

	visible_options.add(daemon_options);
	all_options.add(daemon_options);
#endif

	po::variables_map vm;
	po::store(po::parse_command_line(argc, argv, all_options), vm);

	if (vm.count("help"))
	{
		std::cout << visible_options << std::endl;

		return false;
	}

#ifdef WINDOWS
	if (vm.count("install"))
	{
		if (vm.count("uninstall"))
		{
			throw std::runtime_error("Cannot specify both --install and --uninstall options. Use --reinstall instead.");
		}
		else
		{
			if (win32::install_service())
			{
				std::cout << "Service installed." << std::endl;
			}
			else
			{
				std::cerr << "The service was already installed." << std::endl;
			}

			return false;
		}
	}
	else if (vm.count("uninstall"))
	{
		if (win32::uninstall_service())
		{
			std::cout << "Service uninstalled." << std::endl;
		}
		else
		{
			std::cerr << "The service has already been deleted." << std::endl;
		}

		return false;
	}
	else if (vm.count("reinstall"))
	{
		if (win32::uninstall_service())
		{
			std::cout << "Service uninstalled." << std::endl;
		}
		else
		{
			std::cerr << "The service has already been deleted." << std::endl;
		}

		if (win32::install_service())
		{
			std::cout << "Service installed." << std::endl;
		}
		else
		{
			std::cerr << "The service was already installed." << std::endl;
		}

		return false;
	}
#else
	configuration.foreground = (vm.count("foreground") > 0);

	if (vm.count("pid_file"))
	{
		configuration.pid_file = fs::absolute(vm["pid_file"].as<std::string>());
	}
	else
	{
		char* val = getenv("FREELAN_PID_FILE");

		if (val)
		{
			configuration.pid_file = fs::absolute(std::string(val));
		}
	}
#endif

	fs::path configuration_file;

	if (vm.count("configuration_file"))
	{
		configuration_file = fs::absolute(vm["configuration_file"].as<std::string>());
	}
	else
	{
		char* val = getenv("FREELAN_CONFIGURATION_FILE");

		if (val)
		{
			configuration_file = fs::absolute(std::string(val));
		}
	}

	if (!configuration_file.empty())
	{
		std::cout << "Reading configuration file at: " << configuration_file << std::endl;

		fs::basic_ifstream<char> ifs(configuration_file);

		if (!ifs)
		{
			throw po::reading_file(configuration_file.string().c_str());
		}

		po::store(po::parse_config_file(ifs, configuration_options, true), vm);
	}
	else
	{
		bool configuration_read = false;

		const std::vector<fs::path> configuration_files = get_configuration_files();

		BOOST_FOREACH(const fs::path& conf, configuration_files)
		{
			fs::basic_ifstream<char> ifs(conf);

			if (ifs)
			{
				std::cout << "Reading configuration file at: " << conf << std::endl;

				po::store(po::parse_config_file(ifs, configuration_options, true), vm);

				configuration_file = fs::absolute(conf);

				break;
			}
		}

		if (!configuration_read)
		{
			std::cerr << "Warning ! No configuration file specified and none found in the environment." << std::endl;
			std::cerr << "Looked up locations were:" << std::endl;

			BOOST_FOREACH(const fs::path& conf, configuration_files)
			{
				std::cerr << "- " << conf << std::endl;
			}
Пример #8
0
int main(int argc, char *argv[])
{
    try
    {
        LogPolicy::GetInstance().Unmute();
        std::chrono::time_point<std::chrono::steady_clock> startup_time =
            std::chrono::steady_clock::now();

        boost::filesystem::path config_file_path, input_path, restrictions_path, profile_path;
        int requested_num_threads;

        // declare a group of options that will be allowed only on command line
        boost::program_options::options_description generic_options("Options");
        generic_options.add_options()("version,v", "Show version")("help,h",
                                                                   "Show this help message")(
            "config,c",
            boost::program_options::value<boost::filesystem::path>(&config_file_path)
                ->default_value("contractor.ini"),
            "Path to a configuration file.");

        // declare a group of options that will be allowed both on command line and in config file
        boost::program_options::options_description config_options("Configuration");
        config_options.add_options()(
            "restrictions,r",
            boost::program_options::value<boost::filesystem::path>(&restrictions_path),
            "Restrictions file in .osrm.restrictions format")(
            "profile,p",
            boost::program_options::value<boost::filesystem::path>(&profile_path)
                ->default_value("profile.lua"),
            "Path to LUA routing profile")(
            "threads,t",
            boost::program_options::value<int>(&requested_num_threads)->default_value(8),
            "Number of threads to use");

        // hidden options, will be allowed both on command line and in config file, but will not be
        // shown to the user
        boost::program_options::options_description hidden_options("Hidden options");
        hidden_options.add_options()(
            "input,i",
            boost::program_options::value<boost::filesystem::path>(&input_path),
            "Input file in .osm, .osm.bz2 or .osm.pbf format");

        // positional option
        boost::program_options::positional_options_description positional_options;
        positional_options.add("input", 1);

        // combine above options for parsing
        boost::program_options::options_description cmdline_options;
        cmdline_options.add(generic_options).add(config_options).add(hidden_options);

        boost::program_options::options_description config_file_options;
        config_file_options.add(config_options).add(hidden_options);

        boost::program_options::options_description visible_options(
            "Usage: " + boost::filesystem::basename(argv[0]) + " <input.osrm> [options]");
        visible_options.add(generic_options).add(config_options);

        // parse command line options
        boost::program_options::variables_map option_variables;
        boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
                                          .options(cmdline_options)
                                          .positional(positional_options)
                                          .run(),
                                      option_variables);

        if (option_variables.count("version"))
        {
            SimpleLogger().Write() << g_GIT_DESCRIPTION;
            return 0;
        }

        if (option_variables.count("help"))
        {
            SimpleLogger().Write() << "\n" << visible_options;
            return 0;
        }

        boost::program_options::notify(option_variables);

        if (!option_variables.count("restrictions"))
        {
            restrictions_path = std::string(input_path.string() + ".restrictions");
        }

        if (!option_variables.count("input"))
        {
            SimpleLogger().Write() << "\n" << visible_options;
            return 0;
        }

        if (!boost::filesystem::is_regular_file(input_path))
        {
            SimpleLogger().Write(logWARNING) << "Input file " << input_path.string()
                                             << " not found!";
            return 1;
        }

        if (!boost::filesystem::is_regular_file(profile_path))
        {
            SimpleLogger().Write(logWARNING) << "Profile " << profile_path.string()
                                             << " not found!";
            return 1;
        }

        if (1 > requested_num_threads)
        {
            SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
            return 1;
        }

        int real_num_threads = std::min(omp_get_num_procs(), requested_num_threads);

        SimpleLogger().Write() << "Input file: " << input_path.filename().string();
        SimpleLogger().Write() << "Restrictions file: " << restrictions_path.filename().string();
        SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
        SimpleLogger().Write() << "Threads: " << real_num_threads << " (requested "
                               << requested_num_threads << ")";

        omp_set_num_threads(real_num_threads);
        LogPolicy::GetInstance().Unmute();
        boost::filesystem::ifstream restriction_stream(restrictions_path, std::ios::binary);
        TurnRestriction restriction;
        UUID uuid_loaded, uuid_orig;
        unsigned number_of_usable_restrictions = 0;
        restriction_stream.read((char *)&uuid_loaded, sizeof(UUID));
        if (!uuid_loaded.TestPrepare(uuid_orig))
        {
            SimpleLogger().Write(logWARNING) << ".restrictions was prepared with different build.\n"
                                                "Reprocess to get rid of this warning.";
        }

        restriction_stream.read((char *)&number_of_usable_restrictions, sizeof(unsigned));
        restriction_list.resize(number_of_usable_restrictions);
        restriction_stream.read((char *)&(restriction_list[0]),
                                number_of_usable_restrictions * sizeof(TurnRestriction));
        restriction_stream.close();

        boost::filesystem::ifstream in;
        in.open(input_path, std::ios::in | std::ios::binary);

        const std::string node_filename = input_path.string() + ".nodes";
        const std::string edge_out = input_path.string() + ".edges";
        const std::string geometry_filename = input_path.string() + ".geometry";
        const std::string graphOut = input_path.string() + ".hsgr";
        const std::string rtree_nodes_path = input_path.string() + ".ramIndex";
        const std::string rtree_leafs_path = input_path.string() + ".fileIndex";

        /*** Setup Scripting Environment ***/

        // Create a new lua state
        lua_State *lua_state = luaL_newstate();

        // Connect LuaBind to this lua state
        luabind::open(lua_state);

        // open utility libraries string library;
        luaL_openlibs(lua_state);

        // adjust lua load path
        luaAddScriptFolderToLoadPath(lua_state, profile_path.c_str());

        // Now call our function in a lua script
        if (0 != luaL_dofile(lua_state, profile_path.c_str()))
        {
            std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
            return 1;
        }

        EdgeBasedGraphFactory::SpeedProfileProperties speed_profile;

        if (0 != luaL_dostring(lua_state, "return traffic_signal_penalty\n"))
        {
            std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
            return 1;
        }
        speed_profile.trafficSignalPenalty = 10 * lua_tointeger(lua_state, -1);
        SimpleLogger().Write(logDEBUG)
            << "traffic_signal_penalty: " << speed_profile.trafficSignalPenalty;

        if (0 != luaL_dostring(lua_state, "return u_turn_penalty\n"))
        {
            std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
            return 1;
        }
        speed_profile.uTurnPenalty = 10 * lua_tointeger(lua_state, -1);

        speed_profile.has_turn_penalty_function = lua_function_exists(lua_state, "turn_function");

        std::vector<ImportEdge> edge_list;
        NodeID number_of_node_based_nodes =
            readBinaryOSRMGraphFromStream(in,
                                          edge_list,
                                          barrier_node_list,
                                          traffic_light_list,
                                          &internal_to_external_node_map,
                                          restriction_list);
        in.close();

        if (edge_list.empty())
        {
            SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
            return 1;
        }

        SimpleLogger().Write() << restriction_list.size() << " restrictions, "
                               << barrier_node_list.size() << " bollard nodes, "
                               << traffic_light_list.size() << " traffic lights";

        /***
         * Building an edge-expanded graph from node-based input and turn restrictions
         */

        SimpleLogger().Write() << "Generating edge-expanded graph representation";
        std::shared_ptr<NodeBasedDynamicGraph> node_based_graph =
            NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
        std::unique_ptr<RestrictionMap> restriction_map =
            std::unique_ptr<RestrictionMap>(new RestrictionMap(node_based_graph, restriction_list));
        EdgeBasedGraphFactory *edge_based_graph_factor =
            new EdgeBasedGraphFactory(node_based_graph,
                                      std::move(restriction_map),
                                      barrier_node_list,
                                      traffic_light_list,
                                      internal_to_external_node_map,
                                      speed_profile);
        edge_list.clear();
        edge_list.shrink_to_fit();

        edge_based_graph_factor->Run(edge_out, geometry_filename, lua_state);

        restriction_list.clear();
        restriction_list.shrink_to_fit();
        barrier_node_list.clear();
        barrier_node_list.shrink_to_fit();
        traffic_light_list.clear();
        traffic_light_list.shrink_to_fit();

        unsigned number_of_edge_based_nodes = edge_based_graph_factor->GetNumberOfEdgeBasedNodes();
        BOOST_ASSERT(number_of_edge_based_nodes != std::numeric_limits<unsigned>::max());
        DeallocatingVector<EdgeBasedEdge> edgeBasedEdgeList;
        edge_based_graph_factor->GetEdgeBasedEdges(edgeBasedEdgeList);
        std::vector<EdgeBasedNode> node_based_edge_list;
        edge_based_graph_factor->GetEdgeBasedNodes(node_based_edge_list);
        delete edge_based_graph_factor;

        // TODO actually use scoping: Split this up in subfunctions
        node_based_graph.reset();

        std::chrono::duration<double> end_of_expansion_time =
            std::chrono::steady_clock::now() - startup_time;

        // Building grid-like nearest-neighbor data structure
        SimpleLogger().Write() << "building r-tree ...";
        StaticRTree<EdgeBasedNode> *rtree =
            new StaticRTree<EdgeBasedNode>(node_based_edge_list,
                                           rtree_nodes_path.c_str(),
                                           rtree_leafs_path.c_str(),
                                           internal_to_external_node_map);
        delete rtree;
        IteratorbasedCRC32<std::vector<EdgeBasedNode>> crc32;
        unsigned node_based_edge_list_CRC32 =
            crc32(node_based_edge_list.begin(), node_based_edge_list.end());
        node_based_edge_list.clear();
        node_based_edge_list.shrink_to_fit();
        SimpleLogger().Write() << "CRC32: " << node_based_edge_list_CRC32;

        /***
         * Writing info on original (node-based) nodes
         */

        SimpleLogger().Write() << "writing node map ...";
        boost::filesystem::ofstream node_stream(node_filename, std::ios::binary);
        const unsigned size_of_mapping = internal_to_external_node_map.size();
        node_stream.write((char *)&size_of_mapping, sizeof(unsigned));
        node_stream.write((char *)&(internal_to_external_node_map[0]),
                          size_of_mapping * sizeof(NodeInfo));
        node_stream.close();
        internal_to_external_node_map.clear();
        internal_to_external_node_map.shrink_to_fit();

        /***
         * Contracting the edge-expanded graph
         */

        SimpleLogger().Write() << "initializing contractor";
        Contractor *contractor = new Contractor(number_of_edge_based_nodes, edgeBasedEdgeList);
        std::chrono::time_point<std::chrono::steady_clock> contraction_start_timestamp =
            std::chrono::steady_clock::now();

        contractor->Run();
        std::chrono::duration<double> contraction_duration =
            std::chrono::steady_clock::now() - contraction_start_timestamp;
        SimpleLogger().Write() << "Contraction took " << contraction_duration.count() << " sec";

        DeallocatingVector<QueryEdge> contracted_edge_list;
        contractor->GetEdges(contracted_edge_list);
        delete contractor;

        /***
         * Sorting contracted edges in a way that the static query graph can read some in in-place.
         */

        std::sort(contracted_edge_list.begin(), contracted_edge_list.end());
        unsigned max_used_node_id = 0;
        unsigned contracted_edge_count = contracted_edge_list.size();
        SimpleLogger().Write() << "Serializing compacted graph of " << contracted_edge_count
                               << " edges";

        boost::filesystem::ofstream hsgr_output_stream(graphOut, std::ios::binary);
        hsgr_output_stream.write((char *)&uuid_orig, sizeof(UUID));
        for (const QueryEdge &edge : contracted_edge_list)
        {
            BOOST_ASSERT(UINT_MAX != edge.source);
            BOOST_ASSERT(UINT_MAX != edge.target);

            max_used_node_id = std::max(max_used_node_id, edge.source);
            max_used_node_id = std::max(max_used_node_id, edge.target);
        }
        SimpleLogger().Write(logDEBUG) << "input graph has " << number_of_edge_based_nodes
                                       << " nodes";
        SimpleLogger().Write(logDEBUG) << "contracted graph has " << max_used_node_id << " nodes";
        max_used_node_id += 1;

        std::vector<StaticGraph<EdgeData>::NodeArrayEntry> node_array;
        node_array.resize(number_of_edge_based_nodes + 1);

        SimpleLogger().Write() << "Building node array";
        StaticGraph<EdgeData>::EdgeIterator edge = 0;
        StaticGraph<EdgeData>::EdgeIterator position = 0;
        StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;

        for (StaticGraph<EdgeData>::NodeIterator node = 0; node < max_used_node_id; ++node)
        {
            lastEdge = edge;
            while ((edge < contracted_edge_count) && (contracted_edge_list[edge].source == node))
            {
                ++edge;
            }
            node_array[node].firstEdge = position; //=edge
            position += edge - lastEdge;           // remove
        }

        for (unsigned sentinel_counter = max_used_node_id; sentinel_counter != node_array.size();
             ++sentinel_counter)
        {
            // sentinel element, guarded against underflow
            node_array[sentinel_counter].firstEdge = contracted_edge_count;
        }

        unsigned node_array_size = node_array.size();
        // serialize crc32, aka checksum
        hsgr_output_stream.write((char *)&node_based_edge_list_CRC32, sizeof(unsigned));
        // serialize number of nodes
        hsgr_output_stream.write((char *)&node_array_size, sizeof(unsigned));
        // serialize number of edges
        hsgr_output_stream.write((char *)&contracted_edge_count, sizeof(unsigned));
        // serialize all nodes
        hsgr_output_stream.write((char *)&node_array[0],
                                 sizeof(StaticGraph<EdgeData>::NodeArrayEntry) * node_array_size);
        // serialize all edges

        SimpleLogger().Write() << "Building edge array";
        edge = 0;
        int number_of_used_edges = 0;

        StaticGraph<EdgeData>::EdgeArrayEntry current_edge;
        for (unsigned edge = 0; edge < contracted_edge_list.size(); ++edge)
        {
            // no eigen loops
            BOOST_ASSERT(contracted_edge_list[edge].source != contracted_edge_list[edge].target);
            current_edge.target = contracted_edge_list[edge].target;
            current_edge.data = contracted_edge_list[edge].data;

            // every target needs to be valid
            BOOST_ASSERT(current_edge.target < max_used_node_id);
            if (current_edge.data.distance <= 0)
            {
                SimpleLogger().Write(logWARNING)
                    << "Edge: " << edge << ",source: " << contracted_edge_list[edge].source
                    << ", target: " << contracted_edge_list[edge].target
                    << ", dist: " << current_edge.data.distance;

                SimpleLogger().Write(logWARNING) << "Failed at adjacency list of node "
                                                 << contracted_edge_list[edge].source << "/"
                                                 << node_array.size() - 1;
                return 1;
            }
            hsgr_output_stream.write((char *)&current_edge,
                                     sizeof(StaticGraph<EdgeData>::EdgeArrayEntry));
            ++number_of_used_edges;
        }
        hsgr_output_stream.close();

        std::chrono::duration<double> entire_duration =
            std::chrono::steady_clock::now() - startup_time;

        SimpleLogger().Write() << "Preprocessing : " << entire_duration.count() << " seconds";
        SimpleLogger().Write() << "Expansion  : "
                               << (number_of_node_based_nodes / end_of_expansion_time.count())
                               << " nodes/sec and "
                               << (number_of_edge_based_nodes / end_of_expansion_time.count())
                               << " edges/sec";

        SimpleLogger().Write() << "Contraction: "
                               << (number_of_edge_based_nodes / contraction_duration.count())
                               << " nodes/sec and "
                               << number_of_used_edges / contraction_duration.count()
                               << " edges/sec";

        node_array.clear();
        SimpleLogger().Write() << "finished preprocessing";
    }
    catch (boost::program_options::too_many_positional_options_error &)
    {
        SimpleLogger().Write(logWARNING) << "Only one file can be specified";
        return 1;
    }
    catch (boost::program_options::error &e)
    {
        SimpleLogger().Write(logWARNING) << e.what();
        return 1;
    }
    catch (const std::exception &e)
    {
        SimpleLogger().Write(logWARNING) << "Exception occured: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}
Пример #9
0
        static int main(int argc, char *argv[]) {

            const string DEFAULT_TITLE      = "Sequence Coverage Plot";
            const string DEFAULT_X_LABEL    = "X";
            const string DEFAULT_Y_LABEL    = "Y";
            const int32_t DEFAULT_X_MAX     = 1000;
            const int32_t DEFAULT_Y_MAX     = 1000;
            const uint32_t DEFAULT_FASTA_INDEX = 0;
        
            path        sect_file;           
            string      output_type;
            path        output;
            string      title;
            string      x_label;
            string      y_label;
            uint16_t    width;
            uint16_t    height;
            uint32_t    x_max;
            uint32_t    y_max;
            bool        y_logscale;
            uint32_t    fasta_index;
            string      fasta_header;
            bool        verbose;
            bool        help;

            // Declare the supported options.
            po::options_description generic_options(PlotProfile::helpMessage(), 100);
            generic_options.add_options()
                    ("output_type,p", po::value<string>(&output_type)->default_value("png"), 
                        "The plot file type to create: png, ps, pdf.  Warning... if pdf is selected please ensure your gnuplot installation can export pdf files.")
                    ("output,o", po::value<path>(&output),
                        "The path to the output file")
                    ("title,t", po::value<string>(&title)->default_value(DEFAULT_TITLE),
                        "Title for plot")
                    ("x_label,a", po::value<string>(&x_label)->default_value(DEFAULT_X_LABEL),
                        "Label for the x-axis (value taken from matrix metadata if present)")
                    ("y_label,b", po::value<string>(&y_label)->default_value(DEFAULT_Y_LABEL),
                        "Label for the y-axis (value taken from matrix metadata if present)")
                    ("x_max,x", po::value<uint32_t>(&x_max)->default_value(DEFAULT_X_MAX),
                        "Maximum value for the x-axis (value taken from matrix metadata if present)")
                    ("y_max,y", po::value<uint32_t>(&y_max)->default_value(DEFAULT_Y_MAX),
                        "Maximum value for the y-axis (value taken from matrix metadata if present)")
                    ("width,w", po::value<uint16_t>(&width)->default_value(1024),
                        "Width of canvas")
                    ("height,h", po::value<uint16_t>(&height)->default_value(1024),
                        "Height of canvas")
                    ("index,n", po::value<uint32_t>(&fasta_index)->default_value(DEFAULT_FASTA_INDEX),
                        "Index of fasta entry to plot.  First entry is 1.")
                    ("header,d", po::value<string>(&fasta_header),
                        "Fasta header of fasta entry to plot.  NOTE: \'--header\' has priority over index")
                    ("y_logscale,m", po::bool_switch(&y_logscale)->default_value(false),
                        "Y-axis is logscale.  This overrides the y_min and y_max limits.")
                    ("verbose,v", po::bool_switch(&verbose)->default_value(false), 
                        "Print extra information.")
                    ("help", po::bool_switch(&help)->default_value(false), "Produce help message.")
                    ;

            // Hidden options, will be allowed both on command line and
            // in config file, but will not be shown to the user.
            po::options_description hidden_options("Hidden options");
            hidden_options.add_options()
                    ("sect_file,s", po::value<path>(&sect_file), "Path to the sect profile file to plot.")                    
                    ;

            // Positional option for the input bam file
            po::positional_options_description p;
            p.add("sect_file", 1);


            // Combine non-positional options
            po::options_description cmdline_options;
            cmdline_options.add(generic_options).add(hidden_options);

            // Parse command line
            po::variables_map vm;
            po::store(po::command_line_parser(argc, argv).options(cmdline_options).positional(p).run(), vm);
            po::notify(vm);

            // Output help information the exit if requested
            if (help || argc <= 1) {
                cout << generic_options << endl;
                return 1;
            }

            // Check input file exists
            if (!bfs::exists(sect_file) && !bfs::symbolic_link_exists(sect_file)) {
                cerr << endl << "Could not find matrix file at: " << sect_file << "; please check the path and try again." << endl << endl;
                return 1;
            }

            string header;
            string coverages;

            if (!fasta_header.empty()) {
                header.assign(fasta_header);
                getEntryFromFasta(sect_file, header, coverages);
            }
            else if (fasta_index > 0) {
                getEntryFromFasta(sect_file, fasta_index, header, coverages);
            }

            if (coverages.length() == 0) {
                cerr << "Could not find requested fasta header in sect coverages fasta file" << endl;
            }
            else {
                if (verbose)
                    cerr << "Found requested sequence : " << header << endl << coverages << endl << endl;

                // Split coverages
                vector<uint32_t> cvs = kat::splitUInt32(coverages, ' ');

                uint32_t maxCvgVal = y_max != DEFAULT_Y_MAX ? y_max : (*(std::max_element(cvs.begin(), cvs.end())) + 1);

                string t = autoTitle(title, header);

                if (verbose)
                    cerr << "Acquired K-mer counts" << endl;

                // Initialise gnuplot
                Gnuplot profile_plot = Gnuplot("lines");

                profile_plot.configurePlot(output_type, output.string(), width, height);

                profile_plot.set_title(t);
                profile_plot.set_xlabel(x_label);
                profile_plot.set_ylabel(y_label);
                profile_plot.set_xrange(0, cvs.size());
                profile_plot.set_yrange(0, maxCvgVal);
                
                profile_plot.cmd("set style data linespoints");

                std::ostringstream data_str;

                for(uint32_t i = 0; i < cvs.size(); i++)
                {
                    uint32_t index = i+1;
                    double val = y_logscale ? (double)std::log(cvs[i]) : (double)cvs[i];
                    data_str << index << " " << val << "\n";
                }

                std::ostringstream plot_str;

                plot_str << "plot '-'\n" << data_str.str() << "e\n";

                profile_plot.cmd(plot_str.str());

                if (verbose)
                    cerr << "Plotted data: " << plot_str.str() << endl;
            }

            return 0;
        }