tlog.c 28.2 KB
Newer Older
H
hzcheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

S
slguan 已提交
16
#define _DEFAULT_SOURCE
S
log  
Shengliang Guan 已提交
17
#include "tlog.h"
H
Hongze Cheng 已提交
18
#include "os.h"
19
#include "tconfig.h"
dengyihao's avatar
dengyihao 已提交
20
#include "tutil.h"
D
dapan1121 已提交
21 22
#include "tjson.h"
#include "tglobal.h"
L
Liu Jicong 已提交
23

S
Shengliang Guan 已提交
24 25
#define LOG_MAX_LINE_SIZE             (1024)
#define LOG_MAX_LINE_BUFFER_SIZE      (LOG_MAX_LINE_SIZE + 3)
26
#define LOG_MAX_LINE_DUMP_SIZE        (1024 * 1024)
S
Shengliang Guan 已提交
27
#define LOG_MAX_LINE_DUMP_BUFFER_SIZE (LOG_MAX_LINE_DUMP_SIZE + 3)
S
slguan 已提交
28

S
ulog  
Shengliang Guan 已提交
29 30
#define LOG_FILE_NAME_LEN    300
#define LOG_DEFAULT_BUF_SIZE (20 * 1024 * 1024)  // 20MB
H
hzcheng 已提交
31

S
ulog  
Shengliang Guan 已提交
32 33 34 35 36
#define LOG_DEFAULT_INTERVAL 25
#define LOG_INTERVAL_STEP    5
#define LOG_MIN_INTERVAL     5
#define LOG_MAX_INTERVAL     25
#define LOG_MAX_WAIT_MSEC    1000
D
fix bug  
dapan1121 已提交
37

S
slguan 已提交
38
#define LOG_BUF_BUFFER(x) ((x)->buffer)
S
ulog  
Shengliang Guan 已提交
39 40 41 42
#define LOG_BUF_START(x)  ((x)->buffStart)
#define LOG_BUF_END(x)    ((x)->buffEnd)
#define LOG_BUF_SIZE(x)   ((x)->buffSize)
#define LOG_BUF_MUTEX(x)  ((x)->buffMutex)
S
slguan 已提交
43

H
hzcheng 已提交
44
typedef struct {
dengyihao's avatar
dengyihao 已提交
45
  char         *buffer;
46 47 48 49 50 51 52
  int32_t       buffStart;
  int32_t       buffEnd;
  int32_t       buffSize;
  int32_t       minBuffSize;
  TdFilePtr     pFile;
  int32_t       stop;
  TdThread      asyncThread;
wafwerar's avatar
wafwerar 已提交
53
  TdThreadMutex buffMutex;
H
hzcheng 已提交
54 55
} SLogBuff;

S
slguan 已提交
56
typedef struct {
57 58 59 60 61 62 63
  int32_t       fileNum;
  int32_t       maxLines;
  int32_t       lines;
  int32_t       flag;
  int32_t       openInProgress;
  pid_t         pid;
  char          logName[LOG_FILE_NAME_LEN];
dengyihao's avatar
dengyihao 已提交
64
  SLogBuff     *logHandle;
wafwerar's avatar
wafwerar 已提交
65
  TdThreadMutex logMutex;
S
slguan 已提交
66 67
} SLogObj;

68
extern SConfig *tsCfg;
dengyihao's avatar
dengyihao 已提交
69 70 71 72
static int8_t   tsLogInited = 0;
static SLogObj  tsLogObj = {.fileNum = 1};
static int64_t  tsAsyncLogLostLines = 0;
static int32_t  tsWriteInterval = LOG_DEFAULT_INTERVAL;
dengyihao's avatar
dengyihao 已提交
73
static int32_t  tsDaylightActive; /* Currently in daylight saving time. */
L
Liu Jicong 已提交
74

S
Shengliang Guan 已提交
75
bool    tsLogEmbedded = 0;
S
Shengliang Guan 已提交
76
bool    tsAsyncLog = true;
S
Shengliang Guan 已提交
77
bool    tsAssert = true;
S
Shengliang Guan 已提交
78
int32_t tsNumOfLogLines = 10000000;
S
Shengliang Guan 已提交
79
int32_t tsLogKeepDays = 0;
S
Shengliang Guan 已提交
80
LogFp   tsLogFp = NULL;
S
Shengliang Guan 已提交
81 82 83 84
int64_t tsNumOfErrorLogs = 0;
int64_t tsNumOfInfoLogs = 0;
int64_t tsNumOfDebugLogs = 0;
int64_t tsNumOfTraceLogs = 0;
D
fix bug  
dapan1121 已提交
85

S
Shengliang Guan 已提交
86
// log
S
Shengliang Guan 已提交
87 88 89
int32_t dDebugFlag = 131;
int32_t vDebugFlag = 131;
int32_t mDebugFlag = 131;
S
Shengliang Guan 已提交
90 91
int32_t cDebugFlag = 131;
int32_t jniDebugFlag = 131;
S
Shengliang Guan 已提交
92
int32_t tmrDebugFlag = 131;
S
Shengliang Guan 已提交
93
int32_t uDebugFlag = 131;
S
Shengliang Guan 已提交
94 95
int32_t rpcDebugFlag = 131;
int32_t qDebugFlag = 131;
S
Shengliang Guan 已提交
96 97
int32_t wDebugFlag = 131;
int32_t sDebugFlag = 131;
S
Shengliang Guan 已提交
98
int32_t tsdbDebugFlag = 131;
H
Hongze Cheng 已提交
99
int32_t tdbDebugFlag = 131;
S
Shengliang Guan 已提交
100 101 102 103
int32_t tqDebugFlag = 131;
int32_t fsDebugFlag = 131;
int32_t metaDebugFlag = 131;
int32_t udfDebugFlag = 131;
C
Cary Xu 已提交
104
int32_t smaDebugFlag = 131;
S
Shengliang Guan 已提交
105
int32_t idxDebugFlag = 131;
D
dapan1121 已提交
106

D
fix bug  
dapan1121 已提交
107
int64_t dbgEmptyW = 0;
D
fix bug  
dapan1121 已提交
108 109 110
int64_t dbgWN = 0;
int64_t dbgSmallWN = 0;
int64_t dbgBigWN = 0;
D
fix bug  
dapan1121 已提交
111 112
int64_t dbgWSize = 0;

dengyihao's avatar
dengyihao 已提交
113
static void     *taosAsyncOutputLog(void *param);
114
static int32_t   taosPushLogBuffer(SLogBuff *pLogBuf, const char *msg, int32_t msgLen);
S
slguan 已提交
115
static SLogBuff *taosLogBuffNew(int32_t bufSize);
116
static void      taosCloseLogByFd(TdFilePtr pFile);
S
slguan 已提交
117
static int32_t   taosOpenLogFile(char *fn, int32_t maxLines, int32_t maxFileNum);
S
Shengliang Guan 已提交
118
static int32_t   taosCompressFile(char *srcFileName, char *destFileName);
S
slguan 已提交
119

dengyihao's avatar
dengyihao 已提交
120 121 122 123 124 125 126 127 128 129
static FORCE_INLINE void taosUpdateDaylight() {
  struct tm      Tm, *ptm;
  struct timeval timeSecs;
  taosGetTimeOfDay(&timeSecs);
  time_t curTime = timeSecs.tv_sec;
  ptm = taosLocalTime(&curTime, &Tm);
  tsDaylightActive = ptm->tm_isdst;
}
static FORCE_INLINE int32_t taosGetDaylight() { return tsDaylightActive; }

S
slguan 已提交
130
static int32_t taosStartLog() {
wafwerar's avatar
wafwerar 已提交
131 132 133
  TdThreadAttr threadAttr;
  taosThreadAttrInit(&threadAttr);
  if (taosThreadCreate(&(tsLogObj.logHandle->asyncThread), &threadAttr, taosAsyncOutputLog, tsLogObj.logHandle) != 0) {
H
hzcheng 已提交
134 135
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
136
  taosThreadAttrDestroy(&threadAttr);
H
hzcheng 已提交
137 138 139
  return 0;
}

S
Shengliang Guan 已提交
140
int32_t taosInitLog(const char *logName, int32_t maxFiles) {
S
Shengliang Guan 已提交
141
  if (atomic_val_compare_exchange_8(&tsLogInited, 0, 1) != 0) return 0;
S
osenv  
Shengliang Guan 已提交
142
  osUpdate();
S
Shengliang Guan 已提交
143

S
Shengliang Guan 已提交
144
  char fullName[PATH_MAX] = {0};
dengyihao's avatar
dengyihao 已提交
145 146 147 148 149
  if (strlen(tsLogDir) != 0) {
    snprintf(fullName, PATH_MAX, "%s" TD_DIRSEP "%s", tsLogDir, logName);
  } else {
    snprintf(fullName, PATH_MAX, "%s", logName);
  }
dengyihao's avatar
dengyihao 已提交
150
  taosUpdateDaylight();
S
Shengliang Guan 已提交
151

S
ulog  
Shengliang Guan 已提交
152
  tsLogObj.logHandle = taosLogBuffNew(LOG_DEFAULT_BUF_SIZE);
S
slguan 已提交
153
  if (tsLogObj.logHandle == NULL) return -1;
S
Shengliang Guan 已提交
154
  if (taosOpenLogFile(fullName, tsNumOfLogLines, maxFiles) < 0) return -1;
H
hzcheng 已提交
155 156 157 158
  if (taosStartLog() < 0) return -1;
  return 0;
}

S
slguan 已提交
159 160 161 162
static void taosStopLog() {
  if (tsLogObj.logHandle) {
    tsLogObj.logHandle->stop = 1;
  }
H
hzcheng 已提交
163 164
}

S
slguan 已提交
165
void taosCloseLog() {
166 167 168 169
  if (tsLogObj.logHandle != NULL) {
    taosStopLog();
    if (tsLogObj.logHandle != NULL && taosCheckPthreadValid(tsLogObj.logHandle->asyncThread)) {
      taosThreadJoin(tsLogObj.logHandle->asyncThread, NULL);
170
      taosThreadClear(&tsLogObj.logHandle->asyncThread);
171 172 173 174 175 176 177 178 179 180 181
    }
    tsLogInited = 0;

    taosThreadMutexDestroy(&tsLogObj.logHandle->buffMutex);
    taosCloseFile(&tsLogObj.logHandle->pFile);
    taosMemoryFreeClear(tsLogObj.logHandle->buffer);
    memset(&tsLogObj.logHandle->buffer, 0, sizeof(tsLogObj.logHandle->buffer));
    taosThreadMutexDestroy(&tsLogObj.logMutex);
    taosMemoryFreeClear(tsLogObj.logHandle);
    memset(&tsLogObj.logHandle, 0, sizeof(tsLogObj.logHandle));
    tsLogObj.logHandle = NULL;
S
slguan 已提交
182
  }
H
hzcheng 已提交
183 184
}

185 186
static bool taosLockLogFile(TdFilePtr pFile) {
  if (pFile == NULL) return false;
H
hzcheng 已提交
187

S
slguan 已提交
188
  if (tsLogObj.fileNum > 1) {
189
    int32_t ret = taosLockFile(pFile);
H
hzcheng 已提交
190 191 192 193 194 195 196 197
    if (ret == 0) {
      return true;
    }
  }

  return false;
}

198 199
static void taosUnLockLogFile(TdFilePtr pFile) {
  if (pFile == NULL) return;
H
hzcheng 已提交
200

S
slguan 已提交
201
  if (tsLogObj.fileNum > 1) {
202
    taosUnLockFile(pFile);
H
hzcheng 已提交
203 204 205
  }
}

S
TD-1263  
Shengliang Guan 已提交
206
static void taosKeepOldLog(char *oldName) {
S
TD-1574  
Shengliang Guan 已提交
207
  if (tsLogKeepDays == 0) return;
S
TD-1263  
Shengliang Guan 已提交
208

S
TD-1263  
Shengliang Guan 已提交
209
  int64_t fileSec = taosGetTimestampSec();
S
TD-1263  
Shengliang Guan 已提交
210
  char    fileName[LOG_FILE_NAME_LEN + 20];
S
TD-1263  
Shengliang Guan 已提交
211
  snprintf(fileName, LOG_FILE_NAME_LEN + 20, "%s.%" PRId64, tsLogObj.logName, fileSec);
S
TD-1263  
Shengliang Guan 已提交
212

A
Alex Duan 已提交
213
  (void)taosRenameFile(oldName, fileName);
214

S
TD-1574  
Shengliang Guan 已提交
215 216 217 218
  if (tsLogKeepDays < 0) {
    char compressFileName[LOG_FILE_NAME_LEN + 20];
    snprintf(compressFileName, LOG_FILE_NAME_LEN + 20, "%s.%" PRId64 ".gz", tsLogObj.logName, fileSec);
    if (taosCompressFile(fileName, compressFileName) == 0) {
219
      (void)taosRemoveFile(fileName);
S
TD-1574  
Shengliang Guan 已提交
220 221 222
    }
  }

S
os env  
Shengliang Guan 已提交
223
  taosRemoveOldFiles(tsLogDir, TABS(tsLogKeepDays));
S
TD-1263  
Shengliang Guan 已提交
224 225
}

S
slguan 已提交
226
static void *taosThreadToOpenNewFile(void *param) {
S
TD-1263  
Shengliang Guan 已提交
227 228
  char keepName[LOG_FILE_NAME_LEN + 20];
  sprintf(keepName, "%s.%d", tsLogObj.logName, tsLogObj.flag);
H
hzcheng 已提交
229

S
slguan 已提交
230 231
  tsLogObj.flag ^= 1;
  tsLogObj.lines = 0;
S
TD-1263  
Shengliang Guan 已提交
232
  char name[LOG_FILE_NAME_LEN + 20];
S
slguan 已提交
233
  sprintf(name, "%s.%d", tsLogObj.logName, tsLogObj.flag);
H
hzcheng 已提交
234

S
Shengliang Guan 已提交
235
  taosUmaskFile(0);
H
hzcheng 已提交
236

237
  TdFilePtr pFile = taosOpenFile(name, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
238
  if (pFile == NULL) {
239 240
    tsLogObj.openInProgress = 0;
    tsLogObj.lines = tsLogObj.maxLines - 1000;
241
    uError("open new log file fail! reason:%s, reuse lastlog", strerror(errno));
H
Hui Li 已提交
242 243
    return NULL;
  }
S
TD-1263  
Shengliang Guan 已提交
244

245 246
  taosLockLogFile(pFile);
  (void)taosLSeekFile(pFile, 0, SEEK_SET);
H
hzcheng 已提交
247

248 249
  TdFilePtr pOldFile = tsLogObj.logHandle->pFile;
  tsLogObj.logHandle->pFile = pFile;
S
slguan 已提交
250 251
  tsLogObj.lines = 0;
  tsLogObj.openInProgress = 0;
wafwerar's avatar
wafwerar 已提交
252
  taosSsleep(20);
253
  taosCloseLogByFd(pOldFile);
L
Liu Jicong 已提交
254

S
TD-1263  
Shengliang Guan 已提交
255 256
  uInfo("   new log file:%d is opened", tsLogObj.flag);
  uInfo("==================================");
S
TD-1263  
Shengliang Guan 已提交
257 258
  taosKeepOldLog(keepName);

H
hzcheng 已提交
259 260 261
  return NULL;
}

S
slguan 已提交
262
static int32_t taosOpenNewLogFile() {
wafwerar's avatar
wafwerar 已提交
263
  taosThreadMutexLock(&tsLogObj.logMutex);
H
hzcheng 已提交
264

S
slguan 已提交
265 266
  if (tsLogObj.lines > tsLogObj.maxLines && tsLogObj.openInProgress == 0) {
    tsLogObj.openInProgress = 1;
H
hzcheng 已提交
267

268
    uInfo("open new log file ......");
269
    TdThread     thread;
wafwerar's avatar
wafwerar 已提交
270 271 272
    TdThreadAttr attr;
    taosThreadAttrInit(&attr);
    taosThreadAttrSetDetachState(&attr, PTHREAD_CREATE_DETACHED);
H
hzcheng 已提交
273

wafwerar's avatar
wafwerar 已提交
274 275
    taosThreadCreate(&thread, &attr, taosThreadToOpenNewFile, NULL);
    taosThreadAttrDestroy(&attr);
H
hzcheng 已提交
276 277
  }

wafwerar's avatar
wafwerar 已提交
278
  taosThreadMutexUnlock(&tsLogObj.logMutex);
H
hzcheng 已提交
279 280 281 282

  return 0;
}

S
slguan 已提交
283 284 285
void taosResetLog() {
  char lastName[LOG_FILE_NAME_LEN + 20];
  sprintf(lastName, "%s.%d", tsLogObj.logName, tsLogObj.flag);
H
hzcheng 已提交
286 287

  // force create a new log file
S
slguan 已提交
288
  tsLogObj.lines = tsLogObj.maxLines + 10;
H
hzcheng 已提交
289 290

  taosOpenNewLogFile();
291
  (void)taosRemoveFile(lastName);
H
hzcheng 已提交
292

293 294
  uInfo("==================================");
  uInfo("   reset log file ");
H
hzcheng 已提交
295 296
}

S
slguan 已提交
297
static bool taosCheckFileIsOpen(char *logFileName) {
298 299
  TdFilePtr pFile = taosOpenFile(logFileName, TD_FILE_WRITE);
  if (pFile == NULL) {
300 301 302 303 304 305
    if (errno == ENOENT) {
      return false;
    } else {
      printf("\nfailed to open log file:%s, reason:%s\n", logFileName, strerror(errno));
      return true;
    }
H
hzcheng 已提交
306 307
  }

308 309 310
  if (taosLockLogFile(pFile)) {
    taosUnLockLogFile(pFile);
    taosCloseFile(&pFile);
H
hzcheng 已提交
311 312
    return false;
  } else {
313
    taosCloseFile(&pFile);
H
hzcheng 已提交
314 315 316 317
    return true;
  }
}

S
slguan 已提交
318 319 320
static void taosGetLogFileName(char *fn) {
  if (tsLogObj.fileNum > 1) {
    for (int32_t i = 0; i < tsLogObj.fileNum; i++) {
H
hzcheng 已提交
321 322
      char fileName[LOG_FILE_NAME_LEN];

H
Haojun Liao 已提交
323
      snprintf(fileName, LOG_FILE_NAME_LEN, "%s%d.0", fn, i);
H
hzcheng 已提交
324 325
      bool file1open = taosCheckFileIsOpen(fileName);

H
Haojun Liao 已提交
326
      snprintf(fileName, LOG_FILE_NAME_LEN, "%s%d.1", fn, i);
H
hzcheng 已提交
327 328 329
      bool file2open = taosCheckFileIsOpen(fileName);

      if (!file1open && !file2open) {
H
Haojun Liao 已提交
330
        snprintf(tsLogObj.logName, LOG_FILE_NAME_LEN, "%s%d", fn, i);
H
hzcheng 已提交
331 332 333 334 335
        return;
      }
    }
  }

H
Hui Li 已提交
336 337 338
  if (strlen(fn) < LOG_FILE_NAME_LEN) {
    strcpy(tsLogObj.logName, fn);
  }
H
hzcheng 已提交
339 340
}

S
slguan 已提交
341
static int32_t taosOpenLogFile(char *fn, int32_t maxLines, int32_t maxFileNum) {
S
slguan 已提交
342 343
#ifdef WINDOWS
  /*
L
Liu Jicong 已提交
344 345 346
   * always set maxFileNum to 1
   * means client log filename is unique in windows
   */
S
slguan 已提交
347 348 349
  maxFileNum = 1;
#endif

S
Shengliang Guan 已提交
350 351 352
  char    name[LOG_FILE_NAME_LEN + 50] = "\0";
  int32_t logstat0_mtime, logstat1_mtime;
  int32_t size;
H
hzcheng 已提交
353

S
slguan 已提交
354 355
  tsLogObj.maxLines = maxLines;
  tsLogObj.fileNum = maxFileNum;
H
hzcheng 已提交
356 357
  taosGetLogFileName(fn);

H
Hui Li 已提交
358 359 360 361
  if (strlen(fn) < LOG_FILE_NAME_LEN + 50 - 2) {
    strcpy(name, fn);
    strcat(name, ".0");
  }
S
Shengliang Guan 已提交
362
  bool log0Exist = taosStatFile(name, NULL, &logstat0_mtime) >= 0;
H
hzcheng 已提交
363

S
TD-1263  
Shengliang Guan 已提交
364 365 366 367
  if (strlen(fn) < LOG_FILE_NAME_LEN + 50 - 2) {
    strcpy(name, fn);
    strcat(name, ".1");
  }
S
Shengliang Guan 已提交
368 369
  bool log1Exist = taosStatFile(name, NULL, &logstat1_mtime) >= 0;

H
hzcheng 已提交
370
  // if none of the log files exist, open 0, if both exists, open the old one
S
TD-1263  
Shengliang Guan 已提交
371 372 373
  if (!log0Exist && !log1Exist) {
    tsLogObj.flag = 0;
  } else if (!log1Exist) {
S
slguan 已提交
374
    tsLogObj.flag = 0;
S
TD-1263  
Shengliang Guan 已提交
375 376
  } else if (!log0Exist) {
    tsLogObj.flag = 1;
H
hzcheng 已提交
377
  } else {
S
Shengliang Guan 已提交
378
    tsLogObj.flag = (logstat0_mtime > logstat1_mtime) ? 0 : 1;
H
hzcheng 已提交
379 380
  }

H
Hui Li 已提交
381 382
  char fileName[LOG_FILE_NAME_LEN + 50] = "\0";
  sprintf(fileName, "%s.%d", tsLogObj.logName, tsLogObj.flag);
wafwerar's avatar
wafwerar 已提交
383
  taosThreadMutexInit(&tsLogObj.logMutex, NULL);
H
hzcheng 已提交
384

S
Shengliang Guan 已提交
385
  taosUmaskFile(0);
386
  tsLogObj.logHandle->pFile = taosOpenFile(fileName, TD_FILE_CREATE | TD_FILE_WRITE);
H
hzcheng 已提交
387

388
  if (tsLogObj.logHandle->pFile == NULL) {
H
Hui Li 已提交
389
    printf("\nfailed to open log file:%s, reason:%s\n", fileName, strerror(errno));
H
hzcheng 已提交
390 391
    return -1;
  }
392
  taosLockLogFile(tsLogObj.logHandle->pFile);
H
hzcheng 已提交
393 394

  // only an estimate for number of lines
S
Shengliang Guan 已提交
395
  int64_t filesize = 0;
396
  if (taosFStatFile(tsLogObj.logHandle->pFile, &filesize, NULL) < 0) {
H
Hui Li 已提交
397
    printf("\nfailed to fstat log file:%s, reason:%s\n", fileName, strerror(errno));
H
Hui Li 已提交
398 399
    return -1;
  }
S
Shengliang Guan 已提交
400
  size = (int32_t)filesize;
S
slguan 已提交
401
  tsLogObj.lines = size / 60;
H
hzcheng 已提交
402

403
  taosLSeekFile(tsLogObj.logHandle->pFile, 0, SEEK_END);
H
hzcheng 已提交
404 405

  sprintf(name, "==================================================\n");
406
  taosWriteFile(tsLogObj.logHandle->pFile, name, (uint32_t)strlen(name));
H
hzcheng 已提交
407
  sprintf(name, "                new log file                      \n");
408
  taosWriteFile(tsLogObj.logHandle->pFile, name, (uint32_t)strlen(name));
H
hzcheng 已提交
409
  sprintf(name, "==================================================\n");
410
  taosWriteFile(tsLogObj.logHandle->pFile, name, (uint32_t)strlen(name));
H
hzcheng 已提交
411 412 413 414

  return 0;
}

415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
static void taosUpdateLogNums(ELogLevel level) {
  switch (level) {
    case DEBUG_ERROR:
      atomic_add_fetch_64(&tsNumOfErrorLogs, 1);
      break;
    case DEBUG_INFO:
      atomic_add_fetch_64(&tsNumOfInfoLogs, 1);
      break;
    case DEBUG_DEBUG:
      atomic_add_fetch_64(&tsNumOfDebugLogs, 1);
      break;
    case DEBUG_DUMP:
    case DEBUG_TRACE:
      atomic_add_fetch_64(&tsNumOfTraceLogs, 1);
      break;
    default:
      break;
  }
}

S
Shengliang Guan 已提交
435
static inline int32_t taosBuildLogHead(char *buffer, const char *flags) {
H
hzcheng 已提交
436 437 438
  struct tm      Tm, *ptm;
  struct timeval timeSecs;

S
Shengliang Guan 已提交
439
  taosGetTimeOfDay(&timeSecs);
S
Shengliang Guan 已提交
440
  time_t curTime = timeSecs.tv_sec;
dengyihao's avatar
enh log  
dengyihao 已提交
441
  ptm = taosLocalTime(&curTime, &Tm);
S
slguan 已提交
442

S
Shengliang Guan 已提交
443 444 445
  return sprintf(buffer, "%02d/%02d %02d:%02d:%02d.%06d %08" PRId64 " %s", ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour,
                 ptm->tm_min, ptm->tm_sec, (int32_t)timeSecs.tv_usec, taosGetSelfPthreadId(), flags);
}
H
hzcheng 已提交
446

S
Shengliang Guan 已提交
447
static inline void taosPrintLogImp(ELogLevel level, int32_t dflag, const char *buffer, int32_t len) {
wafwerar's avatar
wafwerar 已提交
448
  if ((dflag & DEBUG_FILE) && tsLogObj.logHandle && tsLogObj.logHandle->pFile != NULL && osLogSpaceAvailable()) {
449
    taosUpdateLogNums(level);
450 451 452
#if 0 
    // DEBUG_FATAL and DEBUG_ERROR are duplicated
    // fsync will cause thread blocking and may also generate log misalignment in case of asyncLog
B
Benguang Zhao 已提交
453
    if (tsAsyncLog && level != DEBUG_FATAL) {
S
slguan 已提交
454
      taosPushLogBuffer(tsLogObj.logHandle, buffer, len);
H
hzcheng 已提交
455
    } else {
456
      taosWriteFile(tsLogObj.logHandle->pFile, buffer, len);
B
Benguang Zhao 已提交
457 458 459
      if (level == DEBUG_FATAL) {
        taosFsyncFile(tsLogObj.logHandle->pFile);
      }
H
hzcheng 已提交
460
    }
461 462 463 464 465 466 467
#else
    if (tsAsyncLog) {
      taosPushLogBuffer(tsLogObj.logHandle, buffer, len);
    } else {
      taosWriteFile(tsLogObj.logHandle->pFile, buffer, len);
    }
#endif
H
hzcheng 已提交
468

S
slguan 已提交
469 470
    if (tsLogObj.maxLines > 0) {
      atomic_add_fetch_32(&tsLogObj.lines, 1);
S
Shengliang Guan 已提交
471 472 473
      if ((tsLogObj.lines > tsLogObj.maxLines) && (tsLogObj.openInProgress == 0)) {
        taosOpenNewLogFile();
      }
H
hzcheng 已提交
474 475 476
    }
  }

477
  if (dflag & DEBUG_SCREEN) {
478 479
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
S
Shengliang Guan 已提交
480
    write(1, buffer, (uint32_t)len);
481
#pragma GCC diagnostic pop
482
  }
H
hzcheng 已提交
483 484
}

S
Shengliang Guan 已提交
485
void taosPrintLog(const char *flags, ELogLevel level, int32_t dflag, const char *format, ...) {
S
Shengliang Guan 已提交
486
  if (!(dflag & DEBUG_FILE) && !(dflag & DEBUG_SCREEN)) return;
S
slguan 已提交
487

S
Shengliang Guan 已提交
488 489
  char    buffer[LOG_MAX_LINE_BUFFER_SIZE];
  int32_t len = taosBuildLogHead(buffer, flags);
H
hzcheng 已提交
490

S
Shengliang Guan 已提交
491 492
  va_list argpointer;
  va_start(argpointer, format);
S
Shengliang Guan 已提交
493
  int32_t writeLen = len + vsnprintf(buffer + len, LOG_MAX_LINE_BUFFER_SIZE - len, format, argpointer);
S
Shengliang Guan 已提交
494
  va_end(argpointer);
H
hzcheng 已提交
495

S
Shengliang Guan 已提交
496 497 498
  if (writeLen > LOG_MAX_LINE_SIZE) writeLen = LOG_MAX_LINE_SIZE;
  buffer[writeLen++] = '\n';
  buffer[writeLen] = 0;
H
hzcheng 已提交
499

S
Shengliang Guan 已提交
500 501 502 503 504 505
  taosPrintLogImp(level, dflag, buffer, writeLen);

  if (tsLogFp && level <= DEBUG_INFO) {
    buffer[writeLen - 1] = 0;
    (*tsLogFp)(taosGetTimestampMs(), level, buffer + len);
  }
H
hzcheng 已提交
506 507
}

508
void taosPrintLongString(const char *flags, ELogLevel level, int32_t dflag, const char *format, ...) {
S
os env  
Shengliang Guan 已提交
509
  if (!osLogSpaceAvailable()) return;
S
Shengliang Guan 已提交
510
  if (!(dflag & DEBUG_FILE) && !(dflag & DEBUG_SCREEN)) return;
S
slguan 已提交
511

dengyihao's avatar
dengyihao 已提交
512
  char   *buffer = taosMemoryMalloc(LOG_MAX_LINE_DUMP_BUFFER_SIZE);
S
Shengliang Guan 已提交
513
  int32_t len = taosBuildLogHead(buffer, flags);
H
hzcheng 已提交
514

S
Shengliang Guan 已提交
515
  va_list argpointer;
H
hzcheng 已提交
516
  va_start(argpointer, format);
S
Shengliang Guan 已提交
517
  len += vsnprintf(buffer + len, LOG_MAX_LINE_DUMP_BUFFER_SIZE - len, format, argpointer);
H
hzcheng 已提交
518 519
  va_end(argpointer);

S
Shengliang Guan 已提交
520
  if (len > LOG_MAX_LINE_DUMP_SIZE) len = LOG_MAX_LINE_DUMP_SIZE;
H
hzcheng 已提交
521 522 523
  buffer[len++] = '\n';
  buffer[len] = 0;

S
Shengliang Guan 已提交
524
  taosPrintLogImp(level, dflag, buffer, len);
525
  taosMemoryFree(buffer);
S
Shengliang Guan 已提交
526
}
L
Liu Jicong 已提交
527

S
Shengliang Guan 已提交
528 529 530
void taosDumpData(unsigned char *msg, int32_t len) {
  if (!osLogSpaceAvailable()) return;
  taosUpdateLogNums(DEBUG_DUMP);
H
hzcheng 已提交
531

532
  char    temp[256] = {0};
S
Shengliang Guan 已提交
533 534 535 536 537 538 539 540 541 542 543
  int32_t i, pos = 0, c = 0;

  for (i = 0; i < len; ++i) {
    sprintf(temp + pos, "%02x ", msg[i]);
    c++;
    pos += 3;
    if (c >= 16) {
      temp[pos++] = '\n';
      taosWriteFile(tsLogObj.logHandle->pFile, temp, (uint32_t)pos);
      c = 0;
      pos = 0;
H
hzcheng 已提交
544 545 546
    }
  }

S
Shengliang Guan 已提交
547 548 549
  temp[pos++] = '\n';

  taosWriteFile(tsLogObj.logHandle->pFile, temp, (uint32_t)pos);
H
hzcheng 已提交
550 551
}

552 553 554 555
static void taosCloseLogByFd(TdFilePtr pFile) {
  if (pFile != NULL) {
    taosUnLockLogFile(pFile);
    taosCloseFile(&pFile);
H
hzcheng 已提交
556 557 558
  }
}

S
slguan 已提交
559
static SLogBuff *taosLogBuffNew(int32_t bufSize) {
560
  SLogBuff *pLogBuf = NULL;
H
hzcheng 已提交
561

562 563
  pLogBuf = taosMemoryCalloc(1, sizeof(SLogBuff));
  if (pLogBuf == NULL) return NULL;
H
hzcheng 已提交
564

565 566
  LOG_BUF_BUFFER(pLogBuf) = taosMemoryMalloc(bufSize);
  if (LOG_BUF_BUFFER(pLogBuf) == NULL) goto _err;
H
hzcheng 已提交
567

568 569 570 571
  LOG_BUF_START(pLogBuf) = LOG_BUF_END(pLogBuf) = 0;
  LOG_BUF_SIZE(pLogBuf) = bufSize;
  pLogBuf->minBuffSize = bufSize / 10;
  pLogBuf->stop = 0;
H
hzcheng 已提交
572

573 574
  if (taosThreadMutexInit(&LOG_BUF_MUTEX(pLogBuf), NULL) < 0) goto _err;
  // tsem_init(&(pLogBuf->buffNotEmpty), 0, 0);
H
hzcheng 已提交
575

576
  return pLogBuf;
H
hzcheng 已提交
577 578

_err:
579 580
  taosMemoryFreeClear(LOG_BUF_BUFFER(pLogBuf));
  taosMemoryFreeClear(pLogBuf);
H
hzcheng 已提交
581 582 583
  return NULL;
}

584
static void taosCopyLogBuffer(SLogBuff *pLogBuf, int32_t start, int32_t end, const char *msg, int32_t msgLen) {
D
fix bug  
dapan1121 已提交
585
  if (start > end) {
586
    memcpy(LOG_BUF_BUFFER(pLogBuf) + end, msg, msgLen);
D
fix bug  
dapan1121 已提交
587
  } else {
588 589 590
    if (LOG_BUF_SIZE(pLogBuf) - end < msgLen) {
      memcpy(LOG_BUF_BUFFER(pLogBuf) + end, msg, LOG_BUF_SIZE(pLogBuf) - end);
      memcpy(LOG_BUF_BUFFER(pLogBuf), msg + LOG_BUF_SIZE(pLogBuf) - end, msgLen - LOG_BUF_SIZE(pLogBuf) + end);
D
fix bug  
dapan1121 已提交
591
    } else {
592
      memcpy(LOG_BUF_BUFFER(pLogBuf) + end, msg, msgLen);
D
fix bug  
dapan1121 已提交
593 594
    }
  }
595
  LOG_BUF_END(pLogBuf) = (LOG_BUF_END(pLogBuf) + msgLen) % LOG_BUF_SIZE(pLogBuf);
D
fix bug  
dapan1121 已提交
596 597
}

598
static int32_t taosPushLogBuffer(SLogBuff *pLogBuf, const char *msg, int32_t msgLen) {
L
Liu Jicong 已提交
599 600 601
  int32_t        start = 0;
  int32_t        end = 0;
  int32_t        remainSize = 0;
D
fix bug  
dapan1121 已提交
602
  static int64_t lostLine = 0;
H
Haojun Liao 已提交
603
  char           tmpBuf[128] = {0};
L
Liu Jicong 已提交
604
  int32_t        tmpBufLen = 0;
H
hzcheng 已提交
605

606
  if (pLogBuf == NULL || pLogBuf->stop) return -1;
H
hzcheng 已提交
607

608 609 610
  taosThreadMutexLock(&LOG_BUF_MUTEX(pLogBuf));
  start = LOG_BUF_START(pLogBuf);
  end = LOG_BUF_END(pLogBuf);
H
hzcheng 已提交
611

612
  remainSize = (start > end) ? (start - end - 1) : (start + LOG_BUF_SIZE(pLogBuf) - end - 1);
H
hzcheng 已提交
613

D
fix bug  
dapan1121 已提交
614
  if (lostLine > 0) {
H
Haojun Liao 已提交
615
    snprintf(tmpBuf, tListLen(tmpBuf), "...Lost %" PRId64 " lines here...\n", lostLine);
D
dapan1121 已提交
616
    tmpBufLen = (int32_t)strlen(tmpBuf);
D
fix bug  
dapan1121 已提交
617 618 619 620
  }

  if (remainSize <= msgLen || ((lostLine > 0) && (remainSize <= (msgLen + tmpBufLen)))) {
    lostLine++;
S
Shengliang Guan 已提交
621
    tsAsyncLogLostLines++;
622
    taosThreadMutexUnlock(&LOG_BUF_MUTEX(pLogBuf));
H
hzcheng 已提交
623 624 625
    return -1;
  }

D
fix bug  
dapan1121 已提交
626
  if (lostLine > 0) {
627
    taosCopyLogBuffer(pLogBuf, start, end, tmpBuf, tmpBufLen);
D
fix bug  
dapan1121 已提交
628
    lostLine = 0;
H
hzcheng 已提交
629
  }
D
fix bug  
dapan1121 已提交
630

631
  taosCopyLogBuffer(pLogBuf, LOG_BUF_START(pLogBuf), LOG_BUF_END(pLogBuf), msg, msgLen);
H
hzcheng 已提交
632

L
Liu Jicong 已提交
633
  // int32_t w = atomic_sub_fetch_32(&waitLock, 1);
D
fix bug  
dapan1121 已提交
634
  /*
635 636
  if (w <= 0 || ((remainSize - msgLen - tmpBufLen) < (LOG_BUF_SIZE(pLogBuf) * 4 /5))) {
    tsem_post(&(pLogBuf->buffNotEmpty));
D
fix bug  
dapan1121 已提交
637 638 639
    dbgPostN++;
  } else {
    dbgNoPostN++;
D
fix bug  
dapan1121 已提交
640
  }
D
fix bug  
dapan1121 已提交
641
  */
H
hzcheng 已提交
642

643
  taosThreadMutexUnlock(&LOG_BUF_MUTEX(pLogBuf));
H
hzcheng 已提交
644 645 646 647

  return 0;
}

648
static int32_t taosGetLogRemainSize(SLogBuff *pLogBuf, int32_t start, int32_t end) {
D
fix bug  
dapan1121 已提交
649
  int32_t rSize = end - start;
H
hzcheng 已提交
650

651
  return rSize >= 0 ? rSize : LOG_BUF_SIZE(pLogBuf) + rSize;
D
fix bug  
dapan1121 已提交
652
}
H
hzcheng 已提交
653

654
static void taosWriteLog(SLogBuff *pLogBuf) {
D
fix bu  
dapan1121 已提交
655
  static int32_t lastDuration = 0;
L
Liu Jicong 已提交
656 657 658
  int32_t        remainChecked = 0;
  int32_t        start, end, pollSize;

D
fix bug  
dapan1121 已提交
659
  do {
D
fix bu  
dapan1121 已提交
660
    if (remainChecked == 0) {
661 662
      start = LOG_BUF_START(pLogBuf);
      end = LOG_BUF_END(pLogBuf);
D
fix bu  
dapan1121 已提交
663 664 665

      if (start == end) {
        dbgEmptyW++;
S
Shengliang Guan 已提交
666
        tsWriteInterval = LOG_MAX_INTERVAL;
D
fix bu  
dapan1121 已提交
667 668
        return;
      }
H
hzcheng 已提交
669

670 671
      pollSize = taosGetLogRemainSize(pLogBuf, start, end);
      if (pollSize < pLogBuf->minBuffSize) {
S
Shengliang Guan 已提交
672
        lastDuration += tsWriteInterval;
D
fix bug  
dapan1121 已提交
673
        if (lastDuration < LOG_MAX_WAIT_MSEC) {
D
fix bu  
dapan1121 已提交
674 675 676
          break;
        }
      }
D
fix bug  
dapan1121 已提交
677

D
fix bu  
dapan1121 已提交
678 679 680 681
      lastDuration = 0;
    }

    if (start < end) {
682
      taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf) + start, pollSize);
H
hzcheng 已提交
683
    } else {
684 685
      int32_t tsize = LOG_BUF_SIZE(pLogBuf) - start;
      taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf) + start, tsize);
D
fix bug  
dapan1121 已提交
686

687
      taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf), end);
H
hzcheng 已提交
688
    }
D
fix bug  
dapan1121 已提交
689 690

    dbgWN++;
L
Liu Jicong 已提交
691 692
    dbgWSize += pollSize;

693
    if (pollSize < pLogBuf->minBuffSize) {
D
fix bug  
dapan1121 已提交
694
      dbgSmallWN++;
S
Shengliang Guan 已提交
695 696
      if (tsWriteInterval < LOG_MAX_INTERVAL) {
        tsWriteInterval += LOG_INTERVAL_STEP;
D
fix bug  
dapan1121 已提交
697
      }
698
    } else if (pollSize > LOG_BUF_SIZE(pLogBuf) / 3) {
D
fix bug  
dapan1121 已提交
699
      dbgBigWN++;
S
Shengliang Guan 已提交
700
      tsWriteInterval = LOG_MIN_INTERVAL;
701
    } else if (pollSize > LOG_BUF_SIZE(pLogBuf) / 4) {
S
Shengliang Guan 已提交
702 703
      if (tsWriteInterval > LOG_MIN_INTERVAL) {
        tsWriteInterval -= LOG_INTERVAL_STEP;
D
fix bug  
dapan1121 已提交
704
      }
D
fix bug  
dapan1121 已提交
705 706
    }

707
    LOG_BUF_START(pLogBuf) = (LOG_BUF_START(pLogBuf) + pollSize) % LOG_BUF_SIZE(pLogBuf);
D
fix bug  
dapan1121 已提交
708

709 710
    start = LOG_BUF_START(pLogBuf);
    end = LOG_BUF_END(pLogBuf);
D
fix bu  
dapan1121 已提交
711

712 713
    pollSize = taosGetLogRemainSize(pLogBuf, start, end);
    if (pollSize < pLogBuf->minBuffSize) {
D
fix bug  
dapan1121 已提交
714 715 716
      break;
    }

S
Shengliang Guan 已提交
717
    tsWriteInterval = LOG_MIN_INTERVAL;
D
fix bu  
dapan1121 已提交
718 719

    remainChecked = 1;
L
Liu Jicong 已提交
720
  } while (1);
H
hzcheng 已提交
721 722
}

S
slguan 已提交
723
static void *taosAsyncOutputLog(void *param) {
724
  SLogBuff *pLogBuf = (SLogBuff *)param;
H
Haojun Liao 已提交
725
  setThreadName("log");
wafwerar's avatar
wafwerar 已提交
726
  int32_t count = 0;
dengyihao's avatar
dengyihao 已提交
727
  int32_t updateCron = 0;
H
hzcheng 已提交
728
  while (1) {
wafwerar's avatar
wafwerar 已提交
729
    count += tsWriteInterval;
dengyihao's avatar
dengyihao 已提交
730
    updateCron++;
S
Shengliang Guan 已提交
731
    taosMsleep(tsWriteInterval);
wafwerar's avatar
wafwerar 已提交
732 733 734 735
    if (count > 1000) {
      osUpdate();
      count = 0;
    }
H
hzcheng 已提交
736 737

    // Polling the buffer
738
    taosWriteLog(pLogBuf);
H
hzcheng 已提交
739

dengyihao's avatar
dengyihao 已提交
740 741 742 743 744
    if (updateCron >= 3600 * 24 * 40 / 2) {
      taosUpdateDaylight();
      updateCron = 0;
    }

745
    if (pLogBuf->stop) break;
H
hzcheng 已提交
746 747 748 749
  }

  return NULL;
}
S
Shengliang Guan 已提交
750 751 752 753 754

int32_t taosCompressFile(char *srcFileName, char *destFileName) {
  int32_t compressSize = 163840;
  int32_t ret = 0;
  int32_t len = 0;
dengyihao's avatar
dengyihao 已提交
755
  char   *data = taosMemoryMalloc(compressSize);
S
ulog  
Shengliang Guan 已提交
756
  //  gzFile  dstFp = NULL;
S
Shengliang Guan 已提交
757

758 759 760
  // srcFp = fopen(srcFileName, "r");
  TdFilePtr pSrcFile = taosOpenFile(srcFileName, TD_FILE_READ);
  if (pSrcFile == NULL) {
S
Shengliang Guan 已提交
761 762 763 764
    ret = -1;
    goto cmp_end;
  }

765
  TdFilePtr pFile = taosOpenFile(destFileName, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
766
  if (pFile == NULL) {
S
Shengliang Guan 已提交
767 768 769 770
    ret = -2;
    goto cmp_end;
  }

S
ulog  
Shengliang Guan 已提交
771 772 773 774 775 776 777 778 779 780 781
  //  dstFp = gzdopen(fd, "wb6f");
  //  if (dstFp == NULL) {
  //    ret = -3;
  //    close(fd);
  //    goto cmp_end;
  //  }
  //
  //  while (!feof(srcFp)) {
  //    len = (int32_t)fread(data, 1, compressSize, srcFp);
  //    (void)gzwrite(dstFp, data, len);
  //  }
S
Shengliang Guan 已提交
782 783

cmp_end:
784 785
  if (pSrcFile) {
    taosCloseFile(&pSrcFile);
S
Shengliang Guan 已提交
786
  }
S
ulog  
Shengliang Guan 已提交
787 788 789
  //  if (dstFp) {
  //    gzclose(dstFp);
  //  }
wafwerar's avatar
wafwerar 已提交
790
  taosMemoryFree(data);
S
Shengliang Guan 已提交
791 792 793

  return ret;
}
S
Shengliang Guan 已提交
794

S
Shengliang Guan 已提交
795
bool taosAssert(bool condition, const char *file, int32_t line, const char *format, ...) {
S
Shengliang Guan 已提交
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
  if (condition) return false;

  const char *flags = "UTL FATAL ";
  ELogLevel   level = DEBUG_FATAL;
  int32_t     dflag = 255;  // tsLogEmbedded ? 255 : uDebugFlag
  char        buffer[LOG_MAX_LINE_BUFFER_SIZE];
  int32_t     len = taosBuildLogHead(buffer, flags);

  va_list argpointer;
  va_start(argpointer, format);
  len = len + vsnprintf(buffer + len, LOG_MAX_LINE_BUFFER_SIZE - len, format, argpointer);
  va_end(argpointer);
  buffer[len++] = '\n';
  buffer[len] = 0;
  taosPrintLogImp(1, 255, buffer, len);

  taosPrintLog(flags, level, dflag, "tAssert at file %s:%d exit:%d", file, line, tsAssert);
D
dapan1121 已提交
813
  taosPrintTrace(flags, level, dflag, -1);
S
Shengliang Guan 已提交
814 815

  if (tsAssert) {
816
    // taosCloseLog();
S
Shengliang Guan 已提交
817 818 819 820 821 822 823 824 825 826
    taosMsleep(300);

#ifdef NDEBUG
    abort();
#else
    assert(0);
#endif
  }

  return true;
D
dapan1121 已提交
827 828
}

D
dapan1121 已提交
829 830 831 832 833 834 835 836 837 838 839 840
int32_t taosGenCrashJsonMsg(int signum, char** pMsg, int64_t clusterId, int64_t startTime) {
  SJson* pJson = tjsonCreateObject();
  if (pJson == NULL) return -1;
  char tmp[4096] = {0};

  tjsonAddDoubleToObject(pJson, "reportVersion", 1);

  tjsonAddIntegerToObject(pJson, "clusterId", clusterId);
  tjsonAddIntegerToObject(pJson, "startTime", startTime);

  taosGetFqdn(tmp);  
  tjsonAddStringToObject(pJson, "fqdn", tmp);
D
dapan1121 已提交
841
  
D
dapan1121 已提交
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
  tjsonAddIntegerToObject(pJson, "pid", taosGetPId());

  taosGetAppName(tmp, NULL);
  tjsonAddStringToObject(pJson, "appName", tmp);  

  if (taosGetOsReleaseName(tmp, sizeof(tmp)) == 0) {
    tjsonAddStringToObject(pJson, "os", tmp);
  }

  float numOfCores = 0;
  if (taosGetCpuInfo(tmp, sizeof(tmp), &numOfCores) == 0) {
    tjsonAddStringToObject(pJson, "cpuModel", tmp);
    tjsonAddDoubleToObject(pJson, "numOfCpu", numOfCores);
  } else {
    tjsonAddDoubleToObject(pJson, "numOfCpu", tsNumOfCores);
  }

  snprintf(tmp, sizeof(tmp), "%" PRId64 " kB", tsTotalMemoryKB);
  tjsonAddStringToObject(pJson, "memory", tmp);

  tjsonAddStringToObject(pJson, "version", version);
  tjsonAddStringToObject(pJson, "buildInfo", buildinfo);
  tjsonAddStringToObject(pJson, "gitInfo", gitinfo);

  tjsonAddIntegerToObject(pJson, "crashSig", signum);
  tjsonAddIntegerToObject(pJson, "crashTs", taosGetTimestampUs());

  taosLogTraceToBuf(tmp, sizeof(tmp), 3);
  tjsonAddStringToObject(pJson, "stackInfo", tmp);
D
dapan1121 已提交
871
  
D
dapan1121 已提交
872 873 874 875 876 877 878 879 880 881
  char* pCont = tjsonToString(pJson);
  tjsonDelete(pJson);

  *pMsg = pCont;

  return TSDB_CODE_SUCCESS;
}


void taosLogCrashInfo(char* nodeType, char* pMsg, int64_t msgLen, int signum, void *sigInfo) {
D
dapan1121 已提交
882 883 884
  const char *flags = "UTL FATAL ";
  ELogLevel   level = DEBUG_FATAL;
  int32_t     dflag = 255;
D
dapan1121 已提交
885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
  char filepath[PATH_MAX] = {0};
  TdFilePtr pFile = NULL;

  if (pMsg && msgLen > 0) {
    snprintf(filepath, sizeof(filepath), "%s%s.%sCrashLog", tsLogDir, TD_DIRSEP, nodeType);

    pFile = taosOpenFile(filepath, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_APPEND);
    if (pFile == NULL) {
      taosPrintLog(flags, level, dflag, "failed to open file:%s since %s", filepath, terrstr());
      goto _return;
    }

    taosLockFile(pFile);

    int64_t writeSize = taosWriteFile(pFile, &msgLen, sizeof(msgLen));
    if (sizeof(msgLen) != writeSize) {
      taosUnLockFile(pFile);
D
dapan1121 已提交
902
      taosPrintLog(flags, level, dflag, "failed to write len to file:%s,%p wlen:%" PRId64 " tlen:%lu since %s", 
D
dapan1121 已提交
903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
          filepath, pFile, writeSize, sizeof(msgLen), terrstr());
      goto _return;
    }

    writeSize = taosWriteFile(pFile, pMsg, msgLen);
    if (msgLen != writeSize) {
      taosUnLockFile(pFile);
      taosPrintLog(flags, level, dflag, "failed to write file:%s,%p wlen:%" PRId64 " tlen:%" PRId64 " since %s", 
          filepath, pFile, writeSize, msgLen, terrstr());
      goto _return;
    }

    taosUnLockFile(pFile);
  }

_return:

  if (pFile) taosCloseFile(&pFile);

  terrno = TAOS_SYSTEM_ERROR(errno);
D
dapan1121 已提交
923 924 925 926 927 928 929
  taosPrintLog(flags, level, dflag, "crash signal is %d", signum);
  
#ifndef WINDOWS
  taosPrintLog(flags, level, dflag, "sender PID:%d cmdline:%s", ((siginfo_t *)sigInfo)->si_pid,
        taosGetCmdlineByPID(((siginfo_t *)sigInfo)->si_pid));
#endif

D
dapan1121 已提交
930
  taosPrintTrace(flags, level, dflag, 3);
D
dapan1121 已提交
931

D
dapan1121 已提交
932 933
  taosMemoryFree(pMsg);
}
D
dapan1121 已提交
934

D
dapan1121 已提交
935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
void taosReadCrashInfo(char* filepath, char** pMsg, int64_t* pMsgLen, TdFilePtr* pFd) {
  const char *flags = "UTL FATAL ";
  ELogLevel   level = DEBUG_FATAL;
  int32_t     dflag = 255;
  TdFilePtr   pFile = NULL;
  bool        truncateFile = false;
  char*       buf = NULL;

  if (NULL == *pFd) {
    int64_t filesize = 0;
    if (taosStatFile(filepath, &filesize, NULL) < 0) {
      if (ENOENT == errno) {
        return;
      }

      terrno = TAOS_SYSTEM_ERROR(errno);
      taosPrintLog(flags, level, dflag, "failed to stat file:%s since %s", filepath, terrstr());
      return;
    }

    if (filesize <= 0) {
      return;
    }

    pFile = taosOpenFile(filepath, TD_FILE_READ|TD_FILE_WRITE);
    if (pFile == NULL) {
      if (ENOENT == errno) {
        return;
      }

      terrno = TAOS_SYSTEM_ERROR(errno);
      taosPrintLog(flags, level, dflag, "failed to open file:%s since %s", filepath, terrstr());
      return;
    }
    
    taosLockFile(pFile);
  } else {
    pFile = *pFd;
  }

  int64_t msgLen = 0;
  int64_t readSize = taosReadFile(pFile, &msgLen, sizeof(msgLen));
  if (sizeof(msgLen) != readSize) {
    truncateFile = true;
    if (readSize < 0) {
D
dapan1121 已提交
980
      taosPrintLog(flags, level, dflag, "failed to read len from file:%s,%p wlen:%" PRId64 " tlen:%lu since %s", 
D
dapan1121 已提交
981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
          filepath, pFile, readSize, sizeof(msgLen), terrstr());
    }
    goto _return;
  }

  buf = taosMemoryMalloc(msgLen);
  if (NULL == buf) {
    taosPrintLog(flags, level, dflag, "failed to malloc buf, size:%" PRId64, msgLen);
    goto _return;
  }
  
  readSize = taosReadFile(pFile, buf, msgLen);
  if (msgLen != readSize) {
    truncateFile = true;
    taosPrintLog(flags, level, dflag, "failed to read file:%s,%p wlen:%" PRId64 " tlen:%" PRId64 " since %s", 
        filepath, pFile, readSize, msgLen, terrstr());
    goto _return;
  }

  *pMsg = buf;
  *pMsgLen = msgLen;
  *pFd = pFile;

  return;

_return:

  if (truncateFile) {
    taosFtruncateFile(pFile, 0);
  }
  taosUnLockFile(pFile);
  taosCloseFile(&pFile);
  taosMemoryFree(buf);

  *pMsg = NULL;
  *pMsgLen = 0;
  *pFd = NULL;
}

void taosReleaseCrashLogFile(TdFilePtr pFile, bool truncateFile) {
  if (truncateFile) {
    taosFtruncateFile(pFile, 0);
  }
  
  taosUnLockFile(pFile);
  taosCloseFile(&pFile);
D
dapan1121 已提交
1027 1028
}