22 #include "mongodb_instance_config.h" 24 #include <config/config.h> 25 #include <core/exceptions/system.h> 26 #include <mongo/client/dbclient.h> 27 #include <utils/sub_process/proc.h> 28 #include <utils/time/wait.h> 30 #include <boost/filesystem.hpp> 36 using namespace std::chrono_literals;
56 set_name(
"MongoDBInstance|%s", cfgname.c_str());
57 config_name_ = cfgname;
63 enabled_ = config->
get_bool(prefix +
"enabled");
68 startup_grace_period_ = 10;
70 startup_grace_period_ = config->
get_uint(prefix +
"startup-grace-period");
75 loop_interval_ = config->
get_float(prefix +
"loop-interval");
78 termination_grace_period_ = config->
get_uint(prefix +
"termination-grace-period");
79 clear_data_on_termination_ = config->
get_bool(prefix +
"clear-data-on-termination");
80 port_ = config->
get_uint(prefix +
"port");
81 data_path_ = config->
get_string(prefix +
"data-path");
82 log_path_ = config->
get_string(prefix +
"log/path");
83 log_append_ = config->
get_bool(prefix +
"log/append");
85 replica_set_ = config->
get_string(prefix +
"replica-set");
89 if (!replica_set_.empty()) {
92 oplog_size_ = config->
get_uint(prefix +
"oplog-size");
98 argv_ = {
"mongod",
"--port", std::to_string(port_),
"--dbpath", data_path_};
100 if (!log_path_.empty()) {
102 argv_.push_back(
"--logappend");
104 argv_.push_back(
"--logpath");
105 argv_.push_back(log_path_);
108 if (!replica_set_.empty()) {
109 argv_.push_back(
"--replSet");
110 argv_.push_back(replica_set_);
111 if (oplog_size_ > 0) {
112 argv_.push_back(
"--oplogSize");
113 argv_.push_back(std::to_string(oplog_size_));
119 if (!extra_args.empty()) {
121 int wrv = wordexp(extra_args.c_str(), &p, WRDE_NOCMD | WRDE_UNDEF);
124 case WRDE_BADCHAR:
throw Exception(
"%s: invalid character in args",
name());
125 case WRDE_BADVAL:
throw Exception(
"%s: undefined variable referenced in args",
name());
127 throw Exception(
"%s: running sub-commands has been disabled for args",
name());
129 case WRDE_SYNTAX:
throw Exception(
"%s: shell syntax error in args",
name());
130 default:
throw Exception(
"Unexpected wordexp error %d when parsing args", wrv);
135 std::vector<std::string> invalid_args = {
"--port",
148 for (
size_t i = 0; i < p.we_wordc; ++i) {
149 for (
size_t j = 0; j < invalid_args.size(); ++j) {
150 if (invalid_args[j] == p.we_wordv[i]) {
152 throw Exception(
"%s: %s may not be passed in args",
name(), invalid_args[j].c_str());
155 argv_.push_back(p.we_wordv[i]);
161 command_line_ = std::accumulate(std::next(argv_.begin()),
164 [](std::string &s,
const std::string &a) {
return s +
" " + a; });
175 "clear data on termination: %s",
176 clear_data_on_termination_ ?
"yes" :
"no");
182 replica_set_.empty() ?
"DISABLED" : replica_set_.c_str());
183 if (!replica_set_.empty()) {
189 throw Exception(
"Instance '%s' cannot be started while disabled",
name());
192 timewait_ =
new TimeWait(
clock, (
int)(loop_interval_ * 1000000.));
199 if (!running_ || !check_alive()) {
225 return command_line_;
234 return termination_grace_period_;
238 MongoDBInstanceConfig::check_alive()
241 std::shared_ptr<mongo::DBClientConnection> client =
242 std::make_shared<mongo::DBClientConnection>();
244 mongo::HostAndPort hostport(
"localhost", port_);
245 if (!client->connect(hostport, errmsg)) {
248 mongo::BSONObj cmd(BSON(
"isMaster" << 1));
249 mongo::BSONObj reply;
250 bool ok = client->runCommand(
"admin", cmd, reply);
255 }
catch (mongo::DBException &e) {
275 boost::filesystem::create_directories(data_path_);
276 }
catch (boost::filesystem::filesystem_error &e) {
277 throw Exception(
"Failed to create data path '%s' for mongod(%s): %s",
279 config_name_.c_str(),
283 if (!log_path_.empty()) {
284 boost::filesystem::path p(log_path_);
286 boost::filesystem::create_directories(p.parent_path());
287 }
catch (boost::filesystem::filesystem_error &e) {
288 throw Exception(
"Failed to create log path '%s' for mongod(%s): %s",
289 p.parent_path().string().c_str(),
290 config_name_.c_str(),
295 std::string progname =
"mongod(" + config_name_ +
")";
297 std::make_shared<SubProcess>(progname,
"mongod", argv_, std::vector<std::string>{},
logger);
299 for (
unsigned i = 0; i < startup_grace_period_ * 4; ++i) {
304 std::this_thread::sleep_for(250ms);
308 throw Exception(
"%s: instance did not start in time",
name());
322 for (
unsigned i = 0; i < termination_grace_period_; ++i) {
325 std::this_thread::sleep_for(1s);
332 boost::filesystem::remove_all(data_path_);
333 }
catch (boost::filesystem::filesystem_error &e) {
334 throw Exception(
"Failed to create data path '%s' for mongod(%s): %s",
336 config_name_.c_str(),
MongoDBInstanceConfig(fawkes::Configuration *config, std::string cfgname, std::string prefix)
Constructor.
void start_mongod()
Start mongod.
virtual void finalize()
Finalize the thread.
Fawkes library namespace.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
unsigned int termination_grace_period() const
Get termination grace period.
Thread class encapsulation of pthreads.
Logger * logger
This is the Logger member used to access the logger.
void wait_systime()
Wait until minimum loop time has been reached in real time.
Clock * clock
By means of this member access to the clock is given.
virtual void init()
Initialize the thread.
void set_name(const char *format,...)
Set name of thread.
Base class for exceptions in Fawkes.
void kill_mongod(bool clear_data)
Stop mongod.
const char * name() const
Get name of thread.
virtual const char * what_no_backtrace() const
Get primary string (does not implicitly print the back trace).
std::string command_line() const
Get command line used to execute program.
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual void log_error(const char *component, const char *format,...)=0
Log error message.
void mark_start()
Mark start of loop.
virtual void loop()
Code to execute in the thread.
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
virtual std::string get_string_or_default(const char *path, const std::string &default_val)
Get value from configuration which is of type string, or the given default if the path does not exist...
virtual unsigned int get_uint(const char *path)=0
Get value from configuration which is of type unsigned int.
Interface for configuration handling.
virtual float get_float(const char *path)=0
Get value from configuration which is of type float.
System ran out of memory and desired operation could not be fulfilled.
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.