コード例 #1
0
ファイル: context.cpp プロジェクト: lucciano/cocaine-core
    static
    result_type
    convert(const dynamic_t& from) {
        result_type component;
        const auto& logging = from.as_object();

        for(auto it = logging.begin(); it != logging.end(); ++it) {
            using namespace blackhole::repository;

            auto object = it->second.as_object();
            auto loggers = object.at("loggers", dynamic_t::empty_array);

            config_t::logging_t::logger_t log {
                logmask(object.at("verbosity", defaults::log_verbosity).as_string()),
                object.at("timestamp", defaults::log_timestamp).as_string(),
                config::parser_t<dynamic_t, blackhole::log_config_t>::parse(it->first, loggers)
            };

            component.loggers[it->first] = log;
        }

        return component;
    }
コード例 #2
0
ファイル: node.cpp プロジェクト: borislitv/cocaine-plugins
node_t::node_t(context_t& context, asio::io_service& asio, const std::string& name, const dynamic_t& args):
    category_type(context, asio, name, args),
    dispatch<io::node_tag>(name),
    context(context),
    log(context.log(name))
{
    on<io::node::start_app>(std::bind(&node_t::start_app, this, ph::_1, ph::_2));
    on<io::node::pause_app>(std::bind(&node_t::pause_app, this, ph::_1));
    on<io::node::list>     (std::bind(&node_t::list, this));
    on<io::node::info>     (std::bind(&node_t::info, this, ph::_1, ph::_2));

    // Context signal/slot.
    signal = std::make_shared<dispatch<io::context_tag>>(name);
    signal->on<io::context::shutdown>(std::bind(&node_t::on_context_shutdown, this));

    const auto runname = args.as_object().at("runlist", "").as_string();

    if(runname.empty()) {
        context.listen(signal, asio);
        return;
    }

    COCAINE_LOG_INFO(log, "reading '%s' runlist", runname);

    typedef std::map<std::string, std::string> runlist_t;
    runlist_t runlist;

    const auto storage = api::storage(context, "core");

    try {
        // TODO: Perform request to a special service, like "storage->runlist(runname)".
        runlist = storage->get<runlist_t>("runlists", runname);
    } catch(const std::system_error& err) {
        COCAINE_LOG_WARNING(log, "unable to read '%s' runlist: %s", runname, err.what());
    }

    if(runlist.empty()) {
        context.listen(signal, asio);
        return;
    }

    COCAINE_LOG_INFO(log, "starting %d app(s)", runlist.size());

    std::vector<std::string> errored;

    for(auto it = runlist.begin(); it != runlist.end(); ++it) {
        blackhole::scoped_attributes_t scope(*log, {{ "app", it->first }});

        try {
            start_app(it->first, it->second);
        } catch(const std::exception& e) {
            COCAINE_LOG_WARNING(log, "unable to initialize app: %s", e.what());
            errored.push_back(it->first);
        }
    }

    if(!errored.empty()) {
        std::ostringstream stream;
        std::ostream_iterator<char> builder(stream);

        boost::spirit::karma::generate(builder, boost::spirit::karma::string % ", ", errored);

        COCAINE_LOG_WARNING(log, "couldn't start %d app(s): %s", errored.size(), stream.str());
    }

    context.listen(signal, asio);
}
コード例 #3
0
ファイル: node.cpp プロジェクト: nail-lian/cocaine-core
node_t::node_t(context_t& context, boost::asio::io_service& asio, const std::string& name, const dynamic_t& args):
    category_type(context, asio, name, args),
    dispatch<node_tag>(name),
    m_context(context),
    m_log(context.log(name))
{
    using namespace std::placeholders;

    on<node::start_app>(std::bind(&node_t::on_start_app, this, _1, _2));
    on<node::pause_app>(std::bind(&node_t::on_pause_app, this, _1));
    on<node::list>(std::bind(&node_t::on_list, this));

    const auto runlist_id = args.as_object().at("runlist", "default").as_string();
    const auto storage = api::storage(m_context, "core");

    typedef std::map<std::string, std::string> runlist_t;

    runlist_t runlist;

    {
        blackhole::scoped_attributes_t attributes(*m_log, {
            blackhole::attribute::make("runlist", runlist_id)
        });

        COCAINE_LOG_INFO(m_log, "reading runlist");

        try {
            runlist = storage->get<runlist_t>("runlists", runlist_id);
        } catch(const storage_error_t& e) {
            COCAINE_LOG_WARNING(m_log, "unable to read runlist: %s", e.what());
        }
    }

    if(runlist.empty()) {
        return;
    }

    COCAINE_LOG_INFO(m_log, "starting %d app(s)", runlist.size());

    std::vector<std::string> errored;

    for(auto it = runlist.begin(); it != runlist.end(); ++it) {
        blackhole::scoped_attributes_t attributes(*m_log, {
            blackhole::attribute::make("app", it->first)
        });

        try {
            on_start_app(it->first, it->second);
        } catch(const std::exception& e) {
            COCAINE_LOG_ERROR(m_log, "unable to initialize app: %s", e.what());
            errored.push_back(it->first);
        } catch(...) {
            COCAINE_LOG_ERROR(m_log, "unable to initialize app");
            errored.push_back(it->first);
        }
    }

    if(!errored.empty()) {
        std::ostringstream stream;
        std::ostream_iterator<char> builder(stream);

        boost::spirit::karma::generate(builder, boost::spirit::karma::stream % ", ", errored);

        COCAINE_LOG_ERROR(m_log, "couldn't start %d app(s): %s", errored.size(), stream.str());
    }
}
コード例 #4
0
ファイル: storage.cpp プロジェクト: kazan417/cocaine-plugins
mongo_storage_t::mongo_storage_t(context_t& context, const std::string& name, const dynamic_t& args):
    category_type(context, name, args),
    m_log(context.log(name)),
    m_client(connect(args.as_object().at("uri", "<unspecified>").to<std::string>()))
{ }
コード例 #5
0
ファイル: raft.cpp プロジェクト: andrusha97/cocaine-core
control_service_t::control_service_t(context_t& context,
                                     io::reactor_t& reactor,
                                     const std::string& name,
                                     const dynamic_t& args):
    api::service_t(context, reactor, name, args),
    dispatch<io::raft_control_tag<msgpack::object, msgpack::object>>(name),
    m_context(context),
    m_log(context.log(name))
{
    using namespace std::placeholders;

    typedef io::raft_control<msgpack::object, msgpack::object> protocol;

    on<protocol::insert>(std::bind(&control_service_t::insert, this, _1, _2));
    on<protocol::erase>(std::bind(&control_service_t::erase, this, _1, _2));
    on<protocol::lock>(std::bind(&control_service_t::lock, this, _1));
    on<protocol::reset>(std::bind(&control_service_t::reset, this, _1, _2));
    on<protocol::dump>(std::bind(&control_service_t::dump, this));
    on<protocol::status>(std::bind(&control_service_t::status, this, _1));
    on<protocol::leader>(std::bind(&control_service_t::leader, this, _1));

    options_t options;

    // The format of the name is "service/<name of service from the config>".
    // So here we drop "service/" part to determine the raft control service name.
    // TODO: Make the context to pass the names to services without "service/" part.
    options.control_service_name = name.substr(8, std::string::npos);
    options.node_service_name = "raft_node";
    options.configuration_machine_name = "configuration";
    options.some_nodes = args.as_object().at("some_nodes", dynamic_t::empty_array).to<std::set<node_id_t>>();
    options.election_timeout = args.as_object().at("election_timeout", 500).to<unsigned int>();
    options.heartbeat_timeout = args.as_object().at("heartbeat_timeout", options.election_timeout / 2).to<unsigned int>();
    options.snapshot_threshold = args.as_object().at("snapshot_threshold", 100000).to<unsigned int>();
    options.message_size = args.as_object().at("message_size", 1000).to<unsigned int>();

    m_context.raft().set_options(options);
    m_context.raft().activate();

    if(m_context.config.create_raft_cluster) {
        typedef log_entry<configuration_machine_t> entry_type;
        typedef configuration<configuration_machine_t> config_type;
        typedef log_traits<configuration_machine_t, config_type::cluster_type>::snapshot_type
                snapshot_type;

        config_type config(m_context,
                           m_context.raft().options().configuration_machine_name,
                           cluster_config_t {std::set<node_id_t>(), boost::none});

        configuration_machine_t config_machine(m_context, *m_context.raft().m_reactor, *this);

        config.log().push(entry_type());
        config.log().push(entry_type());

        std::map<std::string, lockable_config_t> config_snapshot;

        config_snapshot[m_context.raft().options().configuration_machine_name] = lockable_config_t {
            false,
            cluster_config_t {
                std::set<node_id_t>({m_context.raft().id()}),
                boost::none
            }
        };

        config_machine.consume(config_snapshot);
        config.log().set_snapshot(1, 1, snapshot_type(std::move(config_snapshot), config.cluster()));

        config.set_current_term(std::max<uint64_t>(1, config.current_term()));
        config.set_commit_index(1);
        config.set_last_applied(1);

        m_config_actor = m_context.raft().create_cluster(
            m_context.raft().options().configuration_machine_name,
            std::move(config_machine),
            std::move(config)
        );
    } else {
        m_config_actor = m_context.raft().insert(
            m_context.raft().options().configuration_machine_name,
            configuration_machine_t(m_context, *m_context.raft().m_reactor, *this)
        );
    }

    // Run Raft node service.
    auto node_service_reactor = std::make_shared<io::reactor_t>();

    std::unique_ptr<api::service_t> node_service(std::make_unique<node_service_t>(
        m_context,
        *m_context.raft().m_reactor,
        std::string("service/") + m_context.raft().options().node_service_name
    ));

    std::unique_ptr<actor_t> node_service_actor(
        new actor_t(m_context, m_context.raft().m_reactor, std::move(node_service))
    );

    m_context.insert(m_context.raft().options().node_service_name,
                     std::move(node_service_actor));
}
コード例 #6
0
ファイル: multicast.cpp プロジェクト: b-xiang/cocaine-core
 static
 result_type
 convert(const dynamic_t& source) {
     return ip::address::from_string(source.as_string());
 }
コード例 #7
0
ファイル: context.cpp プロジェクト: lucciano/cocaine-core
config_t::config_t(const std::string& config_path) {
    path.config = config_path;

    const auto config_file_status = fs::status(path.config);

    if(!fs::exists(config_file_status) || !fs::is_regular_file(config_file_status)) {
        throw cocaine::error_t("the configuration file path is invalid");
    }

    fs::ifstream stream(path.config);

    if(!stream) {
        throw cocaine::error_t("unable to read the configuration file");
    }

    rapidjson::MemoryPoolAllocator<> json_allocator;
    rapidjson::Reader json_reader(&json_allocator);
    rapidjson_ifstream_t config_stream(&stream);
    dynamic_reader_t config_constructor;

    if(!json_reader.Parse<rapidjson::kParseDefaultFlags>(config_stream, config_constructor)) {
        if(json_reader.HasParseError()) {
            throw cocaine::error_t("the configuration file is corrupted - %s", json_reader.GetParseError());
        } else {
            throw cocaine::error_t("the configuration file is corrupted");
        }
    }

    const dynamic_t root(config_constructor.Result());

    const auto &path_config    = root.as_object().at("paths", dynamic_t::empty_object).as_object();
    const auto &locator_config = root.as_object().at("locator", dynamic_t::empty_object).as_object();
    const auto &network_config = root.as_object().at("network", dynamic_t::empty_object).as_object();

    // Validation

    if(root.as_object().at("version", 0).to<unsigned int>() != 2) {
        throw cocaine::error_t("the configuration file version is invalid");
    }

    // Paths

    path.plugins = path_config.at("plugins", defaults::plugins_path).as_string();
    path.runtime = path_config.at("runtime", defaults::runtime_path).as_string();

    const auto runtime_path_status = fs::status(path.runtime);

    if(!fs::exists(runtime_path_status)) {
        throw cocaine::error_t("the %s directory does not exist", path.runtime);
    } else if(!fs::is_directory(runtime_path_status)) {
        throw cocaine::error_t("the %s path is not a directory", path.runtime);
    }

    // Hostname configuration

    char hostname[256];

    if(gethostname(hostname, 256) != 0) {
        throw std::system_error(errno, std::system_category(), "unable to determine the hostname");
    }

    addrinfo hints,
             *result = nullptr;

    std::memset(&hints, 0, sizeof(addrinfo));

    hints.ai_flags = AI_CANONNAME;

    const int rv = getaddrinfo(hostname, nullptr, &hints, &result);

    if(rv != 0) {
        throw std::system_error(rv, gai_category(), "unable to determine the hostname");
    }

    network.hostname = locator_config.at("hostname", std::string(result->ai_canonname)).as_string();
    network.uuid     = unique_id_t().string();

    freeaddrinfo(result);

    // Locator configuration

    network.endpoint = locator_config.at("endpoint", defaults::endpoint).as_string();
    network.locator  = locator_config.at("port", defaults::locator_port).to<uint16_t>();

    // WARNING: Now only arrays of two items are allowed.
    auto ports = locator_config.find("port-range");

    if(ports != locator_config.end()) {
        network.ports = ports->second.to<std::tuple<uint16_t, uint16_t>>();
    }

    // Cluster configuration

    if(!network_config.empty()) {
        if(network_config.count("group") == 1) {
            network.group = network_config["group"].as_string();
        }

        if(network_config.count("gateway") == 1) {
            network.gateway = {
                network_config["gateway"].as_object().at("type", "adhoc").as_string(),
                network_config["gateway"].as_object().at("args", dynamic_t::empty_object)
            };
        }
    }

#ifdef COCAINE_ALLOW_RAFT
    create_raft_cluster = false;
#endif

    // Component configuration
    logging  = root.as_object().at("logging" , dynamic_t::empty_object).to<config_t::logging_t>();
    services = root.as_object().at("services", dynamic_t::empty_object).to<config_t::component_map_t>();
    storages = root.as_object().at("storages", dynamic_t::empty_object).to<config_t::component_map_t>();
}
コード例 #8
0
ファイル: dynamic.cpp プロジェクト: irakov/cocaine-core
bool
dynamic_t::operator!=(const dynamic_t& other) const {
    return !other.apply(equals_visitor(*this));
}
コード例 #9
0
ファイル: dynamic.cpp プロジェクト: irakov/cocaine-core
dynamic_t::dynamic_t(const dynamic_t& other) :
    m_value(null_t())
{
    other.apply(assign_visitor(*this));
}
コード例 #10
0
ファイル: uniresis.cpp プロジェクト: cocaine/cocaine-plugins
uniresis_t::uniresis_t(context_t& context, asio::io_service& loop, const std::string& name, const dynamic_t& args) :
    api::service_t(context, loop, name, args),
    dispatch<io::uniresis_tag>(name),
    uuid(context.uuid()),
    resources(),
    updater(nullptr),
    log(context.log("uniresis"))
{
    if (resources.cpu == 0) {
        throw std::system_error(uniresis::uniresis_errc::failed_calculate_cpu_count);
    }

    if (resources.mem == 0) {
        throw std::system_error(uniresis::uniresis_errc::failed_calculate_system_memory);
    }

    auto restrictions = args.as_object().at("restrictions", dynamic_t::empty_object).as_object();

    auto cpu_restricted = std::min(
        resources.cpu,
        static_cast<uint>(restrictions.at("cpu", resources.cpu).as_uint())
    );

    if (resources.cpu != cpu_restricted) {
        resources.cpu = cpu_restricted;
        COCAINE_LOG_INFO(log, "restricted available CPU count to {}", resources.cpu);
    }

    auto mem_restricted = std::min(
        resources.mem,
        static_cast<std::uint64_t>(restrictions.at("mem", resources.mem).as_uint())
    );

    if (resources.mem != mem_restricted) {
        resources.mem = mem_restricted;
        COCAINE_LOG_INFO(log, "restricted available system memory to {}", resources.mem);
    }

    auto prefix = args.as_object().at("prefix", defaults::resources_path).as_string();
    auto path = format("{}/{}", prefix, uuid);

    auto hostname = context.config().network().hostname();
    auto endpoints = resolve(hostname);
    dynamic_t::object_t extra;
    if (auto locator = context.config().services().get("locator")) {
        extra = dynamic_converter<dynamic_t::object_t>::convert(
            locator->args().as_object().at("extra_param", dynamic_t::empty_object)
        );
    }
    auto unicorn = api::unicorn(context, args.as_object().at("unicorn", defaults::unicorn_name).as_string());
    updater = std::make_shared<updater_t>(
        std::move(path),
        std::move(hostname),
        std::move(endpoints),
        std::move(extra),
        resources,
        std::move(unicorn),
        log
    );
    updater->notify();

    on<io::uniresis::cpu_count>([&] {
        return resources.cpu;
    });

    on<io::uniresis::memory_count>([&] {
        return resources.mem;
    });

    on<io::uniresis::uuid>([&] {
        return uuid;
    });
}
コード例 #11
0
ファイル: files.cpp プロジェクト: b-xiang/cocaine-core
files_t::files_t(context_t& context, const std::string& name, const dynamic_t& args):
    category_type(context, name, args),
    m_log(context.log(name)),
    m_parent_path(args.as_object().at("path").as_string())
{ }