用户通过如下命令启动tdengine服务端程序
taosd -c /etc/taos/taos.cfg
本文主要分析taosd的启动过程,感谢作者开源这个还算不错的时序数据库产品。
首先检测是否通过-c指定了配置文件,如下:
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-c") == 0) {
if (i < argc - 1) {
strcpy(configDir, argv[++i]);
} else {
printf("'-c' requires a parameter, default:%s\n", configDir);
exit(EXIT_FAILURE);
}
} else if (strcmp(argv[i], "-V") == 0) {
printf("%s %s\n", version, compatible_version);
printf("gitinfo: %s\n", gitinfo);
printf("buildinfo: %s\n", buildinfo);
return 0;
}
}
如果指定了-c选项,则将配置文件路径拷贝到全局变量configDir中,如果不指定,默认如下:
char configDir[TSDB_FILENAME_LEN] = "/etc/taos";
捕获信号并进行处理,参照函数signal_handler
struct sigaction act;
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = signal_handler;
sigaction(SIGTERM, &act, NULL); //kill
sigaction(SIGHUP, &act, NULL); //终端对出
sigaction(SIGINT, &act, NULL); //Ctrl-C
sigaction(SIGUSR1, &act, NULL);//用户使用
sigaction(SIGUSR2, &act, NULL);//用户使用
signal_handler如下,主要就是记录日志,并进行正常的退出操作。
void signal_handler(int signum, siginfo_t *sigInfo, void *context) {
if (signum == SIGUSR1) {
tsCfgDynamicOptions("debugFlag 135");
return;
}
if (signum == SIGUSR2) {
tsCfgDynamicOptions("resetlog");
return;
}
syslog(LOG_INFO, "Shut down signal is %d", signum);
syslog(LOG_INFO, "Shutting down TDengine service...");
// clean the system.
dPrint("shut down signal is %d, sender PID:%d", signum, sigInfo->si_pid);
dnodeCleanUpSystem();
// close the syslog
syslog(LOG_INFO, "Shut down TDengine service successfully");
dPrint("TDengine is shut down!");
closelog();
exit(EXIT_SUCCESS);
}
打开系统日志文件,并记录启动日志
openlog("TDengine:", LOG_PID | LOG_CONS | LOG_NDELAY, LOG_LOCAL1);
syslog(LOG_INFO, "Starting TDengine service...");
初始化系统
if (dnodeInitSystem() < 0) {
syslog(LOG_ERR, "Error initialize TDengine system");
closelog();
初始化过程入口函数是dnodeInitSystem(),下面来看下具体实现.
查看硬件是否支持crc32指令,如果支持,则使用硬件提供的,否则,使用软件版本。
#define SSE42(have) \
do { \
uint32_t eax, ecx; \
eax = 1; \
__asm__("cpuid" : "=c"(ecx) : "a"(eax) : "%ebx", "%edx"); \
(have) = (ecx >> 20) & 1; \
} while (0)
/* Compute a CRC-32C. If the crc32 instruction is available, use the hardware
version. Otherwise, use the software version. */
uint32_t (*crc32c)(uint32_t crci, crc_stream bytes, size_t len) = NULL;
void taosResolveCRC() {
int sse42;
SSE42(sse42);
crc32c = sse42 ? crc32c_hw : crc32c_sf;
/* return sse42 ? crc32c_hw(crci, bytes, len) : crc32c_sf(crci, bytes, len);
*/
}
通过函数指针实现不同硬件平台的具体函数调用。
记录启动时间
tsRebootTime = taosGetTimestampSec();
通过函数tsReadGlobalLogConfig初始化配置文件
tsReadGlobalLogConfig
tsInitGlobalConfig
检测日志目录,不存在则创建
if (stat(logDir, &dirstat) < 0) mkdir(logDir, 0755);
打开并且初始化日志文件
if (taosInitLog(temp, tsNumOfLogLines, 1) < 0) printf("failed to init log file\n");
再次读取配置文件 ??
if (!tsReadGlobalConfig()) { // TODO : Change this function
tsPrintGlobalConfig();
dError("TDengine read global config failed");
return -1;
}
检测并创建相关目录
strcpy(tsDirectory, dataDir);
if (stat(dataDir, &dirstat) < 0) {
mkdir(dataDir, 0755);
}
taosCreateTierDirectory();
sprintf(mgmtDirectory, "%s/mgmt", tsDirectory);
sprintf(tsDirectory, "%s/tsdb", dataDir);
dnodeCheckDbRunning(dataDir);
检测是否有相同的db正在运行,通过对dir/.running文件加锁来判断。
dnodeCheckDbRunning(dataDir);
{
char filepath[256] = {0};
sprintf(filepath, "%s/.running", dir);
int fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
int ret = flock(fd, LOCK_EX | LOCK_NB);
if (ret != 0) {
dError("failed to lock file:%s ret:%d, database may be running, quit", filepath, ret);
exit(0);
}
}
打印输出所有的配置文件
tsPrintGlobalConfig();
初始化dnodeInitModules();
void dnodeInitModules() {
tsModule[TSDB_MOD_HTTP].name = "http";
tsModule[TSDB_MOD_HTTP].initFp = httpInitSystem;
tsModule[TSDB_MOD_HTTP].cleanUpFp = httpCleanUpSystem;
tsModule[TSDB_MOD_HTTP].startFp = httpStartSystem;
tsModule[TSDB_MOD_HTTP].stopFp = httpStopSystem;
tsModule[TSDB_MOD_HTTP].num = (tsEnableHttpModule == 1) ? -1 : 0;
tsModule[TSDB_MOD_HTTP].curNum = 0;
tsModule[TSDB_MOD_HTTP].equalVnodeNum = 0;
tsModule[TSDB_MOD_MONITOR].name = "monitor";
tsModule[TSDB_MOD_MONITOR].initFp = monitorInitSystem;
tsModule[TSDB_MOD_MONITOR].cleanUpFp = monitorCleanUpSystem;
tsModule[TSDB_MOD_MONITOR].startFp = monitorStartSystem;
tsModule[TSDB_MOD_MONITOR].stopFp = monitorStopSystem;
tsModule[TSDB_MOD_MONITOR].num = (tsEnableMonitorModule == 1) ? -1 : 0;
tsModule[TSDB_MOD_MONITOR].curNum = 0;
tsModule[TSDB_MOD_MONITOR].equalVnodeNum = 0;
}