text:
#include "config_core.h"

#include <Compression/CompressionFactory.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTIdentifier.h>
#include <Parsers/ASTLiteral.h>
#include <Poco/String.h>
#include <IO/ReadBuffer.h>
#include <Parsers/queryToString.h>
#include <Compression/CompressionCodecMultiple.h>
#include <Compression/CompressionCodecNone.h>
#include <IO/WriteHelpers.h>

#include <boost/algorithm/string/join.hpp>

namespace DB
{

namespace ErrorCodes
{
    extern const int LOGICAL_ERROR;
    extern const int UNKNOWN_CODEC;
    extern const int UNEXPECTED_AST_STRUCTURE;
    extern const int DATA_TYPE_CANNOT_HAVE_ARGUMENTS;
}

CompressionCodecPtr CompressionCodecFactory::getDefaultCodec() const
{
    return default_codec;
}

CompressionCodecPtr CompressionCodecFactory::get(const String & family_name, std::optional<int> level) const
{
    if (level)
    {
        auto level_literal = std::make_shared<ASTLiteral>(static_cast<UInt64>(*level));
        return get(makeASTFunction("CODEC", makeASTFunction(Poco::toUpper(family_name), level_literal)), {});
    }
    else
    {
        auto identifier = std::make_shared<ASTIdentifier>(Poco::toUpper(family_name));
        return get(makeASTFunction("CODEC", identifier), {});
    }
}

CompressionCodecPtr CompressionCodecFactory::get(
    const ASTPtr & ast, const IDataType * column_type, CompressionCodecPtr current_default, bool only_generic) const
{
    if (current_default == nullptr)
        current_default = default_codec;

    if (const auto * func = ast->as<ASTFunction>())
    {
        Codecs codecs;
        codecs.reserve(func->arguments->children.size());
        for (const auto & inner_codec_ast : func->arguments->children)
        {
            String codec_family_name;
            ASTPtr codec_arguments;
            if (const auto * family_name = inner_codec_ast->as<ASTIdentifier>())
            {
                codec_family_name = family_name->name();
                codec_arguments = {};
            }
            else if (const auto * ast_func = inner_codec_ast->as<ASTFunction>())
            {
                codec_family_name = ast_func->name;
                codec_arguments = ast_func->arguments;
            }
            else
                throw Exception("Unexpected AST element for compression codec", ErrorCodes::UNEXPECTED_AST_STRUCTURE);

            CompressionCodecPtr codec;
            if (codec_family_name == DEFAULT_CODEC_NAME)
                codec = current_default;
            else
                codec = getImpl(codec_family_name, codec_arguments, column_type);

            if (only_generic && !codec->isGenericCompression())
                continue;

            codecs.emplace_back(codec);
        }

        CompressionCodecPtr res;

        if (codecs.size() == 1)
            return codecs.back();
        else if (codecs.size() > 1)
            return std::make_shared<CompressionCodecMultiple>(codecs);
        else
            return std::make_shared<CompressionCodecNone>();
    }

    throw Exception("Unexpected AST structure for compression codec: " + queryToString(ast), ErrorCodes::UNEXPECTED_AST_STRUCTURE);
}

CompressionCodecPtr CompressionCodecFactory::get(uint8_t byte_code) const
{
    const auto family_code_and_creator = family_code_with_codec.find(byte_code);

    if (family_code_and_creator == family_code_with_codec.end())
        throw Exception("Unknown codec family code: " + toString(byte_code), ErrorCodes::UNKNOWN_CODEC);

    return family_code_and_creator->second({}, nullptr);
}

CompressionCodecPtr CompressionCodecFactory::getImpl(const String & family_name, const ASTPtr & arguments, const IDataType * column_type) const
{
    if (family_name == "Multiple")
        throw Exception("Codec Multiple cannot be specified directly", ErrorCodes::UNKNOWN_CODEC);

    const auto family_and_creator = family_name_with_codec.find(family_name);

    if (family_and_creator == family_name_with_codec.end())
        throw Exception("Unknown codec family: " + family_name, ErrorCodes::UNKNOWN_CODEC);

    return family_and_creator->second(arguments, column_type);
}

void CompressionCodecFactory::registerCompressionCodecWithType(
    const String & family_name,
    std::optional<uint8_t> byte_code,
    CreatorWithType creator)
{
    if (creator == nullptr)
        throw Exception("CompressionCodecFactory: the codec family " + family_name + " has been provided a null constructor",
                        ErrorCodes::LOGICAL_ERROR);

    if (!family_name_with_codec.emplace(family_name, creator).second)
        throw Exception("CompressionCodecFactory: the codec family name '" + family_name + "' is not unique", ErrorCodes::LOGICAL_ERROR);

    if (byte_code)
        if (!family_code_with_codec.emplace(*byte_code, creator).second)
            throw Exception("CompressionCodecFactory: the codec family code '" + std::to_string(*byte_code) + "' is not unique", ErrorCodes::LOGICAL_ERROR);
}

void CompressionCodecFactory::registerCompressionCodec(const String & family_name, std::optional<uint8_t> byte_code, Creator creator)
{
    registerCompressionCodecWithType(family_name, byte_code, [family_name, creator](const ASTPtr & ast, const IDataType * /* data_type */)
    {
        return creator(ast);
    });
}

void CompressionCodecFactory::registerSimpleCompressionCodec(
    const String & family_name,
    std::optional<uint8_t> byte_code,
    SimpleCreator creator)
{
    registerCompressionCodec(family_name, byte_code, [family_name, creator](const ASTPtr & ast)
    {
        if (ast)
            throw Exception(ErrorCodes::DATA_TYPE_CANNOT_HAVE_ARGUMENTS, "Compression codec {} cannot have arguments", family_name);
        return creator();
    });
}

void registerCodecNone(CompressionCodecFactory & factory);
void registerCodecLZ4(CompressionCodecFactory & factory);
void registerCodecLZ4HC(CompressionCodecFactory & factory);
void registerCodecZSTD(CompressionCodecFactory & factory);
void registerCodecMultiple(CompressionCodecFactory & factory);

/// Keeper use only general-purpose codecs, so we don't need these special codecs
/// in standalone build
#ifndef KEEPER_STANDALONE_BUILD

void registerCodecDelta(CompressionCodecFactory & factory);
void registerCodecT64(CompressionCodecFactory & factory);
void registerCodecDoubleDelta(CompressionCodecFactory & factory);
void registerCodecGorilla(CompressionCodecFactory & factory);
void registerCodecEncrypted(CompressionCodecFactory & factory);

#endif

CompressionCodecFactory::CompressionCodecFactory()
{
    registerCodecNone(*this);
    registerCodecLZ4(*this);
    registerCodecZSTD(*this);
    registerCodecLZ4HC(*this);
    registerCodecMultiple(*this);

#ifndef KEEPER_STANDALONE_BUILD
    registerCodecDelta(*this);
    registerCodecT64(*this);
    registerCodecDoubleDelta(*this);
    registerCodecGorilla(*this);
    registerCodecEncrypted(*this);
#endif

    default_codec = get("LZ4", {});
}

CompressionCodecFactory & CompressionCodecFactory::instance()
{
    static CompressionCodecFactory ret;
    return ret;
}

}


text:
#include <cstdlib>
#include <fstream>

#include <boost/make_shared.hpp>

#include "Knight.hpp"

Knight::Knight(Color col)
    : ChessPiece(col)
{ }

bool Knight::canMove(const ChessBoard& /* board */, const Coord& from, const Coord& to) const
{
    int dx = to.x - from.x;
    int dy = to.y - from.y;

    return (abs(dx) == 2 && abs(dy) == 1) || (abs(dy) == 2 && abs(dx) == 1);
}

void Knight::save(std::ostream& os) const
{
    os << Knight::LABEL;
    ChessPiece::save(os);
}

void Knight::accept(Visitor& visitor)
{
    visitor.visit(*this);
}

namespace
{
    boost::shared_ptr<ChessPiece> createKnight()
    {
        return boost::make_shared<Knight>();
    }
    const bool registered = ChessPiece::registerCreator(Knight::LABEL, createKnight);
}

ext: cpp

max_stars_repo_name: malor/archive

max_issues_repo_name: malor/archive

max_forks_repo_name: malor/archive


text:
//! \file examples/Minkowski_sum_2/approx_inset.cpp
// Computing the approximated inset of a polygon.

#include <fstream>
#include <iostream>
#include <list>
#include <boost/timer.hpp>

#include <CGAL/approximated_offset_2.h>

#include "bops_circular.h"

typedef CGAL::Polygon_2<Kernel>                         Linear_polygon;

int main(int argc, char* argv[])
{
  // Open the input file and read a polygon.
  const char* filename = (argc > 1) ? argv[1] : "tight.dat";
  std::ifstream in_file(filename);

  if (! in_file.is_open()) {
    std::cerr << "Failed to open the input file." << std::endl;
    return -1;
  }

  // Read the input polygon.
  Linear_polygon P;
  in_file >> P;
  in_file.close();

  std::cout << "Read an input polygon with " << P.size() << " vertices."
            << std::endl;

  // Approximate the offset polygon.
  std::list<Polygon_2> inset_polygons;
  boost::timer timer;
  approximated_inset_2(P, 1, 0.00001, std::back_inserter(inset_polygons));
  double secs = timer.elapsed();

  std::list<Polygon_2>::iterator it;
  std::cout << "The inset comprises " << inset_polygons.size()
            << " polygon(s)." << std::endl;
  for (it = inset_polygons.begin(); it != inset_polygons.end(); ++it)
    std::cout << "    Polygon with " << it->size() << " vertices." << std::endl;
  std::cout << "Inset computation took " << secs << " seconds." << std::endl;
  return 0;
}

max_stars_repo_name: gaschler/cgal

max_issues_repo_name: gaschler/cgal

max_forks_repo_name: gaschler/cgal


text:
//-------------------------------------------------------------------
//  MetaInfo Framework (MIF)
//  https://github.com/tdv/mif
//  Created:     03.2017
//  Copyright (C) 2016-2017 tdv
//-------------------------------------------------------------------

// STD
#include <cstdint>
#include <sstream>
#include <stdexcept>
#include <string>

// BOOST
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <boost/scope_exit.hpp>

// MIF
#include <mif/application/application.h>
#include <mif/common/uuid_generator.h>
#include <mif/common/log.h>
#include <mif/db/transaction.h>
#include <mif/db/id/service.h>
#include <mif/service/create.h>

class Application
    : public Mif::Application::Application
{
public:
    Application(int argc, char const **argv)
        : Mif::Application::Application{argc, argv}
    {
        boost::program_options::options_description commonOptions{"Common database options"};
        commonOptions.add_options()
                ("type", boost::program_options::value<std::string>(&m_type)->default_value("sqlite"),
                        "Database type (postgres or sqlite)")
                ("db-prefix", boost::program_options::value<std::string>(&m_dbPrefix)->default_value("mif_db_test"),
                    "Database name prefix")
                ("clean", boost::program_options::value<bool>(&m_cleanResult)->default_value(true),
                    "Remove all generated data")
                ;
        AddCustomOptions(commonOptions);

        boost::program_options::options_description pgOptions{"PostgreSQL options"};
        pgOptions.add_options()
                ("pg-host", boost::program_options::value<std::string>(&m_pgHost)->default_value("localhost"),
                        "PostgreSQL database host")
                ("pg-port", boost::program_options::value<std::uint16_t>(&m_pgPort)->default_value(5432),
                        "PostgreSQL database port")
                ("pg-user", boost::program_options::value<std::string>(&m_pgUser)->default_value("postgres"),
                        "PostgreSQL database user")
                ("pg-pwd", boost::program_options::value<std::string>(&m_pgPassword)->default_value(""),
                        "PostgreSQL database user password")
                ("pg-timeout", boost::program_options::value<std::uint32_t>(&m_pgConnectionTimeout)->default_value(10),
                        "PostgreSQL database connection timeout")
                ;

        AddCustomOptions(pgOptions);

        boost::program_options::options_description sqliteOptions{"SQLite options"};
        sqliteOptions.add_options()
                ("sqlite-in-memory", boost::program_options::value<bool>(&m_sqliteInMemory)->default_value(true),
                        "SQLite in-memory database")
                ("sqlite-dir", boost::program_options::value<std::string>(&m_sqliteDir)->default_value("."),
                        "SQLite database dir")
                ;

        AddCustomOptions(sqliteOptions);
    }

private:
    std::string m_type;
    std::string m_dbPrefix;
    bool m_cleanResult;

    std::string m_pgHost;
    std::uint16_t m_pgPort;
    std::string m_pgUser;
    std::string m_pgPassword;
    std::uint32_t m_pgConnectionTimeout;

    bool m_sqliteInMemory;
    std::string m_sqliteDir;

    std::string GenerateDbName() const
    {
        auto name = Mif::Common::UuidGenerator{}.Generate();
        boost::algorithm::erase_all(name, "-");

        if (!m_dbPrefix.empty())
            name = m_dbPrefix + "_" + name;

        return name;
    }

    // Mif.Application.Application
    virtual void OnStart() override final
    {
        if (m_type == "postgres")
            DemoPostgreSQL();
        else if (m_type == "sqlite")
            DemoSQLite();
        else
            throw std::invalid_argument{"Type \"" + m_type + "\" not supported."};
    }

    void ShowData(Mif::Db::IConnectionPtr connection)
    {
        // Run a parametrized query
        auto statement = connection->CreateStatement(
                "select * from test "
                "where id >= $1 and id <= $2 "
                "order by id;"
            );
        auto recordset = statement->Execute({"5", "7"});

        auto const count = recordset->GetFieldsCount();
        MIF_LOG(Info) << "Fields count: " << count;
        for (std::size_t i = 0 ; i < count ; ++i)
            MIF_LOG(Info) << "\"" << recordset->GetFieldName(i) << "\" is the name of the field "  << i <<  ".";

        while (recordset->Read())
        {
            for (std::size_t i = 0 ; i < count ; ++i)
            {
                MIF_LOG(Info) << recordset->GetFieldName(i) << ": "
                        << (recordset->IsNull(i) ? std::string{"null"} : recordset->GetAsString(i));
            }
        }
    }

    void DemoPostgreSQL()
    {
        auto dbName = GenerateDbName();

        // Create database
        {
            MIF_LOG(Info) << "Create database \"" << dbName << "\"";
            auto connection = Mif::Service::Create<Mif::Db::Id::Service::PostgreSQL, Mif::Db::IConnection>(
                    m_pgHost, m_pgPort, m_pgUser, m_pgPassword, std::string{}, m_pgConnectionTimeout);
            connection->ExecuteDirect(
                    "CREATE DATABASE " + dbName + " WITH OWNER " + m_pgUser + ";"
                );
        }

        // Drop database on exit from method
        BOOST_SCOPE_EXIT(&m_pgHost, &m_pgPort, &m_pgUser, &m_pgPassword, &m_pgConnectionTimeout,
                &m_cleanResult, &dbName)
        {
            if (m_cleanResult)
            {
                try
                {
                    MIF_LOG(Info) << "Drop database \"" << dbName << "\"";
                    auto connection = Mif::Service::Create<Mif::Db::Id::Service::PostgreSQL, Mif::Db::IConnection>(
                            m_pgHost, m_pgPort, m_pgUser, m_pgPassword, std::string{}, m_pgConnectionTimeout);
                    connection->ExecuteDirect("DROP DATABASE " + dbName + ";");
                }
                catch (std::exception const &e)
                {
                    MIF_LOG(Warning) << "Failed to drop database \"" << dbName << "\" Error: " << e.what();
                }
            }
        }
        BOOST_SCOPE_EXIT_END

        // Connect to database
        MIF_LOG(Info) << "Connect ot database \"" << dbName << "\"";
        auto connection = Mif::Service::Create<Mif::Db::Id::Service::PostgreSQL, Mif::Db::IConnection>(
                m_pgHost, m_pgPort, m_pgUser, m_pgPassword, dbName, m_pgConnectionTimeout);

        Mif::Db::Transaction transaction{connection};

        // Create table 'test'
        MIF_LOG(Info) << "Create table 'test'";
        connection->ExecuteDirect(
                "create table test"
                "("
                "   id serial not null primary key,"
                "   key varchar not null,"
                "   value varchar"
                ");"
            );

        // Create index
        MIF_LOG(Info) << "Create index";
        connection->ExecuteDirect(
                "create unique index test_unique_key_index on test (key);"
            );

        // Fill table
        MIF_LOG(Info) << "Fill table";
        connection->ExecuteDirect(
                "insert into test (key, value) "
                "select 'key_' || t.i::text, 'value_' || t.i::text "
                "from generate_series(1, 10) as t(i);"
            );

        transaction.Commit();

        // Show data
        ShowData(connection);
    }

    void DemoSQLite()
    {
        std::string fileName;

        BOOST_SCOPE_EXIT(&m_cleanResult, &fileName)
        {
            if (m_cleanResult && !fileName.empty())
            {
                // Remove database file
                MIF_LOG(Info) << "Remove database file \"" << fileName << "\"";
                boost::filesystem::remove(fileName);
            }
        }
        BOOST_SCOPE_EXIT_END

        // Connect to database
        Mif::Db::IConnectionPtr connection;
        if (m_sqliteInMemory)
        {
            MIF_LOG(Info) << "Create in-memory database";
            connection = Mif::Service::Create<Mif::Db::Id::Service::SQLite, Mif::Db::IConnection>();
        }
        else
        {
            auto const path = boost::filesystem::absolute(m_sqliteDir).parent_path() / GenerateDbName();
            fileName = path.c_str();
            MIF_LOG(Info) << "Create or connect database from file \"" << fileName << "\"";
            connection = Mif::Service::Create<Mif::Db::Id::Service::SQLite, Mif::Db::IConnection>(fileName);
        }

        Mif::Db::Transaction transaction{connection};

        // Create table 'test'
        MIF_LOG(Info) << "Create table 'test'";
        connection->ExecuteDirect(
                "create table test"
                "("
                "   id integer primary key autoincrement,"
                "   key varchar not null,"
                "   value varchar"
                ");"
            );

        // Fill table
        MIF_LOG(Info) << "Fill table";
        for (int i = 1 ; i <= 10 ; ++i)
        {
            auto const index = std::to_string(i);
            connection->ExecuteDirect(
                    "insert into test (key, value) values ('key_" + index + "', 'value_" + index + "')"
                );
        }

        transaction.Commit();

        // Show data
        ShowData(connection);
    }
};

int main(int argc, char const **argv)
{
    return Mif::Application::Run<Application>(argc, argv);
}

max_stars_repo_name: paceholder/mif

max_issues_repo_name: paceholder/mif

max_forks_repo_name: paceholder/mif


text:
#include <pxp-agent/configuration.hpp>
#include <pxp-agent/time.hpp>

#include "version-inl.hpp"

#include <hocon/config.hpp>

#include <cpp-pcp-client/util/logging.hpp>
#include <cpp-pcp-client/connector/client_metadata.hpp>  // validate SSL certs
#include <cpp-pcp-client/connector/errors.hpp>

#include <leatherman/locale/locale.hpp>

#include <leatherman/file_util/file.hpp>

#include <leatherman/util/strings.hpp>
#include <leatherman/util/uri.hpp>

#include <leatherman/json_container/json_container.hpp>

#define LEATHERMAN_LOGGING_NAMESPACE "puppetlabs.pxp_agent.configuration"
#include <leatherman/logging/logging.hpp>

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include <boost/nowide/iostream.hpp>

#ifdef _WIN32
    #include <leatherman/windows/file_util.hpp>
    #include <leatherman/windows/system_error.hpp>
    #include <leatherman/windows/user.hpp>
    #include <leatherman/windows/windows.hpp>
    #undef ERROR
    #include <Shlobj.h>
#else
    #include <leatherman/util/environment.hpp>
#endif

namespace PXPAgent {

namespace HW = HorseWhisperer;
namespace fs = boost::filesystem;
namespace lth_file = leatherman::file_util;
namespace lth_jc   = leatherman::json_container;
namespace lth_log  = leatherman::logging;
namespace lth_loc  = leatherman::locale;
namespace lth_util = leatherman::util;

//
// Default values
//

#ifdef _WIN32
    namespace lth_w = leatherman::windows;
    static const fs::path DATA_DIR = []() {
        if (!lth_w::user::is_admin()) {
            auto home = lth_w::user::home_dir();
            if (!home.empty()) {
                return fs::path(home) / ".puppetlabs";
            }
            throw Configuration::Error { lth_loc::format("failure getting HOME directory") };
        } else {
            return fs::path();
        }
    }();

    static const fs::path& sys_dir() {
        try {
            static auto ddir = fs::path(lth_w::file_util::get_programdata_dir()) / "PuppetLabs" / "pxp-agent";
            return ddir;
        } catch (lth_w::file_util::unknown_folder_exception &e) {
            throw Configuration::Error {
                lth_loc::format("failure getting Windows AppData directory: {1}", e.what()) };
        }
    }

    static const std::string DEFAULT_MODULES_DIR = []() {
        wchar_t szPath[MAX_PATH];
        if (GetModuleFileNameW(NULL, szPath, MAX_PATH) == 0) {
            throw Configuration::Error {
                lth_loc::translate("failed to retrive pxp-agent binary path") };
        }
        // Go up three times, assuming the subtree from Puppet Specs:
        //      C:\Program Files\Puppet Labs\Puppet
        //          puppet
        //              bin
        //                  pxp-agent.exe
        //          pxp-agent
        //              modules
        //                  pxp-module-puppet
        try {
            return (fs::path(szPath).parent_path().parent_path().parent_path() / "pxp-agent" / "modules").string();
        } catch (const std::exception& e) {
            throw Configuration::Error {
                lth_loc::format("failed to determine the modules directory path: {1}",
                                e.what()) };
        }
    }();

    static fs::path conf_dir() { return sys_dir() / "etc"; }
    static fs::path log_dir() { return sys_dir() / "var" / "log"; }
    static std::string spool_dir() { return (sys_dir() / "var" / "spool").string(); }
    static std::string cache_dir() { return (sys_dir() / "tasks-cache").string(); }
#else
    static const fs::path DATA_DIR = []() {
        if (getuid()) {
            std::string home;
            if (lth_util::environment::get("HOME", home)) {
                return fs::path(home) / ".puppetlabs";
            }
            throw Configuration::Error { lth_loc::format("failure getting HOME directory") };
        } else {
            return fs::path();
        }
    }();

    static const std::string DEFAULT_PID_FILE { DATA_DIR.empty() ?
        std::string("/var/run/puppetlabs/pxp-agent.pid") : (DATA_DIR / "var" / "run" / "pxp-agent.pid").string() };
    static const std::string DEFAULT_MODULES_DIR { "/opt/puppetlabs/pxp-agent/modules" };

    static fs::path conf_dir()     { return "/etc/puppetlabs/pxp-agent"; }
    static fs::path log_dir()      { return "/var/log/puppetlabs/pxp-agent"; }
    static std::string spool_dir() { return "/opt/puppetlabs/pxp-agent/spool"; }
    static std::string cache_dir() { return "/opt/puppetlabs/pxp-agent/tasks-cache"; }
#endif

// DATA_DIR defines the non-root data directory. Functions define the system default.
static const fs::path DEFAULT_CONF_DIR { DATA_DIR.empty() ? conf_dir() : (DATA_DIR / "etc" / "pxp-agent") };
static const fs::path DEFAULT_LOG_DIR { DATA_DIR.empty() ? log_dir() : (DATA_DIR / "var" / "log") };
const std::string DEFAULT_SPOOL_DIR { DATA_DIR.empty() ?
    spool_dir() : (DATA_DIR / "opt" / "pxp-agent" / "spool").string() };
static const std::string DEFAULT_TASK_CACHE_DIR { DATA_DIR.empty() ?
    cache_dir() : (DATA_DIR / "opt" / "pxp-agent" / "tasks-cache").string() };

static const std::string DEFAULT_LOG_FILE { (DEFAULT_LOG_DIR / "pxp-agent.log").string() };
static const std::string DEFAULT_PCP_ACCESS_FILE { (DEFAULT_LOG_DIR / "pcp-access.log").string() };

static const std::string DEFAULT_MODULES_CONF_DIR { (DEFAULT_CONF_DIR / "modules").string() };
static const std::string DEFAULT_CONFIG_FILE { (DEFAULT_CONF_DIR / "pxp-agent.conf").string() };
static const std::string DEFAULT_PCP_VERSION { "1" };
static const std::string DEFAULT_DIR_PURGE_TTL { "14d" };

static const std::string AGENT_CLIENT_TYPE { "agent" };

const fs::perms NIX_FILE_PERMS { fs::owner_read | fs::owner_write | fs::group_read };
const fs::perms NIX_DIR_PERMS  { NIX_FILE_PERMS | fs::owner_exe | fs::group_exe };

// Helper function
static void check_and_create_dir(const fs::path& dir_path,
                                 const std::string& opt,
                                 const bool& create)
{
    if (!fs::exists(dir_path)) {
        if (create) {
            try {
                LOG_INFO("Creating the {1} '{2}'", opt, dir_path.string());
                fs::create_directories(dir_path);
                fs::permissions(dir_path, NIX_DIR_PERMS);
            } catch (const std::exception& e) {
                LOG_DEBUG("Failed to create the {1} '{2}': {3}",
                          opt, dir_path.string(), e.what());
                throw Configuration::Error {
                    lth_loc::format("failed to create the {1} '{2}'",
                                    opt, dir_path.string()) };
            }
        } else {
            throw Configuration::Error {
                lth_loc::format("the {1} '{2}' does not exist",
                                opt, dir_path.string()) };
        }
    } else if (!fs::is_directory(dir_path)) {
        throw Configuration::Error {
                lth_loc::format("the {1} '{2}' is not a directory",
                                opt, dir_path.string()) };
    }
}

//
// Public interface
//

void Configuration::initialize(
        std::function<int(std::vector<std::string>)> start_function)
{
    // Ensure the state is reset (useful for testing)
    HW::Reset();
    HW::SetAppName("pxp-agent");
    HW::SetHelpBanner(lth_loc::translate("Usage: pxp-agent [options]"));
    HW::SetVersion(std::string { PXP_AGENT_VERSION } + "\n");
    broker_ws_uris_.clear();
    valid_ = false;

    // Initialize boost filesystem's locale to a UTF-8 default.
    // Logging gets setup the same way via the default 2nd argument.
#ifdef LEATHERMAN_USE_LOCALES
    // Locale support in GCC on Solaris is busted, so skip it.
    fs::path::imbue(lth_loc::get_locale());
#endif

    setDefaultValues();

    // NOTE(ale): don't need to translate this (forced default action)
    HW::DefineAction("start",                       // action name
                     0,                             // arity
                     false,                         // chainable
                     "Start the agent (Default)",   // description
                     "Start the agent",             // help string
                     start_function);               // callback
}

HW::ParseResult parseArguments(const int argc, char* const argv[])
{
    // manipulate argc and v to make start the default action.
    // TODO(ploubser): Add ability to specify default action to HorseWhisperer
    int modified_argc = argc + 1;
    char* modified_argv[modified_argc];
    char action[] = "start";

    for (int i = 0; i < argc; i++) {
        modified_argv[i] = argv[i];
    }
    modified_argv[modified_argc - 1] = action;

    return HW::Parse(modified_argc, modified_argv);
}

HW::ParseResult Configuration::parseOptions(int argc, char *argv[])
{
    // If parsing options, clear the previous value for master_uris.
    // This is primarily for testing.
    master_uris_.clear();

    // Remember the path to the pxp-agent executable used to start
    // this process, it is supposed to be used to start executables
    // which are installed alongside the pxp-agent executable.
    exec_prefix_ = fs::path(argv[0]).parent_path();
    // If a relative or absolute path was specified, convert to absolute.
    // Otherwise, we'll depend on using PATH to find the task_wrapper.
    if (!exec_prefix_.empty()) {
        exec_prefix_ = fs::absolute(exec_prefix_);
    }

    auto parse_result = parseArguments(argc, argv);

    if (parse_result == HW::ParseResult::FAILURE
        || parse_result == HW::ParseResult::INVALID_FLAG) {
        throw Configuration::Error {
            lth_loc::translate("An error occurred while parsing cli options") };
    }

    if (parse_result == HW::ParseResult::OK) {
        config_file_ = lth_file::tilde_expand(HW::GetFlag<std::string>("config-file"));
        if (!config_file_.empty()) {
            parseConfigFile();
        }
    }

    // Normalize and generate log dirs
    std::vector<std::string> options { "logfile" };
    if (HW::GetFlag<bool>("log-pcp-access")) {
        options.emplace_back("pcp-access-logfile");
    }

    for (const auto& option : options) {
        auto val = HW::GetFlag<std::string>(option);
        // Ignore not-a-directory options
        if (val == "-")
            continue;

        fs::path val_path { lth_file::tilde_expand(val) };
        HW::SetFlag(option, val_path.string());
        auto dir = val_path.parent_path();
        check_and_create_dir(dir, option, true);
    }

    // No further processing or user interaction are required if
    // the parsing outcome is HW::ParseResult::HELP or VERSION
    return parse_result;
}

std::string Configuration::setupLogging()
{
    logfile_ = HW::GetFlag<std::string>("logfile");
    pcp_access_logfile_ = HW::GetFlag<std::string>("pcp-access-logfile");
    auto log_access = HW::GetFlag<bool>("log-pcp-access");
    auto log_on_stdout = (logfile_ == "-");
    auto loglevel = HW::GetFlag<std::string>("loglevel");
    std::ostream *log_stream = nullptr;

    if (!log_on_stdout) {
        // We should log on file
        logfile_fstream_.open(logfile_.c_str(), std::ios_base::app);
        fs::permissions(logfile_, NIX_FILE_PERMS);

        log_stream = &logfile_fstream_;
    } else {
        log_stream = &boost::nowide::cout;
    }

    if (log_access) {
        pcp_access_logfile_ = lth_file::tilde_expand(pcp_access_logfile_);
        pcp_access_fstream_ptr_.reset(
            new boost::nowide::ofstream(pcp_access_logfile_.c_str(),
                                        std::ios_base::app));
        fs::permissions(pcp_access_logfile_, NIX_FILE_PERMS);
    }

#ifndef _WIN32
    if (!HW::GetFlag<bool>("foreground") && log_on_stdout) {
        // NOTE(ale): util/posix/daemonize.cc will ensure that the
        // daemon is not associated with any controlling terminal.
        // It will also redirect stdout to /dev/null, together
        // with the other standard files. Set log_level to none to
        // reduce useless overhead since logfile is set to stdout.
        loglevel = "none";
    }
#endif

    lth_log::log_level lvl = lth_log::log_level::none;
    try {
        // NOTE(ale): ignoring HorseWhisperer's vlevel ("-v" flag)
        const std::map<std::string, lth_log::log_level> option_to_log_level {
            { "none", lth_log::log_level::none },
            { "trace", lth_log::log_level::trace },
            { "debug", lth_log::log_level::debug },
            { "info", lth_log::log_level::info },
            { "warning", lth_log::log_level::warning },
            { "error", lth_log::log_level::error },
            { "fatal", lth_log::log_level::fatal }
        };
        lvl = option_to_log_level.at(loglevel);
    } catch (const std::out_of_range& e) {
        throw Configuration::Error {
            lth_loc::format("invalid log level: '{1}'", loglevel) };
    }

    // Configure logging for pxp-agent
    lth_log::setup_logging(*log_stream);
    lth_log::set_level(lvl);

#ifdef DEV_LOG_COLOR
    // Enable colorozation anyway (development setting - it helps
    // debugging PXP message workflow, but it will add useless shell
    // control sequences to log entries on file)
    lth_log::set_colorization(true);
    bool force_colorization = true;
#else
    bool force_colorization = false;
#endif  // DEV_LOG_COLOR

    // Configure logging for cpp-pcp-client
    PCPClient::Util::setupLogging(*log_stream,
                                  force_colorization,
                                  loglevel,
                                  pcp_access_fstream_ptr_);

    if (!log_on_stdout) {
        // Configure platform-specific things for file logging
        // NB: we do that after setting up lth_log in order to log in
        //     case of failure
        configure_platform_file_logging();
    }

    return loglevel;
}

void Configuration::validate()
{
    validateAndNormalizeWebsocketSettings();
    validateAndNormalizeOtherSettings();
    valid_ = true;
}

const Configuration::Agent& Configuration::getAgentConfiguration() const
{
    assert(valid_);
    agent_configuration_ = Configuration::Agent {
        HW::GetFlag<std::string>("modules-dir"),
        broker_ws_uris_,
        master_uris_,
        HW::GetFlag<std::string>("pcp-version"),
        HW::GetFlag<std::string>("ssl-ca-cert"),
        HW::GetFlag<std::string>("ssl-cert"),
        HW::GetFlag<std::string>("ssl-key"),
        HW::GetFlag<std::string>("spool-dir"),
        HW::GetFlag<std::string>("spool-dir-purge-ttl"),
        HW::GetFlag<std::string>("modules-config-dir"),
        HW::GetFlag<std::string>("task-cache-dir"),
        HW::GetFlag<std::string>("task-cache-dir-purge-ttl"),
        AGENT_CLIENT_TYPE,
        HW::GetFlag<std::string>("broker-ws-proxy"),
        HW::GetFlag<std::string>("master-proxy"),
        HW::GetFlag<int>("connection-timeout") * 1000,
        static_cast<uint32_t >(HW::GetFlag<int>("association-timeout")),
        static_cast<uint32_t >(HW::GetFlag<int>("association-request-ttl")),
        static_cast<uint32_t >(HW::GetFlag<int>("pcp-message-ttl")),
        static_cast<uint32_t >(HW::GetFlag<int>("allowed-keepalive-timeouts")),
        static_cast<uint32_t >(HW::GetFlag<int>("ping-interval")),
        static_cast<uint32_t >(HW::GetFlag<int>("task-download-connect-timeout")),
        static_cast<uint32_t >(HW::GetFlag<int>("task-download-timeout")) };
    return agent_configuration_;
}

void Configuration::reopenLogfiles() const
{
    if (!logfile_.empty() && logfile_ != "-") {
        LOG_INFO("Reopening the pxp-agent log file");

        try {
            logfile_fstream_.close();
        } catch (const std::exception& e) {
            LOG_DEBUG("Failed to close the pxp-agent log file stream; already closed?");
        }
        try {
            logfile_fstream_.open(logfile_.c_str(), std::ios_base::app);
        } catch (const std::exception& e) {
            LOG_ERROR("Failed to open the pxp-agent log file stream");
        }
    } else {
        LOG_DEBUG("pxp-agent logging was not configured; no file will be reopened");
    }

    if (HW::GetFlag<bool>("log-pcp-access")) {
        LOG_INFO("Reopening the PCP Access log file");

        try {
            pcp_access_fstream_ptr_->close();
        } catch (const std::exception& e) {
            LOG_DEBUG("Failed to close the PCP Access log file stream; already closed?");
        }
        try {
            pcp_access_fstream_ptr_->open(pcp_access_logfile_.c_str(), std::ios_base::app);
        } catch (const std::exception& e) {
            LOG_ERROR("Failed to open the PCP Access log file stream");
        }
    } else {
        LOG_DEBUG("PCP Access logging was not configured; no file will be reopened");
    }
}

//
// Private interface
//

Configuration::Configuration() : valid_ { false },
                                 defaults_ {},
                                 config_file_ { "" },
                                 agent_configuration_ {},
                                 logfile_ { "" },
                                 pcp_access_logfile_ { "" },
                                 logfile_fstream_ {},
                                 pcp_access_fstream_ptr_ { nullptr }
{
    defineDefaultValues();
}

void Configuration::defineDefaultValues()
{
    defaults_.insert(
        Option { "config-file",
                 Base_ptr { new Entry<std::string>(
                    "config-file",
                    "",
                    lth_loc::format("Config file, default: {1}", DEFAULT_CONFIG_FILE),
                    Types::String,
                    DEFAULT_CONFIG_FILE) } });

    defaults_.insert(
        Option { "broker-ws-uri",
                 Base_ptr { new Entry<std::string>(
                    "broker-ws-uri",
                    "",
                    lth_loc::translate("WebSocket URI of the PCP broker"),
                    Types::String,
                    "") } });

    defaults_.insert(
        Option { "master-uri",
                 Base_ptr { new Entry<std::string>(
                    "master-uri",
                    "",
                    lth_loc::translate("URI of the Puppet Master"),
                    Types::String,
                    "") } });

    defaults_.insert(
        Option { "pcp-version",
                 Base_ptr { new Entry<std::string>(
                    "pcp-version",
                    "",
                    lth_loc::translate("PCP version to use for communication"),
                    Types::String,
                    DEFAULT_PCP_VERSION) } });

    defaults_.insert(
        Option { "connection-timeout",
                 Base_ptr { new Entry<int>(
                    "connection-timeout",
                    "",
                    lth_loc::translate("Timeout (in seconds) for starting the "
                                       "WebSocket handshake, default: 5 s"),
                    Types::Int,
                    5) } });

    // Hidden option: number of ping/pong timeouts to allow before
    // disconnecting, default: 2
    defaults_.insert(
        Option { "allowed-keepalive-timeouts",
                 Base_ptr { new Entry<int>(
                    "allowed-keepalive-timeouts",
                    "",
                    "<hidden>",
                    Types::Int,
                    2) } });

    // Hidden option: interval between pings, default 120 s
    defaults_.insert(
        Option { "ping-interval",
                 Base_ptr { new Entry<int>(
                    "ping-interval",
                    "",
                    "<hidden>",
                    Types::Int,
                    120) } });

    // Hidden option: PCP Association timeout, default: 15 s
    defaults_.insert(
        Option { "association-timeout",
                 Base_ptr { new Entry<int>(
                    "association-timeout",
                    "",
                    "<hidden>",
                    Types::Int,
                    15) } });

    // Hidden option: TTL of the PCP Association request, default: 10 s
    defaults_.insert(
            Option { "association-request-ttl",
                     Base_ptr { new Entry<int>(
                             "association-request-ttl",
                             "",
                             "<hidden>",
                             Types::Int,
                             10) } });

    // Hidden option: TTL of the PCP messages, default: 5 s
    defaults_.insert(
        Option { "pcp-message-ttl",
                 Base_ptr { new Entry<int>(
                    "pcp-message-ttl",
                    "",
                    "<hidden>",
                    Types::Int,
                    5) } });

    defaults_.insert(
        Option { "task-download-connect-timeout",
                 Base_ptr { new Entry<int>(
                    "task-download-connect-timeout",
                    "",
                    lth_loc::translate("Connection timeout when downloading tasks, default: 120 s"),
                    Types::Int,
                    2*60) } });

    defaults_.insert(
        Option { "task-download-timeout",
                 Base_ptr { new Entry<int>(
                    "task-download-timeout",
                    "",
                    lth_loc::translate("Total timeout when downloading tasks, default: 1800 s"),
                    Types::Int,
                    30*60) } });

    defaults_.insert(
        Option { "ssl-ca-cert",
                 Base_ptr { new Entry<std::string>(
                    "ssl-ca-cert",
                    "",
                    lth_loc::translate("SSL CA certificate"),
                    Types::String,
                    "") } });

    defaults_.insert(
        Option { "ssl-cert",
                 Base_ptr { new Entry<std::string>(
                    "ssl-cert",
                    "",
                    lth_loc::translate("pxp-agent SSL certificate"),
                    Types::String,
                    "") } });

    defaults_.insert(
        Option { "ssl-key",
                 Base_ptr { new Entry<std::string>(
                    "ssl-key",
                    "",
                    lth_loc::translate("pxp-agent private SSL key"),
                    Types::String,
                    "") } });

    defaults_.insert(
        Option { "logfile",
                 Base_ptr { new Entry<std::string>(
                    "logfile",
                    "",
                    lth_loc::format("Log file, default: {1}", DEFAULT_LOG_FILE),
                    Types::String,
                    DEFAULT_LOG_FILE) } });

    defaults_.insert(
        Option { "loglevel",
                 Base_ptr { new Entry<std::string>(
                    "loglevel",
                    "",
                    lth_loc::translate("Valid options are 'none', 'trace', "
                                       "'debug', 'info','warning', 'error' and "
                                       "'fatal'. Defaults to 'info'"),
                    Types::String,
                    "info") } });

    defaults_.insert(
            Option { "log-pcp-access",
                     Base_ptr { new Entry<bool>(
                             "log-pcp-access",
                             "",
                             lth_loc::translate("Enable PCP Access logging, default: false"),
                             Types::Bool,
                             false) } });

    defaults_.insert(
            Option { "pcp-access-logfile",
                     Base_ptr { new Entry<std::string>(
                             "pcp-access-logfile",
                             "",
                             lth_loc::format("PCP Access log file, default: {1}",
                                             DEFAULT_PCP_ACCESS_FILE),
                             Types::String,
                             DEFAULT_PCP_ACCESS_FILE) } });

    defaults_.insert(
        Option { "modules-dir",
                 Base_ptr { new Entry<std::string>(
                    "modules-dir",
                    "",
                    lth_loc::format("Modules directory, default"
#ifdef _WIN32
                                    " (relative to the pxp-agent.exe path)"
#endif
                                    ": {1}", DEFAULT_MODULES_DIR),
                    Types::String,
                    DEFAULT_MODULES_DIR) } });

    defaults_.insert(
        Option { "modules-config-dir",
                 Base_ptr { new Entry<std::string>(
                    "modules-config-dir",
                    "",
                    lth_loc::format("Module config files directory, default: {1}",
                                    DEFAULT_MODULES_CONF_DIR),
                    Types::String,
                    DEFAULT_MODULES_CONF_DIR) } });

    defaults_.insert(
        Option { "task-cache-dir",
                 Base_ptr { new Entry<std::string>(
                    "task-cache-dir",
                    "",
                    lth_loc::format("Tasks cache directory, default: {1}",
                                    DEFAULT_TASK_CACHE_DIR),
                    Types::String,
                    DEFAULT_TASK_CACHE_DIR) } });

    defaults_.insert(
        Option { "spool-dir",
                 Base_ptr { new Entry<std::string>(
                    "spool-dir",
                    "",
                    lth_loc::format("Spool action results directory, default: {1}",
                                    DEFAULT_SPOOL_DIR),
                    Types::String,
                    DEFAULT_SPOOL_DIR) } });

    defaults_.insert(
        Option { "spool-dir-purge-ttl",
                 Base_ptr { new Entry<std::string>(
                    "spool-dir-purge-ttl",
                    "",
                    lth_loc::format("TTL for action results before being deleted, "
                                    "default: '{1}' (days)",
                                    DEFAULT_DIR_PURGE_TTL),
                    Types::String,
                    DEFAULT_DIR_PURGE_TTL) } });

    defaults_.insert(
        Option { "task-cache-dir-purge-ttl",
                 Base_ptr { new Entry<std::string>(
                    "task-cache-dir-purge-ttl",
                    "",
                    lth_loc::format("TTL for cached tasks before being deleted, "
                                    "default: '{1}' (days)",
                                    DEFAULT_DIR_PURGE_TTL),
                    Types::String,
                    DEFAULT_DIR_PURGE_TTL) } });

    defaults_.insert(
        Option { "broker-ws-proxy",
                 Base_ptr { new Entry<std::string>(
                    "broker-ws-proxy",
                    "",
                    lth_loc::translate("PCP-broker WebSocket proxy"),
                    Types::String,
                    "") } });

    defaults_.insert(
        Option { "master-proxy",
                 Base_ptr { new Entry<std::string>(
                    "master-proxy",
                    "",
                    lth_loc::translate("Puppet Master proxy"),
                    Types::String,
                    "") } });

    defaults_.insert(
        Option { "foreground",
                 Base_ptr { new Entry<bool>(
                    "foreground",
                    "",
                    lth_loc::translate("Don't daemonize, default: false"),
                    Types::Bool,
                    false) } });

#ifndef _WIN32
    // NOTE(ale): we don't daemonize on Windows; we rely NSSM to start
    // the pxp-agent service and on CreateMutexA() to avoid multiple
    // pxp-agent instances at once
    defaults_.insert(
        Option { "pidfile",
                 Base_ptr { new Entry<std::string>(
                    "pidfile",
                    "",
                    lth_loc::format("PID file path, default: {1}", DEFAULT_PID_FILE),
                    Types::String,
                    DEFAULT_PID_FILE) } });
#endif
}

void Configuration::setDefaultValues()
{
    for (auto opt_idx = defaults_.get<Option::ByInsertion>().begin();
         opt_idx != defaults_.get<Option::ByInsertion>().end();
         ++opt_idx) {
        opt_idx->ptr->configured = false;
        std::string flag_names { opt_idx->ptr->name };

        if (!opt_idx->ptr->aliases.empty()) {
            flag_names += " " + opt_idx->ptr->aliases;
        }

        switch (opt_idx->ptr->type) {
            case Types::Int:
                {
                    Entry<int>* entry_ptr = (Entry<int>*) opt_idx->ptr.get();
                    HW::DefineGlobalFlag<int>(flag_names, entry_ptr->help,
                                              entry_ptr->value,
                                              [entry_ptr] (int v) {
                                                  entry_ptr->configured = true;
                                              });
                }
                break;
            case Types::Bool:
                {
                    Entry<bool>* entry_ptr = (Entry<bool>*) opt_idx->ptr.get();
                    HW::DefineGlobalFlag<bool>(flag_names, entry_ptr->help,
                                               entry_ptr->value,
                                               [entry_ptr] (bool v) {
                                                   entry_ptr->configured = true;
                                               });
                }
                break;
            case Types::Double:
                {
                    Entry<double>* entry_ptr = (Entry<double>*) opt_idx->ptr.get();
                    HW::DefineGlobalFlag<double>(flag_names, entry_ptr->help,
                                                 entry_ptr->value,
                                                 [entry_ptr] (double v) {
                                                     entry_ptr->configured = true;
                                                 });
                }
                break;
            case Types::String:
                {
                    Entry<std::string>* entry_ptr = (Entry<std::string>*) opt_idx->ptr.get();
                    HW::DefineGlobalFlag<std::string>(flag_names, entry_ptr->help,
                                                      entry_ptr->value,
                                                      [entry_ptr] (std::string v) {
                                                          entry_ptr->configured = true;
                                                      });
                }
                break;
            case Types::MultiString:
                {
                    Entry<std::vector<std::string>>* entry_ptr = (Entry<std::vector<std::string>>*) opt_idx->ptr.get();
                    HW::DefineGlobalFlag<std::vector<std::string>>(flag_names, entry_ptr->help,
                                                      entry_ptr->value,
                                                      [entry_ptr] (std::vector<std::string> v) {
                                                          entry_ptr->configured = true;
                                                      });
                }
                break;
            default:
                // Present because FlagType is not an enum class, and I don't trust
                // compilers to warn/error about missing cases.
                assert(false);
        }
    }
}

void Configuration::parseConfigFile()
{
    if (!lth_file::file_readable(config_file_)) {
        LOG_DEBUG("Config file {1} absent", config_file_);
        return;
    }

    using boost::algorithm::ends_with;
    if (!ends_with(config_file_, ".conf") && !ends_with(config_file_, ".json")) {
        // This is required by the HOCON parser.
        throw Configuration::Error {
            lth_loc::format("config-file {1} must end with .conf or .json", config_file_) };
    }

    hocon::shared_config config;
    try {
        LOG_TRACE("Parsing {1}", config_file_);
        config = hocon::config::parse_file_any_syntax(config_file_)->resolve();
    } catch (hocon::config_exception& e) {
        throw Configuration::Error {
            lth_loc::format("cannot parse config file: {1}", e.what()) };
    }

    auto wrap =
        [] (const std::string& key,
            const std::string& type_str,
            std::function<void()> assignment) {
            try {
                assignment();
            } catch (hocon::config_exception& e) {
                throw Configuration::Error { lth_loc::format("field '{1}' must be of type {2}", key, type_str) };
            }
        };

    bool broker_ws_uri_in_file = false;

    LOG_TRACE("Iterating config: {1}", config->root()->render());
    for (const auto& entry : config->entry_set()) {
        auto key = entry.first;
        LOG_TRACE("Key = {1}", key);
        const auto& opt_idx = defaults_.get<Option::ByName>().find(key);

        if (opt_idx == defaults_.get<Option::ByName>().end()) {
            // broker-ws-uris is restricted to the config file, so it's handled
            // specially here. It's not part of defaults_ because all the extra
            // meta-data for Horsewhisperer isn't needed.
            // TODO: add `servers`, which will populate broker-ws-uris and master-uris
            //       using default ports; expects hostnames only
            if (key == "broker-ws-uris") {
                wrap(key, lth_loc::translate("array of strings"), [&]() {
                    broker_ws_uris_ = config->get_string_list(key);
                });
                continue;
            } else if (key == "master-uris") {
                wrap(key, lth_loc::translate("array of strings"), [&]() {
                    master_uris_ = config->get_string_list(key);
                });
                continue;
            } else {
                LOG_INFO("Ignoring unrecognized option '{1}'", key);
                continue;
            }
        }

        if (opt_idx->ptr->configured)
            continue;

        switch (opt_idx->ptr->type) {
            case Types::Int:
                wrap(key, lth_loc::translate("integer"), [&]() {
                    HW::SetFlag(key, config->get_int(key));
                });
                break;
            case Types::Bool:
                wrap(key, lth_loc::translate("boolean"), [&]() {
                    HW::SetFlag(key, config->get_bool(key));
                });
                break;
            case Types::Double:
                wrap(key, lth_loc::translate("double"), [&]() {
                    HW::SetFlag(key, config->get_double(key));
                });
                break;
            case Types::String:
                if (key == "broker-ws-uri") {
                    broker_ws_uri_in_file = true;
                }
                wrap(key, lth_loc::translate("string"), [&]() {
                    HW::SetFlag(key, config->get_string(key));
                });
                break;
            default:
                // Present because FlagType is not an enum class, and I don't trust
                // compilers to warn/error about missing cases.
                assert(false);
        }
    }

    if (!broker_ws_uris_.empty() && broker_ws_uri_in_file) {
        throw Configuration::Error {
            lth_loc::format("broker-ws-uri and broker-ws-uris cannot both be "
                            "defined in the config file") };
    }
}

// Helper function
std::string check_and_expand_ssl_cert(const std::string& cert_name)
{
    auto c = HW::GetFlag<std::string>(cert_name);
    if (c.empty())
        throw Configuration::Error {
            lth_loc::format("{1} value must be defined", cert_name) };

    c = lth_file::tilde_expand(c);
    if (!fs::exists(c))
        throw Configuration::Error {
            lth_loc::format("{1} file '{2}' not found", cert_name, c) };

    if (!lth_file::file_readable(c))
        throw Configuration::Error {
            lth_loc::format("{1} file '{2}' not readable", cert_name, c) };

    return c;
}

static void validate_wss(std::string const& uri, std::string const& name)
{
    if (uri.compare(0, 6, "wss://") != 0)
        throw Configuration::Error {
            lth_loc::format("{1} value \"{2}\" must start with wss://", name, uri) };
}

void Configuration::validateAndNormalizeWebsocketSettings()
{
    // Check the broker's WebSocket URI
    // broker-ws-uri and broker-ws-uris cannot both be configured in the config
    // file (enforced in parseConfigFile). If broker-ws-uri is set on the CLI,
    // override whatever was in the config file.
    auto broker_ws_uri = HW::GetFlag<std::string>("broker-ws-uri");
    if (!broker_ws_uri.empty()) {
        validate_wss(broker_ws_uri, "broker-ws-uri");
        broker_ws_uris_.clear();
        broker_ws_uris_.push_back(std::move(broker_ws_uri));
    } else {
        for (auto const& uri : broker_ws_uris_) {
            validate_wss(uri, "broker-ws-uris");
        }
    }

    for (auto &uri : master_uris_) {
        auto parsed = lth_util::uri(uri);
        if (parsed.protocol.empty()) {
            parsed.protocol = "https";
        } else if (parsed.protocol != "https") {
            throw Configuration::Error {
                lth_loc::format("master-uris value \"{1}\" must start with https://", uri) };
        }

        if (parsed.port.empty()) {
            parsed.port = "8140";
        }
        uri = parsed.str();
    }

    if (broker_ws_uris_.empty())
        throw Configuration::Error {
            lth_loc::translate("broker-ws-uri or broker-ws-uris must be defined") };

    auto pcp_version = HW::GetFlag<std::string>("pcp-version");
    if (pcp_version != "1" && pcp_version != "2") {
        throw Configuration::Error {
            lth_loc::translate("pcp-version must be either '1' or '2'") };
    }

    // Check the SSL options and expand the paths
    auto ca   = check_and_expand_ssl_cert("ssl-ca-cert");
    auto cert = check_and_expand_ssl_cert("ssl-cert");
    auto key  = check_and_expand_ssl_cert("ssl-key");

    // Ensure client certs are good
    try {
        PCPClient::getCommonNameFromCert(cert);
        PCPClient::validatePrivateKeyCertPair(key, cert);
    } catch (const PCPClient::connection_config_error& e) {
        throw Configuration::Error { e.what() };
    }

    // Set the expanded cert paths
    HW::SetFlag<std::string>("ssl-ca-cert", ca);
    HW::SetFlag<std::string>("ssl-cert", cert);
    HW::SetFlag<std::string>("ssl-key", key);
}

void Configuration::validateAndNormalizeOtherSettings()
{
    // Normalize and check directories. The modules directory
    // is expected to exist, and will usually come from packaging.
    std::vector<std::pair<std::string, bool>> options {
        std::make_pair(std::string("modules-dir"), false),
        std::make_pair(std::string("modules-config-dir"), true),
        std::make_pair(std::string("task-cache-dir"), true),
        std::make_pair(std::string("spool-dir"), true) };

    for (const auto& option : options) {
        auto val = HW::GetFlag<std::string>(option.first);
        fs::path val_path { lth_file::tilde_expand(val) };
        HW::SetFlag(option.first, val_path.string());
        check_and_create_dir(val_path, option.first, option.second);
    }

    fs::path spool_dir_path = HW::GetFlag<std::string>("spool-dir");
    fs::path tmp_path;
    do {
        tmp_path = spool_dir_path / lth_util::get_UUID();
    } while (fs::exists(tmp_path));

    bool is_writable { false };
    try {
        if (fs::create_directories(tmp_path)) {
            is_writable = true;
            fs::remove_all(tmp_path);
        }
    } catch (const std::exception& e) {
        LOG_DEBUG("Failed to create the test dir in spool path '{1}' during"
                  "configuration validation: {2}",
                  spool_dir_path.string(), e.what());
    }

    if (!is_writable)
        throw Configuration::Error {
            lth_loc::format("the spool-dir '{1}' is not writable",
                            spool_dir_path.string()) };

#ifndef _WIN32
    if (!HW::GetFlag<bool>("foreground")) {
        auto pid_file = lth_file::tilde_expand(HW::GetFlag<std::string>("pidfile"));

        if (fs::exists(pid_file) && !(fs::is_regular_file(pid_file)))
            throw Configuration::Error {
                lth_loc::format("the PID file '{1}' is not a regular file", pid_file) };

        auto pid_dir = fs::path(pid_file).parent_path().string();
        HW::SetFlag<std::string>("pidfile", pid_file);
        check_and_create_dir(pid_dir, "pidfile", true);
    }
#endif

    for (auto purge_ttl : {"spool-dir-purge-ttl", "task-cache-dir-purge-ttl"}) {
        try {
            Timestamp(HW::GetFlag<std::string>(purge_ttl));
        } catch (const Timestamp::Error& e) {
            throw Configuration::Error {
                // LOCALE: invalid configuration option
                lth_loc::format("invalid {1}: {2}", purge_ttl, e.what()) };
        }
    }

    for (auto msg_ttl : {"association-timeout",
                         "association-request-ttl",
                         "pcp-message-ttl",
                         "task-download-connect-timeout",
                         "task-download-timeout"}) {
        if (HW::GetFlag<int>(msg_ttl) < 0)
            throw Configuration::Error {
                lth_loc::format("{1} must be positive", msg_ttl) };
    }
}

const Options::iterator Configuration::getDefaultIndex(const std::string& flagname)
{
    const auto& opt_idx = defaults_.get<Option::ByName>().find(flagname);
    if (opt_idx == defaults_.get<Option::ByName>().end())
        throw Configuration::Error {
            lth_loc::format("no default value for {1}", flagname) };
    return opt_idx;
}

std::string Configuration::getInvalidFlagError(const std::string& flagname)
{
    return lth_loc::format("invalid value for {1}", flagname);
}

std::string Configuration::getUnknownFlagError(const std::string& flagname)
{
    return lth_loc::format("unknown flag name: {1}", flagname);
}

void Configuration::checkValidForSetting()
{
    if (!valid_)
        throw Configuration::Error {
            lth_loc::translate("cannot set configuration value until "
                               "configuration is validated") };
}

}  // namespace PXPAgent

ext: cc

max_stars_repo_name: tavilarion/pxp-agent

max_issues_repo_name: tavilarion/pxp-agent

max_forks_repo_name: tavilarion/pxp-agent


text:
/*
 * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include "route_info.h"
#include "comm/tinyxml2.h"
#include "log4cplus.h"
#include "comm/inc_comm.h"
#include <boost/make_shared.hpp>
namespace meituan_mns {

bool IdcUtil::IsSameIdc(const boost::shared_ptr<IDC> &idc1, const boost::shared_ptr<IDC> &idc2) {
  return idc1->GetIdc() == idc2->GetIdc();
}

bool IdcUtil::IsSameCenter(const boost::shared_ptr<IDC> &idc1, const boost::shared_ptr<IDC> &idc2) {
  // exclude NOCENTER
  // NOCENTER不算做一个中心来处理
  return ("NOCENTER" != idc1->GetCenter()) && (idc1->GetCenter() == idc2->GetCenter());
}
bool IdcUtil::IsInIdcs(const std::string &ip){

  NS_LOG_INFO("the local ip  = "<< ip);

  boost::shared_ptr<IDC> local_idc = IdcUtil::GetIdc(ip);
  if (NULL == local_idc.get()) {
    NS_LOG_ERROR("fail to the idc info of local ip = " << ip);
    return false;
  }
  if (local_idc->GetIdc().empty()) {
    return false;
  }
  return true;
}
boost::shared_ptr<IDC> IdcUtil::GetIdc(const std::string &ip) {

  boost::shared_ptr<std::vector<boost::shared_ptr<IDC> > > idcs_tmp;
  idcs_tmp = CXmlFile::GetIdc();
  for (std::vector<boost::shared_ptr<IDC> >::const_iterator iter = idcs_tmp->begin();
      idcs_tmp->end() != iter; ++iter) {
    if ((*iter)->IsSameIdc(ip)) {
      return *iter;
    }
  }
  return boost::make_shared<IDC>();
}

std::string IdcUtil::GetSameIdcZk(const std::string &zk_host,
                                  const std::string &ip) {
  std::vector<std::string> vec_str;
  int32_t ret = SplitStringIntoVector(zk_host.c_str(), "," , vec_str);
  if (0 >= ret) {
    NS_LOG_ERROR("failed to split zk_host to vector, zk_host: " << zk_host);
    return zk_host;
  }

  boost::shared_ptr<IDC> ip_idc = GetIdc(ip);

  std::vector<std::string> vec_res;
  if (NULL != ip_idc.get()) {
    for (std::vector<std::string>::const_iterator iter = vec_str.begin();
         iter != vec_str.end(); ++iter) {

      boost::shared_ptr<IDC> item_idc = GetIdc(*iter);
      if (IsSameIdc(item_idc, ip_idc)) {
        vec_res.push_back(*iter);
      }
    }
  } else {
    NS_LOG_ERROR("fail to get the idc info of ip = " << ip);
  }

  std::string res;
  if (vec_res.empty()) {
    res = zk_host;
  } else {
    res = vec_res[0];
    for (std::vector<std::string>::const_iterator iter = vec_res.begin() + 1;
         iter != vec_res.end(); ++iter) {
      res += "," + *iter;
    }
  }
  return res;
}

}

max_stars_repo_name: wuxianxingkong/octo-ns

max_issues_repo_name: wuxianxingkong/octo-ns

max_forks_repo_name: wuxianxingkong/octo-ns


text:
/*
 * Copyright (C) 2014 MediaSift Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <sstream>
#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>

#include <served/plugins.hpp>

namespace served { namespace plugin {

void access_log(served::response & res, const served::request & req)
{
	std::stringstream ss;

	boost::posix_time::time_facet *facet = new boost::posix_time::time_facet("%d/%b/%Y:%H:%M:%S");
	ss.imbue(std::locale(ss.getloc(), facet));

	std::string source = req.source();
	if ( source.empty() )
	{
		source = "-";
	}

	ss << source << " - - [" << boost::posix_time::second_clock::local_time() << " -0000]";
	ss << " \"" << method_to_string(req.method()) << " " << req.url().path() << " " << req.HTTP_version() << "\"";
	ss << " " << res.status() << " " << res.body_size();

	std::cout << ss.str() << std::endl;
}

} } // plugin, served

max_stars_repo_name: csfilehub/served

max_issues_repo_name: csfilehub/served

max_forks_repo_name: csfilehub/served


text:
//  (C) Copyright Nick Thompson 2021.
//  Use, modification and distribution are subject to the
//  Boost Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <random>
#include <array>
#include <vector>
#include <iostream>
#include <benchmark/benchmark.h>
#include <boost/math/tools/cubic_roots.hpp>

using boost::math::tools::cubic_roots;

template<class Real>
void CubicRoots(benchmark::State& state)
{
    std::random_device rd;
    auto seed = rd();
    // This seed generates 3 real roots:
    //uint32_t seed = 416683252;
    std::mt19937_64 mt(seed);
    std::uniform_real_distribution<Real> unif(-10, 10);

    Real a = unif(mt);
    Real b = unif(mt);
    Real c = unif(mt);
    Real d = unif(mt);
    for (auto _ : state)
    {
        auto roots = cubic_roots(a,b,c,d);
        benchmark::DoNotOptimize(roots[0]);
    }
}

BENCHMARK_TEMPLATE(CubicRoots, float);
BENCHMARK_TEMPLATE(CubicRoots, double);
BENCHMARK_TEMPLATE(CubicRoots, long double);

BENCHMARK_MAIN();


text:
//
// rtidb_cli.cc
// Copyright 2017 elasticlog <elasticlog01@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "rtidb_tablet_server.pb.h"

#include <iostream>
#include <vector>
#include <gflags/gflags.h>
#include <boost/lexical_cast.hpp>
#include "rpc/rpc_client.h"
#include "cli/rtidb_client.h"
#include "util/string_util.h"
#include <signal.h>
#include <unistd.h>

DEFINE_string(ts_endpoint, "127.0.0.1:9527", "config the ip and port that ts serves for");

static volatile bool s_quit = false;
static void SignalIntHandler(int /*sig*/){
  s_quit = true;
}

void HandlePut(const std::string& input, rtidb::RtiDBClient* client) {
    std::vector<std::string> parts;
    ::rtidb::SplitString(input, " ", &parts);
    if (parts.size() < 4) {
        std::cout << "error format input" << std::endl;
        return;
    }
    client->Put(parts[1], parts[2], parts[3]);
}

void HandleScan(const std::string& input, rtidb::RtiDBClient* client) {
    std::vector<std::string> parts;
    ::rtidb::SplitString(input, " ", &parts);
    if (parts.size() < 4) {
        std::cout << "error format input" << std::endl;
        return;
    }
    client->Scan(parts[1], parts[2], parts[3], true);
}

void HandlePutBench(const std::string& input, rtidb::RtiDBClient* client) {
    std::vector<std::string> parts;
    ::rtidb::SplitString(input, " ", &parts);
    char val[400];
    for (int i = 0; i < 400; i++) {
        val[i] ='0';
    }
    std::string sval(val);
    for (int i = 0; i < 10000000; i++) {
        std::string key = "00000000";
        std::string num = boost::lexical_cast<std::string>(i);
        key.replace(key.size()-num.size(), num.size(), num);
        client->Put(parts[1], key, sval);
    }
}

void HandleScanBench(const std::string& input, rtidb::RtiDBClient* client) {
    std::vector<std::string> parts;
    ::rtidb::SplitString(input, " ", &parts);
    for (int i = 0; i < 10000; i++) {
        client->Scan(parts[1], parts[2], parts[3], false);
    }
    client->ShowPercentile();
}

int main(int argc, char* argv[]) {
    ::google::ParseCommandLineFlags(&argc, &argv, true);
    rtidb::RtiDBClient* client = new rtidb::RtiDBClient(FLAGS_ts_endpoint);
    client->Init();
    std::cout << "welcome to rtidb cli!" << std::endl;
    while (!s_quit) {
        std::cout << ">";
        std::string buffer;
        std::getline(std::cin, buffer);
        if (buffer.empty()) {
            continue;
        }
        std::string cmd = buffer.substr(0, 3);
        if (cmd == "put") {
            HandlePut(buffer, client);
        }else if (cmd =="pbe"){
            HandlePutBench(buffer, client);
        }else if (cmd =="sbe" ){
            HandleScanBench(buffer, client);
        }else {
            HandleScan(buffer, client);
        }
    }

}

max_stars_repo_name: Frey-Fu/rtidb

max_issues_repo_name: Frey-Fu/rtidb

max_forks_repo_name: Frey-Fu/rtidb


text:
#include "all.h"

#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <boost/foreach.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

namespace rococo {

Config *Config::config_s = NULL;

std::map<std::string, std::string> SiteInfo::dns_;

std::string SiteInfo::name2host(std::string& site_name) {
    //    Log::debug("find host name by site name: %s", sitename.c_str());
    auto it = SiteInfo::dns_.find(site_name);
    if (it != SiteInfo::dns_.end()) {
        return it->second;
    } else {
        verify(0);
        return site_name;
    }
}

void SiteInfo::load_dns(std::string& hosts_path) {
    std::string host_name, site_name;
    std::ifstream in(hosts_path);
    while (in) {
        in >> host_name;
        in >> site_name;
        dns_[site_name] = host_name ;
    }
}

Config *Config::get_config() {
    if (config_s == NULL)
        config_s = new Config();
    return config_s;
}

int Config::create_config(int argc, char *argv[]) {
    if (config_s != NULL)
        return -1;

    char *filename = NULL;
    unsigned int sid = 0, cid = 0;
    char *end_ptr = NULL;

    char *hostspath = NULL;
    char *ctrl_hostname = NULL;
    char *ctrl_key = NULL;
    char *ctrl_init = NULL/*, *ctrl_run = NULL*/;
    char *logging_path = NULL;
    unsigned int ctrl_port = 0;
    unsigned int ctrl_timeout = 0;
    unsigned int duration = 0;
    bool heart_beat = false;
    single_server_t single_server = SS_DISABLED;
    int server_or_client = -1;

    int c;
    optind = 1;
    while ((c = getopt(argc, argv, "bc:d:f:h:i:k:p:r:s:S:t:H:")) != -1) {
        switch (c) {
            case 'b': // heartbeat to controller
                heart_beat = true;
                break;
            case 'c': // client id
                cid = strtoul(optarg, &end_ptr, 10);
                if (end_ptr == NULL || *end_ptr != '\0')
                    return -4;
                if (server_or_client != -1)
                    return -4;
                server_or_client = 1;
                break;
            case 'd': // duration
                duration = strtoul(optarg, &end_ptr, 10);
                if (end_ptr == NULL || *end_ptr != '\0')
                    return -4;
                break;
            case 'f': // properties.xml
                filename = (char *)malloc((strlen(optarg) + 1) * sizeof(char));
                strcpy(filename, optarg);
                break;
            case 'h': // ctrl_hostname
                ctrl_hostname = (char *)malloc((strlen(optarg) + 1) * sizeof(char));
                strcpy(ctrl_hostname, optarg);
                break;
            case 'H': // ctrl_host
                hostspath = (char *)malloc((strlen(optarg) + 1) * sizeof(char));
                strcpy(hostspath, optarg);
                break;
            case 'i': // ctrl_init
                ctrl_init = (char *)malloc((strlen(optarg) + 1) * sizeof(char));
                strcpy(ctrl_init, optarg);
                break;
            case 'k':
                ctrl_key = (char *)malloc((strlen(optarg) + 1) * sizeof(char));
                strcpy(ctrl_key, optarg);
                break;
            case 'r': // logging path
                logging_path = (char *)malloc((strlen(optarg) + 1) * sizeof(char));
                strcpy(logging_path, optarg);
                break;
            case 'p':
                ctrl_port = strtoul(optarg, &end_ptr, 10);
                if (end_ptr == NULL || *end_ptr != '\0')
                    return -4;
                break;
            //case 'r':
            //    ctrl_run = (char *)malloc((strlen(optarg) + 1) * sizeof(char));
            //    strcpy(ctrl_run, optarg);
            //    break;
            case 's': // site id
                sid = strtoul(optarg, &end_ptr, 10);
                if (end_ptr == NULL || *end_ptr != '\0')
                    return -4;
                if (server_or_client != -1)
                    return -4;
                server_or_client = 0;
                break;
            case 'S': // client touch only single server
                {
                int single_server_buf = strtoul(optarg, &end_ptr, 10);
                if (end_ptr == NULL || *end_ptr != '\0')
                    return -4;
                switch (single_server_buf) {
                    case 0:
                        single_server = SS_DISABLED;
                        break;
                    case 1:
                        single_server = SS_THREAD_SINGLE;
                        break;
                    case 2:
                        single_server = SS_PROCESS_SINGLE;
                        break;
                    default:
                        return -4;
                }
                break;
                }
            case 't':
                ctrl_timeout = strtoul(optarg, &end_ptr, 10);
                if (end_ptr == NULL || *end_ptr != '\0')
                    return -4;
                break;
            case '?':
                if (optopt == 'c' ||
                    optopt == 'd' ||
                    optopt == 'f' ||
                    optopt == 'h' ||
                    optopt == 'i' ||
                    optopt == 'k' ||
                    optopt == 'p' ||
                    optopt == 'r' ||
                    optopt == 's' ||
                    optopt == 't')
                    Log_error("Option -%c requires an argument.", optopt);
                else if (isprint(optopt))
                    Log_error("Unknown option -%c.", optopt);
                else
                    Log_error("Unknown option \\x%x", optopt);
                return -2;
            default:
                return -3;
        }
    }
    if (server_or_client != 0 && server_or_client != 1)
        return -5;
    config_s = new Config(
            cid,
            sid,
            filename,
            ctrl_hostname,
            ctrl_port,
            ctrl_timeout,
            ctrl_key,
            ctrl_init,
            //ctrl_run,
            duration,
            heart_beat,
            single_server,
            server_or_client,
            logging_path,
            hostspath);
    return 0;
}

void Config::destroy_config() {
    if (config_s) {
        delete config_s;
        config_s = NULL;
    }
}

Config::Config() {
    char filename[] = "properties.xml";
    init_sharding(filename);
}

Config::Config(unsigned int cid, unsigned int sid,
               char *filename,
               char *ctrl_hostname, unsigned int ctrl_port,
               unsigned int ctrl_timeout, char *ctrl_key,
               char *ctrl_init/*, char *ctrl_run*/, unsigned int duration,
               bool heart_beat, single_server_t single_server,
               int server_or_client, char *logging_path, char *hostspath) :
        cid_(cid),
        sid_(sid),
        ctrl_hostname_(ctrl_hostname),
        ctrl_port_(ctrl_port),
        ctrl_timeout_(ctrl_timeout),
        ctrl_key_(ctrl_key),
        ctrl_init_(ctrl_init)/*, ctrl_run_(ctrl_run)*/,
        duration_(duration),
        heart_beat_(heart_beat),
        single_server_(single_server),
        server_or_client_(server_or_client),
        logging_path_(logging_path),
        retry_wait_(false) {

    if (hostspath != NULL) {
        init_hostsmap(hostspath);
    }

    if (filename == NULL) {
        char filename_bk[] = "properties.xml";
        init_sharding(filename_bk);
    }
    else {
        init_sharding(filename);
        free(filename);
    }
}

void Config::init_hostsmap(const char *hostspath) {
    std::string hostname, sitename;
    std::ifstream in(hostspath);
    while (in) {
        in >> hostname;
        in >> sitename;
        hostsmap_[sitename] = hostname ;
    }
}

std::string Config::site2host_addr(std::string& siteaddr) {
    auto pos = siteaddr.find_first_of(':');
    verify(pos != std::string::npos);
    std::string sitename = siteaddr.substr(0, pos);
    std::string hostname = site2host_name(sitename);
    std::string hostaddr = siteaddr.replace(0, pos, hostname);
    return hostaddr;
}

std::string Config::site2host_name(std::string& sitename) {
//    Log::debug("find host name by site name: %s", sitename.c_str());
    auto it = hostsmap_.find(sitename);
    if (it != hostsmap_.end()) {
        return it->second;
    } else {
        verify(0);
        return sitename;
    }
}

void Config::init_sharding(const char *filename) {
    std::string filename_str(filename);
    boost::property_tree::ptree pt;
    boost::property_tree::xml_parser::read_xml(
            filename_str, pt,
            boost::property_tree::xml_parser::no_concat_text);

    Sharding::sharding_s = new Sharding();

    // get mode
    std::string mode_str = pt.get<std::string>("benchmark.<xmlattr>.mode", "2PL");
    size_t mode_str_i = 0;
    while (mode_str_i < mode_str.size()) {
        mode_str[mode_str_i] = tolower(mode_str[mode_str_i]);
        mode_str_i++;
    }

    std::map<string, int> modes_map = {
            {"none", MODE_NONE},
            {"2pl", MODE_2PL},
            {"occ", MODE_OCC},
            {"rcc", MODE_RCC},
            {"ro6", MODE_RO6},
            {"rpc_null", MODE_RPC_NULL},
            {"deptran", MODE_DEPTRAN},
            {"deptran_er", MODE_DEPTRAN},
            {"2pl_w", MODE_2PL},
            {"2pl_wait_die", MODE_2PL},
            {"2pl_ww", MODE_2PL},
            {"2pl_wound_die", MODE_2PL}
    };

    if (mode_str == "2pl") {
        mode_ = MODE_2PL;
    } else if (mode_str == "occ") {
        mode_ = MODE_OCC;
    } else if (mode_str == "none") {
        mode_ = MODE_NONE;
    } else if (mode_str == "rcc" || mode_str == "deptran") {
        // deprecated
        mode_ = MODE_DEPTRAN;
        early_return_ = false;
    } else if (mode_str == "deptran_er") {
        // deprecated
        // ??? what is this for?
        mode_ = MODE_RCC;
        early_return_ = true;
    } else if (mode_str == "rpc_null") {
        mode_ = MODE_RPC_NULL;
    } else if (mode_str == "2pl_w") {
        mode_ = MODE_2PL;
        retry_wait_ = true;
    } else if (mode_str == "2pl_wait_die") {
        mode_ = MODE_2PL;
        mdb::FineLockedRow::set_wait_die();
    } else if (mode_str == "2pl_ww" || mode_str == "2pl_wound_die") {
        mode_ = MODE_2PL;
        mdb::FineLockedRow::set_wound_die();
    } else if (mode_str == "ro6") {
        mode_ = MODE_RO6;
    } else {
        // mode not supported.
        verify(0);
    }

    // get benchmark
    std::string benchmark_name = pt.get<std::string>("benchmark.<xmlattr>.name");
    if (benchmark_name == "tpca") {
        benchmark_ = TPCA;
    }
    else if (benchmark_name == "tpcc") {
        benchmark_ = TPCC;
    }
    else if (benchmark_name == "tpcc_dist_part") {
        benchmark_ = TPCC_DIST_PART;
    }
    else if (benchmark_name == "tpcc_real_dist_part") {
        benchmark_ = TPCC_REAL_DIST_PART;
    }
    else if (benchmark_name == "rw_benchmark") {
        benchmark_ = RW_BENCHMARK;
    }
    else if (benchmark_name == "micro_bench") {
        benchmark_ = MICRO_BENCH;
    }
    else {
        Log_error("No implementation for benchmark: %s", benchmark_name.c_str());
        verify(0);
    }

    scale_factor_ = pt.get<unsigned int>("benchmark.<xmlattr>.scale_factor", 1);
    max_retry_ = pt.get<unsigned int>("benchmark.<xmlattr>.max_retry", 1);

    concurrent_txn_ = pt.get<unsigned int>("benchmark.<xmlattr>.concurrent_txn", 1);
    batch_start_ = pt.get<bool>("benchmark.<xmlattr>.batch_start", false);

    std::string txn_weight_str = pt.get<std::string>("benchmark.<xmlattr>.txn_weight", "");
    size_t txn_weight_str_i = 0, end_txn_weight_str_i;
    char *txn_weight_str_endptr;
    while (string::npos != (end_txn_weight_str_i = txn_weight_str.find(':', txn_weight_str_i))) {
        double d = strtod(txn_weight_str.c_str() + txn_weight_str_i, &txn_weight_str_endptr);
        verify(txn_weight_str_endptr == txn_weight_str.c_str() + end_txn_weight_str_i);
        txn_weight_str_i = end_txn_weight_str_i + 1;

        txn_weight_.push_back(d);
    }
    double d = strtod(txn_weight_str.c_str() + txn_weight_str_i, &txn_weight_str_endptr);
    verify(*txn_weight_str_endptr == '\0');
    txn_weight_.push_back(d);

    num_site_ = pt.get<int>("benchmark.hosts.<xmlattr>.number");
    site_ = (char **)malloc(sizeof(char *) * num_site_);
    site_threads_ = (unsigned int *)malloc(sizeof(unsigned int) * num_site_);
    verify(site_ != NULL);
    unsigned int site_found = 0;
    memset(site_, 0, sizeof(char *) * num_site_);
    memset(site_threads_, 0, sizeof(unsigned int) * num_site_);
    BOOST_FOREACH(
            boost::property_tree::ptree::value_type const &value,
            pt.get_child("benchmark.hosts")
    ) {
        if (value.first == "site") {
            int sid = value.second.get<int>("<xmlattr>.id");
            verify(sid < num_site_ && sid >= 0);
            verify(site_[sid] == NULL);

            // set site addr
            std::string siteaddr = value.second.get<std::string>("<xmltext>");
            std::string hostaddr = site2host_addr(siteaddr);

            site_[sid] = (char *)malloc((hostaddr.size() + 1) * sizeof(char));
            verify(site_[sid] != NULL);
            strcpy(site_[sid], hostaddr.c_str());

            // set site threads
            int threads = value.second.get<int>("<xmlattr>.threads");
            verify(threads > 0);
            site_threads_[sid] = (unsigned int)threads;

            site_found++;
        }
    }
    verify(site_found == num_site_);

    int num_clients = pt.get<int>("benchmark.clients.<xmlattr>.number");
    verify(num_clients > 0);
    bool *clients = (bool *)malloc(sizeof(bool) * num_clients);
    for (unsigned int client_index = 0; client_index < num_clients; client_index++)
        clients[client_index] = false;
    start_coordinator_id_ = 0;
    bool client_found = false;
    BOOST_FOREACH(
            boost::property_tree::ptree::value_type const &value,
            pt.get_child("benchmark.clients")
    ) {
        if (value.first == "client") {
            num_coordinator_threads_ = value.second.get<unsigned int>("<xmlattr>.threads");
            std::string client_ids = value.second.get<std::string>("<xmlattr>.id");
            size_t pos = client_ids.find('-');
            if (pos == std::string::npos) { // one client id
                char *end_ptr = NULL;
                unsigned int find_cid = strtoul(client_ids.c_str(), &end_ptr, 10);
                verify(*end_ptr == '\0');
                verify(find_cid < num_clients);
                verify(!clients[find_cid]);
                clients[find_cid] = true;
                if (cid_ == find_cid) {
                    client_found = true;
                    break;
                }
                else {
                    start_coordinator_id_ += num_coordinator_threads_;
                }
            } else { // client id formed as "0-9"
                std::string start = client_ids.substr(0, pos);
                verify(client_ids.size() > pos + 1);
                std::string end = client_ids.substr(pos + 1);
                char *end_ptr = NULL;
                unsigned int start_cid = strtoul(start.c_str(), &end_ptr, 10);
                verify(*end_ptr == '\0');
                unsigned int end_cid = strtoul(end.c_str(), &end_ptr, 10);
                verify(*end_ptr == '\0');
                verify(end_cid < num_clients && start_cid < end_cid);
                for (unsigned int mark_index = start_cid; mark_index <= end_cid; mark_index++) {
                    verify(!clients[mark_index]);
                    clients[mark_index] = true;
                }

                if (cid_ <= end_cid && cid_ >= start_cid) {
                    start_coordinator_id_ += (cid_ - start_cid) * num_coordinator_threads_;
                    client_found = true;
                    break;
                } else {
                    start_coordinator_id_ += (1 + end_cid - start_cid) * num_coordinator_threads_;
                }
            }
        }
    }

    free(clients);
    verify(client_found);

    int *site_buf = (int *)malloc(sizeof(int) * num_site_);
    verify(site_buf != NULL);
    BOOST_FOREACH(
            boost::property_tree::ptree::value_type const &value,
            pt.get_child("benchmark")
    ) {
        if (value.first == "table") {
            std::string tb_name = value.second.get<std::string>("<xmlattr>.name");
            if (Sharding::sharding_s->tb_info_.find(tb_name) != Sharding::sharding_s->tb_info_.end())
                verify(0);

            std::string method = value.second.get<std::string>("<xmlattr>.shard_method");

            unsigned long long int records = value.second.get<unsigned long long int>("<xmlattr>.records");
            Sharding::tb_info_t tb_info(method);

            tb_info.num_records = records * scale_factor_;
            verify(records > 0);

            // set tb_info site info
            bool all_site = value.second.get<bool>("<xmlattr>.all_site", true);
            if (all_site) {
                tb_info.num_site = num_site_;
                tb_info.site_id = (unsigned int *)malloc(sizeof(unsigned int) * num_site_);
                verify(tb_info.site_id != NULL);
                for (unsigned int i = 0; i < num_site_; i++)
                    tb_info.site_id[i] = i;
            }
            else {
                memset(site_buf, 0, sizeof(int) * num_site_);
                unsigned int num_site_buf = 0;
                BOOST_FOREACH(boost::property_tree::ptree::value_type const &site_value, value.second.get_child("site")) {
                    if (site_value.first == "site_id") {
                        int sid = site_value.second.get<int>("<xmltext>");
                        verify(sid < num_site_ && sid >= 0);
                        verify(site_buf[sid] == 0);
                        if (site_buf[sid] == 0)
                            num_site_buf++;
                        site_buf[sid] = 1;
                    }
                }
                tb_info.num_site = num_site_buf;
                tb_info.site_id = (unsigned int *)malloc(sizeof(unsigned int) * num_site_buf);
                verify(tb_info.site_id != NULL);
                unsigned int j = 0;
                for (unsigned int i = 0; i < num_site_; i++)
                    if (site_buf[i] == 1)
                        tb_info.site_id[j++] = i;
                verify(j == num_site_buf);
            }
            verify(tb_info.num_site > 0 && tb_info.num_site <= num_site_);

            // set tb_info.symbol TBL_SORTED or TBL_UNSORTED or TBL_SNAPSHOT
            mdb::symbol_t symbol;
            std::string symbol_str = value.second.get<std::string>("<xmlattr>.type", "sorted");
            if (symbol_str == "sorted") {
                symbol = mdb::TBL_SORTED;
            }
            else if (symbol_str == "unsorted") {
                symbol = mdb::TBL_UNSORTED;
            }
            else if (symbol_str == "snapshot") {
                symbol = mdb::TBL_SNAPSHOT;
            }
            else {
                Log_fatal("Unknown table type: %s", symbol_str.c_str());
                verify(0);
            }
            tb_info.symbol = symbol;

            // set tb_info.columns
            BOOST_FOREACH(boost::property_tree::ptree::value_type const &column, value.second.get_child("schema")) {
                if (column.first == "column") {
                    std::string c_type = column.second.get<std::string>("<xmlattr>.type");
                    verify(c_type.size() > 0);
                    Value::kind c_v_type;
                    if (c_type == "i32")
                        c_v_type = Value::I32;
                    else if (c_type == "i64")
                        c_v_type = Value::I64;
                    else if (c_type == "double")
                        c_v_type = Value::DOUBLE;
                    else if (c_type == "str")
                        c_v_type = Value::STR;
                    else
                        c_v_type = Value::UNKNOWN;

                    std::string c_name = column.second.get<std::string>("<xmlattr>.name");
                    verify(c_name.size() > 0);

                    bool c_primary = column.second.get<bool>("<xmlattr>.primary", false);

                    std::string c_foreign = column.second.get<std::string>("<xmlattr>.foreign", "");
                    Sharding::column_t *foreign_key_column = NULL;
                    Sharding::tb_info_t *foreign_key_tb = NULL;
                    if (c_foreign.size() > 0) {
                        size_t pos = c_foreign.find('.');
                        verify(pos != std::string::npos);

                        std::string foreign_tb = c_foreign.substr(0, pos);
                        verify(c_foreign.size() > pos + 1);
                        std::string foreign_column = c_foreign.substr(pos + 1);

                        std::map<std::string, Sharding::tb_info_t>::iterator ftb_it = Sharding::sharding_s->tb_info_.find(foreign_tb);
                        verify(ftb_it != Sharding::sharding_s->tb_info_.end());
                        foreign_key_tb = &(ftb_it->second);

                        std::vector<Sharding::column_t>::iterator fc_it = ftb_it->second.columns.begin();
                        for (; fc_it != ftb_it->second.columns.end(); fc_it++)
                            if (fc_it->name == foreign_column) {
                                verify(fc_it->type == c_v_type);
                                if (fc_it->values == NULL && server_or_client_ == 0)
                                    fc_it->values = new std::vector<Value>();
                                foreign_key_column = &(*fc_it);
                                break;
                            }
                        verify(fc_it != ftb_it->second.columns.end());
                    }
                    tb_info.columns.push_back(Sharding::column_t(c_v_type, c_name, c_primary, foreign_key_tb, foreign_key_column));
                }
            }

            tb_info.tb_name = tb_name;
            Sharding::sharding_s->tb_info_[tb_name] = tb_info;
        }
    }

    if (benchmark_ == TPCC_REAL_DIST_PART) {
        i32 n_w_id = (i32)(Sharding::sharding_s->tb_info_[std::string(TPCC_TB_WAREHOUSE)].num_records);
        i32 n_d_id = (i32)(num_site_ * Sharding::sharding_s->tb_info_[std::string(TPCC_TB_DISTRICT)].num_records / n_w_id);
        i32 d_id = 0, w_id = 0;
        for (d_id = 0; d_id < n_d_id; d_id++)
            for (w_id = 0; w_id < n_w_id; w_id++) {
                MultiValue mv(std::vector<Value>({
                            Value(d_id),
                            Value(w_id)
                            }));
                Sharding::sharding_s->insert_dist_mapping(mv);
            }

        i32 n_i_id = (i32)(Sharding::sharding_s->tb_info_[std::string(TPCC_TB_ITEM)].num_records);
        i32 i_id = 0;
        for (i_id = 0; i_id < n_i_id; i_id++)
            for (w_id = 0; w_id < n_w_id; w_id++) {
                MultiValue mv(std::vector<Value>({
                            Value(i_id),
                            Value(w_id)
                            }));
                Sharding::sharding_s->insert_stock_mapping(mv);
            }
    }
    free(site_buf);
}

Config::~Config() {
    if (Sharding::sharding_s) {
        delete Sharding::sharding_s;
        Sharding::sharding_s = NULL;
    }
    if (site_) {
        for (unsigned int i = 0; i < num_site_; i++)
            if (site_[i])
                free(site_[i]);
        free(site_);
        site_ = NULL;
    }
    if (site_threads_) {
        free(site_threads_);
        site_threads_ = NULL;
    }
    if (ctrl_hostname_) {
        free(ctrl_hostname_);
        ctrl_hostname_ = NULL;
    }
    if (ctrl_key_) {
        free(ctrl_key_);
        ctrl_key_ = NULL;
    }
    if (ctrl_init_) {
        free(ctrl_init_);
        ctrl_init_ = NULL;
    }
    //if (ctrl_run_) {
    //    free(ctrl_run_);
    //    ctrl_run_ = NULL;
    //}
    if (logging_path_) {
        free(logging_path_);
        logging_path_ = NULL;
    }
}

unsigned int Config::get_site_id() {
    return sid_;
}

unsigned int Config::get_client_id() {
    return cid_;
}

unsigned int Config::get_ctrl_port() {
    return ctrl_port_;
}

unsigned int Config::get_ctrl_timeout() {
    return ctrl_timeout_;
}

const char *Config::get_ctrl_hostname() {
    return ctrl_hostname_;
}

const char *Config::get_ctrl_key() {
    return ctrl_key_;
}

const char *Config::get_ctrl_init() {
    return ctrl_init_;
}

//const char *Config::get_ctrl_run() {
//    return ctrl_run_;
//}
//

int Config::get_all_site_addr(std::vector<std::string> &servers) {
    if (site_ == NULL)
        return -1;
    unsigned int i = 0;
    for (; i < num_site_; i++) {
        if (site_[i] == NULL) {
            servers.clear();
            return -2;
        }
        std::string siteaddr(site_[i]);
        //std::string hostaddr = site2host_addr(siteaddr);
//        Log::info("site address: %s", hostaddr.c_str());
        servers.push_back(siteaddr);
    }
    return servers.size();
}

int Config::get_site_addr(unsigned int sid, std::string &server) {
    if (site_ == NULL)
        return -1;
    if (sid >= num_site_)
        return -2;
    if (site_[sid] == NULL)
        return -3;
    std::string siteaddr(site_[sid]);
//    std::string hostaddr = site2host_addr(siteaddr);
    server.assign(siteaddr);
    return 0;
}

int Config::get_my_addr(std::string &server) {
    if (site_ == NULL)
        return -1;
    if (sid_ >= num_site_)
        return -2;
    if (site_[sid_] == NULL)
        return -3;
    server.assign("0.0.0.0:");
    unsigned int len = strlen(site_[sid_]), p_start = 0;
    for (unsigned int i = 0; i < len; i++) {
        if (site_[sid_][i] == ':') {
            p_start = i + 1;
            break;
        }
    }
    verify(p_start < len && p_start > 0);
    server.append(site_[sid_] + p_start);
    return 0;
}

int Config::get_threads(unsigned int &threads) {
    if (site_threads_ == NULL)
        return -1;
    if (sid_ >= num_site_)
        return -2;
    threads = site_threads_[sid_];
    return 0;
}

unsigned int Config::get_duration() {
    return duration_;
}

bool Config::do_heart_beat() {
    return heart_beat_;
}

int Config::get_mode() {
    return mode_;
}

unsigned int Config::get_num_threads() {
    return num_coordinator_threads_;
}

unsigned int Config::get_start_coordinator_id() {
    return start_coordinator_id_;
}

int Config::get_benchmark() {
    return benchmark_;
}

unsigned int Config::get_num_site() {
    return num_site_;
}

unsigned int Config::get_scale_factor() {
    return scale_factor_;
}

unsigned int Config::get_max_retry() {
    return max_retry_;
}

Config::single_server_t Config::get_single_server() {
    return single_server_;
}

unsigned int Config::get_concurrent_txn() {
    return concurrent_txn_;
}

bool Config::get_batch_start() {
    return batch_start_;
}

std::vector<double> &Config::get_txn_weight() {
    return txn_weight_;
}

#ifdef CPU_PROFILE
int Config::get_prof_filename(char *prof_file) {
    if (prof_file == NULL)
        return -1;
    return sprintf(prof_file, "log/site-%d.prof", sid_);
}
#endif

bool Config::do_early_return() {
    return early_return_;
}

bool Config::do_logging() {
    return logging_path_ != NULL;
}

char *Config::log_path() {
    return logging_path_;
}

bool Config::retry_wait() {
    return retry_wait_;
}

}

max_stars_repo_name: SJTU-IPADS/dst

max_issues_repo_name: SJTU-IPADS/dst

max_forks_repo_name: SJTU-IPADS/dst