| /* |
| * The MIT License (MIT) |
| * |
| * Copyright (c) 2015 Microsoft Corporation |
| * |
| * -=- Robust Distributed System Nucleus (rDSN) -=- |
| * |
| * 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 "runtime/tool_api.h" |
| |
| #include <algorithm> |
| #include <functional> |
| #include <map> |
| #include <memory> |
| #include <type_traits> |
| #include <utility> |
| |
| #include "runtime/global_config.h" |
| #include "runtime/rpc/message_parser_manager.h" |
| #include "runtime/service_engine.h" |
| #include "runtime/task/task.h" |
| #include "runtime/task/task_code.h" |
| #include "utils/error_code.h" |
| #include "utils/factory_store.h" |
| #include "utils/fmt_logging.h" |
| #include "utils/singleton_store.h" |
| #include "utils/sys_exit_hook.h" |
| #include "utils/threadpool_code.h" |
| |
| namespace dsn { |
| |
| DEFINE_TASK_CODE(LPC_CONTROL_SERVICE_APP, TASK_PRIORITY_HIGH, THREAD_POOL_DEFAULT) |
| |
| class service_control_task : public task |
| { |
| public: |
| service_control_task(service_node *node, bool start, bool cleanup = false) |
| : task(LPC_CONTROL_SERVICE_APP, 0, node), _node(node), _start(start), _cleanup(cleanup) |
| { |
| } |
| |
| void exec() |
| { |
| auto &sp = _node->spec(); |
| |
| if (_start) { |
| error_code err; |
| err = _node->start_app(); |
| CHECK_EQ_MSG(err, ERR_OK, "start app failed"); |
| } else { |
| LOG_INFO("stop app result({})", _node->stop_app(_cleanup)); |
| } |
| } |
| |
| private: |
| service_node *_node; |
| bool _start; // false for stop |
| bool _cleanup; // for stop |
| }; |
| |
| namespace tools { |
| |
| tool_base::tool_base(const char *name) { _name = name; } |
| |
| toollet::toollet(const char *name) : tool_base(name) {} |
| |
| tool_app::tool_app(const char *name) : tool_base(name) {} |
| |
| void tool_app::start_all_apps() |
| { |
| const auto &apps = service_engine::instance().get_all_nodes(); |
| for (const auto &kv : apps) { |
| task *t = new service_control_task(kv.second.get(), true); |
| t->set_delay(1000 * kv.second.get()->spec().delay_seconds); |
| t->enqueue(); |
| } |
| } |
| |
| void tool_app::stop_all_apps(bool cleanup) |
| { |
| const auto &apps = service_engine::instance().get_all_nodes(); |
| for (const auto &kv : apps) { |
| task *t = new service_control_task(kv.second.get(), false, cleanup); |
| t->enqueue(); |
| } |
| } |
| |
| const service_spec &tool_app::get_service_spec() { return service_engine::instance().spec(); } |
| |
| const service_spec &spec() { return service_engine::instance().spec(); } |
| |
| const char *get_service_node_name(service_node *node) { return node->full_name(); } |
| |
| join_point<void> sys_init_before_app_created("system.init.1"); |
| join_point<void> sys_init_after_app_created("system.init.2"); |
| join_point<void, sys_exit_type> sys_exit("system.exit"); |
| |
| namespace internal_use_only { |
| bool register_toollet(const char *name, toollet::factory f, ::dsn::provider_type type) |
| { |
| return dsn::utils::factory_store<toollet>::register_factory(name, f, type); |
| } |
| |
| bool register_tool(const char *name, tool_app::factory f, ::dsn::provider_type type) |
| { |
| return dsn::utils::factory_store<tool_app>::register_factory(name, f, type); |
| } |
| |
| bool register_component_provider(const char *name, |
| timer_service::factory f, |
| ::dsn::provider_type type) |
| { |
| return dsn::utils::factory_store<timer_service>::register_factory(name, f, type); |
| } |
| |
| bool register_component_provider(const char *name, task_queue::factory f, ::dsn::provider_type type) |
| { |
| return dsn::utils::factory_store<task_queue>::register_factory(name, f, type); |
| } |
| |
| bool register_component_provider(const char *name, |
| task_worker::factory f, |
| ::dsn::provider_type type) |
| { |
| return dsn::utils::factory_store<task_worker>::register_factory(name, f, type); |
| } |
| |
| bool register_component_provider(const char *name, network::factory f, ::dsn::provider_type type) |
| { |
| return dsn::utils::factory_store<network>::register_factory(name, f, type); |
| } |
| |
| bool register_component_provider(const char *name, |
| env_provider::factory f, |
| ::dsn::provider_type type) |
| { |
| return dsn::utils::factory_store<env_provider>::register_factory(name, f, type); |
| } |
| |
| bool register_component_provider(network_header_format fmt, |
| const std::vector<const char *> &signatures, |
| message_parser::factory f, |
| size_t sz) |
| { |
| message_parser_manager::instance().register_factory(fmt, signatures, f, sz); |
| return true; |
| } |
| |
| toollet *get_toollet(const char *name, ::dsn::provider_type type) |
| { |
| toollet *tlt = nullptr; |
| if (utils::singleton_store<std::string, toollet *>::instance().get(name, tlt)) |
| return tlt; |
| else { |
| tlt = utils::factory_store<toollet>::create(name, type, name); |
| utils::singleton_store<std::string, toollet *>::instance().put(name, tlt); |
| return tlt; |
| } |
| } |
| } // namespace internal_use_only |
| } // namespace tools |
| } // namespace dsn |