• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #3903

24 Apr 2025 11:36AM UTC coverage: 55.307% (+0.09%) from 55.213%
#3903

push

travis-ci

happyguoxy
Sync branches at 2025-04-24 19:35

175024 of 316459 relevant lines covered (55.31%)

1151858.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

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

16
#define _DEFAULT_SOURCE
17
#include "tlog.h"
18
#include "os.h"
19
#include "tconfig.h"
20
#include "tglobal.h"
21
#include "tjson.h"
22
#include "ttime.h"
23
#include "tutil.h"
24
#include "tcommon.h"
25

26
#define LOG_MAX_LINE_SIZE              (10024)
27
#define LOG_MAX_LINE_BUFFER_SIZE       (LOG_MAX_LINE_SIZE + 3)
28
#define LOG_MAX_STACK_LINE_SIZE        (512)
29
#define LOG_MAX_STACK_LINE_BUFFER_SIZE (LOG_MAX_STACK_LINE_SIZE + 3)
30
#define LOG_MAX_LINE_DUMP_SIZE         (1024 * 1024)
31
#define LOG_MAX_LINE_DUMP_BUFFER_SIZE  (LOG_MAX_LINE_DUMP_SIZE + 128)
32

33
#define LOG_FILE_DAY_LEN 64
34

35
#define LOG_DEFAULT_BUF_SIZE (20 * 1024 * 1024)  // 20MB
36
#define LOG_SLOW_BUF_SIZE    (10 * 1024 * 1024)  // 10MB
37

38
#define LOG_DEFAULT_INTERVAL 25
39
#define LOG_INTERVAL_STEP    5
40
#define LOG_MIN_INTERVAL     5
41
#define LOG_MAX_INTERVAL     25
42
#define LOG_MAX_WAIT_MSEC    1000
43

44
#define LOG_BUF_BUFFER(x) ((x)->buffer)
45
#define LOG_BUF_START(x)  ((x)->buffStart)
46
#define LOG_BUF_END(x)    ((x)->buffEnd)
47
#define LOG_BUF_SIZE(x)   ((x)->buffSize)
48
#define LOG_BUF_MUTEX(x)  ((x)->buffMutex)
49

50
#ifdef TD_ENTERPRISE
51
#define LOG_EDITION_FLG ("E")
52
#else
53
#define LOG_EDITION_FLG ("C")
54
#endif
55

56
typedef enum {
57
  LOG_OUTPUT_FILE = 0,    // default
58
  LOG_OUTPUT_STDOUT = 1,  // stdout set by -o option on the command line
59
  LOG_OUTPUT_STDERR = 2,  // stderr set by -o option on the command line
60
  LOG_OUTPUT_NULL = 4,    // /dev/null set by -o option on the command line
61
} ELogOutputType;
62

63
typedef struct {
64
  char         *buffer;
65
  int32_t       buffStart;
66
  int32_t       buffEnd;
67
  int32_t       buffSize;
68
  int32_t       minBuffSize;
69
  TdFilePtr     pFile;
70
  int32_t       stop;
71
  TdThread      asyncThread;
72
  TdThreadMutex buffMutex;
73
  int32_t       writeInterval;
74
  int32_t       lastDuration;
75
  int32_t       lock;
76
} SLogBuff;
77

78
typedef struct {
79
  int32_t       fileNum;
80
  int32_t       lines;
81
  int32_t       flag;
82
  int32_t       openInProgress;
83
  int64_t       lastKeepFileSec;
84
  int64_t       timestampToday;
85
  int8_t        outputType;  // ELogOutputType
86
  pid_t         pid;
87
  char          logName[PATH_MAX];
88
  char          slowLogName[PATH_MAX];
89
  SLogBuff     *logHandle;
90
  SLogBuff     *slowHandle;
91
  TdThreadMutex logMutex;
92
} SLogObj;
93

94
extern SConfig *tsCfg;
95
static int8_t   tsLogInited = 0;
96
static SLogObj  tsLogObj = {.fileNum = 1, .slowHandle = NULL};
97
static int64_t  tsAsyncLogLostLines = 0;
98
static int32_t  tsDaylightActive; /* Currently in daylight saving time. */
99
static SRWLatch tsLogRotateLatch = 0;
100

101
bool tsLogEmbedded = 0;
102
bool tsAsyncLog = true;
103
#ifdef ASSERT_NOT_CORE
104
bool tsAssert = false;
105
#else
106
bool tsAssert = true;
107
#endif
108
int32_t tsNumOfLogLines = 10000000;
109
int32_t tsLogKeepDays = 0;
110
char   *tsLogOutput = NULL;
111
LogFp   tsLogFp = NULL;
112
int64_t tsNumOfErrorLogs = 0;
113
int64_t tsNumOfInfoLogs = 0;
114
int64_t tsNumOfDebugLogs = 0;
115
int64_t tsNumOfTraceLogs = 0;
116
int64_t tsNumOfSlowLogs = 0;
117

118
// log
119
int32_t dDebugFlag = 131;
120
int32_t vDebugFlag = 131;
121
int32_t mDebugFlag = 131;
122
int32_t cDebugFlag = 131;
123
int32_t jniDebugFlag = 131;
124
int32_t tmrDebugFlag = 131;
125
int32_t uDebugFlag = 131;
126
int32_t rpcDebugFlag = 131;
127
int32_t qDebugFlag = 131;
128
int32_t stDebugFlag = 131;
129
int32_t wDebugFlag = 131;
130
int32_t azDebugFlag = 131;
131
int32_t sDebugFlag = 131;
132
int32_t tsdbDebugFlag = 131;
133
int32_t tdbDebugFlag = 131;
134
int32_t tqDebugFlag = 131;
135
int32_t fsDebugFlag = 131;
136
int32_t metaDebugFlag = 131;
137
int32_t udfDebugFlag = 131;
138
int32_t smaDebugFlag = 131;
139
int32_t idxDebugFlag = 131;
140
int32_t sndDebugFlag = 131;
141
int32_t simDebugFlag = 131;
142

143
int32_t tqClientDebugFlag = 131;
144

145
int64_t dbgEmptyW = 0;
146
int64_t dbgWN = 0;
147
int64_t dbgSmallWN = 0;
148
int64_t dbgBigWN = 0;
149
int64_t dbgWSize = 0;
150

151
static void     *taosAsyncOutputLog(void *param);
152
static int32_t   taosPushLogBuffer(SLogBuff *pLogBuf, const char *msg, int32_t msgLen);
153
static SLogBuff *taosLogBuffNew(int32_t bufSize);
154
static void      taosCloseLogByFd(TdFilePtr pFile);
155
static int32_t   taosInitNormalLog(const char *fn, int32_t maxFileNum);
156
static void      taosWriteLog(SLogBuff *pLogBuf);
157
static void      taosWriteSlowLog(SLogBuff *pLogBuf);
158

159
static int32_t taosStartLog() {
588✔
160
  TdThreadAttr threadAttr;
161
  (void)taosThreadAttrInit(&threadAttr);
588✔
162
#ifdef TD_COMPACT_OS
163
  (void)taosThreadAttrSetStackSize(&threadAttr, STACK_SIZE_SMALL);
164
#endif
165
  if (taosThreadCreate(&(tsLogObj.logHandle->asyncThread), &threadAttr, taosAsyncOutputLog, tsLogObj.logHandle) != 0) {
588✔
166
    return terrno;
×
167
  }
168
  (void)taosThreadAttrDestroy(&threadAttr);
588✔
169
  return 0;
588✔
170
}
171

172
static int32_t getDay(char *buf, int32_t bufSize) {
570✔
173
  time_t  t;
174
  int32_t code = taosTime(&t);
570✔
175
  if (code != 0) {
570✔
176
    return code;
×
177
  }
178
  struct tm tmInfo;
179
  if (taosLocalTime(&t, &tmInfo, buf, bufSize, NULL) != NULL) {
570✔
180
    TAOS_UNUSED(taosStrfTime(buf, bufSize, "%Y-%m-%d", &tmInfo));
570✔
181
  }
182
  return 0;
570✔
183
}
184

185
static void getFullPathName(char *fullName, const char *logName) {
1,157✔
186
  if (strlen(tsLogDir) != 0) {
1,157✔
187
    char lastC = tsLogDir[strlen(tsLogDir) - 1];
1,157✔
188
    if (lastC == '\\' || lastC == '/') {
1,157✔
189
      snprintf(fullName, PATH_MAX,
666✔
190
               "%s"
191
               "%s",
192
               tsLogDir, logName);
193
    } else {
194
      snprintf(fullName, PATH_MAX, "%s" TD_DIRSEP "%s", tsLogDir, logName);
491✔
195
    }
196
  } else {
197
    snprintf(fullName, PATH_MAX, "%s", logName);
×
198
  }
199
}
1,157✔
200

201
int32_t taosInitSlowLog() {
569✔
202
  char logFileName[64] = {0};
569✔
203
#ifdef CUS_PROMPT
204
  (void)snprintf(logFileName, 64, "%sSlowLog", CUS_PROMPT);
569✔
205
#else
206
  (void)snprintf(logFileName, 64, "taosSlowLog");
207
#endif
208

209
  getFullPathName(tsLogObj.slowLogName, logFileName);
569✔
210

211
  char    name[PATH_MAX + TD_TIME_STR_LEN] = {0};
569✔
212
  char    day[TD_TIME_STR_LEN] = {0};
569✔
213
  int32_t code = getDay(day, sizeof(day));
569✔
214
  if (code != 0) {
569✔
215
    (void)printf("failed to get day, reason:%s\n", tstrerror(code));
×
216
    return code;
×
217
  }
218
  (void)snprintf(name, PATH_MAX + TD_TIME_STR_LEN, "%s.%s", tsLogObj.slowLogName, day);
569✔
219

220
  tsLogObj.timestampToday = taosGetTimestampToday(TSDB_TIME_PRECISION_SECONDS, NULL);
569✔
221
  tsLogObj.slowHandle = taosLogBuffNew(LOG_SLOW_BUF_SIZE);
569✔
222
  if (tsLogObj.slowHandle == NULL) return terrno;
569✔
223

224
  TAOS_UNUSED(taosUmaskFile(0));
569✔
225
  tsLogObj.slowHandle->pFile = taosOpenFile(name, TD_FILE_CREATE | TD_FILE_READ | TD_FILE_WRITE | TD_FILE_APPEND);
569✔
226
  if (tsLogObj.slowHandle->pFile == NULL) {
569✔
227
    (void)printf("\nfailed to open slow log file:%s, reason:%s\n", name, strerror(ERRNO));
×
228
    return terrno;
×
229
  }
230

231
  return 0;
569✔
232
}
233

234
int32_t taosInitLogOutput(const char **ppLogName) {
583✔
235
  const char *pLog = tsLogOutput;
583✔
236
  const char *pLogName = NULL;
583✔
237
  if (pLog) {
583✔
238
    if (!tIsValidFilePath(pLog, NULL)) {
20✔
239
      fprintf(stderr, "invalid log output destination:%s, contains illegal char\n", pLog);
3✔
240
      return TSDB_CODE_INVALID_CFG;
3✔
241
    }
242
    if (0 == strcasecmp(pLog, "stdout")) {
17✔
243
      tsLogObj.outputType = LOG_OUTPUT_STDOUT;
2✔
244
      if (ppLogName) *ppLogName = pLog;
2✔
245
      return 0;
2✔
246
    }
247
    if (0 == strcasecmp(pLog, "stderr")) {
15✔
248
      tsLogObj.outputType = LOG_OUTPUT_STDERR;
2✔
249
      if (ppLogName) *ppLogName = pLog;
2✔
250
      return 0;
2✔
251
    }
252
    if (0 == strcasecmp(pLog, "/dev/null")) {
13✔
253
      tsLogObj.outputType = LOG_OUTPUT_NULL;
1✔
254
      if (ppLogName) *ppLogName = pLog;
1✔
255
      return 0;
1✔
256
    }
257
    int32_t len = strlen(pLog);
12✔
258
    if (len < 1) {
12✔
259
      fprintf(stderr, "invalid log output destination:%s, should not be empty\n", pLog);
×
260
      return TSDB_CODE_INVALID_CFG;
×
261
    }
262
    const char *p = pLog + (len - 1);
12✔
263
    if (*p == '/' || *p == '\\') {
12✔
264
      return 0;
4✔
265
    }
266

267
    if ((p = strrchr(pLog, '/')) || (p = strrchr(pLog, '\\'))) {
8✔
268
      pLogName = p + 1;
4✔
269
    } else {
270
      pLogName = pLog;
4✔
271
    }
272
    if (strcmp(pLogName, ".") == 0 || strcmp(pLogName, "..") == 0) {
8✔
273
      fprintf(stderr, "invalid log output destination:%s\n", pLog);
2✔
274
      return TSDB_CODE_INVALID_CFG;
2✔
275
    }
276

277
    if (!tIsValidFileName(pLogName, NULL)) {
6✔
278
      fprintf(stderr, "invalid log output destination:%s, contains illegal char\n", pLog);
×
279
      return TSDB_CODE_INVALID_CFG;
×
280
    }
281
    if (ppLogName) *ppLogName = pLogName;
6✔
282
  }
283
  return 0;
569✔
284
}
285

286
int32_t taosInitLog(const char *logName, int32_t maxFiles, bool tsc) {
672✔
287
  if (atomic_val_compare_exchange_8(&tsLogInited, 0, 1) != 0) return 0;
672✔
288
  int32_t code = osUpdate();
590✔
289
  if (code != 0) {
590✔
290
    uError("failed to update os info, reason:%s", tstrerror(code));
×
291
  }
292

293
  if (tsLogObj.outputType == LOG_OUTPUT_STDOUT || tsLogObj.outputType == LOG_OUTPUT_STDERR ||
590✔
294
      tsLogObj.outputType == LOG_OUTPUT_NULL) {
588✔
295
    return 0;
2✔
296
  }
297

298
  TAOS_CHECK_RETURN(taosInitNormalLog(logName, maxFiles));
588✔
299
  if (tsc) {
588✔
300
    TAOS_CHECK_RETURN(taosInitSlowLog());
569✔
301
  }
302
  TAOS_CHECK_RETURN(taosStartLog());
588✔
303
  return 0;
588✔
304
}
305

306
void taosSetNoNewFile() { tsLogObj.openInProgress = 1; }
1✔
307

308
static void taosStopLog() {
579✔
309
  if (tsLogObj.logHandle) {
579✔
310
    tsLogObj.logHandle->stop = 1;
577✔
311
  }
312
  if (tsLogObj.slowHandle) {
579✔
313
    tsLogObj.slowHandle->stop = 1;
565✔
314
  }
315
}
579✔
316

317
void taosCloseLog() {
579✔
318
  taosStopLog();
579✔
319

320
  if (tsLogObj.logHandle != NULL && taosCheckPthreadValid(tsLogObj.logHandle->asyncThread)) {
579✔
321
    (void)taosThreadJoin(tsLogObj.logHandle->asyncThread, NULL);
577✔
322
    taosThreadClear(&tsLogObj.logHandle->asyncThread);
577✔
323
  }
324

325
  if (tsLogObj.slowHandle != NULL) {
579✔
326
    (void)taosThreadMutexDestroy(&tsLogObj.slowHandle->buffMutex);
565✔
327
    (void)taosCloseFile(&tsLogObj.slowHandle->pFile);
565✔
328
    taosMemoryFreeClear(tsLogObj.slowHandle->buffer);
565✔
329
    taosMemoryFreeClear(tsLogObj.slowHandle);
565✔
330
  }
331

332
  if (tsLogObj.logHandle != NULL) {
579✔
333
    tsLogInited = 0;
577✔
334

335
    (void)taosThreadMutexDestroy(&tsLogObj.logHandle->buffMutex);
577✔
336
    (void)taosCloseFile(&tsLogObj.logHandle->pFile);
577✔
337
    taosMemoryFreeClear(tsLogObj.logHandle->buffer);
577✔
338
    (void)taosThreadMutexDestroy(&tsLogObj.logMutex);
577✔
339
    taosMemoryFreeClear(tsLogObj.logHandle);
577✔
340
    tsLogObj.logHandle = NULL;
577✔
341
  }
342
  taosMemoryFreeClear(tsLogOutput);
579✔
343
}
579✔
344

345
static bool taosLockLogFile(TdFilePtr pFile) {
1,086✔
346
  if (pFile == NULL) return false;
1,086✔
347

348
  if (tsLogObj.fileNum > 1) {
1,086✔
349
    int32_t ret = taosLockFile(pFile);
922✔
350
    if (ret == 0) {
922✔
351
      return true;
689✔
352
    }
353
  }
354

355
  return false;
397✔
356
}
357

358
static void taosUnLockLogFile(TdFilePtr pFile) {
265✔
359
  if (pFile == NULL) return;
265✔
360

361
  if (tsLogObj.fileNum > 1) {
265✔
362
    int32_t code = taosUnLockFile(pFile);
265✔
363
    if (code != 0) {
265✔
364
      TAOS_UNUSED(printf("failed to unlock log file:%p, reason:%s\n", pFile, tstrerror(code)));
×
365
    }
366
  }
367
}
368

369
static void taosReserveOldLog(char *oldName, char *keepName) {
×
370
  if (tsLogKeepDays <= 0) {
×
371
    keepName[0] = 0;
×
372
    return;
×
373
  }
374

375
  int32_t code = 0;
×
376
  int64_t fileSec = taosGetTimestampSec();
×
377
  if (tsLogObj.lastKeepFileSec < fileSec) {
×
378
    tsLogObj.lastKeepFileSec = fileSec;
×
379
  } else {
380
    fileSec = ++tsLogObj.lastKeepFileSec;
×
381
  }
382
  snprintf(keepName, PATH_MAX + 20, "%s.%" PRId64, tsLogObj.logName, fileSec);
×
383
  if ((code = taosRenameFile(oldName, keepName))) {
×
384
    keepName[0] = 0;
×
385
    uError("failed to rename file:%s to %s since %s", oldName, keepName, tstrerror(code));
×
386
  }
387
}
388

389
static void taosKeepOldLog(char *oldName) {
×
390
  if (oldName[0] != 0) {
×
391
    int32_t   code = 0, lino = 0;
×
392
    TdFilePtr oldFile = NULL;
×
393
    if ((oldFile = taosOpenFile(oldName, TD_FILE_READ))) {
×
394
      TAOS_CHECK_GOTO(taosLockFile(oldFile), &lino, _exit2);
×
395
      char compressFileName[PATH_MAX + 20];
396
      snprintf(compressFileName, PATH_MAX + 20, "%s.gz", oldName);
×
397
      TAOS_CHECK_GOTO(taosCompressFile(oldName, compressFileName), &lino, _exit1);
×
398
      TAOS_CHECK_GOTO(taosRemoveFile(oldName), &lino, _exit1);
×
399
    _exit1:
×
400
      TAOS_UNUSED(taosUnLockFile(oldFile));
×
401
    _exit2:
×
402
      TAOS_UNUSED(taosCloseFile(&oldFile));
×
403
    } else {
404
      code = terrno;
×
405
    }
406
    if (code != 0 && tsLogEmbedded == 1) {  // print error messages only in embedded log mode
×
407
      // avoid using uWarn or uError, as they may open a new log file and potentially cause a deadlock.
408
      fprintf(stderr, "WARN: failed at line %d to keep old log file:%s, reason:%s\n", lino, oldName, tstrerror(code));
×
409
    }
410
  }
411
}
×
412
typedef struct {
413
  TdFilePtr pOldFile;
414
  char      keepName[PATH_MAX + 20];
415
} OldFileKeeper;
416
static OldFileKeeper *taosOpenNewFile() {
×
417
  char keepName[PATH_MAX + 20];
418
  TAOS_UNUSED(snprintf(keepName, sizeof(keepName), "%s.%d", tsLogObj.logName, tsLogObj.flag));
×
419

420
  tsLogObj.flag ^= 1;
×
421
  tsLogObj.lines = 0;
×
422
  char name[PATH_MAX + 20];
423
  TAOS_UNUSED(snprintf(name, sizeof(name), "%s.%d", tsLogObj.logName, tsLogObj.flag));
×
424

425
  TAOS_UNUSED(taosUmaskFile(0));
×
426

427
  TdFilePtr pFile = taosOpenFile(name, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
×
428
  if (pFile == NULL) {
×
429
    tsLogObj.flag ^= 1;
×
430
    tsLogObj.lines = tsNumOfLogLines - 1000;
×
431
    uError("open new log file %s fail! reason:%s, reuse lastlog", name, tstrerror(terrno));
×
432
    return NULL;
×
433
  }
434

435
  TAOS_UNUSED(taosLockLogFile(pFile));
×
436
  if (taosLSeekFile(pFile, 0, SEEK_SET) < 0) {
×
437
    uWarn("failed to seek file:%s, reason:%s", name, tstrerror(terrno));
×
438
  }
439

440
  TdFilePtr pOldFile = tsLogObj.logHandle->pFile;
×
441
  tsLogObj.logHandle->pFile = pFile;
×
442
  tsLogObj.lines = 0;
×
443
  OldFileKeeper *oldFileKeeper = taosMemoryMalloc(sizeof(OldFileKeeper));
×
444
  if (oldFileKeeper == NULL) {
×
445
    uError("create old log keep info faild! mem is not enough.");
×
446
    return NULL;
×
447
  }
448
  oldFileKeeper->pOldFile = pOldFile;
×
449
  taosReserveOldLog(keepName, oldFileKeeper->keepName);
×
450

451
  uInfo("   new log file:%d is opened", tsLogObj.flag);
×
452
  uInfo("==================================");
×
453
  return oldFileKeeper;
×
454
}
455

456
static void *taosThreadToCloseOldFile(void *param) {
×
457
  if (!param) return NULL;
×
458
  OldFileKeeper *oldFileKeeper = (OldFileKeeper *)param;
×
459
  taosSsleep(20);
×
460
  taosWLockLatch(&tsLogRotateLatch);
×
461
  taosCloseLogByFd(oldFileKeeper->pOldFile);
×
462
  taosKeepOldLog(oldFileKeeper->keepName);
×
463
  taosMemoryFree(oldFileKeeper);
×
464
  if (tsLogKeepDays > 0) {
×
465
    taosRemoveOldFiles(tsLogDir, tsLogKeepDays);
×
466
  }
467
  taosWUnLockLatch(&tsLogRotateLatch);
×
468
  return NULL;
×
469
}
470

471
static int32_t taosOpenNewLogFile() {
×
472
  (void)taosThreadMutexLock(&tsLogObj.logMutex);
×
473

474
  if (tsLogObj.lines > tsNumOfLogLines && tsLogObj.openInProgress == 0) {
×
475
    tsLogObj.openInProgress = 1;
×
476

477
    uInfo("open new log file ......");
×
478
    TdThread     thread;
479
    TdThreadAttr attr;
480
    (void)taosThreadAttrInit(&attr);
×
481
    (void)taosThreadAttrSetDetachState(&attr, PTHREAD_CREATE_DETACHED);
×
482
#ifdef TD_COMPACT_OS
483
    (void)taosThreadAttrSetStackSize(&attr, STACK_SIZE_SMALL);
484
#endif
485
    OldFileKeeper *oldFileKeeper = taosOpenNewFile();
×
486
    if (!oldFileKeeper) {
×
487
      tsLogObj.openInProgress = 0;
×
488
      TAOS_UNUSED(taosThreadMutexUnlock(&tsLogObj.logMutex));
×
489
      (void)taosThreadAttrDestroy(&attr);
×
490
      return terrno;
×
491
    }
492
    if (taosThreadCreate(&thread, &attr, taosThreadToCloseOldFile, oldFileKeeper) != 0) {
×
493
      uError("failed to create thread to close old log file");
×
494
      taosMemoryFreeClear(oldFileKeeper);
×
495
    }
496
    (void)taosThreadAttrDestroy(&attr);
×
497
    tsLogObj.openInProgress = 0;
×
498
  }
499

500
  (void)taosThreadMutexUnlock(&tsLogObj.logMutex);
×
501

502
  return 0;
×
503
}
504

505
void taosOpenNewSlowLogFile() {
2✔
506
  (void)taosThreadMutexLock(&tsLogObj.logMutex);
2✔
507
  int64_t delta = taosGetTimestampSec() - tsLogObj.timestampToday;
2✔
508
  if (delta >= 0 && delta < 86400) {
2✔
509
    uInfo("timestampToday is already equal to today, no need to open new slow log file");
1✔
510
    (void)taosThreadMutexUnlock(&tsLogObj.logMutex);
1✔
511
    return;
1✔
512
  }
513

514
  for (int32_t i = 1; atomic_val_compare_exchange_32(&tsLogObj.slowHandle->lock, 0, 1) == 1; ++i) {
1✔
515
    if (i % 1000 == 0) {
×
516
      TAOS_UNUSED(sched_yield());
×
517
    }
518
  }
519
  tsLogObj.slowHandle->lastDuration = LOG_MAX_WAIT_MSEC;  // force write
1✔
520
  taosWriteLog(tsLogObj.slowHandle);
1✔
521
  atomic_store_32(&tsLogObj.slowHandle->lock, 0);
1✔
522

523
  char    day[TD_TIME_STR_LEN] = {0};
1✔
524
  int32_t code = getDay(day, sizeof(day));
1✔
525
  if (code != 0) {
1✔
526
    uError("failed to get day, reason:%s", tstrerror(code));
×
527
    (void)taosThreadMutexUnlock(&tsLogObj.logMutex);
×
528
    return;
×
529
  }
530
  TdFilePtr pFile = NULL;
1✔
531
  char      name[PATH_MAX + TD_TIME_STR_LEN] = {0};
1✔
532
  (void)snprintf(name, PATH_MAX + TD_TIME_STR_LEN, "%s.%s", tsLogObj.slowLogName, day);
1✔
533
  pFile = taosOpenFile(name, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_APPEND);
1✔
534
  if (pFile == NULL) {
1✔
535
    uError("open new log file fail! reason:%s, reuse lastlog", strerror(ERRNO));
×
536
    (void)taosThreadMutexUnlock(&tsLogObj.logMutex);
×
537
    return;
×
538
  }
539

540
  TdFilePtr pOldFile = tsLogObj.slowHandle->pFile;
1✔
541
  tsLogObj.slowHandle->pFile = pFile;
1✔
542
  (void)taosCloseFile(&pOldFile);
1✔
543
  tsLogObj.timestampToday = taosGetTimestampToday(TSDB_TIME_PRECISION_SECONDS, NULL);
1✔
544
  (void)taosThreadMutexUnlock(&tsLogObj.logMutex);
1✔
545
}
546

547
void taosResetLog() {
×
548
  // force create a new log file
549
  tsLogObj.lines = tsNumOfLogLines + 10;
×
550

551
  if (tsLogObj.logHandle) {
×
552
    int32_t code = taosOpenNewLogFile();
×
553
    if (code != 0) {
×
554
      uError("failed to open new log file, reason:%s", tstrerror(code));
×
555
    }
556
    uInfo("==================================");
×
557
    uInfo("   reset log file ");
×
558
  }
559
}
×
560

561
void taosLogObjSetToday(int64_t ts) { tsLogObj.timestampToday = ts; }
1✔
562

563
static bool taosCheckFileIsOpen(char *logFileName) {
1,314✔
564
  TdFilePtr pFile = taosOpenFile(logFileName, TD_FILE_WRITE);
1,314✔
565
  if (pFile == NULL) {
1,314✔
566
    if (lastErrorIsFileNotExist()) {
816✔
567
      return false;
816✔
568
    } else {
569
      printf("\n%s:%d failed to open log file:%s, reason:%s\n", __func__, __LINE__, logFileName, strerror(ERRNO));
×
570
      return true;
×
571
    }
572
  }
573

574
  if (taosLockLogFile(pFile)) {
498✔
575
    taosUnLockLogFile(pFile);
265✔
576
    (void)taosCloseFile(&pFile);
265✔
577
    return false;
265✔
578
  } else {
579
    (void)taosCloseFile(&pFile);
233✔
580
    return true;
233✔
581
  }
582
}
583

584
static void decideLogFileName(const char *fn, int32_t maxFileNum) {
588✔
585
  tsLogObj.fileNum = maxFileNum;
588✔
586
  if (tsLogObj.fileNum > 1) {
588✔
587
    for (int32_t i = 0; i < tsLogObj.fileNum; i++) {
657✔
588
      char fileName[PATH_MAX + 10];
589

590
      (void)snprintf(fileName, PATH_MAX + 10, "%s%d.0", fn, i);
657✔
591
      bool file1open = taosCheckFileIsOpen(fileName);
657✔
592

593
      (void)snprintf(fileName, PATH_MAX + 10, "%s%d.1", fn, i);
657✔
594
      bool file2open = taosCheckFileIsOpen(fileName);
657✔
595

596
      if (!file1open && !file2open) {
657✔
597
        (void)snprintf(tsLogObj.logName, PATH_MAX, "%s%d", fn, i);
424✔
598
        return;
424✔
599
      }
600
    }
601
  }
602

603
  if (strlen(fn) < PATH_MAX) {
164✔
604
    tstrncpy(tsLogObj.logName, fn, PATH_MAX);
164✔
605
  }
606
}
607

608
static void decideLogFileNameFlag() {
588✔
609
  char    name[PATH_MAX] = "\0";
588✔
610
  int64_t logstat0_mtime = 0;
588✔
611
  int64_t logstat1_mtime = 0;
588✔
612
  bool    log0Exist = false;
588✔
613
  bool    log1Exist = false;
588✔
614

615
  int32_t logNameLen = strlen(tsLogObj.logName) + 2;
588✔
616
  if (logNameLen < PATH_MAX) {
588✔
617
    TAOS_UNUSED(snprintf(name, PATH_MAX, "%s%s", tsLogObj.logName, ".0"));
588✔
618
    log0Exist = taosStatFile(name, NULL, &logstat0_mtime, NULL) == 0;
588✔
619
    name[logNameLen - 1] = '1';
588✔
620
    log1Exist = taosStatFile(name, NULL, &logstat1_mtime, NULL) == 0;
588✔
621
  }
622

623
  // if none of the log files exist, open 0, if both exists, open the old one
624
  if (!log0Exist && !log1Exist) {
588✔
625
    tsLogObj.flag = 0;
295✔
626
  } else if (!log1Exist) {
293✔
627
    tsLogObj.flag = 0;
293✔
628
  } else if (!log0Exist) {
×
629
    tsLogObj.flag = 1;
×
630
  } else {
631
    tsLogObj.flag = (logstat0_mtime > logstat1_mtime) ? 0 : 1;
×
632
  }
633
}
588✔
634

635
static void processLogFileName(const char *logName, int32_t maxFileNum) {
588✔
636
  char fullName[PATH_MAX] = {0};
588✔
637
  getFullPathName(fullName, logName);
588✔
638
  decideLogFileName(fullName, maxFileNum);
588✔
639
  decideLogFileNameFlag();
588✔
640
}
588✔
641

642
static int32_t taosInitNormalLog(const char *logName, int32_t maxFileNum) {
588✔
643
  int32_t code = 0, lino = 0;
588✔
644
#ifdef WINDOWS_STASH
645
  /*
646
   * always set maxFileNum to 1
647
   * means client log filename is unique in windows
648
   */
649
  maxFileNum = 1;
650
#endif
651

652
  processLogFileName(logName, maxFileNum);
588✔
653

654
  int32_t logNameLen = strlen(tsLogObj.logName) + 2;  // logName + ".0" or ".1"
588✔
655

656
  if (logNameLen < 0 || logNameLen >= PATH_MAX) {
588✔
657
    uError("log name:%s is invalid since length:%d is out of range", logName, logNameLen);
×
658
    return TSDB_CODE_INVALID_CFG;
×
659
  }
660

661
  char name[PATH_MAX] = "\0";
588✔
662
  (void)snprintf(name, sizeof(name), "%s.%d", tsLogObj.logName, tsLogObj.flag);
588✔
663
  (void)taosThreadMutexInit(&tsLogObj.logMutex, NULL);
588✔
664

665
  TAOS_UNUSED(taosUmaskFile(0));
588✔
666
  tsLogObj.logHandle = taosLogBuffNew(LOG_DEFAULT_BUF_SIZE);
588✔
667
  if (tsLogObj.logHandle == NULL) return terrno;
588✔
668

669
  tsLogObj.logHandle->pFile = taosOpenFile(name, TD_FILE_CREATE | TD_FILE_READ | TD_FILE_WRITE);
588✔
670
  if (tsLogObj.logHandle->pFile == NULL) {
588✔
671
    (void)printf("\n%s:%d failed to open log file:%s, reason:%s\n", __func__, __LINE__, name, strerror(ERRNO));
×
672
    return terrno;
×
673
  }
674
  TAOS_UNUSED(taosLockLogFile(tsLogObj.logHandle->pFile));
588✔
675

676
  // only an estimate for number of lines
677
  int64_t filesize = 0;
588✔
678
  TAOS_CHECK_EXIT(taosFStatFile(tsLogObj.logHandle->pFile, &filesize, NULL));
588✔
679

680
  tsLogObj.lines = (int32_t)(filesize / 60);
588✔
681

682
  if (taosLSeekFile(tsLogObj.logHandle->pFile, 0, SEEK_END) < 0) {
588✔
683
    TAOS_CHECK_EXIT(terrno);
×
684
  }
685

686
  (void)snprintf(name, sizeof(name),
588✔
687
                 "==================================================\n"
688
                 "                new log file\n"
689
                 "==================================================\n");
690
  if (taosWriteFile(tsLogObj.logHandle->pFile, name, (uint32_t)strlen(name)) <= 0) {
588✔
691
    TAOS_CHECK_EXIT(terrno);
×
692
  }
693

694
_exit:
588✔
695
  if (code != 0) {
588✔
696
    taosUnLockLogFile(tsLogObj.logHandle->pFile);
×
697
    TAOS_UNUSED(printf("failed to init normal log file:%s at line %d, reason:%s\n", name, lino, tstrerror(code)));
×
698
  }
699
  return code;
588✔
700
}
701

702
static void taosUpdateLogNums(ELogLevel level) {
9,521,854✔
703
  switch (level) {
9,521,854✔
704
    case DEBUG_ERROR:
16,160✔
705
      TAOS_UNUSED(atomic_add_fetch_64(&tsNumOfErrorLogs, 1));
16,160✔
706
      break;
16,160✔
707
    case DEBUG_INFO:
493,878✔
708
      TAOS_UNUSED(atomic_add_fetch_64(&tsNumOfInfoLogs, 1));
493,878✔
709
      break;
493,954✔
710
    case DEBUG_DEBUG:
8,394,259✔
711
      TAOS_UNUSED(atomic_add_fetch_64(&tsNumOfDebugLogs, 1));
8,394,259✔
712
      break;
8,394,906✔
713
    case DEBUG_DUMP:
617,887✔
714
    case DEBUG_TRACE:
715
      TAOS_UNUSED(atomic_add_fetch_64(&tsNumOfTraceLogs, 1));
617,887✔
716
      break;
618,005✔
717
    default:
×
718
      break;
×
719
  }
720
}
9,522,695✔
721

722
static inline int32_t taosBuildLogHead(char *buffer, const char *flags) {
9,975,389✔
723
  struct tm      Tm, *ptm;
724
  struct timeval timeSecs;
725

726
  TAOS_UNUSED(taosGetTimeOfDay(&timeSecs));
9,975,389✔
727
  time_t curTime = timeSecs.tv_sec;
9,975,268✔
728
  ptm = taosLocalTime(&curTime, &Tm, NULL, 0, NULL);
9,975,268✔
729
  if (ptm == NULL) {
9,978,079✔
730
    uError("%s failed to get local time, code:%d", __FUNCTION__, ERRNO);
×
731
    return 0;
×
732
  }
733
  return snprintf(buffer, LOG_MAX_STACK_LINE_BUFFER_SIZE, "%02d/%02d %02d:%02d:%02d.%06d %08" PRId64 " %s %s",
9,978,079✔
734
                  ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, (int32_t)timeSecs.tv_usec,
9,978,044✔
735
                  taosGetSelfPthreadId(), LOG_EDITION_FLG, flags);
736
}
737

738
static inline void taosPrintLogImp(ELogLevel level, int32_t dflag, const char *buffer, int32_t len) {
9,934,437✔
739
  if ((dflag & DEBUG_FILE) && tsLogObj.logHandle && tsLogObj.logHandle->pFile != NULL && osLogSpaceSufficient()) {
9,934,437✔
740
    taosUpdateLogNums(level);
9,522,078✔
741
    if (tsAsyncLog) {
9,522,867✔
742
      TAOS_UNUSED(taosPushLogBuffer(tsLogObj.logHandle, buffer, len));
141,829✔
743
    } else {
744
      TAOS_UNUSED(taosWriteFile(tsLogObj.logHandle->pFile, buffer, len));
9,381,038✔
745
    }
746

747
    if (tsNumOfLogLines > 0) {
9,522,958✔
748
      TAOS_UNUSED(atomic_add_fetch_32(&tsLogObj.lines, 1));
9,523,808✔
749
      if ((tsLogObj.lines > tsNumOfLogLines) && (tsLogObj.openInProgress == 0)) {
9,523,815✔
750
        TAOS_UNUSED(taosOpenNewLogFile());
×
751
      }
752
    }
753
  }
754

755
  int fd = 0;
9,937,340✔
756
  if (tsLogObj.outputType == LOG_OUTPUT_FILE) {
9,937,340✔
757
#ifndef TAOSD_INTEGRATED    
758
    if (dflag & DEBUG_SCREEN) fd = 1;
9,936,874✔
759
#else
760
    if ((dflag & DEBUG_SCREEN) && tsLogEmbedded) fd = 1;
761
#endif
762
  } else if (tsLogObj.outputType == LOG_OUTPUT_STDOUT) {
466✔
763
    fd = 1;
223✔
764
  } else if (tsLogObj.outputType == LOG_OUTPUT_STDERR) {
243✔
765
    fd = 2;
223✔
766
  }
767

768
  if (fd) {
9,937,340✔
769
#pragma GCC diagnostic push
770
#pragma GCC diagnostic ignored "-Wunused-result"
771
#ifndef TD_ASTRA
772
    if (write(fd, buffer, (uint32_t)len) < 0) {
707,578✔
773
      TAOS_UNUSED(printf("failed to write log to screen, reason:%s\n", strerror(ERRNO)));
×
774
    }
775
#else
776
    TAOS_UNUSED(fprintf(fd == 1 ? stdout : stderr, "%s", buffer));
777
#endif
778
#pragma GCC diagnostic pop
779
  }
780
}
9,937,342✔
781

782
/*
783
  use taosPrintLogImpl_useStackBuffer to avoid stack overflow
784

785
*/
786
static int8_t taosPrintLogImplUseStackBuffer(const char *flags, int32_t level, int32_t dflag, const char *format,
9,935,127✔
787
                                             va_list args) {
788
  char    buffer[LOG_MAX_STACK_LINE_BUFFER_SIZE];
789
  int32_t len = taosBuildLogHead(buffer, flags);
9,935,127✔
790

791
  int32_t writeLen = len + vsnprintf(buffer + len, LOG_MAX_STACK_LINE_BUFFER_SIZE - len - 1, format, args);
9,935,679✔
792
  if (writeLen > LOG_MAX_STACK_LINE_SIZE) {
9,935,679✔
793
    return 1;
40,796✔
794
  }
795

796
  buffer[writeLen++] = '\n';
9,894,883✔
797
  buffer[writeLen] = 0;
9,894,883✔
798

799
  taosPrintLogImp(level, dflag, buffer, writeLen);
9,894,883✔
800

801
  if (tsLogFp && level <= DEBUG_INFO) {
9,892,906✔
802
    buffer[writeLen - 1] = 0;
257,673✔
803
    (*tsLogFp)(taosGetTimestampMs(), level, buffer + len);
515,346✔
804
  }
805
  return 0;
9,896,048✔
806
}
807
static int8_t taosPrintLogImplUseHeapBuffer(const char *flags, int32_t level, int32_t dflag, const char *format,
40,794✔
808
                                            va_list args) {
809
  char *buffer = taosMemoryCalloc(1, LOG_MAX_LINE_BUFFER_SIZE + 1);
40,794✔
810
  if (buffer == NULL) {
40,796✔
811
    return 1;
×
812
  }
813
  int32_t len = taosBuildLogHead(buffer, flags);
40,796✔
814

815
  int32_t writeLen = len + vsnprintf(buffer + len, LOG_MAX_LINE_BUFFER_SIZE - len - 1, format, args);
40,796✔
816

817
  if (writeLen > LOG_MAX_LINE_SIZE) writeLen = LOG_MAX_LINE_SIZE;
40,796✔
818
  buffer[writeLen++] = '\n';
40,796✔
819
  buffer[writeLen] = 0;
40,796✔
820

821
  taosPrintLogImp(level, dflag, buffer, writeLen);
40,796✔
822

823
  if (tsLogFp && level <= DEBUG_INFO) {
40,796✔
824
    buffer[writeLen - 1] = 0;
1,451✔
825
    (*tsLogFp)(taosGetTimestampMs(), level, buffer + len);
2,902✔
826
  }
827
  taosMemoryFree(buffer);
40,796✔
828
  return 0;
40,796✔
829
}
830
void taosPrintLog(const char *flags, int32_t level, int32_t dflag, const char *format, ...) {
9,934,402✔
831
  if (!(dflag & DEBUG_FILE) && !(dflag & DEBUG_SCREEN)) return;
9,934,402✔
832

833
  va_list argpointer, argpointer_copy;
834
  va_start(argpointer, format);
9,934,402✔
835
  va_copy(argpointer_copy, argpointer);
9,934,402✔
836

837
  if (taosPrintLogImplUseStackBuffer(flags, level, dflag, format, argpointer) == 0) {
9,934,402✔
838
  } else {
839
    TAOS_UNUSED(taosPrintLogImplUseHeapBuffer(flags, level, dflag, format, argpointer_copy));
40,794✔
840
  }
841
  va_end(argpointer_copy);
9,937,286✔
842
  va_end(argpointer);
9,937,286✔
843
}
844

845
void taosPrintLongString(const char *flags, int32_t level, int32_t dflag, const char *format, ...) {
4✔
846
  if (!osLogSpaceSufficient()) return;
4✔
847
  if (!(dflag & DEBUG_FILE) && !(dflag & DEBUG_SCREEN)) return;
4✔
848

849
  char *buffer = taosMemoryMalloc(LOG_MAX_LINE_DUMP_BUFFER_SIZE);
4✔
850
  if (!buffer) return;
4✔
851
  int32_t len = taosBuildLogHead(buffer, flags);
4✔
852

853
  va_list argpointer;
854
  va_start(argpointer, format);
4✔
855
  len += vsnprintf(buffer + len, LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2 - len, format, argpointer);
4✔
856
  va_end(argpointer);
4✔
857

858
  len = len > LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2 ? LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2 : len;
4✔
859
  buffer[len++] = '\n';
4✔
860
  buffer[len] = 0;
4✔
861

862
  taosPrintLogImp(level, dflag, buffer, len);
4✔
863
  taosMemoryFree(buffer);
4✔
864
}
865

866
void taosPrintSlowLog(const char *format, ...) {
26✔
867
  if (!osLogSpaceSufficient()) return;
26✔
868

869
  int64_t delta = taosGetTimestampSec() - tsLogObj.timestampToday;
26✔
870
  if (delta >= 86400 || delta < 0) {
26✔
871
    taosOpenNewSlowLogFile();
1✔
872
  }
873

874
  char   *buffer = taosMemoryMalloc(LOG_MAX_LINE_DUMP_BUFFER_SIZE);
26✔
875
  int32_t len = taosBuildLogHead(buffer, "");
26✔
876

877
  va_list argpointer;
878
  va_start(argpointer, format);
26✔
879
  len += vsnprintf(buffer + len, LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2 - len, format, argpointer);
26✔
880
  va_end(argpointer);
26✔
881

882
  if (len < 0 || len > LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2) {
26✔
883
    len = LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2;
×
884
  }
885
  buffer[len++] = '\n';
26✔
886
  buffer[len] = 0;
26✔
887

888
  TAOS_UNUSED(atomic_add_fetch_64(&tsNumOfSlowLogs, 1));
26✔
889

890
  if (tsAsyncLog) {
26✔
891
    TAOS_UNUSED(taosPushLogBuffer(tsLogObj.slowHandle, buffer, len));
5✔
892
  } else {
893
    TAOS_UNUSED(taosWriteFile(tsLogObj.slowHandle->pFile, buffer, len));
21✔
894
  }
895

896
  taosMemoryFree(buffer);
26✔
897
}
898

899
static void taosCloseLogByFd(TdFilePtr pFile) {
×
900
  if (pFile != NULL) {
×
901
    taosUnLockLogFile(pFile);
×
902
    (void)taosCloseFile(&pFile);
×
903
  }
904
}
×
905

906
static SLogBuff *taosLogBuffNew(int32_t bufSize) {
1,157✔
907
  SLogBuff *pLogBuf = NULL;
1,157✔
908

909
  pLogBuf = taosMemoryCalloc(1, sizeof(SLogBuff));
1,157✔
910
  if (pLogBuf == NULL) return NULL;
1,157✔
911

912
  LOG_BUF_BUFFER(pLogBuf) = taosMemoryMalloc(bufSize);
1,157✔
913
  if (LOG_BUF_BUFFER(pLogBuf) == NULL) goto _err;
1,157✔
914

915
  LOG_BUF_START(pLogBuf) = LOG_BUF_END(pLogBuf) = 0;
1,157✔
916
  LOG_BUF_SIZE(pLogBuf) = bufSize;
1,157✔
917
  pLogBuf->minBuffSize = bufSize / 10;
1,157✔
918
  pLogBuf->stop = 0;
1,157✔
919
  pLogBuf->writeInterval = LOG_DEFAULT_INTERVAL;
1,157✔
920
  pLogBuf->lock = 0;
1,157✔
921
  if (taosThreadMutexInit(&LOG_BUF_MUTEX(pLogBuf), NULL) < 0) goto _err;
1,157✔
922
  // tsem_init(&(pLogBuf->buffNotEmpty), 0, 0);
923

924
  return pLogBuf;
1,157✔
925

926
_err:
×
927
  taosMemoryFreeClear(LOG_BUF_BUFFER(pLogBuf));
×
928
  taosMemoryFreeClear(pLogBuf);
×
929
  return NULL;
×
930
}
931

932
static void taosCopyLogBuffer(SLogBuff *pLogBuf, int32_t start, int32_t end, const char *msg, int32_t msgLen) {
141,849✔
933
  if (start > end) {
141,849✔
934
    memcpy(LOG_BUF_BUFFER(pLogBuf) + end, msg, msgLen);
×
935
  } else {
936
    if (LOG_BUF_SIZE(pLogBuf) - end < msgLen) {
141,849✔
937
      memcpy(LOG_BUF_BUFFER(pLogBuf) + end, msg, LOG_BUF_SIZE(pLogBuf) - end);
×
938
      memcpy(LOG_BUF_BUFFER(pLogBuf), msg + LOG_BUF_SIZE(pLogBuf) - end, msgLen - LOG_BUF_SIZE(pLogBuf) + end);
×
939
    } else {
940
      memcpy(LOG_BUF_BUFFER(pLogBuf) + end, msg, msgLen);
141,849✔
941
    }
942
  }
943
  LOG_BUF_END(pLogBuf) = (LOG_BUF_END(pLogBuf) + msgLen) % LOG_BUF_SIZE(pLogBuf);
141,849✔
944
}
141,849✔
945

946
static int32_t taosPushLogBuffer(SLogBuff *pLogBuf, const char *msg, int32_t msgLen) {
141,802✔
947
  int32_t        start = 0;
141,802✔
948
  int32_t        end = 0;
141,802✔
949
  int32_t        remainSize = 0;
141,802✔
950
  static int64_t lostLine = 0;
951
  char           tmpBuf[128];
952
  int32_t        tmpBufLen = 0;
141,802✔
953

954
  if (pLogBuf == NULL || pLogBuf->stop) return -1;
141,802✔
955

956
  (void)taosThreadMutexLock(&LOG_BUF_MUTEX(pLogBuf));
141,814✔
957
  start = LOG_BUF_START(pLogBuf);
141,849✔
958
  end = LOG_BUF_END(pLogBuf);
141,849✔
959

960
  remainSize = (start > end) ? (start - end - 1) : (start + LOG_BUF_SIZE(pLogBuf) - end - 1);
141,849✔
961

962
  if (lostLine > 0) {
141,849✔
963
    snprintf(tmpBuf, tListLen(tmpBuf), "...Lost %" PRId64 " lines here...\n", lostLine);
×
964
    tmpBufLen = (int32_t)strlen(tmpBuf);
×
965
  }
966

967
  if (remainSize <= msgLen || ((lostLine > 0) && (remainSize <= (msgLen + tmpBufLen)))) {
141,849✔
968
    lostLine++;
×
969
    tsAsyncLogLostLines++;
×
970
    (void)taosThreadMutexUnlock(&LOG_BUF_MUTEX(pLogBuf));
×
971
    return -1;
×
972
  }
973

974
  if (lostLine > 0) {
141,849✔
975
    taosCopyLogBuffer(pLogBuf, start, end, tmpBuf, tmpBufLen);
×
976
    lostLine = 0;
×
977
  }
978

979
  taosCopyLogBuffer(pLogBuf, LOG_BUF_START(pLogBuf), LOG_BUF_END(pLogBuf), msg, msgLen);
141,849✔
980

981
  // int32_t w = atomic_sub_fetch_32(&waitLock, 1);
982
  /*
983
  if (w <= 0 || ((remainSize - msgLen - tmpBufLen) < (LOG_BUF_SIZE(pLogBuf) * 4 /5))) {
984
    tsem_post(&(pLogBuf->buffNotEmpty));
985
    dbgPostN++;
986
  } else {
987
    dbgNoPostN++;
988
  }
989
  */
990

991
  (void)taosThreadMutexUnlock(&LOG_BUF_MUTEX(pLogBuf));
141,849✔
992

993
  return 0;
141,861✔
994
}
995

996
static int32_t taosGetLogRemainSize(SLogBuff *pLogBuf, int32_t start, int32_t end) {
43,075✔
997
  int32_t rSize = end - start;
43,075✔
998

999
  return rSize >= 0 ? rSize : LOG_BUF_SIZE(pLogBuf) + rSize;
43,075✔
1000
}
1001

1002
static void taosWriteSlowLog(SLogBuff *pLogBuf) {
606,207✔
1003
  int32_t lock = atomic_val_compare_exchange_32(&pLogBuf->lock, 0, 1);
606,207✔
1004
  if (lock == 1) return;
606,207✔
1005
  taosWriteLog(pLogBuf);
606,207✔
1006
  atomic_store_32(&pLogBuf->lock, 0);
606,207✔
1007
}
1008
static void taosWriteLog(SLogBuff *pLogBuf) {
1,221,984✔
1009
  int32_t start = LOG_BUF_START(pLogBuf);
1,221,984✔
1010
  int32_t end = LOG_BUF_END(pLogBuf);
1,221,984✔
1011

1012
  if (start == end) {
1,221,984✔
1013
    dbgEmptyW++;
1,180,245✔
1014
    pLogBuf->writeInterval = LOG_MAX_INTERVAL;
1,180,245✔
1015
    return;
1,180,245✔
1016
  }
1017

1018
  int32_t pollSize = taosGetLogRemainSize(pLogBuf, start, end);
41,739✔
1019
  if (pollSize < pLogBuf->minBuffSize) {
41,739✔
1020
    pLogBuf->lastDuration += pLogBuf->writeInterval;
41,739✔
1021
    if (pLogBuf->lastDuration < LOG_MAX_WAIT_MSEC) {
41,739✔
1022
      return;
40,403✔
1023
    }
1024
  }
1025

1026
  pLogBuf->lastDuration = 0;
1,336✔
1027

1028
  if (start < end) {
1,336✔
1029
    TAOS_UNUSED(taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf) + start, pollSize));
1,336✔
1030
  } else {
1031
    int32_t tsize = LOG_BUF_SIZE(pLogBuf) - start;
×
1032
    TAOS_UNUSED(taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf) + start, tsize));
×
1033

1034
    TAOS_UNUSED(taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf), end));
×
1035
  }
1036

1037
  dbgWN++;
1,336✔
1038
  dbgWSize += pollSize;
1,336✔
1039

1040
  if (pollSize < pLogBuf->minBuffSize) {
1,336✔
1041
    dbgSmallWN++;
1,336✔
1042
    if (pLogBuf->writeInterval < LOG_MAX_INTERVAL) {
1,336✔
1043
      pLogBuf->writeInterval += LOG_INTERVAL_STEP;
×
1044
    }
1045
  } else if (pollSize > LOG_BUF_SIZE(pLogBuf) / 3) {
×
1046
    dbgBigWN++;
×
1047
    pLogBuf->writeInterval = LOG_MIN_INTERVAL;
×
1048
  } else if (pollSize > LOG_BUF_SIZE(pLogBuf) / 4) {
×
1049
    if (pLogBuf->writeInterval > LOG_MIN_INTERVAL) {
×
1050
      pLogBuf->writeInterval -= LOG_INTERVAL_STEP;
×
1051
    }
1052
  }
1053

1054
  LOG_BUF_START(pLogBuf) = (LOG_BUF_START(pLogBuf) + pollSize) % LOG_BUF_SIZE(pLogBuf);
1,336✔
1055

1056
  start = LOG_BUF_START(pLogBuf);
1,336✔
1057
  end = LOG_BUF_END(pLogBuf);
1,336✔
1058

1059
  pollSize = taosGetLogRemainSize(pLogBuf, start, end);
1,336✔
1060
  if (pollSize < pLogBuf->minBuffSize) {
1,336✔
1061
    return;
1,336✔
1062
  }
1063

1064
  pLogBuf->writeInterval = 0;
×
1065
}
1066

1067
#define LOG_ROTATE_INTERVAL 3600
1068
#if !defined(TD_ENTERPRISE) || defined(ASSERT_NOT_CORE) || defined(GRANTS_CFG)
1069
#define LOG_INACTIVE_TIME 7200
1070
#define LOG_ROTATE_BOOT   900
1071
#else
1072
#define LOG_INACTIVE_TIME 5
1073
#define LOG_ROTATE_BOOT   (LOG_INACTIVE_TIME + 1)
1074
#endif
1075

1076
static void *taosLogRotateFunc(void *param) {
262✔
1077
  setThreadName("logRotate");
262✔
1078
  int32_t code = 0;
262✔
1079
  taosWLockLatch(&tsLogRotateLatch);
262✔
1080
  // compress or remove the old log files
1081
  TdDirPtr pDir = taosOpenDir(tsLogDir);
262✔
1082
  if (!pDir) goto _exit;
262✔
1083
  TdDirEntryPtr de = NULL;
262✔
1084
  while ((de = taosReadDir(pDir))) {
1,602✔
1085
    if (taosDirEntryIsDir(de)) {
1,340✔
1086
      continue;
1,340✔
1087
    }
1088
    char *fname = taosGetDirEntryName(de);
814✔
1089
    if (!fname) {
814✔
1090
      continue;
×
1091
    }
1092

1093
    char *pSec = strrchr(fname, '.');
814✔
1094
    if (!pSec) {
814✔
1095
      continue;
3✔
1096
    }
1097
    char *pIter = pSec;
811✔
1098
    bool  isSec = true;
811✔
1099
    while (*(++pIter)) {
2,308✔
1100
      if (!isdigit(*pIter)) {
1,829✔
1101
        isSec = false;
332✔
1102
        break;
332✔
1103
      }
1104
    }
1105
    if (!isSec) {
811✔
1106
      continue;
332✔
1107
    }
1108

1109
    int64_t fileSec = 0;
479✔
1110
    if ((code = taosStr2int64(pSec + 1, &fileSec)) != 0) {
479✔
1111
      uWarn("%s:%d failed to convert %s to int64 since %s", __func__, __LINE__, pSec + 1, tstrerror(code));
×
1112
      continue;
×
1113
    }
1114
    if (fileSec <= 100) {
479✔
1115
      continue;
479✔
1116
    }
1117

1118
    char fullName[PATH_MAX] = {0};
×
1119
    snprintf(fullName, sizeof(fullName), "%s%s%s", tsLogDir, TD_DIRSEP, fname);
×
1120

1121
    int64_t mtime = 0;
×
1122
    if ((code = taosStatFile(fullName, NULL, &mtime, NULL)) != 0) {
×
1123
      uWarn("%s:%d failed to stat file %s since %s", __func__, __LINE__, fullName, tstrerror(code));
×
1124
      continue;
×
1125
    }
1126

1127
    int64_t inactiveSec = taosGetTimestampMs() / 1000 - mtime;
×
1128

1129
    if (inactiveSec < LOG_INACTIVE_TIME) {
×
1130
      continue;
×
1131
    }
1132

1133
    int32_t days = inactiveSec / 86400 + 1;
×
1134
    if (tsLogKeepDays > 0 && days > tsLogKeepDays) {
×
1135
      TAOS_UNUSED(taosRemoveFile(fullName));
×
1136
      uInfo("file:%s is removed, days:%d, keepDays:%d, sed:%" PRId64, fullName, days, tsLogKeepDays, fileSec);
×
1137
    } else {
1138
      taosKeepOldLog(fullName);  // compress
×
1139
    }
1140
  }
1141
  if ((code = taosCloseDir(&pDir)) != 0) {
262✔
1142
    uWarn("%s:%d failed to close dir %s since %s\n", __func__, __LINE__, tsLogDir, tstrerror(code));
×
1143
  }
1144

1145
  if (tsLogKeepDays > 0) {
262✔
1146
    taosRemoveOldFiles(tsLogDir, tsLogKeepDays);
2✔
1147
  }
1148
_exit:
260✔
1149
  taosWUnLockLatch(&tsLogRotateLatch);
262✔
1150
  return NULL;
262✔
1151
}
1152

1153
static void *taosAsyncOutputLog(void *param) {
588✔
1154
  SLogBuff *pLogBuf = (SLogBuff *)tsLogObj.logHandle;
588✔
1155
  SLogBuff *pSlowBuf = (SLogBuff *)tsLogObj.slowHandle;
588✔
1156

1157
  setThreadName("log");
588✔
1158
  int32_t count = 0;
588✔
1159
  int32_t updateCron = 0;
588✔
1160
  int32_t writeInterval = 0;
588✔
1161
  int64_t lastCheckSec = taosGetTimestampMs() / 1000 - (LOG_ROTATE_INTERVAL - LOG_ROTATE_BOOT);
588✔
1162

1163
  while (1) {
614,622✔
1164
    if (pSlowBuf) {
615,210✔
1165
      writeInterval = TMIN(pLogBuf->writeInterval, pSlowBuf->writeInterval);
605,646✔
1166
    } else {
1167
      writeInterval = pLogBuf->writeInterval;
9,564✔
1168
    }
1169
    count += writeInterval;
615,210✔
1170
    updateCron++;
615,210✔
1171
    taosMsleep(writeInterval);
615,210✔
1172
    if (count > 1000) {
615,199✔
1173
      TAOS_UNUSED(osUpdate());
14,758✔
1174
      count = 0;
14,758✔
1175
    }
1176

1177
    // Polling the buffer
1178
    taosWriteLog(pLogBuf);
615,199✔
1179
    if (pSlowBuf) taosWriteSlowLog(pSlowBuf);
615,199✔
1180

1181
    if (pLogBuf->stop || (pSlowBuf && pSlowBuf->stop)) {
615,199✔
1182
      pLogBuf->lastDuration = LOG_MAX_WAIT_MSEC;
577✔
1183
      taosWriteLog(pLogBuf);
577✔
1184
      if (pSlowBuf) taosWriteSlowLog(pSlowBuf);
577✔
1185
      break;
577✔
1186
    }
1187

1188
    // process the log rotation every LOG_ROTATE_INTERVAL
1189
    int64_t curSec = taosGetTimestampMs() / 1000;
614,622✔
1190
    if (curSec >= lastCheckSec) {
614,622✔
1191
      if ((curSec - lastCheckSec) >= LOG_ROTATE_INTERVAL) {
614,622✔
1192
        TdThread     thread;
1193
        TdThreadAttr attr;
1194
        (void)taosThreadAttrInit(&attr);
262✔
1195
        (void)taosThreadAttrSetDetachState(&attr, PTHREAD_CREATE_DETACHED);
262✔
1196
#ifdef TD_COMPACT_OS
1197
        (void)taosThreadAttrSetStackSize(&attr, STACK_SIZE_SMALL);
1198
#endif
1199
        if (taosThreadCreate(&thread, &attr, taosLogRotateFunc, tsLogObj.logHandle) == 0) {
262✔
1200
          uInfo("process log rotation");
262✔
1201
          lastCheckSec = curSec;
262✔
1202
        } else {
1203
          uWarn("failed to create thread to process log rotation");
×
1204
        }
1205
        (void)taosThreadAttrDestroy(&attr);
262✔
1206
      }
1207
    } else if (curSec < lastCheckSec) {
×
1208
      lastCheckSec = curSec;
×
1209
    }
1210
  }
1211

1212
  return NULL;
577✔
1213
}
1214

1215
bool taosAssertDebug(bool condition, const char *file, int32_t line, bool core, const char *format, ...) {
2✔
1216
  if (condition) return false;
2✔
1217

1218
  const char *flags = "UTL FATAL ";
1✔
1219
  ELogLevel   level = DEBUG_FATAL;
1✔
1220
  int32_t     dflag = 255;  // tsLogEmbedded ? 255 : uDebugFlag
1✔
1221
  char        buffer[LOG_MAX_LINE_BUFFER_SIZE];
1222
  int32_t     len = taosBuildLogHead(buffer, flags);
1✔
1223

1224
  va_list argpointer;
1225
  va_start(argpointer, format);
1✔
1226
  len = len + vsnprintf(buffer + len, LOG_MAX_LINE_BUFFER_SIZE - len, format, argpointer);
1✔
1227
  va_end(argpointer);
1✔
1228
  buffer[len++] = '\n';
1✔
1229
  buffer[len] = 0;
1✔
1230
  taosPrintLogImp(1, 255, buffer, len);
1✔
1231

1232
  taosPrintLog(flags, level, dflag, "tAssert at file %s:%d exit:%d", file, line, tsAssert);
1✔
1233
#ifndef TD_ASTRA
1234
  taosPrintTrace(flags, level, dflag, -1);
16✔
1235
#endif
1236
  if (tsAssert || core) {
1✔
1237
    taosCloseLog();
×
1238
    taosMsleep(300);
×
1239

1240
#ifdef NDEBUG
1241
    abort();
1242
#else
1243
    assert(0);
×
1244
#endif
1245
  }
1246

1247
  return true;
1✔
1248
}
1249
#ifdef USE_REPORT
1250
void taosLogCrashInfo(char *nodeType, char *pMsg, int64_t msgLen, int signum, void *sigInfo) {
2✔
1251
  const char *flags = "UTL FATAL ";
2✔
1252
  ELogLevel   level = DEBUG_FATAL;
2✔
1253
  int32_t     dflag = 255;
2✔
1254
  char        filepath[PATH_MAX] = {0};
2✔
1255
  TdFilePtr   pFile = NULL;
2✔
1256

1257
  if (pMsg && msgLen > 0) {
2✔
1258
    snprintf(filepath, sizeof(filepath), "%s%s.%sCrashLog", tsLogDir, TD_DIRSEP, nodeType);
1✔
1259

1260
    pFile = taosOpenFile(filepath, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_APPEND);
1✔
1261
    if (pFile == NULL) {
1✔
1262
      taosPrintLog(flags, level, dflag, "failed to open file:%s since %s", filepath, terrstr());
×
1263
      goto _return;
×
1264
    }
1265

1266
    if (taosLockFile(pFile) < 0) {
1✔
1267
      taosPrintLog(flags, level, dflag, "failed to lock file:%s since %s", filepath, terrstr());
×
1268
      goto _return;
×
1269
    }
1270

1271
    int64_t writeSize = taosWriteFile(pFile, &msgLen, sizeof(msgLen));
1✔
1272
    if (sizeof(msgLen) != writeSize) {
1✔
1273
      TAOS_UNUSED(taosUnLockFile(pFile));
×
1274
      taosPrintLog(flags, level, dflag, "failed to write len to file:%s,%p wlen:%" PRId64 " tlen:%lu since %s",
×
1275
                   filepath, pFile, writeSize, sizeof(msgLen), terrstr());
1276
      goto _return;
×
1277
    }
1278

1279
    writeSize = taosWriteFile(pFile, pMsg, msgLen);
1✔
1280
    if (msgLen != writeSize) {
1✔
1281
      TAOS_UNUSED(taosUnLockFile(pFile));
×
1282
      taosPrintLog(flags, level, dflag, "failed to write file:%s,%p wlen:%" PRId64 " tlen:%" PRId64 " since %s",
×
1283
                   filepath, pFile, writeSize, msgLen, terrstr());
1284
      goto _return;
×
1285
    }
1286

1287
    TAOS_UNUSED(taosUnLockFile(pFile));
1✔
1288
  }
1289

1290
_return:
1✔
1291

1292
  if (pFile) (void)taosCloseFile(&pFile);
2✔
1293

1294
  taosPrintLog(flags, level, dflag, "crash signal is %d", signum);
2✔
1295

1296
// print the stack trace
1297
#if 0
1298
#ifdef _TD_DARWIN_64
1299
  taosPrintTrace(flags, level, dflag, 4);
1300
#elif !defined(WINDOWS)
1301
  taosPrintLog(flags, level, dflag, "sender PID:%d cmdline:%s", ((siginfo_t *)sigInfo)->si_pid,
1302
               taosGetCmdlineByPID(((siginfo_t *)sigInfo)->si_pid));
1303
  taosPrintTrace(flags, level, dflag, 3);
1304
#else
1305
  taosPrintTrace(flags, level, dflag, 8);
1306
#endif
1307
#endif
1308
  taosMemoryFree(pMsg);
2✔
1309
}
2✔
1310

1311
typedef enum {
1312
  CRASH_LOG_WRITER_UNKNOWN = 0,
1313
  CRASH_LOG_WRITER_INIT = 1,
1314
  CRASH_LOG_WRITER_WAIT,
1315
  CRASH_LOG_WRITER_RUNNING,
1316
  CRASH_LOG_WRITER_QUIT
1317
} CrashStatus;
1318
typedef struct crashBasicInfo {
1319
  int8_t  status;
1320
  int64_t clusterId;
1321
  int64_t startTime;
1322
  char   *nodeType;
1323
  int     signum;
1324
  void   *sigInfo;
1325
  tsem_t  sem;
1326
  int64_t reportThread;
1327
} crashBasicInfo;
1328

1329
crashBasicInfo gCrashBasicInfo = {0};
1330

1331
void setCrashWriterStatus(int8_t status) { atomic_store_8(&gCrashBasicInfo.status, status); }
2✔
1332
bool reportThreadSetQuit() {
×
1333
  CrashStatus status =
×
1334
      atomic_val_compare_exchange_8(&gCrashBasicInfo.status, CRASH_LOG_WRITER_INIT, CRASH_LOG_WRITER_QUIT);
×
1335
  if (status == CRASH_LOG_WRITER_INIT) {
×
1336
    return true;
×
1337
  } else {
1338
    return false;
×
1339
  }
1340
}
1341

1342
bool setReportThreadWait() {
1✔
1343
  CrashStatus status =
1✔
1344
      atomic_val_compare_exchange_8(&gCrashBasicInfo.status, CRASH_LOG_WRITER_INIT, CRASH_LOG_WRITER_WAIT);
1✔
1345
  if (status == CRASH_LOG_WRITER_INIT) {
1✔
1346
    return true;
1✔
1347
  } else {
1348
    return false;
×
1349
  }
1350
}
1351
bool setReportThreadRunning() {
1✔
1352
  CrashStatus status =
1✔
1353
      atomic_val_compare_exchange_8(&gCrashBasicInfo.status, CRASH_LOG_WRITER_WAIT, CRASH_LOG_WRITER_RUNNING);
1✔
1354
  if (status == CRASH_LOG_WRITER_WAIT) {
1✔
1355
    return true;
1✔
1356
  } else {
1357
    return false;
×
1358
  }
1359
}
1360
static void checkWriteCrashLogToFileInNewThead() {
1✔
1361
  if (setReportThreadRunning()) {
1✔
1362
    char       *pMsg = NULL;
1✔
1363
    const char *flags = "UTL FATAL ";
1✔
1364
    ELogLevel   level = DEBUG_FATAL;
1✔
1365
    int32_t     dflag = 255;
1✔
1366
    int64_t     msgLen = -1;
1✔
1367

1368
    if (tsEnableCrashReport) {
1✔
1369
      if (taosGenCrashJsonMsg(gCrashBasicInfo.signum, &pMsg, gCrashBasicInfo.clusterId, gCrashBasicInfo.startTime)) {
×
1370
        taosPrintLog(flags, level, dflag, "failed to generate crash json msg");
×
1371
      } else {
1372
        msgLen = strlen(pMsg);
×
1373
      }
1374
    }
1375
    taosLogCrashInfo(gCrashBasicInfo.nodeType, pMsg, msgLen, gCrashBasicInfo.signum, gCrashBasicInfo.sigInfo);
1✔
1376
    setCrashWriterStatus(CRASH_LOG_WRITER_INIT);
1✔
1377
    int32_t code = tsem_post(&gCrashBasicInfo.sem);
1✔
1378
    if (code != 0 ) {
1✔
1379
      uError("failed to post sem for crashBasicInfo, code:%d", code);
×
1380
    }
1381
    TAOS_UNUSED(tsem_post(&gCrashBasicInfo.sem));
1✔
1382
  }
1383
}
1✔
1384

1385
void checkAndPrepareCrashInfo() {
1✔
1386
  return checkWriteCrashLogToFileInNewThead();
1✔
1387
}
1388

1389
int32_t initCrashLogWriter() {
1✔
1390
  int32_t code = tsem_init(&gCrashBasicInfo.sem, 0, 0);
1✔
1391
  if (code != 0) {
1✔
1392
    uError("failed to init sem for crashLogWriter, code:%d", code);
×
1393
    return code;
×
1394
  }
1395
  gCrashBasicInfo.reportThread = taosGetSelfPthreadId();
1✔
1396
  setCrashWriterStatus(CRASH_LOG_WRITER_INIT);
1✔
1397
  return code;
1✔
1398
}
1399

1400
void writeCrashLogToFile(int signum, void *sigInfo, char *nodeType, int64_t clusterId, int64_t startTime) {
2✔
1401
  if (gCrashBasicInfo.reportThread == taosGetSelfPthreadId()) {
2✔
1402
    return;
1✔
1403
  }
1404
  if (setReportThreadWait()) {
1✔
1405
    gCrashBasicInfo.clusterId = clusterId;
1✔
1406
    gCrashBasicInfo.startTime = startTime;
1✔
1407
    gCrashBasicInfo.nodeType = nodeType;
1✔
1408
    gCrashBasicInfo.signum = signum;
1✔
1409
    gCrashBasicInfo.sigInfo = sigInfo;
1✔
1410
    TAOS_UNUSED(tsem_wait(&gCrashBasicInfo.sem));
1✔
1411
  }
1412
}
1413

1414
void taosReadCrashInfo(char *filepath, char **pMsg, int64_t *pMsgLen, TdFilePtr *pFd) {
2✔
1415
  const char *flags = "UTL FATAL ";
2✔
1416
  ELogLevel   level = DEBUG_FATAL;
2✔
1417
  int32_t     dflag = 255;
2✔
1418
  TdFilePtr   pFile = NULL;
2✔
1419
  bool        truncateFile = false;
2✔
1420
  char       *buf = NULL;
2✔
1421

1422
  if (NULL == *pFd) {
2✔
1423
    int64_t filesize = 0;
2✔
1424
    if (taosStatFile(filepath, &filesize, NULL, NULL) < 0) {
2✔
1425
      if (TAOS_SYSTEM_ERROR(ENOENT) == terrno) {
×
1426
        return;
×
1427
      }
1428

1429
      taosPrintLog(flags, level, dflag, "failed to stat file:%s since %s", filepath, terrstr());
×
1430
      return;
×
1431
    }
1432

1433
    if (filesize <= 0) {
2✔
1434
      return;
×
1435
    }
1436

1437
    pFile = taosOpenFile(filepath, TD_FILE_READ | TD_FILE_WRITE);
2✔
1438
    if (pFile == NULL) {
2✔
1439
      if (ENOENT == ERRNO) {
×
1440
        return;
×
1441
      }
1442

1443
      taosPrintLog(flags, level, dflag, "failed to open file:%s since %s", filepath, terrstr());
×
1444
      return;
×
1445
    }
1446

1447
    TAOS_UNUSED(taosLockFile(pFile));
2✔
1448
  } else {
1449
    pFile = *pFd;
×
1450
  }
1451

1452
  int64_t msgLen = 0;
2✔
1453
  int64_t readSize = taosReadFile(pFile, &msgLen, sizeof(msgLen));
2✔
1454
  if (sizeof(msgLen) != readSize) {
2✔
1455
    truncateFile = true;
×
1456
    if (readSize < 0) {
×
1457
      taosPrintLog(flags, level, dflag, "failed to read len from file:%s,%p wlen:%" PRId64 " tlen:%lu since %s",
×
1458
                   filepath, pFile, readSize, sizeof(msgLen), terrstr());
1459
    }
1460
    goto _return;
×
1461
  }
1462

1463
  buf = taosMemoryMalloc(msgLen);
2✔
1464
  if (NULL == buf) {
2✔
1465
    taosPrintLog(flags, level, dflag, "failed to malloc buf, size:%" PRId64, msgLen);
×
1466
    goto _return;
×
1467
  }
1468

1469
  readSize = taosReadFile(pFile, buf, msgLen);
2✔
1470
  if (msgLen != readSize) {
2✔
1471
    truncateFile = true;
1✔
1472
    taosPrintLog(flags, level, dflag, "failed to read file:%s,%p wlen:%" PRId64 " tlen:%" PRId64 " since %s", filepath,
1✔
1473
                 pFile, readSize, msgLen, terrstr());
1474
    goto _return;
1✔
1475
  }
1476

1477
  *pMsg = buf;
1✔
1478
  *pMsgLen = msgLen;
1✔
1479
  *pFd = pFile;
1✔
1480

1481
  return;
1✔
1482

1483
_return:
1✔
1484

1485
  if (truncateFile) {
1✔
1486
    TAOS_UNUSED(taosFtruncateFile(pFile, 0));
1✔
1487
  }
1488
  TAOS_UNUSED(taosUnLockFile(pFile));
1✔
1489
  TAOS_UNUSED(taosCloseFile(&pFile));
1✔
1490
  taosMemoryFree(buf);
1✔
1491

1492
  *pMsg = NULL;
1✔
1493
  *pMsgLen = 0;
1✔
1494
  *pFd = NULL;
1✔
1495
}
1496

1497
void taosReleaseCrashLogFile(TdFilePtr pFile, bool truncateFile) {
1✔
1498
  if (truncateFile) {
1✔
1499
    TAOS_UNUSED(taosFtruncateFile(pFile, 0));
1✔
1500
  }
1501

1502
  TAOS_UNUSED(taosUnLockFile(pFile));
1✔
1503
  TAOS_UNUSED(taosCloseFile(&pFile));
1✔
1504
}
1✔
1505
#endif // USE_REPORT
1506

1507
#ifdef NDEBUG
1508
bool taosAssertRelease(bool condition) {
1509
  if (condition) return false;
1510

1511
  const char *flags = "UTL FATAL ";
1512
  ELogLevel   level = DEBUG_FATAL;
1513
  int32_t     dflag = 255;  // tsLogEmbedded ? 255 : uDebugFlag
1514

1515
  taosPrintLog(flags, level, dflag, "tAssert called in release mode, exit:%d", tsAssert);
1516
  taosPrintTrace(flags, level, dflag, 0);
1517

1518
  if (tsAssert) {
1519
    taosMsleep(300);
1520
    abort();
1521
  }
1522

1523
  return true;
1524
}
1525
#endif
1526

1527
#define NUM_BASE 100
1528
#define DIGIT_LENGTH 2
1529
#define MAX_DIGITS 24
1530

1531
char* u64toaFastLut(uint64_t val, char* buf) {
5✔
1532
  // Look-up table for 2-digit numbers
1533
  static const char* lut =
1534
      "0001020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455"
1535
      "5657585960616263646566676869707172737475767778798081828384858687888990919293949596979899";
1536

1537
  char  temp[MAX_DIGITS];
1538
  char* p = temp + tListLen(temp);
5✔
1539

1540
  // Process the digits greater than or equal to 100
1541
  while (val >= NUM_BASE) {
11✔
1542
    // Get the last 2 digits from the look-up table and add to the buffer
1543
    p -= DIGIT_LENGTH;
6✔
1544
    strncpy(p, lut + (val % NUM_BASE) * DIGIT_LENGTH, DIGIT_LENGTH);
6✔
1545
    val /= NUM_BASE;
6✔
1546
  }
1547

1548
  // Process the remaining 1 or 2 digits
1549
  if (val >= 10) {
5✔
1550
    // If the number is 10 or more, get the 2 digits from the look-up table
1551
    p -= DIGIT_LENGTH;
2✔
1552
    strncpy(p, lut + val * DIGIT_LENGTH, DIGIT_LENGTH);
2✔
1553
  } else if (val > 0 || p == temp) {
3✔
1554
    // If the number is less than 10, add the single digit to the buffer
1555
    p -= 1;
2✔
1556
    *p = val + '0';
2✔
1557
  }
1558

1559
  int64_t len = temp + tListLen(temp) - p;
5✔
1560
  if (len > 0) {
5✔
1561
    memcpy(buf, p, len);
4✔
1562
  } else {
1563
    buf[0] = '0';
1✔
1564
    len = 1;
1✔
1565
  }
1566
  buf[len] = '\0';
5✔
1567

1568
  return buf + len;
5✔
1569
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc