2016-12-20 01:32:44 +08:00
|
|
|
#include <signal.h>
|
2017-05-30 22:26:16 +08:00
|
|
|
#include <experimental/filesystem>
|
2017-01-23 19:02:11 +08:00
|
|
|
#include <iostream>
|
2016-08-10 16:39:02 +08:00
|
|
|
|
2017-05-22 18:31:04 +08:00
|
|
|
#include "gflags/gflags.h"
|
|
|
|
|
2017-03-06 20:37:51 +08:00
|
|
|
#include "dbms/dbms.hpp"
|
|
|
|
#include "query/engine.hpp"
|
2016-08-10 16:39:02 +08:00
|
|
|
|
2017-03-06 20:37:51 +08:00
|
|
|
#include "communication/bolt/v1/session.hpp"
|
|
|
|
#include "communication/server.hpp"
|
|
|
|
|
|
|
|
#include "io/network/network_endpoint.hpp"
|
|
|
|
#include "io/network/network_error.hpp"
|
2016-08-10 16:39:02 +08:00
|
|
|
#include "io/network/socket.hpp"
|
|
|
|
|
|
|
|
#include "logging/default.hpp"
|
|
|
|
#include "logging/streams/stdout.hpp"
|
|
|
|
|
2016-12-16 20:56:36 +08:00
|
|
|
#include "utils/signals/handler.hpp"
|
2016-12-20 01:32:44 +08:00
|
|
|
#include "utils/stacktrace/log.hpp"
|
2017-01-13 17:47:17 +08:00
|
|
|
#include "utils/terminate_handler.hpp"
|
2016-08-01 01:58:12 +08:00
|
|
|
|
2017-05-30 22:26:16 +08:00
|
|
|
namespace fs = std::experimental::filesystem;
|
2017-03-06 20:37:51 +08:00
|
|
|
using endpoint_t = io::network::NetworkEndpoint;
|
|
|
|
using socket_t = io::network::Socket;
|
2017-03-22 23:36:48 +08:00
|
|
|
using session_t = communication::bolt::Session<socket_t>;
|
2017-05-22 18:31:04 +08:00
|
|
|
using result_stream_t =
|
|
|
|
communication::bolt::ResultStream<communication::bolt::Encoder<
|
|
|
|
communication::bolt::ChunkedEncoderBuffer<socket_t>>>;
|
2017-03-28 18:42:04 +08:00
|
|
|
using bolt_server_t =
|
|
|
|
communication::Server<session_t, result_stream_t, socket_t>;
|
2017-03-06 20:37:51 +08:00
|
|
|
|
|
|
|
static bolt_server_t *serverptr;
|
2016-08-10 16:39:02 +08:00
|
|
|
|
|
|
|
Logger logger;
|
|
|
|
|
2017-05-22 18:31:04 +08:00
|
|
|
DEFINE_string(interface, "0.0.0.0", "Default interface on which to listen.");
|
|
|
|
DEFINE_string(port, "7687", "Default port on which to listen.");
|
2017-06-06 21:48:04 +08:00
|
|
|
DEFINE_int32(num_workers, std::thread::hardware_concurrency(),
|
|
|
|
"Number of workers");
|
2016-08-01 01:58:12 +08:00
|
|
|
|
2017-01-23 19:02:11 +08:00
|
|
|
void throw_and_stacktace(std::string message) {
|
|
|
|
Stacktrace stacktrace;
|
|
|
|
logger.info(stacktrace.dump());
|
2017-01-13 17:47:17 +08:00
|
|
|
}
|
|
|
|
|
2017-06-07 21:23:08 +08:00
|
|
|
// Load flags in this order, the last one has the highest priority:
|
|
|
|
// 1) /etc/memgraph/config
|
|
|
|
// 2) ~/.memgraph/config
|
|
|
|
// 3) env - MEMGRAPH_CONFIG
|
|
|
|
// 4) command line flags
|
|
|
|
|
|
|
|
void load_config(int &argc, char **&argv) {
|
|
|
|
std::vector<fs::path> configs = {fs::path("/etc/memgraph/config")};
|
|
|
|
if (getenv("HOME") != nullptr)
|
|
|
|
configs.emplace_back(fs::path(getenv("HOME")) /
|
|
|
|
fs::path(".memgraph/config"));
|
|
|
|
if (getenv("MEMGRAPH_CONFIG") != nullptr)
|
|
|
|
configs.emplace_back(fs::path(getenv("MEMGRAPH_CONFIG")));
|
|
|
|
|
|
|
|
std::vector<std::string> flagfile_arguments;
|
|
|
|
for (const auto &config : configs)
|
|
|
|
if (fs::exists(config)) {
|
|
|
|
flagfile_arguments.emplace_back(
|
|
|
|
std::string("--flagfile=" + config.generic_string()));
|
|
|
|
}
|
|
|
|
|
|
|
|
int custom_argc = static_cast<int>(flagfile_arguments.size()) + 1;
|
|
|
|
char **custom_argv = new char *[custom_argc];
|
|
|
|
|
|
|
|
custom_argv[0] = strdup(std::string("memgraph").c_str());
|
|
|
|
for (int i = 0; i < (int)flagfile_arguments.size(); ++i) {
|
|
|
|
custom_argv[i + 1] = strdup(flagfile_arguments[i].c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
// setup flags from config flags
|
|
|
|
gflags::ParseCommandLineFlags(&custom_argc, &custom_argv, false);
|
|
|
|
|
|
|
|
// unconsumed arguments have to be freed to avoid memory leak since they are
|
|
|
|
// strdup-ed.
|
|
|
|
for (int i = 0; i < custom_argc; ++i) free(custom_argv[i]);
|
|
|
|
delete[] custom_argv;
|
|
|
|
|
|
|
|
// setup flags from command line
|
|
|
|
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
|
|
|
}
|
|
|
|
|
2017-01-23 19:02:11 +08:00
|
|
|
int main(int argc, char **argv) {
|
2017-05-30 22:26:16 +08:00
|
|
|
fs::current_path(fs::path(argv[0]).parent_path());
|
2017-06-07 21:23:08 +08:00
|
|
|
load_config(argc, argv);
|
2017-06-06 21:48:04 +08:00
|
|
|
// Logging init.
|
2016-08-19 08:28:22 +08:00
|
|
|
#ifdef SYNC_LOGGER
|
2017-01-23 19:02:11 +08:00
|
|
|
logging::init_sync();
|
2016-08-19 08:28:22 +08:00
|
|
|
#else
|
2017-01-23 19:02:11 +08:00
|
|
|
logging::init_async();
|
2016-08-19 08:28:22 +08:00
|
|
|
#endif
|
2017-01-23 19:02:11 +08:00
|
|
|
logging::log->pipe(std::make_unique<Stdout>());
|
|
|
|
|
2017-06-06 21:48:04 +08:00
|
|
|
// Get logger.
|
2017-01-23 19:02:11 +08:00
|
|
|
logger = logging::log->logger("Main");
|
|
|
|
logger.info("{}", logging::log->type());
|
|
|
|
|
2017-06-06 21:48:04 +08:00
|
|
|
// Unhandled exception handler init.
|
2017-01-23 19:02:11 +08:00
|
|
|
std::set_terminate(&terminate_handler);
|
|
|
|
|
2017-06-06 21:48:04 +08:00
|
|
|
// Signal handling init.
|
2017-01-23 19:02:11 +08:00
|
|
|
SignalHandler::register_handler(Signal::SegmentationFault, []() {
|
|
|
|
log_stacktrace("SegmentationFault signal raised");
|
|
|
|
std::exit(EXIT_FAILURE);
|
|
|
|
});
|
|
|
|
SignalHandler::register_handler(Signal::Terminate, []() {
|
|
|
|
log_stacktrace("Terminate signal raised");
|
|
|
|
std::exit(EXIT_FAILURE);
|
|
|
|
});
|
|
|
|
SignalHandler::register_handler(Signal::Abort, []() {
|
|
|
|
log_stacktrace("Abort signal raised");
|
|
|
|
std::exit(EXIT_FAILURE);
|
|
|
|
});
|
|
|
|
|
2017-06-06 21:48:04 +08:00
|
|
|
// Initialize endpoint.
|
2017-03-06 20:37:51 +08:00
|
|
|
endpoint_t endpoint;
|
2017-01-23 19:02:11 +08:00
|
|
|
try {
|
2017-05-22 18:31:04 +08:00
|
|
|
endpoint = endpoint_t(FLAGS_interface, FLAGS_port);
|
2017-03-06 20:37:51 +08:00
|
|
|
} catch (io::network::NetworkEndpointException &e) {
|
2017-01-23 19:02:11 +08:00
|
|
|
logger.error("{}", e.what());
|
|
|
|
std::exit(EXIT_FAILURE);
|
|
|
|
}
|
2017-03-06 20:37:51 +08:00
|
|
|
|
2017-06-06 21:48:04 +08:00
|
|
|
// Initialize socket.
|
2017-03-06 20:37:51 +08:00
|
|
|
socket_t socket;
|
|
|
|
if (!socket.Bind(endpoint)) {
|
2017-05-22 18:31:04 +08:00
|
|
|
logger.error("Cannot bind to socket on {} at {}", FLAGS_interface,
|
|
|
|
FLAGS_port);
|
2017-03-06 20:37:51 +08:00
|
|
|
std::exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
if (!socket.SetNonBlocking()) {
|
|
|
|
logger.error("Cannot set socket to non blocking!");
|
|
|
|
std::exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
if (!socket.Listen(1024)) {
|
|
|
|
logger.error("Cannot listen on socket!");
|
|
|
|
std::exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2017-05-22 18:31:04 +08:00
|
|
|
logger.info("Listening on {} at {}", FLAGS_interface, FLAGS_port);
|
2017-01-23 19:02:11 +08:00
|
|
|
|
2017-03-06 20:37:51 +08:00
|
|
|
Dbms dbms;
|
2017-03-22 23:36:48 +08:00
|
|
|
QueryEngine<result_stream_t> query_engine;
|
2017-03-06 20:37:51 +08:00
|
|
|
|
2017-06-06 21:48:04 +08:00
|
|
|
// Initialize server.
|
2017-03-06 20:37:51 +08:00
|
|
|
bolt_server_t server(std::move(socket), dbms, query_engine);
|
2017-01-23 19:02:11 +08:00
|
|
|
serverptr = &server;
|
|
|
|
|
2017-06-06 21:48:04 +08:00
|
|
|
// Start worker threads.
|
|
|
|
logger.info("Starting {} workers", FLAGS_num_workers);
|
|
|
|
server.Start(FLAGS_num_workers);
|
2017-01-23 19:02:11 +08:00
|
|
|
|
|
|
|
logger.info("Shutting down...");
|
|
|
|
return EXIT_SUCCESS;
|
2016-08-01 01:58:12 +08:00
|
|
|
}
|