用戶通過如下命令啓動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;
}