* This file is part of the oGRAC project.
* Copyright (c) 2024 Huawei Technologies Co.,Ltd.
*
* oGRAC is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*
* srv_main.c
*
*
* IDENTIFICATION
* src/server/srv_main.c
*
* -------------------------------------------------------------------------
*/
#include "srv_module.h"
#include "cm_defs.h"
#include "cm_file.h"
#include "srv_instance.h"
#include "cm_coredump.h"
#include "upgrade_struct_check.h"
#include <malloc.h>
typedef struct st_setup_assit {
db_startup_phase_t start_mode;
bool32 is_coordinator;
bool32 is_datanode;
bool32 is_gts;
} setup_assist_t;
static inline int srv_find_arg(int argc, char * const argv[], const char *find_arg)
{
for (int i = 1; i < argc; i++) {
if (cm_str_equal_ins(argv[i], find_arg)) {
return i;
}
}
return 0;
}
#define OG_MAX_OGRACD_ARG 5
#ifdef __OGRACD_CN__
static void srv_usage()
{
printf("Usage: oGRACd [OPTION]\n"
" Or: oGRACd [-h|-H]\n"
" Or: oGRACd [-v|-V]\n"
" Or: oGRACd [mode]\n"
" Or: oGRACd [mode] -D db_home_path\n"
" Or: oGRACd [mount/open] [node_type] -D db_home_path\n"
"Option:\n"
"\t -h/-H show the help information.\n"
"\t -v/-V show version information.\n"
"\t mode specify database starting mode, nomount/mount/open, default open.\n"
"\t -D specify database home path.\n"
"\t node_type specify sharding node type, --datanode/--coordinator/--gtsnode.\n");
}
static status_t srv_check_args(int argc, char * const argv[])
{
int32 i = 1;
if (argc > OG_MAX_OGRACD_ARG) {
printf("too many argument\n");
return OG_ERROR;
}
while (i < argc) {
if (strcmp(argv[i], "nomount") == 0) {
} else if (strcmp(argv[i], "mount") == 0) {
} else if (strcmp(argv[i], "open") == 0) {
} else if (cm_str_equal_ins(argv[i], "--coordinator")) {
} else if (cm_str_equal_ins(argv[i], "--datanode")) {
} else if (cm_str_equal_ins(argv[i], "--gtsnode")) {
} else if ((strcmp(argv[i], "-D") == 0)) {
if (i + 1 >= argc) {
printf("invalid argument: %s\n", argv[i]);
return OG_ERROR;
}
i++;
int len = (int)strlen((char *)argv[i]);
if (len <= 1 || len >= (OG_MAX_PATH_LEN - 1)) {
printf("invalid argument: %s %s\n", argv[i - 1], argv[i]);
return OG_ERROR;
}
} else {
printf("invalid argument: %s\n", argv[i]);
return OG_ERROR;
}
i++;
}
return OG_SUCCESS;
}
static status_t srv_process_node_type_args(int argc, char *argv[], setup_assist_t *assist)
{
int pos = srv_find_arg(argc, argv, "--coordinator");
assist->is_coordinator = pos > 0 ? OG_TRUE : OG_FALSE;
pos = srv_find_arg(argc, argv, "--datanode");
assist->is_datanode = pos > 0 ? OG_TRUE : OG_FALSE;
pos = srv_find_arg(argc, argv, "--gtsnode");
assist->is_gts = pos > 0 ? OG_TRUE : OG_FALSE;
if (assist->is_coordinator + assist->is_datanode + assist->is_gts > 1) {
printf("invalid argument: the database node_type should be --coordinator or --datanode or --gtsnode.\n");
return OG_ERROR;
}
return OG_SUCCESS;
}
#else
static void srv_usage(void)
{
printf("Usage: ogracd [OPTION]\n"
" Or: ogracd [-h|-H]\n"
" Or: ogracd [-v|-V]\n"
" Or: ogracd [mode]\n"
" Or: ogracd [mode] -D db_home_path\n"
" Or: ogracd [mount/open] [node_type] -D db_home_path\n"
"Option:\n"
"\t -h/-H show the help information.\n"
"\t -v/-V show version information.\n"
"\t mode specify database starting mode, nomount/mount/open, default open.\n"
"\t -D specify database home path.\n"
"\t node_type specify node type, --datanode.\n");
}
static status_t srv_check_args(int argc, char * const argv[])
{
int32 i = 1;
if (argc > OG_MAX_OGRACD_ARG) {
printf("too many argument\n");
return OG_ERROR;
}
while (i < argc) {
if (strcmp(argv[i], "nomount") == 0) {
} else if (strcmp(argv[i], "mount") == 0) {
} else if (strcmp(argv[i], "open") == 0) {
} else if (cm_str_equal_ins(argv[i], "--datanode")) {
} else if ((strcmp(argv[i], "-D") == 0)) {
if (i + 1 >= argc) {
printf("invalid argument: %s\n", argv[i]);
return OG_ERROR;
}
i++;
int len = (int)strlen((char *)argv[i]);
if (len <= 1 || len >= (OG_MAX_PATH_LEN - 1)) {
printf("invalid argument: %s %s\n", argv[i - 1], argv[i]);
return OG_ERROR;
}
} else {
printf("invalid argument: %s\n", argv[i]);
return OG_ERROR;
}
i++;
}
return OG_SUCCESS;
}
static status_t srv_process_node_type_args(int argc, char *argv[], setup_assist_t *assist)
{
int pos = srv_find_arg(argc, argv, "--datanode");
assist->is_datanode = pos > 0 ? OG_TRUE : OG_FALSE;
return OG_SUCCESS;
}
#endif
static status_t srv_process_setup_args(int argc, char *argv[], setup_assist_t *assist)
{
if (srv_process_node_type_args(argc, argv, assist) != OG_SUCCESS) {
return OG_ERROR;
}
if (srv_find_arg(argc, argv, "nomount")) {
assist->start_mode = STARTUP_NOMOUNT;
if (assist->is_coordinator || assist->is_datanode || assist->is_gts) {
printf("invalid argument: the database is initializing for nomount, --datanode or "
"--coordinator or --gtsnode are not allowed.\n");
return OG_ERROR;
}
} else if (srv_find_arg(argc, argv, "mount")) {
assist->start_mode = STARTUP_MOUNT;
} else {
assist->start_mode = STARTUP_OPEN;
}
int pos = srv_find_arg(argc, argv, "-D");
if (pos > 0 && (pos + 1) < argc) {
g_database_home = argv[pos + 1];
}
return OG_SUCCESS;
}
static status_t srv_startup(int argc, char *argv[])
{
setup_assist_t assist;
assist.start_mode = STARTUP_OPEN;
assist.is_coordinator = OG_FALSE;
assist.is_datanode = OG_FALSE;
assist.is_gts = OG_FALSE;
if (argc > 1) {
OG_RETURN_IFERR(srv_check_args(argc, argv));
OG_RETURN_IFERR(srv_process_setup_args(argc, argv, &assist));
}
return srv_instance_startup(assist.start_mode, assist.is_coordinator, assist.is_datanode, assist.is_gts);
}
#ifdef WIN32
char *oGRACd_get_dbversion()
{
return "NONE";
}
#else
extern char *oGRACd_get_dbversion(void);
#endif
static inline void srv_print_version(void)
{
printf("%s\n", oGRACd_get_dbversion());
}
#define OG_ARENA_MAX 32
static inline void set_mallopt()
{
(void)mallopt(M_ARENA_MAX, 1);
}
static inline void oGRACd_pre_exit(void)
{
srv_unlock_db();
}
static EXTER_ATTACK int32 oGRACd_lib_main(int argc, char *argv[])
{
SET_UNHANDLED_EXECEPTION_FILTER("ogracd");
#ifndef WIN32
set_mallopt();
if (save_origin_argument(argc, &argv) != OG_SUCCESS) {
OG_LOG_RUN_ERR("Aborted due to resave the argv and environ");
printf("instance startup failed\n");
fflush(stdout);
return OG_ERROR;
}
if (geteuid() == 0 || getuid() != geteuid()) {
printf("The root user is not permitted to execute the ogracd server "
"and the real uids must be the same as the effective uids.\n");
fflush(stdout);
return OG_ERROR;
}
#endif
if (argc == 2) {
if (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "-V") == 0) {
srv_print_version();
return OG_SUCCESS;
} else if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-H") == 0) {
srv_usage();
return OG_SUCCESS;
}
}
log_param_t *log_param = cm_log_param_instance();
log_param->log_instance_startup = OG_FALSE;
cm_init_error_handler(cm_set_srv_error);
cm_set_hook_pre_exit(oGRACd_pre_exit);
if (srv_startup(argc, argv) != OG_SUCCESS) {
OG_LOG_RUN_ERR("Instance Startup Failed");
printf("instance startup failed\n");
fflush(stdout);
return OG_ERROR;
}
log_param->log_instance_startup = OG_FALSE;
if (srv_instance_loop() != OG_SUCCESS) {
cm_unlock_fd(g_instance->lock_fd);
cm_close_file(g_instance->lock_fd);
printf("instance exit\n");
fflush(stdout);
return OG_ERROR;
}
cm_unlock_fd(g_instance->lock_fd);
cm_close_file(g_instance->lock_fd);
return OG_SUCCESS;
}
#ifdef BUILD_SRV_MAIN
EXTER_ATTACK int32 main(int argc, char *argv[])
{
return oGRACd_lib_main(argc, argv);
}
#endif