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;
}

你可能感兴趣的:(TDengine)