OmniSciDB  eee9fa949c
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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 
17 #include "MapDServer.h"
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 "MapDRelease.h"
37 
38 #include "Archive/S3Archive.h"
39 #include "Shared/Logger.h"
40 #include "Shared/MapDParameters.h"
41 #include "Shared/file_delete.h"
43 #include "Shared/mapd_shared_ptr.h"
44 #include "Shared/scope.h"
45 
46 #include <boost/algorithm/string.hpp>
47 #include <boost/algorithm/string/trim.hpp>
48 #include <boost/filesystem.hpp>
49 #include <boost/locale/generator.hpp>
50 #include <boost/make_shared.hpp>
51 #include <boost/program_options.hpp>
52 
53 #include <csignal>
54 #include <sstream>
55 #include <thread>
56 #include <vector>
57 #include "MapDRelease.h"
58 #include "Shared/Compressor.h"
59 #include "Shared/MapDParameters.h"
60 #include "Shared/file_delete.h"
61 #include "Shared/mapd_shared_ptr.h"
62 #include "Shared/scope.h"
63 
64 using namespace ::apache::thrift;
65 using namespace ::apache::thrift::concurrency;
66 using namespace ::apache::thrift::protocol;
67 using namespace ::apache::thrift::server;
68 using namespace ::apache::thrift::transport;
69 
70 unsigned connect_timeout{20000};
71 unsigned recv_timeout{300000};
72 unsigned send_timeout{300000};
73 
74 extern bool g_cache_string_hash;
75 extern size_t g_leaf_count;
76 extern bool g_skip_intermediate_count;
77 extern bool g_enable_bump_allocator;
78 extern size_t g_max_memory_allocation_size;
79 extern size_t g_min_memory_allocation_size;
81 extern bool g_enable_table_functions;
82 
84 
85 std::atomic<bool> g_running{true};
86 std::atomic<int> g_saw_signal{-1};
87 
89 TThreadedServer* g_thrift_http_server{nullptr};
90 TThreadedServer* g_thrift_buf_server{nullptr};
91 
93  const std::vector<TTableGeneration>& thrift_table_generations) {
94  TableGenerations table_generations;
95  for (const auto& thrift_table_generation : thrift_table_generations) {
96  table_generations.setGeneration(
97  thrift_table_generation.table_id,
98  TableGeneration{static_cast<size_t>(thrift_table_generation.tuple_count),
99  static_cast<size_t>(thrift_table_generation.start_rowid)});
100  }
101  return table_generations;
102 }
103 
104 mapd::shared_ptr<MapDHandler> g_warmup_handler =
105  0; // global "g_warmup_handler" needed to avoid circular dependency
106  // between "MapDHandler" & function "run_warmup_queries"
107 mapd::shared_ptr<MapDHandler> g_mapd_handler = 0;
108 std::once_flag g_shutdown_once_flag;
109 
111  if (g_mapd_handler) {
112  std::call_once(g_shutdown_once_flag, []() { g_mapd_handler->shutdown(); });
113  }
114 }
115 
116 void register_signal_handler(int signum, void (*handler)(int)) {
117  struct sigaction act;
118  memset(&act, 0, sizeof(act));
119  if (handler != SIG_DFL && handler != SIG_IGN) {
120  // block all signal deliveries while inside the signal handler
121  sigfillset(&act.sa_mask);
122  }
123  act.sa_handler = handler;
124  sigaction(signum, &act, NULL);
125 }
126 
127 // Signal handler to set a global flag telling the server to exit.
128 // Do not call other functions inside this (or any) signal handler
129 // unless you really know what you are doing. See also:
130 // man 7 signal-safety
131 // man 7 signal
132 // https://en.wikipedia.org/wiki/Reentrancy_(computing)
133 void omnisci_signal_handler(int signum) {
134  // Record the signal number for logging during shutdown.
135  // Only records the first signal if called more than once.
136  int expected_signal{-1};
137  if (!g_saw_signal.compare_exchange_strong(expected_signal, signum)) {
138  return; // this wasn't the first signal
139  }
140 
141  // This point should never be reached more than once.
142 
143  // Tell heartbeat() to shutdown by unsetting the 'g_running' flag.
144  // If 'g_running' is already false, this has no effect and the
145  // shutdown is already in progress.
146  g_running = false;
147 
148  // Handle core dumps specially by pausing inside this signal handler
149  // because on some systems, some signals will execute their default
150  // action immediately when and if the signal handler returns.
151  // We would like to do some emergency cleanup before core dump.
152  if (signum == SIGQUIT || signum == SIGABRT || signum == SIGSEGV || signum == SIGFPE) {
153  // Wait briefly to give heartbeat() a chance to flush the logs and
154  // do any other emergency shutdown tasks.
155  sleep(2);
156 
157  // Explicitly trigger whatever default action this signal would
158  // have done, such as terminate the process or dump core.
159  // Signals are currently blocked so this new signal will be queued
160  // until this signal handler returns.
161  register_signal_handler(signum, SIG_DFL);
162  kill(getpid(), signum);
163  }
164 }
165 
173  // Thrift secure socket can cause problems with SIGPIPE
174  register_signal_handler(SIGPIPE, SIG_IGN);
175 }
176 
177 void start_server(TThreadedServer& server, const int port) {
178  try {
179  server.serve();
180  } catch (std::exception& e) {
181  LOG(ERROR) << "Exception: " << e.what() << ": port " << port << std::endl;
182  }
183 }
184 
185 void releaseWarmupSession(TSessionId& sessionId, std::ifstream& query_file) {
186  query_file.close();
187  if (sessionId != g_warmup_handler->getInvalidSessionId()) {
188  g_warmup_handler->disconnect(sessionId);
189  }
190 }
191 
192 void run_warmup_queries(mapd::shared_ptr<MapDHandler> handler,
193  std::string base_path,
194  std::string query_file_path) {
195  // run warmup queries to load cache if requested
196  if (query_file_path.empty()) {
197  return;
198  }
199  LOG(INFO) << "Running DB warmup with queries from " << query_file_path;
200  try {
201  g_warmup_handler = handler;
202  std::string db_info;
203  std::string user_keyword, user_name, db_name;
204  std::ifstream query_file;
207  TSessionId sessionId = g_warmup_handler->getInvalidSessionId();
208 
209  ScopeGuard session_guard = [&] { releaseWarmupSession(sessionId, query_file); };
210  query_file.open(query_file_path);
211  while (std::getline(query_file, db_info)) {
212  if (db_info.length() == 0) {
213  continue;
214  }
215  std::istringstream iss(db_info);
216  iss >> user_keyword >> user_name >> db_name;
217  if (user_keyword.compare(0, 4, "USER") == 0) {
218  // connect to DB for given user_name/db_name with super_user_rights (without
219  // password), & start session
220  g_warmup_handler->super_user_rights_ = true;
221  g_warmup_handler->connect(sessionId, user_name, "", db_name);
222  g_warmup_handler->super_user_rights_ = false;
223 
224  // read and run one query at a time for the DB with the setup connection
225  TQueryResult ret;
226  std::string single_query;
227  while (std::getline(query_file, single_query)) {
228  boost::algorithm::trim(single_query);
229  if (single_query.length() == 0) {
230  continue;
231  }
232  if (single_query[0] == '}') {
233  single_query.clear();
234  break;
235  }
236  if (single_query.find(';') == single_query.npos) {
237  std::string multiline_query;
238  std::getline(query_file, multiline_query, ';');
239  single_query += multiline_query;
240  }
241 
242  try {
243  g_warmup_handler->sql_execute(ret, sessionId, single_query, true, "", -1, -1);
244  } catch (...) {
245  LOG(WARNING) << "Exception while executing '" << single_query
246  << "', ignoring";
247  }
248  single_query.clear();
249  }
250 
251  // stop session and disconnect from the DB
252  g_warmup_handler->disconnect(sessionId);
253  sessionId = g_warmup_handler->getInvalidSessionId();
254  } else {
255  LOG(WARNING) << "\nSyntax error in the file: " << query_file_path.c_str()
256  << " Missing expected keyword USER. Following line will be ignored: "
257  << db_info.c_str() << std::endl;
258  }
259  db_info.clear();
260  }
261  } catch (...) {
262  LOG(WARNING) << "Exception while executing warmup queries. "
263  << "Warmup may not be fully completed. Will proceed nevertheless."
264  << std::endl;
265  }
266 }
267 
268 namespace po = boost::program_options;
269 
271  public:
272  MapDProgramOptions(char const* argv0, bool dist_v5_ = false)
273  : log_options_(argv0), dist_v5_(dist_v5_) {
274  fillOptions();
276  }
277  int http_port = 6278;
278  size_t reserved_gpu_mem = 1 << 27;
279  std::string base_path;
280  std::string cluster_file = {"cluster.conf"};
281  std::string cluster_topology_file = {"cluster_topology.conf"};
282  std::string license_path = {""};
283  bool cpu_only = false;
284  bool verbose_logging = false;
285  bool jit_debug = false;
286  bool intel_jit_profile = false;
287  bool allow_multifrag = true;
288  bool read_only = false;
289  bool allow_loop_joins = false;
290  bool enable_legacy_syntax = true;
292 
294  bool enable_rendering = false;
296  int render_oom_retry_threshold = 0; // in milliseconds
297  size_t render_mem_bytes = 500000000;
298  size_t render_poly_cache_bytes = 300000000;
299 
300  bool enable_runtime_udf = false;
301 
302  bool enable_watchdog = true;
304  unsigned dynamic_watchdog_time_limit = 10000;
305 
310  int num_gpus = -1;
311  int start_gpu = 0;
315  size_t num_reader_threads = 0;
319  std::string db_query_file = {""};
323  bool exit_after_warmup = false;
333  std::string udf_file_name = {""};
334 
335  void fillOptions();
336  void fillAdvancedOptions();
337 
338  po::options_description help_desc;
339  po::options_description developer_desc;
341  po::positional_options_description positional_options;
342 
343  public:
344  std::vector<LeafHostInfo> db_leaves;
345  std::vector<LeafHostInfo> string_leaves;
346  po::variables_map vm;
347  std::string clusterIds_arg;
348 
349  std::string getNodeIds();
350  std::vector<std::string> getNodeIdsArray();
351  static const std::string nodeIds_token;
352 
353  boost::optional<int> parse_command_line(int argc, char const* const* argv);
354  void validate();
355  void validate_base_path();
356  void init_logging();
357  const bool dist_v5_;
358 };
359 
363  }
366 }
367 
369  help_desc.add_options()("help,h", "Show available options.");
370  help_desc.add_options()(
371  "allow-cpu-retry",
372  po::value<bool>(&g_allow_cpu_retry)
373  ->default_value(g_allow_cpu_retry)
374  ->implicit_value(true),
375  R"(Allow the queries which failed on GPU to retry on CPU, even when watchdog is enabled.)");
376  help_desc.add_options()("allow-loop-joins",
377  po::value<bool>(&allow_loop_joins)
378  ->default_value(allow_loop_joins)
379  ->implicit_value(true),
380  "Enable loop joins.");
381  help_desc.add_options()("bigint-count",
382  po::value<bool>(&g_bigint_count)
383  ->default_value(g_bigint_count)
384  ->implicit_value(false),
385  "Use 64-bit count.");
386  help_desc.add_options()("calcite-max-mem",
387  po::value<size_t>(&mapd_parameters.calcite_max_mem)
388  ->default_value(mapd_parameters.calcite_max_mem),
389  "Max memory available to calcite JVM.");
390  if (!dist_v5_) {
391  help_desc.add_options()("calcite-port",
392  po::value<int>(&mapd_parameters.calcite_port)
393  ->default_value(mapd_parameters.calcite_port),
394  "Calcite port number.");
395  }
396  help_desc.add_options()("config",
397  po::value<std::string>(&mapd_parameters.config_file),
398  "Path to server configuration file.");
399  help_desc.add_options()("cpu-buffer-mem-bytes",
400  po::value<size_t>(&mapd_parameters.cpu_buffer_mem_bytes)
401  ->default_value(mapd_parameters.cpu_buffer_mem_bytes),
402  "Size of memory reserved for CPU buffers, in bytes.");
403  help_desc.add_options()(
404  "cpu-only",
405  po::value<bool>(&cpu_only)->default_value(cpu_only)->implicit_value(true),
406  "Run on CPU only, even if GPUs are available.");
407  help_desc.add_options()("cuda-block-size",
408  po::value<size_t>(&mapd_parameters.cuda_block_size)
409  ->default_value(mapd_parameters.cuda_block_size),
410  "Size of block to use on GPU.");
411  help_desc.add_options()("cuda-grid-size",
412  po::value<size_t>(&mapd_parameters.cuda_grid_size)
413  ->default_value(mapd_parameters.cuda_grid_size),
414  "Size of grid to use on GPU.");
415  if (!dist_v5_) {
416  help_desc.add_options()(
417  "data",
418  po::value<std::string>(&base_path)->required()->default_value("data"),
419  "Directory path to OmniSci data storage (catalogs, raw data, log files, etc).");
420  positional_options.add("data", 1);
421  }
422  help_desc.add_options()("db-query-list",
423  po::value<std::string>(&db_query_file),
424  "Path to file containing OmniSci warmup queries.");
425  help_desc.add_options()(
426  "exit-after-warmup",
427  po::value<bool>(&exit_after_warmup)->default_value(false)->implicit_value(true),
428  "Exit after OmniSci warmup queries.");
429  help_desc.add_options()("dynamic-watchdog-time-limit",
430  po::value<unsigned>(&dynamic_watchdog_time_limit)
431  ->default_value(dynamic_watchdog_time_limit)
432  ->implicit_value(10000),
433  "Dynamic watchdog time limit, in milliseconds.");
434  help_desc.add_options()("enable-debug-timer",
435  po::value<bool>(&g_enable_debug_timer)
436  ->default_value(g_enable_debug_timer)
437  ->implicit_value(true),
438  "Enable debug timer logging.");
439  help_desc.add_options()("enable-dynamic-watchdog",
440  po::value<bool>(&enable_dynamic_watchdog)
441  ->default_value(enable_dynamic_watchdog)
442  ->implicit_value(true),
443  "Enable dynamic watchdog.");
444  help_desc.add_options()("enable-filter-push-down",
445  po::value<bool>(&g_enable_filter_push_down)
446  ->default_value(g_enable_filter_push_down)
447  ->implicit_value(true),
448  "Enable filter push down through joins.");
449  help_desc.add_options()("enable-overlaps-hashjoin",
450  po::value<bool>(&g_enable_overlaps_hashjoin)
451  ->default_value(g_enable_overlaps_hashjoin)
452  ->implicit_value(true),
453  "Enable the overlaps hash join framework allowing for range "
454  "join (e.g. spatial overlaps) computation using a hash table.");
455  if (!dist_v5_) {
456  help_desc.add_options()(
457  "enable-string-dict-hash-cache",
458  po::value<bool>(&g_cache_string_hash)
459  ->default_value(g_cache_string_hash)
460  ->implicit_value(true),
461  "Cache string hash values in the string dictionary server during import.");
462  }
463  help_desc.add_options()(
464  "enable-thrift-logs",
465  po::value<bool>(&g_enable_thrift_logs)
466  ->default_value(g_enable_thrift_logs)
467  ->implicit_value(true),
468  "Enable writing messages directly from thrift to stdout/stderr.");
469  help_desc.add_options()("enable-watchdog",
470  po::value<bool>(&enable_watchdog)
471  ->default_value(enable_watchdog)
472  ->implicit_value(true),
473  "Enable watchdog.");
474  help_desc.add_options()(
475  "filter-push-down-low-frac",
476  po::value<float>(&g_filter_push_down_low_frac)
477  ->default_value(g_filter_push_down_low_frac)
478  ->implicit_value(g_filter_push_down_low_frac),
479  "Lower threshold for selectivity of filters that are pushed down.");
480  help_desc.add_options()(
481  "filter-push-down-high-frac",
482  po::value<float>(&g_filter_push_down_high_frac)
483  ->default_value(g_filter_push_down_high_frac)
484  ->implicit_value(g_filter_push_down_high_frac),
485  "Higher threshold for selectivity of filters that are pushed down.");
486  help_desc.add_options()("filter-push-down-passing-row-ubound",
487  po::value<size_t>(&g_filter_push_down_passing_row_ubound)
489  ->implicit_value(g_filter_push_down_passing_row_ubound),
490  "Upperbound on the number of rows that should pass the filter "
491  "if the selectivity is less than "
492  "the high fraction threshold.");
493  help_desc.add_options()("from-table-reordering",
494  po::value<bool>(&g_from_table_reordering)
495  ->default_value(g_from_table_reordering)
496  ->implicit_value(true),
497  "Enable automatic table reordering in FROM clause.");
498  help_desc.add_options()("gpu-buffer-mem-bytes",
499  po::value<size_t>(&mapd_parameters.gpu_buffer_mem_bytes)
500  ->default_value(mapd_parameters.gpu_buffer_mem_bytes),
501  "Size of memory reserved for GPU buffers, in bytes, per GPU.");
502  help_desc.add_options()("gpu-input-mem-limit",
503  po::value<double>(&mapd_parameters.gpu_input_mem_limit)
504  ->default_value(mapd_parameters.gpu_input_mem_limit),
505  "Force query to CPU when input data memory usage exceeds this "
506  "percentage of available GPU memory.");
507  help_desc.add_options()(
508  "hll-precision-bits",
509  po::value<int>(&g_hll_precision_bits)
510  ->default_value(g_hll_precision_bits)
511  ->implicit_value(g_hll_precision_bits),
512  "Number of bits used from the hash value used to specify the bucket number.");
513  if (!dist_v5_) {
514  help_desc.add_options()("http-port",
515  po::value<int>(&http_port)->default_value(http_port),
516  "HTTP port number.");
517  }
518  help_desc.add_options()(
519  "idle-session-duration",
520  po::value<int>(&idle_session_duration)->default_value(idle_session_duration),
521  "Maximum duration of idle session.");
522  help_desc.add_options()("inner-join-fragment-skipping",
523  po::value<bool>(&g_inner_join_fragment_skipping)
524  ->default_value(g_inner_join_fragment_skipping)
525  ->implicit_value(true),
526  "Enable/disable inner join fragment skipping. This feature is "
527  "considered stable and is enabled by default. This "
528  "parameter will be removed in a future release.");
529  help_desc.add_options()(
530  "max-session-duration",
531  po::value<int>(&max_session_duration)->default_value(max_session_duration),
532  "Maximum duration of active session.");
533  help_desc.add_options()(
534  "null-div-by-zero",
535  po::value<bool>(&g_null_div_by_zero)
536  ->default_value(g_null_div_by_zero)
537  ->implicit_value(true),
538  "Return null on division by zero instead of throwing an exception.");
539  help_desc.add_options()(
540  "num-reader-threads",
541  po::value<size_t>(&num_reader_threads)->default_value(num_reader_threads),
542  "Number of reader threads to use.");
543  help_desc.add_options()(
544  "overlaps-max-table-size-bytes",
545  po::value<size_t>(&g_overlaps_max_table_size_bytes)
546  ->default_value(g_overlaps_max_table_size_bytes),
547  "The maximum size in bytes of the hash table for an overlaps hash join.");
548  if (!dist_v5_) {
549  help_desc.add_options()("port,p",
550  po::value<int>(&mapd_parameters.omnisci_server_port)
551  ->default_value(mapd_parameters.omnisci_server_port),
552  "TCP Port number.");
553  }
554  help_desc.add_options()("num-gpus",
555  po::value<int>(&num_gpus)->default_value(num_gpus),
556  "Number of gpus to use.");
557  help_desc.add_options()(
558  "read-only",
559  po::value<bool>(&read_only)->default_value(read_only)->implicit_value(true),
560  "Enable read-only mode.");
561  help_desc.add_options()(
562  "res-gpu-mem",
563  po::value<size_t>(&reserved_gpu_mem)->default_value(reserved_gpu_mem),
564  "Reduces GPU memory available to the OmniSci allocator by this amount. Used for "
565  "compiled code cache and ancillary GPU functions and other processes that may also "
566  "be using the GPU concurrent with OmniSciDB.");
567  help_desc.add_options()("start-gpu",
568  po::value<int>(&start_gpu)->default_value(start_gpu),
569  "First gpu to use.");
570  help_desc.add_options()("trivial-loop-join-threshold",
571  po::value<unsigned>(&g_trivial_loop_join_threshold)
572  ->default_value(g_trivial_loop_join_threshold)
573  ->implicit_value(1000),
574  "The maximum number of rows in the inner table of a loop join "
575  "considered to be trivially small.");
576  help_desc.add_options()("verbose",
577  po::value<bool>(&verbose_logging)
578  ->default_value(verbose_logging)
579  ->implicit_value(true),
580  "Write additional debug log messages to server logs.");
581  help_desc.add_options()(
582  "enable-runtime-udf",
583  po::value<bool>(&enable_runtime_udf)
584  ->default_value(enable_runtime_udf)
585  ->implicit_value(true),
586  "Enable runtime UDF registration by passing signatures and corresponding LLVM IR "
587  "to the `register_runtime_udf` endpoint. For use with the Python Remote Backend "
588  "Compiler server, packaged separately.");
589  help_desc.add_options()("version,v", "Print Version Number.");
590  help_desc.add_options()("enable-experimental-string-functions",
593  ->implicit_value(true),
594  "Enable experimental string functions.");
595 
597 }
598 
600  developer_desc.add_options()("dev-options", "Print internal developer options.");
601  developer_desc.add_options()(
602  "enable-calcite-view-optimize",
605  ->implicit_value(true),
606  "Enable additional calcite (query plan) optimizations when a view is part of the "
607  "query.");
608  developer_desc.add_options()(
609  "enable-columnar-output",
610  po::value<bool>(&g_enable_columnar_output)
611  ->default_value(g_enable_columnar_output)
612  ->implicit_value(true),
613  "Enable columnar output for intermediate/final query steps.");
614  developer_desc.add_options()("enable-legacy-syntax",
615  po::value<bool>(&enable_legacy_syntax)
616  ->default_value(enable_legacy_syntax)
617  ->implicit_value(true),
618  "Enable legacy syntax.");
619  developer_desc.add_options()(
620  "enable-multifrag",
621  po::value<bool>(&allow_multifrag)
622  ->default_value(allow_multifrag)
623  ->implicit_value(true),
624  "Enable execution over multiple fragments in a single round-trip to GPU.");
625  developer_desc.add_options()(
626  "enable-shared-mem-group-by",
627  po::value<bool>(&g_enable_smem_group_by)
628  ->default_value(g_enable_smem_group_by)
629  ->implicit_value(true),
630  "Enable using GPU shared memory for some GROUP BY queries.");
631  developer_desc.add_options()("enable-direct-columnarization",
632  po::value<bool>(&g_enable_direct_columnarization)
633  ->default_value(g_enable_direct_columnarization)
634  ->implicit_value(true),
635  "Enables/disables a more optimized columnarization method "
636  "for intermediate steps in multi-step queries.");
637  developer_desc.add_options()("enable-window-functions",
638  po::value<bool>(&g_enable_window_functions)
639  ->default_value(g_enable_window_functions)
640  ->implicit_value(true),
641  "Enable experimental window function support.");
642  developer_desc.add_options()("enable-table-functions",
643  po::value<bool>(&g_enable_table_functions)
644  ->default_value(g_enable_table_functions)
645  ->implicit_value(true),
646  "Enable experimental table functions support.");
647  developer_desc.add_options()(
648  "jit-debug-ir",
649  po::value<bool>(&jit_debug)->default_value(jit_debug)->implicit_value(true),
650  "Enable runtime debugger support for the JIT. Note that this flag is "
651  "incompatible "
652  "with the `ENABLE_JIT_DEBUG` build flag. The generated code can be found at "
653  "`/tmp/mapdquery`.");
654  developer_desc.add_options()(
655  "intel-jit-profile",
656  po::value<bool>(&intel_jit_profile)
657  ->default_value(intel_jit_profile)
658  ->implicit_value(true),
659  "Enable runtime support for the JIT code profiling using Intel VTune.");
660  developer_desc.add_options()(
661  "skip-intermediate-count",
662  po::value<bool>(&g_skip_intermediate_count)
663  ->default_value(g_skip_intermediate_count)
664  ->implicit_value(true),
665  "Skip pre-flight counts for intermediate projections with no filters.");
666  developer_desc.add_options()(
667  "strip-join-covered-quals",
668  po::value<bool>(&g_strip_join_covered_quals)
669  ->default_value(g_strip_join_covered_quals)
670  ->implicit_value(true),
671  "Remove quals from the filtered count if they are covered by a "
672  "join condition (currently only ST_Contains).");
673  developer_desc.add_options()(
674  "max-output-projection-allocation-bytes",
675  po::value<size_t>(&g_max_memory_allocation_size)
676  ->default_value(g_max_memory_allocation_size),
677  "Maximum allocation size for a fixed output buffer allocation for projection "
678  "queries with no pre-flight count. Default is the maximum slab size (sizes "
679  "greater "
680  "than the maximum slab size have no affect). Requires bump allocator.");
681  developer_desc.add_options()(
682  "min-output-projection-allocation-bytes",
683  po::value<size_t>(&g_min_memory_allocation_size)
684  ->default_value(g_min_memory_allocation_size),
685  "Minimum allocation size for a fixed output buffer allocation for projection "
686  "queries with no pre-flight count. If an allocation of this size cannot be "
687  "obtained, the query will be retried with different execution parameters and/or "
688  "on "
689  "CPU (if allow-cpu-retry is enabled). Requires bump allocator.");
690  developer_desc.add_options()("enable-bump-allocator",
691  po::value<bool>(&g_enable_bump_allocator)
692  ->default_value(g_enable_bump_allocator)
693  ->implicit_value(true),
694  "Enable the bump allocator for projection queries on "
695  "GPU. The bump allocator will "
696  "allocate a fixed size buffer for each query, track the "
697  "number of rows passing the "
698  "kernel during query execution, and copy back only the "
699  "rows that passed the kernel "
700  "to CPU after execution. When disabled, pre-flight "
701  "count queries are used to size "
702  "the output buffer for projection queries.");
703 
704  developer_desc.add_options()("ssl-cert",
705  po::value<std::string>(&mapd_parameters.ssl_cert_file)
706  ->default_value(std::string("")),
707  "SSL Validated public certficate.");
708 
709  developer_desc.add_options()(
710  "pki-db-client-auth",
711  po::value<bool>(&authMetadata.pki_db_client_auth)->default_value(false),
712  "Use client PKI authentication to the database.");
713 
714  developer_desc.add_options()(
715  "ssl-transport-client-auth",
716  po::value<bool>(&mapd_parameters.ssl_transport_client_auth)->default_value(false),
717  "SSL Use client PKI authentication at the transport layer.");
718 
719  developer_desc.add_options()("ssl-private-key",
720  po::value<std::string>(&mapd_parameters.ssl_key_file)
721  ->default_value(std::string("")),
722  "SSL private key file.");
723  // Note ssl_trust_store is passed through to Calcite via mapd_parameters
724  // todo(jack): add ensure ssl-trust-store exists if cert and private key in use
725  developer_desc.add_options()("ssl-trust-store",
726  po::value<std::string>(&mapd_parameters.ssl_trust_store)
727  ->default_value(std::string("")),
728  "SSL public CA certifcates (java trust store) to validate "
729  "TLS connections (passed through to the Calcite server).");
730 
731  developer_desc.add_options()(
732  "ssl-trust-password",
733  po::value<std::string>(&mapd_parameters.ssl_trust_password)
734  ->default_value(std::string("")),
735  "SSL password for java trust store provided via --ssl-trust-store parameter.");
736 
737  developer_desc.add_options()(
738  "ssl-trust-ca",
739  po::value<std::string>(&mapd_parameters.ssl_trust_ca_file)
740  ->default_value(std::string("")),
741  "SSL public CA certificates to validate TLS connection(as a client).");
742 
743  developer_desc.add_options()(
744  "ssl-trust-ca-server",
745  po::value<std::string>(&authMetadata.ca_file_name)->default_value(std::string("")),
746  "SSL public CA certificates to validate TLS connection(as a server).");
747 
748  developer_desc.add_options()("ssl-keystore",
749  po::value<std::string>(&mapd_parameters.ssl_keystore)
750  ->default_value(std::string("")),
751  "SSL server credentials as a java key store (passed "
752  "through to the Calcite server).");
753 
754  developer_desc.add_options()(
755  "ssl-keystore-password",
756  po::value<std::string>(&mapd_parameters.ssl_keystore_password)
757  ->default_value(std::string("")),
758  "SSL password for java keystore, provide by via --ssl-keystore.");
759 
760  developer_desc.add_options()(
761  "udf",
762  po::value<std::string>(&udf_file_name),
763  "Load user defined extension functions from this file at startup. The file is "
764  "expected to be a C/C++ file with extension .cpp.");
765 }
766 
767 namespace {
768 
769 std::stringstream sanitize_config_file(std::ifstream& in) {
770  // Strip the web section out of the config file so boost can validate program options
771  std::stringstream ss;
772  std::string line;
773  while (std::getline(in, line)) {
774  ss << line << "\n";
775  if (line == "[web]") {
776  break;
777  }
778  }
779  return ss;
780 }
781 
782 bool trim_and_check_file_exists(std::string& filename, const std::string desc) {
783  if (!filename.empty()) {
784  boost::algorithm::trim_if(filename, boost::is_any_of("\"'"));
785  if (!boost::filesystem::exists(filename)) {
786  std::cerr << desc << " " << filename << " does not exist." << std::endl;
787  return false;
788  }
789  }
790  return true;
791 }
792 
793 } // namespace
794 
796  boost::algorithm::trim_if(base_path, boost::is_any_of("\"'"));
797  if (!boost::filesystem::exists(base_path)) {
798  throw std::runtime_error("OmniSci base directory does not exist at " + base_path);
799  }
800 }
801 
803  boost::algorithm::trim_if(base_path, boost::is_any_of("\"'"));
804  const auto data_path = boost::filesystem::path(base_path) / "mapd_data";
805  if (!boost::filesystem::exists(data_path)) {
806  throw std::runtime_error("OmniSci data directory does not exist at '" + base_path +
807  "'");
808  }
809 
810  {
811  const auto lock_file = boost::filesystem::path(base_path) / "omnisci_server_pid.lck";
812  auto pid = std::to_string(getpid());
813 
814  int pid_fd = open(lock_file.c_str(), O_RDWR | O_CREAT, 0644);
815  if (pid_fd == -1) {
816  auto err = std::string("Failed to open PID file ") + lock_file.c_str() + ". " +
817  strerror(errno) + ".";
818  throw std::runtime_error(err);
819  }
820  if (lockf(pid_fd, F_TLOCK, 0) == -1) {
821  close(pid_fd);
822  auto err = std::string("Another OmniSci Server is using data directory ") +
823  base_path + ".";
824  throw std::runtime_error(err);
825  }
826  if (ftruncate(pid_fd, 0) == -1) {
827  close(pid_fd);
828  auto err = std::string("Failed to truncate PID file ") + lock_file.c_str() + ". " +
829  strerror(errno) + ".";
830  throw std::runtime_error(err);
831  }
832  if (write(pid_fd, pid.c_str(), pid.length()) == -1) {
833  close(pid_fd);
834  auto err = std::string("Failed to write PID file ") + lock_file.c_str() + ". " +
835  strerror(errno) + ".";
836  throw std::runtime_error(err);
837  }
838  }
839  boost::algorithm::trim_if(db_query_file, boost::is_any_of("\"'"));
840  if (db_query_file.length() > 0 && !boost::filesystem::exists(db_query_file)) {
841  throw std::runtime_error("File containing DB queries " + db_query_file +
842  " does not exist.");
843  }
844  const auto db_file =
845  boost::filesystem::path(base_path) / "mapd_catalogs" / OMNISCI_SYSTEM_CATALOG;
846  if (!boost::filesystem::exists(db_file)) {
847  { // check old system catalog existsense
848  const auto db_file = boost::filesystem::path(base_path) / "mapd_catalogs/mapd";
849  if (!boost::filesystem::exists(db_file)) {
850  throw std::runtime_error("OmniSci system catalog " + OMNISCI_SYSTEM_CATALOG +
851  " does not exist.");
852  }
853  }
854  }
855 
856  // add all parameters to be displayed on startup
857  LOG(INFO) << "OmniSci started with data directory at '" << base_path << "'";
858  LOG(INFO) << " Watchdog is set to " << enable_watchdog;
859  LOG(INFO) << " Dynamic Watchdog is set to " << enable_dynamic_watchdog;
861  LOG(INFO) << " Dynamic Watchdog timeout is set to " << dynamic_watchdog_time_limit;
862  }
863 
864  LOG(INFO) << " Debug Timer is set to " << g_enable_debug_timer;
865 
866  LOG(INFO) << " Maximum Idle session duration " << idle_session_duration;
867 
868  LOG(INFO) << " Maximum active session duration " << max_session_duration;
869 }
870 
871 boost::optional<int> MapDProgramOptions::parse_command_line(int argc,
872  char const* const* argv) {
873  po::options_description all_desc("All options");
874  all_desc.add(help_desc).add(developer_desc);
875 
876  try {
877  po::store(po::command_line_parser(argc, argv)
878  .options(all_desc)
879  .positional(positional_options)
880  .run(),
881  vm);
882  po::notify(vm);
883 
884  if (vm.count("config")) {
885  std::ifstream settings_file(mapd_parameters.config_file);
886 
887  auto sanitized_settings = sanitize_config_file(settings_file);
888 
889  po::store(po::parse_config_file(sanitized_settings, all_desc, false), vm);
890  po::notify(vm);
891  settings_file.close();
892  }
893 
895  return 1;
896  }
897  if (!trim_and_check_file_exists(authMetadata.ca_file_name, "ca file name")) {
898  return 1;
899  }
901  return 1;
902  }
904  return 1;
905  }
907  return 1;
908  }
910  return 1;
911  }
912 
913  if (vm.count("help")) {
914  std::cerr << "Usage: omnisci_server <data directory path> [-p <port number>] "
915  "[--http-port <http port number>] [--flush-log] [--version|-v]"
916  << std::endl
917  << std::endl;
918  std::cout << help_desc << std::endl;
919  return 0;
920  }
921  if (vm.count("dev-options")) {
922  std::cout << "Usage: omnisci_server <data directory path> [-p <port number>] "
923  "[--http-port <http port number>] [--flush-log] [--version|-v]"
924  << std::endl
925  << std::endl;
926  std::cout << developer_desc << std::endl;
927  return 0;
928  }
929  if (vm.count("version")) {
930  std::cout << "OmniSci Version: " << MAPD_RELEASE << std::endl;
931  return 0;
932  }
933 
937  } catch (po::error& e) {
938  std::cerr << "Usage Error: " << e.what() << std::endl;
939  return 1;
940  }
941 
942  if (g_hll_precision_bits < 1 || g_hll_precision_bits > 16) {
943  std::cerr << "hll-precision-bits must be between 1 and 16." << std::endl;
944  return 1;
945  }
946 
948  LOG(INFO) << " From clause table reordering is disabled";
949  }
950 
952  LOG(INFO) << " Filter push down for JOIN is enabled";
953  }
954 
955  if (vm.count("udf")) {
956  boost::algorithm::trim_if(udf_file_name, boost::is_any_of("\"'"));
957 
958  if (!boost::filesystem::exists(udf_file_name)) {
959  LOG(ERROR) << " User defined function file " << udf_file_name << " does not exist.";
960  return 1;
961  }
962 
963  LOG(INFO) << " User provided extension functions loaded from " << udf_file_name;
964  }
965 
966  if (enable_runtime_udf) {
967  LOG(INFO) << " Runtime user defined extension functions enabled globally.";
968  }
969 
970  boost::algorithm::trim_if(mapd_parameters.ha_brokers, boost::is_any_of("\"'"));
971  boost::algorithm::trim_if(mapd_parameters.ha_group_id, boost::is_any_of("\"'"));
972  boost::algorithm::trim_if(mapd_parameters.ha_shared_data, boost::is_any_of("\"'"));
973  boost::algorithm::trim_if(mapd_parameters.ha_unique_server_id, boost::is_any_of("\"'"));
974 
975  if (!mapd_parameters.ha_group_id.empty()) {
976  LOG(INFO) << " HA group id " << mapd_parameters.ha_group_id;
977  if (mapd_parameters.ha_unique_server_id.empty()) {
978  LOG(ERROR) << "Starting server in HA mode --ha-unique-server-id must be set ";
979  return 5;
980  } else {
981  LOG(INFO) << " HA unique server id " << mapd_parameters.ha_unique_server_id;
982  }
983  if (mapd_parameters.ha_brokers.empty()) {
984  LOG(ERROR) << "Starting server in HA mode --ha-brokers must be set ";
985  return 6;
986  } else {
987  LOG(INFO) << " HA brokers " << mapd_parameters.ha_brokers;
988  }
989  if (mapd_parameters.ha_shared_data.empty()) {
990  LOG(ERROR) << "Starting server in HA mode --ha-shared-data must be set ";
991  return 7;
992  } else {
993  LOG(INFO) << " HA shared data is " << mapd_parameters.ha_shared_data;
994  }
995  }
996  LOG(INFO) << " cuda block size " << mapd_parameters.cuda_block_size;
997  LOG(INFO) << " cuda grid size " << mapd_parameters.cuda_grid_size;
998  LOG(INFO) << " calcite JVM max memory " << mapd_parameters.calcite_max_mem;
999  LOG(INFO) << " OmniSci Server Port " << mapd_parameters.omnisci_server_port;
1000  LOG(INFO) << " OmniSci Calcite Port " << mapd_parameters.calcite_port;
1001  LOG(INFO) << " Enable Calcite view optimize "
1003 
1004  LOG(INFO) << " Allow Local Auth Fallback: "
1005  << (authMetadata.allowLocalAuthFallback ? "enabled" : "disabled");
1006 
1007  boost::algorithm::trim_if(authMetadata.distinguishedName, boost::is_any_of("\"'"));
1008  boost::algorithm::trim_if(authMetadata.uri, boost::is_any_of("\"'"));
1009  boost::algorithm::trim_if(authMetadata.ldapQueryUrl, boost::is_any_of("\"'"));
1010  boost::algorithm::trim_if(authMetadata.ldapRoleRegex, boost::is_any_of("\"'"));
1011  boost::algorithm::trim_if(authMetadata.ldapSuperUserRole, boost::is_any_of("\"'"));
1012  boost::algorithm::trim_if(authMetadata.restToken, boost::is_any_of("\"'"));
1013  boost::algorithm::trim_if(authMetadata.restUrl, boost::is_any_of("\"'"));
1014 
1015  return boost::none;
1016 }
1017 
1018 void heartbeat() {
1019  // Block all signals for this heartbeat thread, only.
1020  sigset_t set;
1021  sigfillset(&set);
1022  int result = pthread_sigmask(SIG_BLOCK, &set, NULL);
1023  if (result != 0) {
1024  throw std::runtime_error("heartbeat() thread startup failed");
1025  }
1026 
1027  // Sleep until omnisci_signal_handler or anything clears the g_running flag.
1028  VLOG(1) << "heartbeat thread starting";
1029  while (::g_running) {
1030  using namespace std::chrono;
1031  std::this_thread::sleep_for(1s);
1032  }
1033  VLOG(1) << "heartbeat thread exiting";
1034 
1035  // Get the signal number if there was a signal.
1036  int signum = g_saw_signal;
1037  if (signum >= 1 && signum != SIGTERM) {
1038  LOG(INFO) << "Interrupt signal (" << signum << ") received.";
1039  }
1040 
1041  // if dumping core, try to do some quick stuff
1042  if (signum == SIGQUIT || signum == SIGABRT || signum == SIGSEGV || signum == SIGFPE) {
1043  if (g_mapd_handler) {
1044  std::call_once(g_shutdown_once_flag,
1045  []() { g_mapd_handler->emergency_shutdown(); });
1046  }
1047  logger::shutdown();
1048  return;
1049  // core dump should begin soon after this, see omnisci_signal_handler()
1050  }
1051 
1052  // trigger an orderly shutdown by telling Thrift to stop serving
1053  {
1054  mapd_shared_lock<mapd_shared_mutex> read_lock(g_thrift_mutex);
1055  auto httpserv = g_thrift_http_server;
1056  if (httpserv) {
1057  httpserv->stop();
1058  }
1059  auto bufserv = g_thrift_buf_server;
1060  if (bufserv) {
1061  bufserv->stop();
1062  }
1063  // main() should return soon after this
1064  }
1065 }
1066 
1067 int startMapdServer(MapDProgramOptions& prog_config_opts, bool start_http_server = true) {
1068  // try to enforce an orderly shutdown even after a signal
1070 
1071  // register shutdown procedures for when a normal shutdown happens
1072  // be aware that atexit() functions run in reverse order
1073  atexit(&logger::shutdown);
1074  atexit(&shutdown_handler);
1075 
1076 #ifdef HAVE_AWS_S3
1077  // hold a s3 archive here to survive from a segfault that happens on centos
1078  // when s3 transactions and others openssl-ed sessions are interleaved...
1079  auto s3_survivor = std::make_unique<S3Archive>("s3://omnisci/s3_survivor.txt", true);
1080 #endif
1081 
1082  // start background thread to clean up _DELETE_ME files
1083  const unsigned int wait_interval =
1084  3; // wait time in secs after looking for deleted file before looking again
1085  std::thread file_delete_thread(file_delete,
1086  std::ref(g_running),
1087  wait_interval,
1088  prog_config_opts.base_path + "/mapd_data");
1089  std::thread heartbeat_thread(heartbeat);
1090 
1091  if (!g_enable_thrift_logs) {
1092  apache::thrift::GlobalOutput.setOutputFunction([](const char* msg) {});
1093  }
1094 
1096  // Use the locale setting of the server by default. The generate parameter can be
1097  // updated appropriately if a locale override option is ever supported.
1098  boost::locale::generator generator;
1099  std::locale::global(generator.generate(""));
1100  }
1101 
1102  try {
1103  g_mapd_handler =
1104  mapd::make_shared<MapDHandler>(prog_config_opts.db_leaves,
1105  prog_config_opts.string_leaves,
1106  prog_config_opts.base_path,
1107  prog_config_opts.cpu_only,
1108  prog_config_opts.allow_multifrag,
1109  prog_config_opts.jit_debug,
1110  prog_config_opts.intel_jit_profile,
1111  prog_config_opts.read_only,
1112  prog_config_opts.allow_loop_joins,
1113  prog_config_opts.enable_rendering,
1114  prog_config_opts.enable_auto_clear_render_mem,
1115  prog_config_opts.render_oom_retry_threshold,
1116  prog_config_opts.render_mem_bytes,
1117  prog_config_opts.num_gpus,
1118  prog_config_opts.start_gpu,
1119  prog_config_opts.reserved_gpu_mem,
1120  prog_config_opts.num_reader_threads,
1121  prog_config_opts.authMetadata,
1122  prog_config_opts.mapd_parameters,
1123  prog_config_opts.enable_legacy_syntax,
1124  prog_config_opts.idle_session_duration,
1125  prog_config_opts.max_session_duration,
1126  prog_config_opts.enable_runtime_udf,
1127  prog_config_opts.udf_file_name);
1128  } catch (const std::exception& e) {
1129  LOG(FATAL) << "Failed to initialize service handler: " << e.what();
1130  }
1131 
1132  mapd::shared_ptr<TServerSocket> serverSocket;
1133  mapd::shared_ptr<TServerSocket> httpServerSocket;
1134  if (!prog_config_opts.mapd_parameters.ssl_cert_file.empty() &&
1135  !prog_config_opts.mapd_parameters.ssl_key_file.empty()) {
1136  mapd::shared_ptr<TSSLSocketFactory> sslSocketFactory;
1137  sslSocketFactory =
1138  mapd::shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory(SSLProtocol::SSLTLS));
1139  sslSocketFactory->loadCertificate(
1140  prog_config_opts.mapd_parameters.ssl_cert_file.c_str());
1141  sslSocketFactory->loadPrivateKey(
1142  prog_config_opts.mapd_parameters.ssl_key_file.c_str());
1143  if (prog_config_opts.mapd_parameters.ssl_transport_client_auth) {
1144  sslSocketFactory->authenticate(true);
1145  } else {
1146  sslSocketFactory->authenticate(false);
1147  }
1148  sslSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
1149  serverSocket = mapd::shared_ptr<TServerSocket>(new TSSLServerSocket(
1150  prog_config_opts.mapd_parameters.omnisci_server_port, sslSocketFactory));
1151  httpServerSocket = mapd::shared_ptr<TServerSocket>(
1152  new TSSLServerSocket(prog_config_opts.http_port, sslSocketFactory));
1153  LOG(INFO) << " OmniSci server using encrypted connection. Cert file ["
1154  << prog_config_opts.mapd_parameters.ssl_cert_file << "], key file ["
1155  << prog_config_opts.mapd_parameters.ssl_key_file << "]";
1156  } else {
1157  LOG(INFO) << " OmniSci server using unencrypted connection";
1158  serverSocket = mapd::shared_ptr<TServerSocket>(
1159  new TServerSocket(prog_config_opts.mapd_parameters.omnisci_server_port));
1160  httpServerSocket =
1161  mapd::shared_ptr<TServerSocket>(new TServerSocket(prog_config_opts.http_port));
1162  }
1163 
1164  ScopeGuard pointer_to_thrift_guard = [] {
1165  mapd_lock_guard<mapd_shared_mutex> write_lock(g_thrift_mutex);
1167  };
1168 
1169  if (prog_config_opts.mapd_parameters.ha_group_id.empty()) {
1170  mapd::shared_ptr<TProcessor> processor(new MapDTrackingProcessor(g_mapd_handler));
1171  mapd::shared_ptr<TTransportFactory> bufTransportFactory(
1172  new TBufferedTransportFactory());
1173  mapd::shared_ptr<TProtocolFactory> bufProtocolFactory(new TBinaryProtocolFactory());
1174 
1175  mapd::shared_ptr<TServerTransport> bufServerTransport(serverSocket);
1176  TThreadedServer bufServer(
1177  processor, bufServerTransport, bufTransportFactory, bufProtocolFactory);
1178  {
1179  mapd_lock_guard<mapd_shared_mutex> write_lock(g_thrift_mutex);
1180  g_thrift_buf_server = &bufServer;
1181  }
1182 
1183  std::thread bufThread(start_server,
1184  std::ref(bufServer),
1185  prog_config_opts.mapd_parameters.omnisci_server_port);
1186 
1187  // TEMPORARY
1188  auto warmup_queries = [&prog_config_opts]() {
1189  // run warm up queries if any exists
1191  g_mapd_handler, prog_config_opts.base_path, prog_config_opts.db_query_file);
1192  if (prog_config_opts.exit_after_warmup) {
1193  g_running = false;
1194  }
1195  };
1196 
1197  mapd::shared_ptr<TServerTransport> httpServerTransport(httpServerSocket);
1198  mapd::shared_ptr<TTransportFactory> httpTransportFactory(
1199  new THttpServerTransportFactory());
1200  mapd::shared_ptr<TProtocolFactory> httpProtocolFactory(new TJSONProtocolFactory());
1201  TThreadedServer httpServer(
1202  processor, httpServerTransport, httpTransportFactory, httpProtocolFactory);
1203  if (start_http_server) {
1204  {
1205  mapd_lock_guard<mapd_shared_mutex> write_lock(g_thrift_mutex);
1206  g_thrift_http_server = &httpServer;
1207  }
1208  std::thread httpThread(
1209  start_server, std::ref(httpServer), prog_config_opts.http_port);
1210 
1211  warmup_queries();
1212 
1213  bufThread.join();
1214  httpThread.join();
1215  } else {
1216  warmup_queries();
1217  bufThread.join();
1218  }
1219  } else { // running ha server
1220  LOG(FATAL) << "No High Availability module available, please contact OmniSci support";
1221  }
1222 
1223  g_running = false;
1224  file_delete_thread.join();
1225  heartbeat_thread.join();
1226 
1227  int signum = g_saw_signal;
1228  if (signum <= 0 || signum == SIGTERM) {
1229  return 0;
1230  } else {
1231  return signum;
1232  }
1233 }
1234 
1235 const std::string MapDProgramOptions::nodeIds_token = {"node_id"};
1236 
1237 int main(int argc, char** argv) {
1238  bool has_clust_topo = false;
1239 
1240  MapDProgramOptions prog_config_opts(argv[0], has_clust_topo);
1241 
1242  try {
1243  if (auto return_code = prog_config_opts.parse_command_line(argc, argv)) {
1244  return *return_code;
1245  }
1246 
1247  if (!has_clust_topo) {
1248  prog_config_opts.validate_base_path();
1249  prog_config_opts.init_logging();
1250  prog_config_opts.validate();
1251  return (startMapdServer(prog_config_opts));
1252  }
1253  } catch (std::runtime_error& e) {
1254  std::cerr << "Can't start: " << e.what() << std::endl;
1255  return 1;
1256  } catch (boost::program_options::error& e) {
1257  std::cerr << "Usage Error: " << e.what() << std::endl;
1258  return 1;
1259  }
1260 }
std::string distinguishedName
Definition: AuthMetadata.h:25
mapd_shared_mutex g_thrift_mutex
Definition: MapDServer.cpp:88
TThreadedServer * g_thrift_buf_server
Definition: MapDServer.cpp:90
boost::optional< int > parse_command_line(int argc, char const *const *argv)
Definition: MapDServer.cpp:871
std::string filename(char const *path)
Definition: Logger.cpp:62
bool g_enable_smem_group_by
float g_filter_push_down_low_frac
Definition: Execute.cpp:83
std::string ldapQueryUrl
Definition: AuthMetadata.h:26
mapd::shared_ptr< MapDHandler > g_mapd_handler
Definition: MapDServer.cpp:107
bool enable_calcite_view_optimize
bool g_enable_bump_allocator
Definition: Execute.cpp:99
bool g_strip_join_covered_quals
Definition: Execute.cpp:90
std::string ssl_key_file
bool g_enable_direct_columnarization
Definition: Execute.cpp:101
std::once_flag g_shutdown_once_flag
Definition: MapDServer.cpp:108
#define LOG(tag)
Definition: Logger.h:188
size_t gpu_buffer_mem_bytes
bool g_enable_debug_timer
Definition: Logger.cpp:17
static const std::string nodeIds_token
Definition: MapDServer.cpp:351
std::string ldapRoleRegex
Definition: AuthMetadata.h:27
shared utility for mapd_server and string dictionary server to remove old files
std::string cluster_topology_file
Definition: MapDServer.cpp:281
void run_warmup_queries(mapd::shared_ptr< MapDHandler > handler, std::string base_path, std::string query_file_path)
Definition: MapDServer.cpp:192
static constexpr int64_t kMinsPerHour
std::string ssl_trust_store
const std::string OMNISCI_SYSTEM_CATALOG
Definition: SysCatalog.h:58
std::string udf_file_name
Definition: MapDServer.cpp:333
bool ssl_transport_client_auth
std::string ssl_trust_ca_file
size_t g_filter_push_down_passing_row_ubound
Definition: Execute.cpp:85
void heartbeat()
bool g_enable_dynamic_watchdog
Definition: Execute.cpp:72
unsigned g_trivial_loop_join_threshold
Definition: Execute.cpp:76
size_t render_poly_cache_bytes
Definition: MapDServer.cpp:298
int g_hll_precision_bits
size_t cuda_block_size
unsigned connect_timeout
Definition: MapDServer.cpp:70
po::options_description help_desc
Definition: MapDServer.cpp:338
std::string to_string(char const *&&v)
MapDProgramOptions(char const *argv0, bool dist_v5_=false)
Definition: MapDServer.cpp:272
bool g_enable_overlaps_hashjoin
Definition: Execute.cpp:87
size_t g_max_memory_allocation_size
Definition: Execute.cpp:95
bool g_enable_watchdog
bool g_inner_join_fragment_skipping
Definition: Execute.cpp:78
boost::program_options::options_description const & get_options() const
Definition: Logger.cpp:79
static constexpr int64_t kMinsPerMonth
std::string ha_shared_data
const bool dist_v5_
Definition: MapDServer.cpp:357
bool g_null_div_by_zero
Definition: Execute.cpp:75
std::string restToken
Definition: AuthMetadata.h:31
TThreadedServer * g_thrift_http_server
Definition: MapDServer.cpp:89
bool g_enable_columnar_output
Definition: Execute.cpp:86
std::string getNodeIds()
void releaseWarmupSession(TSessionId &sessionId, std::ifstream &query_file)
Definition: MapDServer.cpp:185
std::string license_path
Definition: MapDServer.cpp:282
MapDParameters mapd_parameters
Definition: MapDServer.cpp:293
po::options_description developer_desc
Definition: MapDServer.cpp:339
bool g_from_table_reordering
Definition: Execute.cpp:77
singleton class to handle concurrancy and state for blosc library. A C++ wraper over a pure C library...
size_t g_min_memory_allocation_size
Definition: Execute.cpp:96
size_t g_leaf_count
Definition: ParserNode.cpp:66
std::string ssl_keystore
void init(LogOptions const &log_opts)
Definition: Logger.cpp:276
std::string restUrl
Definition: AuthMetadata.h:30
std::vector< LeafHostInfo > db_leaves
Definition: MapDServer.cpp:344
TableGenerations table_generations_from_thrift(const std::vector< TTableGeneration > &thrift_table_generations)
Definition: MapDServer.cpp:92
std::string config_file
std::string ssl_keystore_password
std::shared_timed_mutex mapd_shared_mutex
unsigned dynamic_watchdog_time_limit
Definition: MapDServer.cpp:304
size_t cuda_grid_size
float g_filter_push_down_high_frac
Definition: Execute.cpp:84
bool g_enable_thrift_logs
Definition: initdb.cpp:39
std::string ssl_trust_password
std::string uri
Definition: AuthMetadata.h:24
bool g_bigint_count
std::string base_path
Definition: MapDServer.cpp:279
void start_server(TThreadedServer &server, const int port)
Definition: MapDServer.cpp:177
size_t g_overlaps_max_table_size_bytes
Definition: Execute.cpp:89
bool enable_auto_clear_render_mem
Definition: MapDServer.cpp:295
std::string ca_file_name
Definition: AuthMetadata.h:33
std::string ssl_cert_file
po::variables_map vm
Definition: MapDServer.cpp:346
size_t calcite_max_mem
bool g_enable_window_functions
Definition: Execute.cpp:93
void shutdown_handler()
Definition: MapDServer.cpp:110
std::atomic< int > g_saw_signal
Definition: MapDServer.cpp:86
std::string ldapSuperUserRole
Definition: AuthMetadata.h:28
void fillAdvancedOptions()
Definition: MapDServer.cpp:599
bool trim_and_check_file_exists(std::string &filename, const std::string desc)
Definition: MapDServer.cpp:782
std::string ha_brokers
AuthMetadata authMetadata
Definition: MapDServer.cpp:291
std::string db_query_file
Definition: MapDServer.cpp:319
void register_signal_handlers()
Definition: MapDServer.cpp:166
double gpu_input_mem_limit
void setGeneration(const uint32_t id, const TableGeneration &generation)
void shutdown()
Definition: Logger.cpp:310
bool g_enable_experimental_string_functions
unsigned send_timeout
Definition: MapDServer.cpp:72
std::atomic< bool > g_running
Definition: MapDServer.cpp:85
std::stringstream sanitize_config_file(std::ifstream &in)
Definition: MapDServer.cpp:769
size_t cpu_buffer_mem_bytes
std::string cluster_file
Definition: MapDServer.cpp:280
mapd::shared_ptr< MapDHandler > g_warmup_handler
Definition: MapDServer.cpp:104
void register_signal_handler(int signum, void(*handler)(int))
Definition: MapDServer.cpp:116
std::vector< std::string > getNodeIdsArray()
bool g_cache_string_hash
Definition: Execute.cpp:88
bool g_enable_table_functions
Definition: Execute.cpp:94
Severity severity_
Definition: Logger.h:118
bool g_enable_filter_push_down
Definition: Execute.cpp:82
FILE * open(int fileId)
Opens/creates the file with the given id; returns NULL on error.
Definition: File.cpp:82
bool g_skip_intermediate_count
bool allowLocalAuthFallback
Definition: AuthMetadata.h:34
std::vector< LeafHostInfo > string_leaves
Definition: MapDServer.cpp:345
size_t write(FILE *f, const size_t offset, const size_t size, int8_t *buf)
Writes the specified number of bytes to the offset position in file f from buf.
Definition: File.cpp:120
void set_base_path(std::string const &base_path)
Definition: Logger.cpp:93
po::positional_options_description positional_options
Definition: MapDServer.cpp:341
void close(FILE *f)
Closes the file pointed to by the FILE pointer.
Definition: File.cpp:101
bool g_allow_cpu_retry
Definition: Execute.cpp:74
int startMapdServer(MapDProgramOptions &prog_config_opts, bool start_http_server=true)
std::string ha_group_id
static const std::string MAPD_RELEASE
Definition: release.h:43
void file_delete(std::atomic< bool > &program_is_running, const unsigned int wait_interval_seconds, const std::string base_path)
Definition: File.cpp:227
static bool run
bool pki_db_client_auth
Definition: AuthMetadata.h:32
unsigned g_dynamic_watchdog_time_limit
Definition: Execute.cpp:73
void omnisci_signal_handler(int signum)
Definition: MapDServer.cpp:133
unsigned recv_timeout
Definition: MapDServer.cpp:71
#define VLOG(n)
Definition: Logger.h:291
logger::LogOptions log_options_
Definition: MapDServer.cpp:340
std::string ha_unique_server_id
std::string clusterIds_arg
Definition: MapDServer.cpp:347