OmniSciDB  d2f719934e
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
/home/jenkins-slave/workspace/core-os-doxygen/MapDServer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018 OmniSci, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
19 
20 #ifdef HAVE_THRIFT_THREADFACTORY
21 #include <thrift/concurrency/ThreadFactory.h>
22 #else
23 #include <thrift/concurrency/PlatformThreadFactory.h>
24 #endif
25 
26 #include <thrift/concurrency/ThreadManager.h>
27 #include <thrift/protocol/TBinaryProtocol.h>
28 #include <thrift/protocol/TJSONProtocol.h>
29 #include <thrift/server/TThreadedServer.h>
30 #include <thrift/transport/TBufferTransports.h>
31 #include <thrift/transport/THttpServer.h>
32 #include <thrift/transport/TSSLServerSocket.h>
33 #include <thrift/transport/TSSLSocket.h>
34 #include <thrift/transport/TServerSocket.h>
35 
36 #include "Logger/Logger.h"
38 #include "Shared/file_delete.h"
40 #include "Shared/scope.h"
41 
42 #include <boost/algorithm/string.hpp>
43 #include <boost/algorithm/string/trim.hpp>
44 #include <boost/filesystem.hpp>
45 #include <boost/locale/generator.hpp>
46 #include <boost/make_shared.hpp>
47 #include <boost/program_options.hpp>
48 
49 #include <csignal>
50 #include <cstdlib>
51 #include <sstream>
52 #include <thread>
53 #include <vector>
54 
55 #ifdef HAVE_AWS_S3
56 #include "DataMgr/OmniSciAwsSdk.h"
57 #endif
58 #include "MapDRelease.h"
59 #include "Shared/Compressor.h"
61 #include "Shared/file_delete.h"
62 #include "Shared/scope.h"
64 
65 using namespace ::apache::thrift;
66 using namespace ::apache::thrift::concurrency;
67 using namespace ::apache::thrift::protocol;
68 using namespace ::apache::thrift::server;
69 using namespace ::apache::thrift::transport;
70 
71 extern bool g_enable_thrift_logs;
72 
73 // Set g_running to false to trigger normal server shutdown.
74 std::atomic<bool> g_running{true};
75 
76 namespace { // anonymous
77 
78 std::atomic<int> g_saw_signal{-1};
79 
80 std::shared_ptr<TThreadedServer> g_thrift_http_server;
81 std::shared_ptr<TThreadedServer> g_thrift_tcp_server;
82 
83 std::shared_ptr<DBHandler> g_warmup_handler;
84 // global "g_warmup_handler" needed to avoid circular dependency
85 // between "DBHandler" & function "run_warmup_queries"
86 
87 std::shared_ptr<DBHandler> g_mapd_handler;
88 
89 void register_signal_handler(int signum, void (*handler)(int)) {
90 #ifdef _WIN32
91  signal(signum, handler);
92 #else
93  struct sigaction act;
94  memset(&act, 0, sizeof(act));
95  if (handler != SIG_DFL && handler != SIG_IGN) {
96  // block all signal deliveries while inside the signal handler
97  sigfillset(&act.sa_mask);
98  }
99  act.sa_handler = handler;
100  sigaction(signum, &act, NULL);
101 #endif
102 }
103 
104 // Signal handler to set a global flag telling the server to exit.
105 // Do not call other functions inside this (or any) signal handler
106 // unless you really know what you are doing. See also:
107 // man 7 signal-safety
108 // man 7 signal
109 // https://en.wikipedia.org/wiki/Reentrancy_(computing)
110 void omnisci_signal_handler(int signum) {
111  // Record the signal number for logging during shutdown.
112  // Only records the first signal if called more than once.
113  int expected_signal{-1};
114  if (!g_saw_signal.compare_exchange_strong(expected_signal, signum)) {
115  return; // this wasn't the first signal
116  }
117 
118  // This point should never be reached more than once.
119 
120  // Tell heartbeat() to shutdown by unsetting the 'g_running' flag.
121  // If 'g_running' is already false, this has no effect and the
122  // shutdown is already in progress.
123  g_running = false;
124 
125  // Handle core dumps specially by pausing inside this signal handler
126  // because on some systems, some signals will execute their default
127  // action immediately when and if the signal handler returns.
128  // We would like to do some emergency cleanup before core dump.
129  if (signum == SIGABRT || signum == SIGSEGV || signum == SIGFPE
130 #ifndef _WIN32
131  || signum == SIGQUIT
132 #endif
133  ) {
134  // Wait briefly to give heartbeat() a chance to flush the logs and
135  // do any other emergency shutdown tasks.
136  std::this_thread::sleep_for(std::chrono::seconds(2));
137 
138  // Explicitly trigger whatever default action this signal would
139  // have done, such as terminate the process or dump core.
140  // Signals are currently blocked so this new signal will be queued
141  // until this signal handler returns.
142  register_signal_handler(signum, SIG_DFL);
143 #ifdef _WIN32
144  raise(signum);
145 #else
146  kill(getpid(), signum);
147 #endif
148  std::this_thread::sleep_for(std::chrono::seconds(5));
149 
150 #ifndef __APPLE__
151  // as a last resort, abort
152  // primary used in Docker environments, where we can end up with PID 1 and fail to
153  // catch unix signals
154  quick_exit(signum);
155 #endif
156  }
157 }
158 
161 #ifndef _WIN32
164 #endif
168 #ifndef _WIN32
169  // Thrift secure socket can cause problems with SIGPIPE
170  register_signal_handler(SIGPIPE, SIG_IGN);
171 #endif
172 }
173 
174 } // anonymous namespace
175 
176 void start_server(std::shared_ptr<TThreadedServer> server, const int port) {
177  try {
178  server->serve();
179  if (errno != 0) {
180  throw std::runtime_error(std::string("Thrift server exited: ") +
181  std::strerror(errno));
182  }
183  } catch (std::exception& e) {
184  LOG(ERROR) << "Exception: " << e.what() << ": port " << port << std::endl;
185  }
186 }
187 
188 void releaseWarmupSession(TSessionId& sessionId, std::ifstream& query_file) noexcept {
189  query_file.close();
190  if (sessionId != g_warmup_handler->getInvalidSessionId()) {
191  try {
192  g_warmup_handler->disconnect(sessionId);
193  } catch (...) {
194  LOG(ERROR) << "Failed to disconnect warmup session, possible failure to run warmup "
195  "queries.";
196  }
197  }
198 }
199 
200 void run_warmup_queries(std::shared_ptr<DBHandler> handler,
201  std::string base_path,
202  std::string query_file_path) {
203  // run warmup queries to load cache if requested
204  if (query_file_path.empty()) {
205  return;
206  }
207  if (handler->isAggregator()) {
208  LOG(INFO) << "Skipping warmup query execution on the aggregator, queries should be "
209  "run directly on the leaf nodes.";
210  return;
211  }
212 
213  LOG(INFO) << "Running DB warmup with queries from " << query_file_path;
214  try {
215  g_warmup_handler = handler;
216  std::string db_info;
217  std::string user_keyword, user_name, db_name;
218  std::ifstream query_file;
221  TSessionId sessionId = g_warmup_handler->getInvalidSessionId();
222 
223  ScopeGuard session_guard = [&] { releaseWarmupSession(sessionId, query_file); };
224  query_file.open(query_file_path);
225  while (std::getline(query_file, db_info)) {
226  if (db_info.length() == 0) {
227  continue;
228  }
229  std::istringstream iss(db_info);
230  iss >> user_keyword >> user_name >> db_name;
231  if (user_keyword.compare(0, 4, "USER") == 0) {
232  // connect to DB for given user_name/db_name with super_user_rights (without
233  // password), & start session
234  g_warmup_handler->super_user_rights_ = true;
235  g_warmup_handler->connect(sessionId, user_name, "", db_name);
236  g_warmup_handler->super_user_rights_ = false;
237 
238  // read and run one query at a time for the DB with the setup connection
239  TQueryResult ret;
240  std::string single_query;
241  while (std::getline(query_file, single_query)) {
242  boost::algorithm::trim(single_query);
243  if (single_query.length() == 0 || single_query[0] == '-') {
244  continue;
245  }
246  if (single_query[0] == '}') {
247  single_query.clear();
248  break;
249  }
250  if (single_query.find(';') == single_query.npos) {
251  std::string multiline_query;
252  std::getline(query_file, multiline_query, ';');
253  single_query += multiline_query;
254  }
255 
256  try {
257  g_warmup_handler->sql_execute(ret, sessionId, single_query, true, "", -1, -1);
258  } catch (...) {
259  LOG(WARNING) << "Exception while executing '" << single_query
260  << "', ignoring";
261  }
262  single_query.clear();
263  }
264 
265  // stop session and disconnect from the DB
266  g_warmup_handler->disconnect(sessionId);
267  sessionId = g_warmup_handler->getInvalidSessionId();
268  } else {
269  LOG(WARNING) << "\nSyntax error in the file: " << query_file_path.c_str()
270  << " Missing expected keyword USER. Following line will be ignored: "
271  << db_info.c_str() << std::endl;
272  }
273  db_info.clear();
274  }
275  } catch (const std::exception& e) {
276  LOG(WARNING)
277  << "Exception while executing warmup queries. "
278  << "Warmup may not be fully completed. Will proceed nevertheless.\nError was: "
279  << e.what();
280  }
281 }
282 
283 void thrift_stop() {
284  if (auto thrift_http_server = g_thrift_http_server; thrift_http_server) {
285  thrift_http_server->stop();
286  }
287  g_thrift_http_server.reset();
288 
289  if (auto thrift_tcp_server = g_thrift_tcp_server; thrift_tcp_server) {
290  thrift_tcp_server->stop();
291  }
292  g_thrift_tcp_server.reset();
293 }
294 
295 void heartbeat() {
296 #ifndef _WIN32
297  // Block all signals for this heartbeat thread, only.
298  sigset_t set;
299  sigfillset(&set);
300  int result = pthread_sigmask(SIG_BLOCK, &set, NULL);
301  if (result != 0) {
302  throw std::runtime_error("heartbeat() thread startup failed");
303  }
304 #endif
305 
306  // Sleep until omnisci_signal_handler or anything clears the g_running flag.
307  VLOG(1) << "heartbeat thread starting";
308  while (::g_running) {
309  using namespace std::chrono;
310  std::this_thread::sleep_for(1s);
311  }
312  VLOG(1) << "heartbeat thread exiting";
313 
314  // Get the signal number if there was a signal.
315  int signum = g_saw_signal;
316  if (signum >= 1 && signum != SIGTERM) {
317  LOG(INFO) << "Interrupt signal (" << signum << ") received.";
318  }
319 
320  // If dumping core, try to do some quick stuff.
321  if (signum == SIGABRT || signum == SIGSEGV || signum == SIGFPE
322 #ifndef _WIN32
323  || signum == SIGQUIT
324 #endif
325  ) {
326  // Need to shut down calcite.
327  if (auto mapd_handler = g_mapd_handler; mapd_handler) {
328  mapd_handler->emergency_shutdown();
329  }
330  // Need to flush the logs for debugging.
332  return;
333  // Core dump should begin soon after this. See omnisci_signal_handler().
334  // We leave the rest of the server process as is for the core dump image.
335  }
336 
337  // Stopping the Thrift thread(s) will allow main() to return.
338  thrift_stop();
339 }
340 
341 #ifdef HAVE_THRIFT_MESSAGE_LIMIT
342 namespace {
343 // Creates a configuration object with the maximum possible value for the message size
344 // limit (~2GB).
345 inline std::shared_ptr<TConfiguration> create_unbounded_transport_config() {
346  return std::make_shared<TConfiguration>(std::numeric_limits<int32_t>::max());
347 }
348 
349 class UnboundedTBufferedTransportFactory : public TBufferedTransportFactory {
350  public:
351  UnboundedTBufferedTransportFactory() : TBufferedTransportFactory() {}
352 
353  std::shared_ptr<TTransport> getTransport(
354  std::shared_ptr<TTransport> transport) override {
355  return std::shared_ptr<TTransport>(
356  new TBufferedTransport(transport, create_unbounded_transport_config()));
357  }
358 };
359 
360 class UnboundedTHttpServerTransportFactory : public THttpServerTransportFactory {
361  public:
362  UnboundedTHttpServerTransportFactory() : THttpServerTransportFactory() {}
363 
364  std::shared_ptr<TTransport> getTransport(
365  std::shared_ptr<TTransport> transport) override {
366  return std::shared_ptr<TTransport>(
367  new THttpServer(transport, create_unbounded_transport_config()));
368  }
369 };
370 } // namespace
371 #endif
372 
373 int startMapdServer(CommandLineOptions& prog_config_opts, bool start_http_server = true) {
374  // Prepare to launch the Thrift server.
375  LOG(INFO) << "OmniSciDB starting up";
377 #ifdef HAVE_AWS_S3
379 #endif // HAVE_AWS_S3
380  std::set<std::unique_ptr<std::thread>> server_threads;
381  auto wait_for_server_threads = [&] {
382  for (auto& th : server_threads) {
383  try {
384  th->join();
385  } catch (const std::system_error& e) {
386  if (e.code() != std::errc::invalid_argument) {
387  LOG(WARNING) << "std::thread join failed: " << e.what();
388  }
389  } catch (const std::exception& e) {
390  LOG(WARNING) << "std::thread join failed: " << e.what();
391  } catch (...) {
392  LOG(WARNING) << "std::thread join failed";
393  }
394  }
395  };
396  ScopeGuard server_shutdown_guard = [&] {
397  // This function will never be called by exit(), but we shouldn't ever be calling
398  // exit(), we should be setting g_running to false instead.
399  LOG(INFO) << "OmniSciDB shutting down";
400 
401  g_running = false;
402 
403  thrift_stop();
404 
405  g_mapd_handler.reset();
406 
407  wait_for_server_threads();
408 
409  if (g_enable_fsi) {
411  }
412 
414 
415 #ifdef HAVE_AWS_S3
417 #endif // HAVE_AWS_S3
418 
419  // Flush the logs last to capture maximum debugging information.
421  };
422 
423  // start background thread to clean up _DELETE_ME files
424  const unsigned int wait_interval =
425  3; // wait time in secs after looking for deleted file before looking again
426  server_threads.insert(
427  std::make_unique<std::thread>(file_delete,
428  std::ref(g_running),
429  wait_interval,
430  prog_config_opts.base_path + "/mapd_data"));
431  server_threads.insert(std::make_unique<std::thread>(heartbeat));
432 
433  if (!g_enable_thrift_logs) {
434  apache::thrift::GlobalOutput.setOutputFunction([](const char* msg) {});
435  }
436 
438  // Use the locale setting of the server by default. The generate parameter can be
439  // updated appropriately if a locale override option is ever supported.
440  boost::locale::generator generator;
441  std::locale::global(generator.generate(""));
442  }
443 
444  // Thrift event handler for database server setup.
445  try {
446  if (prog_config_opts.system_parameters.master_address.empty()) {
447  // Handler for a single database server. (DBHandler)
448  g_mapd_handler =
449  std::make_shared<DBHandler>(prog_config_opts.db_leaves,
450  prog_config_opts.string_leaves,
451  prog_config_opts.base_path,
452  prog_config_opts.allow_multifrag,
453  prog_config_opts.jit_debug,
454  prog_config_opts.intel_jit_profile,
455  prog_config_opts.read_only,
456  prog_config_opts.allow_loop_joins,
457  prog_config_opts.enable_rendering,
458  prog_config_opts.renderer_use_vulkan_driver,
459  prog_config_opts.renderer_prefer_igpu,
460  prog_config_opts.renderer_vulkan_timeout_ms,
461  prog_config_opts.enable_auto_clear_render_mem,
462  prog_config_opts.render_oom_retry_threshold,
463  prog_config_opts.render_mem_bytes,
464  prog_config_opts.max_concurrent_render_sessions,
465  prog_config_opts.reserved_gpu_mem,
466  prog_config_opts.render_compositor_use_last_gpu,
467  prog_config_opts.num_reader_threads,
468  prog_config_opts.authMetadata,
469  prog_config_opts.system_parameters,
470  prog_config_opts.enable_legacy_syntax,
471  prog_config_opts.idle_session_duration,
472  prog_config_opts.max_session_duration,
473  prog_config_opts.enable_runtime_udf,
474  prog_config_opts.udf_file_name,
475  prog_config_opts.udf_compiler_path,
476  prog_config_opts.udf_compiler_options,
477 #ifdef ENABLE_GEOS
478  prog_config_opts.libgeos_so_filename,
479 #endif
480  prog_config_opts.disk_cache_config,
481  false);
482  } else { // running ha server
483  LOG(FATAL)
484  << "No High Availability module available, please contact OmniSci support";
485  }
486  } catch (const std::exception& e) {
487  LOG(FATAL) << "Failed to initialize service handler: " << e.what();
488  }
489 
490  if (g_enable_fsi) {
492  }
493 
494  // TCP port setup. We use Thrift both for a TCP socket and for an optional HTTP socket.
495  std::shared_ptr<TServerSocket> tcp_socket;
496  std::shared_ptr<TServerSocket> http_socket;
497 
498  if (!prog_config_opts.system_parameters.ssl_cert_file.empty() &&
499  !prog_config_opts.system_parameters.ssl_key_file.empty()) {
500  // SSL port setup.
501  auto sslSocketFactory = std::make_shared<TSSLSocketFactory>(SSLProtocol::SSLTLS);
502  sslSocketFactory->loadCertificate(
503  prog_config_opts.system_parameters.ssl_cert_file.c_str());
504  sslSocketFactory->loadPrivateKey(
505  prog_config_opts.system_parameters.ssl_key_file.c_str());
506  if (prog_config_opts.system_parameters.ssl_transport_client_auth) {
507  sslSocketFactory->authenticate(true);
508  } else {
509  sslSocketFactory->authenticate(false);
510  }
511  sslSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
512  tcp_socket = std::make_shared<TSSLServerSocket>(
513  prog_config_opts.system_parameters.omnisci_server_port, sslSocketFactory);
514  if (start_http_server) {
515  http_socket = std::make_shared<TSSLServerSocket>(prog_config_opts.http_port,
516  sslSocketFactory);
517  }
518  LOG(INFO) << " OmniSci server using encrypted connection. Cert file ["
519  << prog_config_opts.system_parameters.ssl_cert_file << "], key file ["
520  << prog_config_opts.system_parameters.ssl_key_file << "]";
521 
522  } else {
523  // Non-SSL port setup.
524  LOG(INFO) << " OmniSci server using unencrypted connection";
525  tcp_socket = std::make_shared<TServerSocket>(
526  prog_config_opts.system_parameters.omnisci_server_port);
527  if (start_http_server) {
528  http_socket = std::make_shared<TServerSocket>(prog_config_opts.http_port);
529  }
530  }
531 
532  // Thrift uses the same processor for both the TCP port and the HTTP port.
533  std::shared_ptr<TProcessor> processor{std::make_shared<TrackingProcessor>(
534  g_mapd_handler, prog_config_opts.log_user_origin)};
535 
536  // Thrift TCP server launch.
537  std::shared_ptr<TServerTransport> tcp_st = tcp_socket;
538 #ifdef HAVE_THRIFT_MESSAGE_LIMIT
539  std::shared_ptr<TTransportFactory> tcp_tf{
540  std::make_shared<UnboundedTBufferedTransportFactory>()};
541 #else
542  std::shared_ptr<TTransportFactory> tcp_tf{
543  std::make_shared<TBufferedTransportFactory>()};
544 #endif
545  std::shared_ptr<TProtocolFactory> tcp_pf{std::make_shared<TBinaryProtocolFactory>()};
546  g_thrift_tcp_server.reset(new TThreadedServer(processor, tcp_st, tcp_tf, tcp_pf));
547  server_threads.insert(std::make_unique<std::thread>(
548  start_server,
549  g_thrift_tcp_server,
550  prog_config_opts.system_parameters.omnisci_server_port));
551 
552  // Thrift HTTP server launch.
553  if (start_http_server) {
554  std::shared_ptr<TServerTransport> http_st = http_socket;
555 #ifdef HAVE_THRIFT_MESSAGE_LIMIT
556  std::shared_ptr<TTransportFactory> http_tf{
557  std::make_shared<UnboundedTHttpServerTransportFactory>()};
558 #else
559  std::shared_ptr<TTransportFactory> http_tf{
560  std::make_shared<THttpServerTransportFactory>()};
561 #endif
562  std::shared_ptr<TProtocolFactory> http_pf{std::make_shared<TJSONProtocolFactory>()};
563  g_thrift_http_server.reset(new TThreadedServer(processor, http_st, http_tf, http_pf));
564  server_threads.insert(std::make_unique<std::thread>(
565  start_server, g_thrift_http_server, prog_config_opts.http_port));
566  }
567 
568  // Run warm up queries if any exist.
570  g_mapd_handler, prog_config_opts.base_path, prog_config_opts.db_query_file);
571  if (prog_config_opts.exit_after_warmup) {
572  g_running = false;
573  }
574 
575  // Main thread blocks for as long as the servers are running.
576  wait_for_server_threads();
577 
578  // Clean shutdown.
579  int signum = g_saw_signal;
580  if (signum <= 0 || signum == SIGTERM) {
581  return 0;
582  } else {
583  return signum;
584  }
585 }
586 
587 int main(int argc, char** argv) {
588  bool has_clust_topo = false;
589 
590  CommandLineOptions prog_config_opts(argv[0], has_clust_topo);
591 
592  try {
593  if (auto return_code =
594  prog_config_opts.parse_command_line(argc, argv, !has_clust_topo)) {
595  return *return_code;
596  }
597 
598  if (!has_clust_topo) {
599  prog_config_opts.validate_base_path();
600  prog_config_opts.validate();
601  return (startMapdServer(prog_config_opts));
602  }
603  } catch (std::runtime_error& e) {
604  std::cerr << "Server Error: " << e.what() << std::endl;
605  return 1;
606  } catch (boost::program_options::error& e) {
607  std::cerr << "Usage Error: " << e.what() << std::endl;
608  return 1;
609  }
610 }
void register_signal_handler(int signum, void(*handler)(int))
Definition: MapDServer.cpp:89
void thrift_stop()
Definition: MapDServer.cpp:283
unsigned renderer_vulkan_timeout_ms
std::vector< LeafHostInfo > string_leaves
void releaseWarmupSession(TSessionId &sessionId, std::ifstream &query_file) noexcept
Definition: MapDServer.cpp:188
std::string udf_compiler_path
#define LOG(tag)
Definition: Logger.h:205
shared utility for the db server and string dictionary server to remove old files ...
void heartbeat()
Definition: MapDServer.cpp:295
boost::optional< int > parse_command_line(int argc, char const *const *argv, const bool should_init_logging=false)
size_t max_concurrent_render_sessions
void run_warmup_queries(std::shared_ptr< DBHandler > handler, std::string base_path, std::string query_file_path)
Definition: MapDServer.cpp:200
singleton class to handle concurrancy and state for blosc library. A C++ wrapper over a pure C librar...
std::vector< LeafHostInfo > db_leaves
std::string ssl_key_file
void start_server(std::shared_ptr< TThreadedServer > server, const int port)
Definition: MapDServer.cpp:176
AuthMetadata authMetadata
std::shared_ptr< DBHandler > g_warmup_handler
Definition: MapDServer.cpp:83
static void start(std::atomic< bool > &is_program_running)
void shutdown()
Definition: Logger.cpp:340
bool g_enable_experimental_string_functions
std::atomic< bool > g_running
Definition: MapDServer.cpp:74
std::vector< std::string > udf_compiler_options
std::shared_ptr< TThreadedServer > g_thrift_http_server
Definition: MapDServer.cpp:80
std::shared_ptr< DBHandler > g_mapd_handler
Definition: MapDServer.cpp:87
File_Namespace::DiskCacheConfig disk_cache_config
void file_delete(std::atomic< bool > &program_is_running, const unsigned int wait_interval_seconds, const std::string base_path)
Definition: File.cpp:282
std::shared_ptr< TThreadedServer > g_thrift_tcp_server
Definition: MapDServer.cpp:81
bool g_enable_fsi
Definition: Catalog.cpp:94
int startMapdServer(CommandLineOptions &prog_config_opts, bool start_http_server=true)
Definition: MapDServer.cpp:373
bool g_enable_thrift_logs
Definition: initdb.cpp:40
#define VLOG(n)
Definition: Logger.h:305
std::string master_address
SystemParameters system_parameters
std::string ssl_cert_file