TDengine源碼解析-啓動

用戶通過如下命令啓動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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章