libserverframe/src/sf_global.c

453 lines
15 KiB
C

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include "fastcommon/common_define.h"
#include "fastcommon/shared_func.h"
#include "fastcommon/logger.h"
#include "sf_nio.h"
#include "sf_global.h"
SFGlobalVariables g_sf_global_vars = {
DEFAULT_CONNECT_TIMEOUT, DEFAULT_NETWORK_TIMEOUT,
{'/', 't', 'm', 'p', '\0'}, true,
SF_DEF_THREAD_STACK_SIZE, DEFAULT_MAX_CONNECTONS,
SF_DEF_MAX_PACKAGE_SIZE, SF_DEF_MIN_BUFF_SIZE, SF_DEF_MAX_BUFF_SIZE,
SYNC_LOG_BUFF_DEF_INTERVAL, 0, 0, 0, {'\0'}, {'\0'}, false, 0, {0, 0}
};
SFContext g_sf_context = {
NULL, 0, -1, -1, 0, 0, 1, DEFAULT_WORK_THREADS,
{'\0'}, {'\0'}, 0, true, true, NULL, NULL, NULL,
sf_task_finish_clean_up, NULL
};
static inline void set_config_str_value(const char *value,
char *dest, const int dest_size)
{
if (value == NULL) {
*dest = '\0';
} else {
snprintf(dest, dest_size, "%s", value);
}
}
static int load_network_parameters(IniContext *pIniContext)
{
int result;
char *pMaxPkgSize;
char *pMinBuffSize;
char *pMaxBuffSize;
int64_t max_pkg_size;
int64_t min_buff_size;
int64_t max_buff_size;
g_sf_global_vars.connect_timeout = iniGetIntValue(NULL,
"connect_timeout", pIniContext, DEFAULT_CONNECT_TIMEOUT);
if (g_sf_global_vars.connect_timeout <= 0) {
g_sf_global_vars.connect_timeout = DEFAULT_CONNECT_TIMEOUT;
}
g_sf_global_vars.network_timeout = iniGetIntValue(NULL,
"network_timeout", pIniContext, DEFAULT_NETWORK_TIMEOUT);
if (g_sf_global_vars.network_timeout <= 0) {
g_sf_global_vars.network_timeout = DEFAULT_NETWORK_TIMEOUT;
}
g_sf_global_vars.max_connections = iniGetIntValue(NULL,
"max_connections", pIniContext, DEFAULT_MAX_CONNECTONS);
if (g_sf_global_vars.max_connections <= 0) {
g_sf_global_vars.max_connections = DEFAULT_MAX_CONNECTONS;
}
if ((result=set_rlimit(RLIMIT_NOFILE, g_sf_global_vars.
max_connections)) != 0)
{
return result;
}
pMaxPkgSize = iniGetStrValue(NULL,
"max_pkg_size", pIniContext);
if (pMaxPkgSize == NULL) {
max_pkg_size = SF_DEF_MAX_PACKAGE_SIZE;
}
else if ((result=parse_bytes(pMaxPkgSize, 1,
&max_pkg_size)) != 0)
{
return result;
} else if (max_pkg_size < 4096) {
logWarning("file: "__FILE__", line: %d, "
"max_pkg_size: %d is too small, set to 4096",
__LINE__, (int)max_pkg_size);
max_pkg_size = 4096;
}
g_sf_global_vars.max_pkg_size = (int)max_pkg_size;
pMinBuffSize = iniGetStrValue(NULL,
"min_buff_size", pIniContext);
if (pMinBuffSize == NULL) {
min_buff_size = SF_DEF_MIN_BUFF_SIZE;
}
else if ((result=parse_bytes(pMinBuffSize, 1,
&min_buff_size)) != 0)
{
return result;
} else if (min_buff_size < 2048) {
logWarning("file: "__FILE__", line: %d, "
"min_buff_size: %d is too small, set to 2048",
__LINE__, (int)min_buff_size);
min_buff_size = 2048;
}
g_sf_global_vars.min_buff_size = (int)min_buff_size;
pMaxBuffSize = iniGetStrValue(NULL,
"max_buff_size", pIniContext);
if (pMaxBuffSize == NULL) {
max_buff_size = SF_DEF_MAX_BUFF_SIZE;
}
else if ((result=parse_bytes(pMaxBuffSize, 1,
&max_buff_size)) != 0)
{
return result;
}
g_sf_global_vars.max_buff_size = (int)max_buff_size;
if (pMinBuffSize == NULL || pMaxBuffSize == NULL) {
g_sf_global_vars.min_buff_size = g_sf_global_vars.max_pkg_size;
g_sf_global_vars.max_buff_size = g_sf_global_vars.max_pkg_size;
}
else {
if (g_sf_global_vars.max_buff_size < g_sf_global_vars.max_pkg_size) {
g_sf_global_vars.max_buff_size = g_sf_global_vars.max_pkg_size;
}
if (g_sf_global_vars.max_buff_size < g_sf_global_vars.min_buff_size) {
logWarning("file: "__FILE__", line: %d, "
"max_buff_size: %d < min_buff_size: %d, "
"set max_buff_size to min_buff_size", __LINE__,
g_sf_global_vars.max_buff_size,
g_sf_global_vars.min_buff_size);
g_sf_global_vars.max_buff_size = g_sf_global_vars.min_buff_size;
}
}
return 0;
}
int sf_load_global_config_ex(const char *server_name, const char *filename,
IniContext *pIniContext, const bool load_network_params)
{
int result;
char *pBasePath;
char *pRunByGroup;
char *pRunByUser;
char *pThreadStackSize;
int64_t thread_stack_size;
pBasePath = iniGetStrValue(NULL, "base_path", pIniContext);
if (pBasePath == NULL) {
logError("file: "__FILE__", line: %d, "
"conf file \"%s\" must have item "
"\"base_path\"!", __LINE__, filename);
return ENOENT;
}
snprintf(g_sf_global_vars.base_path, sizeof(g_sf_global_vars.base_path),
"%s", pBasePath);
chopPath(g_sf_global_vars.base_path);
if (!fileExists(g_sf_global_vars.base_path)) {
logError("file: "__FILE__", line: %d, "
"\"%s\" can't be accessed, error info: %s",
__LINE__, g_sf_global_vars.base_path, strerror(errno));
return errno != 0 ? errno : ENOENT;
}
if (!isDir(g_sf_global_vars.base_path)) {
logError("file: "__FILE__", line: %d, "
"\"%s\" is not a directory!",
__LINE__, g_sf_global_vars.base_path);
return ENOTDIR;
}
if (load_network_params) {
if ((result=load_network_parameters(pIniContext)) != 0) {
return result;
}
}
pRunByGroup = iniGetStrValue(NULL, "run_by_group", pIniContext);
pRunByUser = iniGetStrValue(NULL, "run_by_user", pIniContext);
if (pRunByGroup == NULL) {
*g_sf_global_vars.run_by_group = '\0';
}
else {
snprintf(g_sf_global_vars.run_by_group,
sizeof(g_sf_global_vars.run_by_group),
"%s", pRunByGroup);
}
if (*(g_sf_global_vars.run_by_group) == '\0') {
g_sf_global_vars.run_by_gid = getegid();
}
else {
struct group *pGroup;
pGroup = getgrnam(g_sf_global_vars.run_by_group);
if (pGroup == NULL) {
result = errno != 0 ? errno : ENOENT;
logError("file: "__FILE__", line: %d, "
"getgrnam fail, errno: %d, "
"error info: %s", __LINE__,
result, strerror(result));
return result;
}
g_sf_global_vars.run_by_gid = pGroup->gr_gid;
}
if (pRunByUser == NULL) {
*g_sf_global_vars.run_by_user = '\0';
}
else {
snprintf(g_sf_global_vars.run_by_user,
sizeof(g_sf_global_vars.run_by_user),
"%s", pRunByUser);
}
if (*(g_sf_global_vars.run_by_user) == '\0') {
g_sf_global_vars.run_by_uid = geteuid();
}
else {
struct passwd *pUser;
pUser = getpwnam(g_sf_global_vars.run_by_user);
if (pUser == NULL) {
result = errno != 0 ? errno : ENOENT;
logError("file: "__FILE__", line: %d, "
"getpwnam fail, errno: %d, "
"error info: %s", __LINE__,
result, strerror(result));
return result;
}
g_sf_global_vars.run_by_uid = pUser->pw_uid;
}
if ((result=set_run_by(g_sf_global_vars.run_by_group,
g_sf_global_vars.run_by_user)) != 0)
{
return result;
}
g_sf_global_vars.sync_log_buff_interval = iniGetIntValue(NULL,
"sync_log_buff_interval", pIniContext,
SYNC_LOG_BUFF_DEF_INTERVAL);
if (g_sf_global_vars.sync_log_buff_interval <= 0) {
g_sf_global_vars.sync_log_buff_interval = SYNC_LOG_BUFF_DEF_INTERVAL;
}
pThreadStackSize = iniGetStrValue(NULL,
"thread_stack_size", pIniContext);
if (pThreadStackSize == NULL) {
thread_stack_size = SF_DEF_THREAD_STACK_SIZE;
}
else if ((result=parse_bytes(pThreadStackSize, 1,
&thread_stack_size)) != 0)
{
return result;
}
g_sf_global_vars.thread_stack_size = (int)thread_stack_size;
g_sf_global_vars.rotate_error_log = iniGetBoolValue(NULL,
"rotate_error_log", pIniContext, false);
g_sf_global_vars.log_file_keep_days = iniGetIntValue(NULL,
"log_file_keep_days", pIniContext, 0);
load_log_level(pIniContext);
if ((result=log_set_prefix(g_sf_global_vars.base_path, server_name)) != 0) {
return result;
}
return 0;
}
int sf_load_config_ex(const char *server_name, const char *filename,
IniContext *pIniContext, const char *section_name,
const int default_inner_port, const int default_outer_port)
{
int result;
if ((result=sf_load_global_config(server_name,
filename, pIniContext)) != 0)
{
return result;
}
return sf_load_context_from_config(&g_sf_context, filename, pIniContext,
section_name, default_inner_port, default_outer_port);
}
int sf_load_config(const char *server_name, const char *filename,
IniContext *pIniContext, const int default_inner_port,
const int default_outer_port)
{
return sf_load_config_ex(server_name, filename, pIniContext, "",
default_inner_port, default_outer_port);
}
int sf_load_context_from_config(SFContext *sf_context,
const char *filename, IniContext *pIniContext,
const char *section_name, const int default_inner_port,
const int default_outer_port)
{
char *inner_port;
char *outer_port;
char *inner_bind_addr;
char *outer_bind_addr;
char *bind_addr;
int port;
sf_context->inner_port = sf_context->outer_port = 0;
inner_port = iniGetStrValue(section_name, "inner_port", pIniContext);
outer_port = iniGetStrValue(section_name, "outer_port", pIniContext);
if (inner_port == NULL && outer_port == NULL) {
port = iniGetIntValue(section_name, "port", pIniContext, 0);
if (port > 0) {
sf_context->inner_port = sf_context->outer_port = port;
}
} else {
if (inner_port != NULL) {
sf_context->inner_port = atoi(inner_port);
}
if (outer_port != NULL) {
sf_context->outer_port = atoi(outer_port);
}
}
if (sf_context->inner_port <= 0) {
sf_context->inner_port = default_inner_port;
}
if (sf_context->outer_port <= 0) {
sf_context->outer_port = default_outer_port;
}
inner_bind_addr = iniGetStrValue(section_name,
"inner_bind_addr", pIniContext);
outer_bind_addr = iniGetStrValue(section_name,
"outer_bind_addr", pIniContext);
if (inner_bind_addr == NULL && outer_bind_addr == NULL) {
bind_addr = iniGetStrValue(section_name,
"bind_addr", pIniContext);
if (bind_addr != NULL) {
inner_bind_addr = outer_bind_addr = bind_addr;
}
}
set_config_str_value(inner_bind_addr, sf_context->inner_bind_addr,
sizeof(sf_context->inner_bind_addr));
set_config_str_value(outer_bind_addr, sf_context->outer_bind_addr,
sizeof(sf_context->outer_bind_addr));
sf_context->accept_threads = iniGetIntValue(section_name,
"accept_threads", pIniContext, 1);
if (sf_context->accept_threads <= 0) {
logError("file: "__FILE__", line: %d, "
"config file: %s, section: %s, "
"item \"accept_threads\" is invalid, "
"value: %d <= 0!", __LINE__, filename,
section_name, sf_context->accept_threads);
return EINVAL;
}
sf_context->work_threads = iniGetIntValue(section_name,
"work_threads", pIniContext, DEFAULT_WORK_THREADS);
if (sf_context->work_threads <= 0) {
logError("file: "__FILE__", line: %d, "
"config file: %s, section: %s, "
"item \"work_threads\" is invalid, "
"value: %d <= 0!", __LINE__, filename,
section_name, sf_context->work_threads);
return EINVAL;
}
return 0;
}
void sf_context_config_to_string(const SFContext *sf_context,
char *output, const int size)
{
int len;
len = 0;
if ((sf_context->inner_port == sf_context->outer_port) &&
(strcmp(sf_context->inner_bind_addr,
sf_context->outer_bind_addr) == 0))
{
len += snprintf(output + len, size - len,
"port=%d, bind_addr=%s",
sf_context->inner_port,
sf_context->inner_bind_addr);
} else {
len += snprintf(output + len, size - len,
"inner_port=%d, inner_bind_addr=%s, "
"outer_port=%d, outer_bind_addr=%s",
sf_context->inner_port, sf_context->inner_bind_addr,
sf_context->outer_port, sf_context->outer_bind_addr);
}
len += snprintf(output + len, size - len,
", accept_threads=%d, work_threads=%d",
sf_context->accept_threads, sf_context->work_threads);
}
void sf_global_config_to_string(char *output, const int size)
{
char sz_thread_stack_size[32];
char sz_max_pkg_size[32];
char sz_min_buff_size[32];
char sz_max_buff_size[32];
snprintf(output, size,
"base_path=%s, max_connections=%d, connect_timeout=%d, "
"network_timeout=%d, thread_stack_size=%s, max_pkg_size=%s, "
"min_buff_size=%s, max_buff_size=%s, log_level=%s, "
"sync_log_buff_interval=%d, rotate_error_log=%d, "
"log_file_keep_days=%d, run_by_group=%s, run_by_user=%s",
g_sf_global_vars.base_path,
g_sf_global_vars.max_connections,
g_sf_global_vars.connect_timeout,
g_sf_global_vars.network_timeout,
int_to_comma_str(g_sf_global_vars.thread_stack_size,
sz_thread_stack_size),
int_to_comma_str(g_sf_global_vars.max_pkg_size, sz_max_pkg_size),
int_to_comma_str(g_sf_global_vars.min_buff_size, sz_min_buff_size),
int_to_comma_str(g_sf_global_vars.max_buff_size, sz_max_buff_size),
log_get_level_caption(),
g_sf_global_vars.sync_log_buff_interval,
g_sf_global_vars.rotate_error_log,
g_sf_global_vars.log_file_keep_days,
g_sf_global_vars.run_by_group,
g_sf_global_vars.run_by_user
);
}
void sf_log_config_ex(const char *other_config)
{
char sz_global_config[512];
char sz_context_config[128];
sf_global_config_to_string(sz_global_config, sizeof(sz_global_config));
sf_context_config_to_string(&g_sf_context,
sz_context_config, sizeof(sz_context_config));
logInfo("%s, %s%s%s",
sz_global_config, sz_context_config,
(other_config != NULL && *other_config != '\0') ? ", " : "",
(other_config != NULL) ? other_config : ""
);
}