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

taosdata / TDengine / #3530

16 Nov 2024 07:44AM UTC coverage: 60.219% (-0.7%) from 60.888%
#3530

push

travis-ci

web-flow
Update 03-ad.md

118417 of 252124 branches covered (46.97%)

Branch coverage included in aggregate %.

198982 of 274951 relevant lines covered (72.37%)

6072359.98 hits per line

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

52.77
/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 "tutil.h"
23

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

31
#define LOG_FILE_DAY_LEN 64
32

33
#define LOG_DEFAULT_BUF_SIZE (20 * 1024 * 1024)  // 20MB
34
#define LOG_SLOW_BUF_SIZE    (10 * 1024 * 1024)  // 10MB
35

36
#define LOG_DEFAULT_INTERVAL 25
37
#define LOG_INTERVAL_STEP    5
38
#define LOG_MIN_INTERVAL     5
39
#define LOG_MAX_INTERVAL     25
40
#define LOG_MAX_WAIT_MSEC    1000
41

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

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

54
typedef struct {
55
  char         *buffer;
56
  int32_t       buffStart;
57
  int32_t       buffEnd;
58
  int32_t       buffSize;
59
  int32_t       minBuffSize;
60
  TdFilePtr     pFile;
61
  int32_t       stop;
62
  TdThread      asyncThread;
63
  TdThreadMutex buffMutex;
64
  int32_t       writeInterval;
65
  int32_t       lastDuration;
66
  int32_t       lock;
67
} SLogBuff;
68

69
typedef struct {
70
  int32_t       fileNum;
71
  int32_t       lines;
72
  int32_t       flag;
73
  int32_t       openInProgress;
74
  int64_t       lastKeepFileSec;
75
  int64_t       timestampToday;
76
  pid_t         pid;
77
  char          logName[PATH_MAX];
78
  char          slowLogName[PATH_MAX];
79
  SLogBuff     *logHandle;
80
  SLogBuff     *slowHandle;
81
  TdThreadMutex logMutex;
82
} SLogObj;
83

84
extern SConfig *tsCfg;
85
static int8_t   tsLogInited = 0;
86
static SLogObj  tsLogObj = {.fileNum = 1, .slowHandle = NULL};
87
static int64_t  tsAsyncLogLostLines = 0;
88
static int32_t  tsDaylightActive; /* Currently in daylight saving time. */
89

90
bool tsLogEmbedded = 0;
91
bool tsAsyncLog = true;
92
#ifdef ASSERT_NOT_CORE
93
bool tsAssert = false;
94
#else
95
bool tsAssert = true;
96
#endif
97
int32_t tsNumOfLogLines = 10000000;
98
int32_t tsLogKeepDays = 0;
99
LogFp   tsLogFp = NULL;
100
int64_t tsNumOfErrorLogs = 0;
101
int64_t tsNumOfInfoLogs = 0;
102
int64_t tsNumOfDebugLogs = 0;
103
int64_t tsNumOfTraceLogs = 0;
104
int64_t tsNumOfSlowLogs = 0;
105

106
// log
107
int32_t dDebugFlag = 131;
108
int32_t vDebugFlag = 131;
109
int32_t mDebugFlag = 131;
110
int32_t cDebugFlag = 131;
111
int32_t jniDebugFlag = 131;
112
int32_t tmrDebugFlag = 131;
113
int32_t uDebugFlag = 131;
114
int32_t rpcDebugFlag = 131;
115
int32_t qDebugFlag = 131;
116
int32_t stDebugFlag = 131;
117
int32_t wDebugFlag = 131;
118
int32_t azDebugFlag = 131;
119
int32_t sDebugFlag = 131;
120
int32_t tsdbDebugFlag = 131;
121
int32_t tdbDebugFlag = 131;
122
int32_t tqDebugFlag = 131;
123
int32_t fsDebugFlag = 131;
124
int32_t metaDebugFlag = 131;
125
int32_t udfDebugFlag = 131;
126
int32_t smaDebugFlag = 131;
127
int32_t idxDebugFlag = 131;
128
int32_t sndDebugFlag = 131;
129
int32_t simDebugFlag = 131;
130

131
int32_t tqClientDebugFlag = 131;
132

133
int64_t dbgEmptyW = 0;
134
int64_t dbgWN = 0;
135
int64_t dbgSmallWN = 0;
136
int64_t dbgBigWN = 0;
137
int64_t dbgWSize = 0;
138

139
static void     *taosAsyncOutputLog(void *param);
140
static int32_t   taosPushLogBuffer(SLogBuff *pLogBuf, const char *msg, int32_t msgLen);
141
static SLogBuff *taosLogBuffNew(int32_t bufSize);
142
static void      taosCloseLogByFd(TdFilePtr pFile);
143
static int32_t   taosInitNormalLog(const char *fn, int32_t maxFileNum);
144
static void      taosWriteLog(SLogBuff *pLogBuf);
145
static void      taosWriteSlowLog(SLogBuff *pLogBuf);
146

147
static int32_t taosStartLog() {
8,172✔
148
  TdThreadAttr threadAttr;
149
  (void)taosThreadAttrInit(&threadAttr);
8,172✔
150
  if (taosThreadCreate(&(tsLogObj.logHandle->asyncThread), &threadAttr, taosAsyncOutputLog, tsLogObj.logHandle) != 0) {
8,172!
151
    return terrno;
×
152
  }
153
  (void)taosThreadAttrDestroy(&threadAttr);
8,172✔
154
  return 0;
8,172✔
155
}
156

157
static int32_t getDay(char *buf, int32_t bufSize) {
3,288✔
158
  time_t    t;
159
  int32_t code = taosTime(&t);
3,288✔
160
  if(code != 0) {
3,288!
161
    return code;
×
162
  }
163
  struct tm tmInfo;
164
  if (taosLocalTime(&t, &tmInfo, buf, bufSize) != NULL) {
3,288!
165
    TAOS_UNUSED(strftime(buf, bufSize, "%Y-%m-%d", &tmInfo));
3,288✔
166
  }
167
  return 0;
3,288✔
168
}
169

170
static int64_t getTimestampToday() {
3,288✔
171
  time_t    t;
172
  int32_t code = taosTime(&t);
3,288✔
173
  if (code != 0) {
3,288!
174
    uError("failed to get time, reason:%s", tstrerror(code));
×
175
    return 0;
×
176
  }
177
  struct tm tm;
178
  if (taosLocalTime(&t, &tm, NULL, 0) == NULL) {
3,288!
179
    return 0;
×
180
  }
181
  tm.tm_hour = 0;
3,288✔
182
  tm.tm_min = 0;
3,288✔
183
  tm.tm_sec = 0;
3,288✔
184

185
  return (int64_t)taosMktime(&tm);
3,288✔
186
}
187

188
static void getFullPathName(char *fullName, const char *logName) {
11,460✔
189
  if (strlen(tsLogDir) != 0) {
11,460!
190
    char lastC = tsLogDir[strlen(tsLogDir) - 1];
11,460✔
191
    if (lastC == '\\' || lastC == '/') {
11,460!
192
      snprintf(fullName, PATH_MAX,
3,111✔
193
               "%s"
194
               "%s",
195
               tsLogDir, logName);
196
    } else {
197
      snprintf(fullName, PATH_MAX, "%s" TD_DIRSEP "%s", tsLogDir, logName);
8,349✔
198
    }
199
  } else {
200
    snprintf(fullName, PATH_MAX, "%s", logName);
×
201
  }
202
}
11,460✔
203

204
int32_t taosInitSlowLog() {
3,288✔
205
  char logFileName[64] = {0};
3,288✔
206
#ifdef CUS_PROMPT
207
  (void)snprintf(logFileName, 64, "%sSlowLog", CUS_PROMPT);
208
#else
209
  (void)snprintf(logFileName, 64, "taosSlowLog");
3,288✔
210
#endif
211

212
  getFullPathName(tsLogObj.slowLogName, logFileName);
3,288✔
213

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

223
  tsLogObj.timestampToday = getTimestampToday();
3,288✔
224
  tsLogObj.slowHandle = taosLogBuffNew(LOG_SLOW_BUF_SIZE);
3,288✔
225
  if (tsLogObj.slowHandle == NULL) return terrno;
3,288!
226

227
  TAOS_UNUSED(taosUmaskFile(0));
3,288✔
228
  tsLogObj.slowHandle->pFile = taosOpenFile(name, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_APPEND);
3,288✔
229
  if (tsLogObj.slowHandle->pFile == NULL) {
3,288!
230
    (void)printf("\nfailed to open slow log file:%s, reason:%s\n", name, strerror(errno));
×
231
    return terrno;
×
232
  }
233

234
  return 0;
3,288✔
235
}
236

237
int32_t taosInitLog(const char *logName, int32_t maxFiles, bool tsc) {
8,659✔
238
  if (atomic_val_compare_exchange_8(&tsLogInited, 0, 1) != 0) return 0;
8,659✔
239
  int32_t code = osUpdate();
8,172✔
240
  if (code != 0) {
8,172!
241
    uError("failed to update os info, reason:%s", tstrerror(code));
×
242
  }
243

244
  TAOS_CHECK_RETURN(taosInitNormalLog(logName, maxFiles));
8,172!
245
  if (tsc) {
8,172✔
246
    TAOS_CHECK_RETURN(taosInitSlowLog());
3,288!
247
  }
248
  TAOS_CHECK_RETURN(taosStartLog());
8,172!
249
  return 0;
8,172✔
250
}
251

252
static void taosStopLog() {
8,172✔
253
  if (tsLogObj.logHandle) {
8,172✔
254
    tsLogObj.logHandle->stop = 1;
8,171✔
255
  }
256
  if (tsLogObj.slowHandle) {
8,172✔
257
    tsLogObj.slowHandle->stop = 1;
3,288✔
258
  }
259
}
8,172✔
260

261
void taosCloseLog() {
8,172✔
262
  taosStopLog();
8,172✔
263

264
  if (tsLogObj.logHandle != NULL && taosCheckPthreadValid(tsLogObj.logHandle->asyncThread)) {
8,172!
265
    (void)taosThreadJoin(tsLogObj.logHandle->asyncThread, NULL);
8,171✔
266
    taosThreadClear(&tsLogObj.logHandle->asyncThread);
8,171✔
267
  }
268

269
  if (tsLogObj.slowHandle != NULL) {
8,172✔
270
    (void)taosThreadMutexDestroy(&tsLogObj.slowHandle->buffMutex);
3,288✔
271
    (void)taosCloseFile(&tsLogObj.slowHandle->pFile);
3,288✔
272
    taosMemoryFreeClear(tsLogObj.slowHandle->buffer);
3,288!
273
    taosMemoryFreeClear(tsLogObj.slowHandle);
3,288!
274
  }
275

276
  if (tsLogObj.logHandle != NULL) {
8,172✔
277
    tsLogInited = 0;
8,171✔
278

279
    (void)taosThreadMutexDestroy(&tsLogObj.logHandle->buffMutex);
8,171✔
280
    (void)taosCloseFile(&tsLogObj.logHandle->pFile);
8,171✔
281
    taosMemoryFreeClear(tsLogObj.logHandle->buffer);
8,171!
282
    (void)taosThreadMutexDestroy(&tsLogObj.logMutex);
8,171✔
283
    taosMemoryFreeClear(tsLogObj.logHandle);
8,171!
284
    tsLogObj.logHandle = NULL;
8,171✔
285
  }
286
}
8,172✔
287

288
static bool taosLockLogFile(TdFilePtr pFile) {
10,290✔
289
  if (pFile == NULL) return false;
10,290!
290

291
  if (tsLogObj.fileNum > 1) {
10,290✔
292
    int32_t ret = taosLockFile(pFile);
4,916✔
293
    if (ret == 0) {
4,916✔
294
      return true;
4,552✔
295
    }
296
  }
297

298
  return false;
5,738✔
299
}
300

301
static void taosUnLockLogFile(TdFilePtr pFile) {
1,753✔
302
  if (pFile == NULL) return;
1,753!
303

304
  if (tsLogObj.fileNum > 1) {
1,753!
305
    int32_t code = taosUnLockFile(pFile);
1,753✔
306
    if (code != 0) {
1,753!
307
      TAOS_UNUSED(printf("failed to unlock log file:%p, reason:%s\n", pFile, tstrerror(code)));
×
308
    }
309
  }
310
}
311

312
static void taosReserveOldLog(char *oldName, char *keepName) {
3✔
313
  if (tsLogKeepDays <= 0) {
3!
314
    keepName[0] = 0;
3✔
315
    return;
3✔
316
  }
317

318
  int32_t code = 0;
×
319
  int64_t fileSec = taosGetTimestampSec();
×
320
  if (tsLogObj.lastKeepFileSec < fileSec) {
×
321
    tsLogObj.lastKeepFileSec = fileSec;
×
322
  } else {
323
    fileSec = ++tsLogObj.lastKeepFileSec;
×
324
  }
325
  snprintf(keepName, PATH_MAX + 20, "%s.%" PRId64, tsLogObj.logName, fileSec);
×
326
  if ((code = taosRenameFile(oldName, keepName))) {
×
327
    keepName[0] = 0;
×
328
    uError("failed to rename file:%s to %s since %s", oldName, keepName, tstrerror(code));
×
329
  }
330
}
331

332
static void taosKeepOldLog(char *oldName) {
×
333
  if (oldName[0] != 0) {
×
334
    char compressFileName[PATH_MAX + 20];
335
    snprintf(compressFileName, PATH_MAX + 20, "%s.gz", oldName);
×
336
    if (taosCompressFile(oldName, compressFileName) == 0) {
×
337
      int32_t code = taosRemoveFile(oldName);
×
338
      if (code != 0) {
×
339
        TAOS_UNUSED(printf("failed to remove file:%s, reason:%s\n", oldName, tstrerror(code)));
×
340
      }
341
    }
342
  }
343

344
  if (tsLogKeepDays > 0) {
×
345
    taosRemoveOldFiles(tsLogDir, tsLogKeepDays);
×
346
  }
347
}
×
348
typedef struct {
349
  TdFilePtr pOldFile;
350
  char      keepName[PATH_MAX + 20];
351
} OldFileKeeper;
352
static OldFileKeeper *taosOpenNewFile() {
3✔
353
  char keepName[PATH_MAX + 20];
354
  sprintf(keepName, "%s.%d", tsLogObj.logName, tsLogObj.flag);
3✔
355

356
  tsLogObj.flag ^= 1;
3✔
357
  tsLogObj.lines = 0;
3✔
358
  char name[PATH_MAX + 20];
359
  sprintf(name, "%s.%d", tsLogObj.logName, tsLogObj.flag);
3✔
360

361
  TAOS_UNUSED(taosUmaskFile(0));
3✔
362

363
  TdFilePtr pFile = taosOpenFile(name, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
3✔
364
  if (pFile == NULL) {
3!
365
    tsLogObj.openInProgress = 0;
×
366
    tsLogObj.lines = tsNumOfLogLines - 1000;
×
367
    uError("open new log file fail! reason:%s, reuse lastlog", strerror(errno));
×
368
    return NULL;
×
369
  }
370

371
  TAOS_UNUSED(taosLockLogFile(pFile));
3✔
372
  if (taosLSeekFile(pFile, 0, SEEK_SET) < 0) {
3!
373
    uWarn("failed to seek file:%s, reason:%s", name, tstrerror(terrno));
×
374
  }
375

376
  TdFilePtr pOldFile = tsLogObj.logHandle->pFile;
3✔
377
  tsLogObj.logHandle->pFile = pFile;
3✔
378
  tsLogObj.lines = 0;
3✔
379
  tsLogObj.openInProgress = 0;
3✔
380
  OldFileKeeper *oldFileKeeper = taosMemoryMalloc(sizeof(OldFileKeeper));
3✔
381
  if (oldFileKeeper == NULL) {
3!
382
    uError("create old log keep info faild! mem is not enough.");
×
383
    return NULL;
×
384
  }
385
  oldFileKeeper->pOldFile = pOldFile;
3✔
386
  taosReserveOldLog(keepName, oldFileKeeper->keepName);
3✔
387

388
  uInfo("   new log file:%d is opened", tsLogObj.flag);
3!
389
  uInfo("==================================");
3!
390
  return oldFileKeeper;
3✔
391
}
392

393
static void *taosThreadToCloseOldFile(void *param) {
3✔
394
  if (!param) return NULL;
3!
395
  OldFileKeeper *oldFileKeeper = (OldFileKeeper *)param;
3✔
396
  taosSsleep(20);
3✔
397
  taosCloseLogByFd(oldFileKeeper->pOldFile);
×
398
  taosKeepOldLog(oldFileKeeper->keepName);
×
399
  taosMemoryFree(oldFileKeeper);
×
400
  return NULL;
×
401
}
402

403
static int32_t taosOpenNewLogFile() {
3✔
404
  (void)taosThreadMutexLock(&tsLogObj.logMutex);
3✔
405

406
  if (tsLogObj.lines > tsNumOfLogLines && tsLogObj.openInProgress == 0) {
3!
407
    tsLogObj.openInProgress = 1;
3✔
408

409
    uInfo("open new log file ......");
3!
410
    TdThread     thread;
411
    TdThreadAttr attr;
412
    (void)taosThreadAttrInit(&attr);
3✔
413
    (void)taosThreadAttrSetDetachState(&attr, PTHREAD_CREATE_DETACHED);
3✔
414

415
    OldFileKeeper *oldFileKeeper = taosOpenNewFile();
3✔
416
    if (!oldFileKeeper) {
3!
417
      TAOS_UNUSED(taosThreadMutexUnlock(&tsLogObj.logMutex));
×
418
      return terrno;
×
419
    }
420
    if (taosThreadCreate(&thread, &attr, taosThreadToCloseOldFile, oldFileKeeper) != 0) {
3!
421
      uError("failed to create thread to close old log file");
×
422
      taosMemoryFreeClear(oldFileKeeper);
×
423
    }
424
    (void)taosThreadAttrDestroy(&attr);
3✔
425
  }
426

427
  (void)taosThreadMutexUnlock(&tsLogObj.logMutex);
3✔
428

429
  return 0;
3✔
430
}
431

432
static void taosOpenNewSlowLogFile() {
×
433
  (void)taosThreadMutexLock(&tsLogObj.logMutex);
×
434
  int64_t delta = taosGetTimestampSec() - tsLogObj.timestampToday;
×
435
  if (delta >= 0 && delta < 86400) {
×
436
    uInfo("timestampToday is already equal to today, no need to open new slow log file");
×
437
    (void)taosThreadMutexUnlock(&tsLogObj.logMutex);
×
438
    return;
×
439
  }
440

441
  for (int32_t i = 1; atomic_val_compare_exchange_32(&tsLogObj.slowHandle->lock, 0, 1) == 1; ++i) {
×
442
    if (i % 1000 == 0) {
×
443
      TAOS_UNUSED(sched_yield());
×
444
    }
445
  }
446
  tsLogObj.slowHandle->lastDuration = LOG_MAX_WAIT_MSEC;  // force write
×
447
  taosWriteLog(tsLogObj.slowHandle);
×
448
  atomic_store_32(&tsLogObj.slowHandle->lock, 0);
×
449

450
  char day[TD_TIME_STR_LEN] = {0};
×
451
  int32_t code = getDay(day, sizeof(day));
×
452
  if (code != 0) {
×
453
    uError("failed to get day, reason:%s", tstrerror(code));
×
454
    (void)taosThreadMutexUnlock(&tsLogObj.logMutex);
×
455
    return;
×
456
  }
457
  TdFilePtr pFile = NULL;
×
458
  char      name[PATH_MAX + TD_TIME_STR_LEN] = {0};
×
459
  (void)snprintf(name, PATH_MAX + TD_TIME_STR_LEN, "%s.%s", tsLogObj.slowLogName, day);
×
460
  pFile = taosOpenFile(name, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_APPEND);
×
461
  if (pFile == NULL) {
×
462
    uError("open new log file fail! reason:%s, reuse lastlog", strerror(errno));
×
463
    (void)taosThreadMutexUnlock(&tsLogObj.logMutex);
×
464
    return;
×
465
  }
466

467
  TdFilePtr pOldFile = tsLogObj.slowHandle->pFile;
×
468
  tsLogObj.slowHandle->pFile = pFile;
×
469
  (void)taosCloseFile(&pOldFile);
×
470
  tsLogObj.timestampToday = getTimestampToday();
×
471
  (void)taosThreadMutexUnlock(&tsLogObj.logMutex);
×
472
}
473

474
void taosResetLog() {
2✔
475
  // force create a new log file
476
  tsLogObj.lines = tsNumOfLogLines + 10;
2✔
477

478
  if (tsLogObj.logHandle) {
2!
479
    int32_t code = taosOpenNewLogFile();
2✔
480
    if (code != 0) {
2!
481
      uError("failed to open new log file, reason:%s", tstrerror(code));
×
482
    }
483
    uInfo("==================================");
2!
484
    uInfo("   reset log file ");
2!
485
  }
486
}
2✔
487

488
static bool taosCheckFileIsOpen(char *logFileName) {
6,326✔
489
  TdFilePtr pFile = taosOpenFile(logFileName, TD_FILE_WRITE);
6,326✔
490
  if (pFile == NULL) {
6,326✔
491
    if (lastErrorIsFileNotExist()) {
4,211!
492
      return false;
4,211✔
493
    } else {
494
      printf("\nfailed to open log file:%s, reason:%s\n", logFileName, strerror(errno));
×
495
      return true;
×
496
    }
497
  }
498

499
  if (taosLockLogFile(pFile)) {
2,115✔
500
    taosUnLockLogFile(pFile);
1,753✔
501
    (void)taosCloseFile(&pFile);
1,753✔
502
    return false;
1,753✔
503
  } else {
504
    (void)taosCloseFile(&pFile);
362✔
505
    return true;
362✔
506
  }
507
}
508

509
static void decideLogFileName(const char *fn, int32_t maxFileNum) {
8,172✔
510
  tsLogObj.fileNum = maxFileNum;
8,172✔
511
  if (tsLogObj.fileNum > 1) {
8,172✔
512
    for (int32_t i = 0; i < tsLogObj.fileNum; i++) {
3,163!
513
      char fileName[PATH_MAX + 10];
514

515
      (void)snprintf(fileName, PATH_MAX + 10, "%s%d.0", fn, i);
3,163✔
516
      bool file1open = taosCheckFileIsOpen(fileName);
3,163✔
517

518
      (void)snprintf(fileName, PATH_MAX + 10, "%s%d.1", fn, i);
3,163✔
519
      bool file2open = taosCheckFileIsOpen(fileName);
3,163✔
520

521
      if (!file1open && !file2open) {
3,163!
522
        (void)snprintf(tsLogObj.logName, PATH_MAX, "%s%d", fn, i);
2,801✔
523
        return;
2,801✔
524
      }
525
    }
526
  }
527

528
  if (strlen(fn) < PATH_MAX) {
5,371!
529
    strcpy(tsLogObj.logName, fn);
5,371✔
530
  }
531
}
532

533
static void decideLogFileNameFlag() {
8,172✔
534
  char    name[PATH_MAX + 50] = "\0";
8,172✔
535
  int32_t logstat0_mtime = 0;
8,172✔
536
  int32_t logstat1_mtime = 0;
8,172✔
537
  bool    log0Exist = false;
8,172✔
538
  bool    log1Exist = false;
8,172✔
539

540
  if (strlen(tsLogObj.logName) < PATH_MAX + 50 - 2) {
8,172!
541
    strcpy(name, tsLogObj.logName);
8,172✔
542
    strcat(name, ".0");
8,172✔
543
    log0Exist = taosStatFile(name, NULL, &logstat0_mtime, NULL) == 0;
8,172✔
544
    name[strlen(name) - 1] = '1';
8,172✔
545
    log1Exist = taosStatFile(name, NULL, &logstat1_mtime, NULL) == 0;
8,172✔
546
  }
547

548
  // if none of the log files exist, open 0, if both exists, open the old one
549
  if (!log0Exist && !log1Exist) {
8,172!
550
    tsLogObj.flag = 0;
5,557✔
551
  } else if (!log1Exist) {
2,615!
552
    tsLogObj.flag = 0;
2,615✔
553
  } else if (!log0Exist) {
×
554
    tsLogObj.flag = 1;
×
555
  } else {
556
    tsLogObj.flag = (logstat0_mtime > logstat1_mtime) ? 0 : 1;
×
557
  }
558
}
8,172✔
559

560
static void processLogFileName(const char *logName, int32_t maxFileNum) {
8,172✔
561
  char fullName[PATH_MAX] = {0};
8,172✔
562
  getFullPathName(fullName, logName);
8,172✔
563
  decideLogFileName(fullName, maxFileNum);
8,172✔
564
  decideLogFileNameFlag();
8,172✔
565
}
8,172✔
566

567
static int32_t taosInitNormalLog(const char *logName, int32_t maxFileNum) {
8,172✔
568
#ifdef WINDOWS_STASH
569
  /*
570
   * always set maxFileNum to 1
571
   * means client log filename is unique in windows
572
   */
573
  maxFileNum = 1;
574
#endif
575

576
  processLogFileName(logName, maxFileNum);
8,172✔
577

578
  char name[PATH_MAX + 50] = "\0";
8,172✔
579
  (void)sprintf(name, "%s.%d", tsLogObj.logName, tsLogObj.flag);
8,172✔
580
  (void)taosThreadMutexInit(&tsLogObj.logMutex, NULL);
8,172✔
581

582
  TAOS_UNUSED(taosUmaskFile(0));
8,172✔
583
  tsLogObj.logHandle = taosLogBuffNew(LOG_DEFAULT_BUF_SIZE);
8,172✔
584
  if (tsLogObj.logHandle == NULL) return terrno;
8,172!
585

586
  tsLogObj.logHandle->pFile = taosOpenFile(name, TD_FILE_CREATE | TD_FILE_WRITE);
8,172✔
587
  if (tsLogObj.logHandle->pFile == NULL) {
8,172!
588
    (void)printf("\nfailed to open log file:%s, reason:%s\n", name, strerror(errno));
×
589
    return terrno;
×
590
  }
591
  TAOS_UNUSED(taosLockLogFile(tsLogObj.logHandle->pFile));
8,172✔
592

593
  // only an estimate for number of lines
594
  int64_t filesize = 0;
8,172✔
595
  if (taosFStatFile(tsLogObj.logHandle->pFile, &filesize, NULL) != 0) {
8,172!
596
    (void)printf("\nfailed to fstat log file:%s, reason:%s\n", name, strerror(errno));
×
597
    taosUnLockLogFile(tsLogObj.logHandle->pFile);
×
598
    return terrno;
×
599
  }
600
  tsLogObj.lines = (int32_t)(filesize / 60);
8,172✔
601

602
  if (taosLSeekFile(tsLogObj.logHandle->pFile, 0, SEEK_END) < 0) {
8,172!
603
    TAOS_UNUSED(printf("failed to seek to the end of log file:%s, reason:%s\n", name, tstrerror(terrno)));
×
604
    taosUnLockLogFile(tsLogObj.logHandle->pFile);
×
605
    return terrno;
×
606
  }
607

608
  (void)sprintf(name, "==================================================\n");
8,172✔
609
  if (taosWriteFile(tsLogObj.logHandle->pFile, name, (uint32_t)strlen(name)) <= 0) {
8,172!
610
    TAOS_UNUSED(printf("failed to write to log file:%s, reason:%s\n", name, tstrerror(terrno)));
×
611
    taosUnLockLogFile(tsLogObj.logHandle->pFile);
×
612
    return terrno;
×
613
  }
614
  (void)sprintf(name, "                new log file                      \n");
8,172✔
615
  if (taosWriteFile(tsLogObj.logHandle->pFile, name, (uint32_t)strlen(name)) <= 0) {
8,172!
616
    TAOS_UNUSED(printf("failed to write to log file:%s, reason:%s\n", name, tstrerror(terrno)));
×
617
    taosUnLockLogFile(tsLogObj.logHandle->pFile);
×
618
    return terrno;
×
619
  }
620
  (void)sprintf(name, "==================================================\n");
8,172✔
621
  if (taosWriteFile(tsLogObj.logHandle->pFile, name, (uint32_t)strlen(name)) <= 0) {
8,172!
622
    TAOS_UNUSED(printf("failed to write to log file:%s, reason:%s\n", name, tstrerror(terrno)));
×
623
    taosUnLockLogFile(tsLogObj.logHandle->pFile);
×
624
    return terrno;
×
625
  }
626

627
  return 0;
8,172✔
628
}
629

630
static void taosUpdateLogNums(ELogLevel level) {
561,437,597✔
631
  switch (level) {
561,437,597!
632
    case DEBUG_ERROR:
4,078,233✔
633
      TAOS_UNUSED(atomic_add_fetch_64(&tsNumOfErrorLogs, 1));
4,078,233✔
634
      break;
4,078,621✔
635
    case DEBUG_INFO:
13,233,201✔
636
      TAOS_UNUSED(atomic_add_fetch_64(&tsNumOfInfoLogs, 1));
13,233,201✔
637
      break;
13,235,529✔
638
    case DEBUG_DEBUG:
473,283,925✔
639
      TAOS_UNUSED(atomic_add_fetch_64(&tsNumOfDebugLogs, 1));
473,283,925✔
640
      break;
473,433,387✔
641
    case DEBUG_DUMP:
70,872,893✔
642
    case DEBUG_TRACE:
643
      TAOS_UNUSED(atomic_add_fetch_64(&tsNumOfTraceLogs, 1));
70,872,893✔
644
      break;
70,879,312✔
645
    default:
×
646
      break;
×
647
  }
648
}
561,596,194✔
649

650
static inline int32_t taosBuildLogHead(char *buffer, const char *flags) {
561,820,737✔
651
  struct tm      Tm, *ptm;
652
  struct timeval timeSecs;
653

654
  TAOS_UNUSED(taosGetTimeOfDay(&timeSecs));
561,820,737✔
655
  time_t curTime = timeSecs.tv_sec;
561,683,179✔
656
  ptm = taosLocalTime(&curTime, &Tm, NULL, 0);
561,683,179✔
657

658
  return sprintf(buffer, "%02d/%02d %02d:%02d:%02d.%06d %08" PRId64 " %s %s", ptm->tm_mon + 1, ptm->tm_mday,
562,073,142✔
659
                 ptm->tm_hour, ptm->tm_min, ptm->tm_sec, (int32_t)timeSecs.tv_usec, taosGetSelfPthreadId(),
561,956,258✔
660
                 LOG_EDITION_FLG, flags);
661
}
662

663
static inline void taosPrintLogImp(ELogLevel level, int32_t dflag, const char *buffer, int32_t len) {
561,537,736✔
664
  if ((dflag & DEBUG_FILE) && tsLogObj.logHandle && tsLogObj.logHandle->pFile != NULL && osLogSpaceSufficient()) {
561,537,736!
665
    taosUpdateLogNums(level);
561,454,672✔
666
    if (tsAsyncLog) {
561,600,131✔
667
      TAOS_UNUSED(taosPushLogBuffer(tsLogObj.logHandle, buffer, len));
808,298✔
668
    } else {
669
      TAOS_UNUSED(taosWriteFile(tsLogObj.logHandle->pFile, buffer, len));
560,791,833✔
670
    }
671

672
    if (tsNumOfLogLines > 0) {
561,671,067!
673
      TAOS_UNUSED(atomic_add_fetch_32(&tsLogObj.lines, 1));
561,673,844✔
674
      if ((tsLogObj.lines > tsNumOfLogLines) && (tsLogObj.openInProgress == 0)) {
561,677,131✔
675
        int32_t code = taosOpenNewLogFile();
1✔
676
        if (code != 0) {
1!
677
          uError("failed to open new log file, reason:%s", tstrerror(code));
×
678
        }
679
      }
680
    }
681
  }
682

683
  if (dflag & DEBUG_SCREEN) {
561,647,564✔
684
#pragma GCC diagnostic push
685
#pragma GCC diagnostic ignored "-Wunused-result"
686
    if (write(1, buffer, (uint32_t)len) < 0) {
12,286,118✔
687
      TAOS_UNUSED(printf("failed to write log to screen, reason:%s\n", strerror(errno)));
937✔
688
    }
689
#pragma GCC diagnostic pop
690
  }
691
}
561,647,500✔
692

693
/*
694
  use taosPrintLogImpl_useStackBuffer to avoid stack overflow
695

696
*/
697
static int8_t taosPrintLogImplUseStackBuffer(const char *flags, int32_t level, int32_t dflag, const char *format,
560,948,497✔
698
                                             va_list args) {
699
  char    buffer[LOG_MAX_STACK_LINE_BUFFER_SIZE];
700
  int32_t len = taosBuildLogHead(buffer, flags);
560,948,497✔
701

702
  int32_t writeLen = len + vsnprintf(buffer + len, LOG_MAX_STACK_LINE_BUFFER_SIZE - len - 1, format, args);
560,998,131✔
703
  if (writeLen > LOG_MAX_STACK_LINE_SIZE) {
560,998,131✔
704
    return 1;
357,039✔
705
  }
706

707
  buffer[writeLen++] = '\n';
560,641,092✔
708
  buffer[writeLen] = 0;
560,641,092✔
709

710
  taosPrintLogImp(level, dflag, buffer, writeLen);
560,641,092✔
711

712
  if (tsLogFp && level <= DEBUG_INFO) {
560,790,928✔
713
    buffer[writeLen - 1] = 0;
11,153,339✔
714
    (*tsLogFp)(taosGetTimestampMs(), level, buffer + len);
22,306,585✔
715
  }
716
  return 0;
560,792,631✔
717
}
718
static int8_t taosPrintLogImplUseHeapBuffer(const char *flags, int32_t level, int32_t dflag, const char *format,
357,039✔
719
                                            va_list args) {
720
  char *buffer = taosMemoryCalloc(1, LOG_MAX_LINE_BUFFER_SIZE + 1);
357,039✔
721
  if (buffer == NULL) {
357,026!
722
    return 1;
×
723
  }
724
  int32_t len = taosBuildLogHead(buffer, flags);
357,026✔
725

726
  int32_t writeLen = len + vsnprintf(buffer + len, LOG_MAX_LINE_BUFFER_SIZE - len - 1, format, args);
357,045✔
727

728
  if (writeLen > LOG_MAX_LINE_SIZE) writeLen = LOG_MAX_LINE_SIZE;
357,045✔
729
  buffer[writeLen++] = '\n';
357,045✔
730
  buffer[writeLen] = 0;
357,045✔
731

732
  taosPrintLogImp(level, dflag, buffer, writeLen);
357,045✔
733

734
  if (tsLogFp && level <= DEBUG_INFO) {
357,045✔
735
    buffer[writeLen - 1] = 0;
69,283✔
736
    (*tsLogFp)(taosGetTimestampMs(), level, buffer + len);
138,566✔
737
  }
738
  taosMemoryFree(buffer);
357,045✔
739
  return 0;
357,045✔
740
}
741
void taosPrintLog(const char *flags, int32_t level, int32_t dflag, const char *format, ...) {
560,768,364✔
742
  if (!(dflag & DEBUG_FILE) && !(dflag & DEBUG_SCREEN)) return;
560,768,364!
743

744
  va_list argpointer, argpointer_copy;
745
  va_start(argpointer, format);
560,768,364✔
746
  va_copy(argpointer_copy, argpointer);
560,768,364✔
747

748
  if (taosPrintLogImplUseStackBuffer(flags, level, dflag, format, argpointer) == 0) {
560,768,364✔
749
  } else {
750
    TAOS_UNUSED(taosPrintLogImplUseHeapBuffer(flags, level, dflag, format, argpointer_copy));
357,039✔
751
  }
752
  va_end(argpointer_copy);
561,150,637✔
753
  va_end(argpointer);
561,150,637✔
754
}
755

756
void taosPrintLongString(const char *flags, int32_t level, int32_t dflag, const char *format, ...) {
585,517✔
757
  if (!osLogSpaceSufficient()) return;
585,517!
758
  if (!(dflag & DEBUG_FILE) && !(dflag & DEBUG_SCREEN)) return;
585,517!
759

760
  char *buffer = taosMemoryMalloc(LOG_MAX_LINE_DUMP_BUFFER_SIZE);
585,517✔
761
  if (!buffer) return;
585,517!
762
  int32_t len = taosBuildLogHead(buffer, flags);
585,517✔
763

764
  va_list argpointer;
765
  va_start(argpointer, format);
585,517✔
766
  len += vsnprintf(buffer + len, LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2 - len, format, argpointer);
585,517✔
767
  va_end(argpointer);
585,517✔
768

769
  len = len > LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2 ? LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2 : len;
585,517✔
770
  buffer[len++] = '\n';
585,517✔
771
  buffer[len] = 0;
585,517✔
772

773
  taosPrintLogImp(level, dflag, buffer, len);
585,517✔
774
  taosMemoryFree(buffer);
585,517✔
775
}
776

777
void taosPrintSlowLog(const char *format, ...) {
168✔
778
  if (!osLogSpaceSufficient()) return;
168!
779

780
  int64_t delta = taosGetTimestampSec() - tsLogObj.timestampToday;
168✔
781
  if (delta >= 86400 || delta < 0) {
168!
782
    taosOpenNewSlowLogFile();
×
783
  }
784

785
  char   *buffer = taosMemoryMalloc(LOG_MAX_LINE_DUMP_BUFFER_SIZE);
168✔
786
  int32_t len = taosBuildLogHead(buffer, "");
168✔
787

788
  va_list argpointer;
789
  va_start(argpointer, format);
168✔
790
  len += vsnprintf(buffer + len, LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2 - len, format, argpointer);
168✔
791
  va_end(argpointer);
168✔
792

793
  if (len < 0 || len > LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2) {
168!
794
    len = LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2;
×
795
  }
796
  buffer[len++] = '\n';
168✔
797
  buffer[len] = 0;
168✔
798

799
  TAOS_UNUSED(atomic_add_fetch_64(&tsNumOfSlowLogs, 1));
168✔
800

801
  if (tsAsyncLog) {
168!
802
    TAOS_UNUSED(taosPushLogBuffer(tsLogObj.slowHandle, buffer, len));
×
803
  } else {
804
    TAOS_UNUSED(taosWriteFile(tsLogObj.slowHandle->pFile, buffer, len));
168✔
805
  }
806

807
  taosMemoryFree(buffer);
168✔
808
}
809

810
void taosDumpData(unsigned char *msg, int32_t len) {
×
811
  if (!osLogSpaceAvailable()) return;
×
812
  taosUpdateLogNums(DEBUG_DUMP);
×
813

814
  char    temp[256] = {0};
×
815
  int32_t i, pos = 0, c = 0;
×
816

817
  for (i = 0; i < len; ++i) {
×
818
    sprintf(temp + pos, "%02x ", msg[i]);
×
819
    c++;
×
820
    pos += 3;
×
821
    if (c >= 16) {
×
822
      temp[pos++] = '\n';
×
823
      TAOS_UNUSED((taosWriteFile(tsLogObj.logHandle->pFile, temp, (uint32_t)pos) <= 0));
×
824
      c = 0;
×
825
      pos = 0;
×
826
    }
827
  }
828

829
  temp[pos++] = '\n';
×
830

831
  TAOS_UNUSED(taosWriteFile(tsLogObj.logHandle->pFile, temp, (uint32_t)pos));
×
832
}
833

834
static void taosCloseLogByFd(TdFilePtr pFile) {
×
835
  if (pFile != NULL) {
×
836
    taosUnLockLogFile(pFile);
×
837
    (void)taosCloseFile(&pFile);
×
838
  }
839
}
×
840

841
static SLogBuff *taosLogBuffNew(int32_t bufSize) {
11,460✔
842
  SLogBuff *pLogBuf = NULL;
11,460✔
843

844
  pLogBuf = taosMemoryCalloc(1, sizeof(SLogBuff));
11,460✔
845
  if (pLogBuf == NULL) return NULL;
11,460!
846

847
  LOG_BUF_BUFFER(pLogBuf) = taosMemoryMalloc(bufSize);
11,460✔
848
  if (LOG_BUF_BUFFER(pLogBuf) == NULL) goto _err;
11,460!
849

850
  LOG_BUF_START(pLogBuf) = LOG_BUF_END(pLogBuf) = 0;
11,460✔
851
  LOG_BUF_SIZE(pLogBuf) = bufSize;
11,460✔
852
  pLogBuf->minBuffSize = bufSize / 10;
11,460✔
853
  pLogBuf->stop = 0;
11,460✔
854
  pLogBuf->writeInterval = LOG_DEFAULT_INTERVAL;
11,460✔
855
  pLogBuf->lock = 0;
11,460✔
856
  if (taosThreadMutexInit(&LOG_BUF_MUTEX(pLogBuf), NULL) < 0) goto _err;
11,460!
857
  // tsem_init(&(pLogBuf->buffNotEmpty), 0, 0);
858

859
  return pLogBuf;
11,460✔
860

861
_err:
×
862
  taosMemoryFreeClear(LOG_BUF_BUFFER(pLogBuf));
×
863
  taosMemoryFreeClear(pLogBuf);
×
864
  return NULL;
×
865
}
866

867
static void taosCopyLogBuffer(SLogBuff *pLogBuf, int32_t start, int32_t end, const char *msg, int32_t msgLen) {
808,355✔
868
  if (start > end) {
808,355!
869
    memcpy(LOG_BUF_BUFFER(pLogBuf) + end, msg, msgLen);
×
870
  } else {
871
    if (LOG_BUF_SIZE(pLogBuf) - end < msgLen) {
808,355!
872
      memcpy(LOG_BUF_BUFFER(pLogBuf) + end, msg, LOG_BUF_SIZE(pLogBuf) - end);
×
873
      memcpy(LOG_BUF_BUFFER(pLogBuf), msg + LOG_BUF_SIZE(pLogBuf) - end, msgLen - LOG_BUF_SIZE(pLogBuf) + end);
×
874
    } else {
875
      memcpy(LOG_BUF_BUFFER(pLogBuf) + end, msg, msgLen);
808,355✔
876
    }
877
  }
878
  LOG_BUF_END(pLogBuf) = (LOG_BUF_END(pLogBuf) + msgLen) % LOG_BUF_SIZE(pLogBuf);
808,355✔
879
}
808,355✔
880

881
static int32_t taosPushLogBuffer(SLogBuff *pLogBuf, const char *msg, int32_t msgLen) {
808,260✔
882
  int32_t        start = 0;
808,260✔
883
  int32_t        end = 0;
808,260✔
884
  int32_t        remainSize = 0;
808,260✔
885
  static int64_t lostLine = 0;
886
  char           tmpBuf[128];
887
  int32_t        tmpBufLen = 0;
808,260✔
888

889
  if (pLogBuf == NULL || pLogBuf->stop) return -1;
808,260!
890

891
  (void)taosThreadMutexLock(&LOG_BUF_MUTEX(pLogBuf));
808,254✔
892
  start = LOG_BUF_START(pLogBuf);
808,355✔
893
  end = LOG_BUF_END(pLogBuf);
808,355✔
894

895
  remainSize = (start > end) ? (start - end - 1) : (start + LOG_BUF_SIZE(pLogBuf) - end - 1);
808,355!
896

897
  if (lostLine > 0) {
808,355!
898
    snprintf(tmpBuf, tListLen(tmpBuf), "...Lost %" PRId64 " lines here...\n", lostLine);
×
899
    tmpBufLen = (int32_t)strlen(tmpBuf);
×
900
  }
901

902
  if (remainSize <= msgLen || ((lostLine > 0) && (remainSize <= (msgLen + tmpBufLen)))) {
808,355!
903
    lostLine++;
×
904
    tsAsyncLogLostLines++;
×
905
    (void)taosThreadMutexUnlock(&LOG_BUF_MUTEX(pLogBuf));
×
906
    return -1;
×
907
  }
908

909
  if (lostLine > 0) {
808,355!
910
    taosCopyLogBuffer(pLogBuf, start, end, tmpBuf, tmpBufLen);
×
911
    lostLine = 0;
×
912
  }
913

914
  taosCopyLogBuffer(pLogBuf, LOG_BUF_START(pLogBuf), LOG_BUF_END(pLogBuf), msg, msgLen);
808,355✔
915

916
  // int32_t w = atomic_sub_fetch_32(&waitLock, 1);
917
  /*
918
  if (w <= 0 || ((remainSize - msgLen - tmpBufLen) < (LOG_BUF_SIZE(pLogBuf) * 4 /5))) {
919
    tsem_post(&(pLogBuf->buffNotEmpty));
920
    dbgPostN++;
921
  } else {
922
    dbgNoPostN++;
923
  }
924
  */
925

926
  (void)taosThreadMutexUnlock(&LOG_BUF_MUTEX(pLogBuf));
808,355✔
927

928
  return 0;
808,318✔
929
}
930

931
static int32_t taosGetLogRemainSize(SLogBuff *pLogBuf, int32_t start, int32_t end) {
81,112✔
932
  int32_t rSize = end - start;
81,112✔
933

934
  return rSize >= 0 ? rSize : LOG_BUF_SIZE(pLogBuf) + rSize;
81,112!
935
}
936

937
static void taosWriteSlowLog(SLogBuff *pLogBuf) {
2,325,020✔
938
  int32_t lock = atomic_val_compare_exchange_32(&pLogBuf->lock, 0, 1);
2,325,020✔
939
  if (lock == 1) return;
2,325,020!
940
  taosWriteLog(pLogBuf);
2,325,020✔
941
  atomic_store_32(&pLogBuf->lock, 0);
2,325,020✔
942
}
943
static void taosWriteLog(SLogBuff *pLogBuf) {
11,379,529✔
944
  int32_t start = LOG_BUF_START(pLogBuf);
11,379,529✔
945
  int32_t end = LOG_BUF_END(pLogBuf);
11,379,529✔
946

947
  if (start == end) {
11,379,529✔
948
    dbgEmptyW++;
11,301,624✔
949
    pLogBuf->writeInterval = LOG_MAX_INTERVAL;
11,301,624✔
950
    return;
11,301,624✔
951
  }
952

953
  int32_t pollSize = taosGetLogRemainSize(pLogBuf, start, end);
77,905✔
954
  if (pollSize < pLogBuf->minBuffSize) {
77,905!
955
    pLogBuf->lastDuration += pLogBuf->writeInterval;
77,905✔
956
    if (pLogBuf->lastDuration < LOG_MAX_WAIT_MSEC) {
77,905✔
957
      return;
74,698✔
958
    }
959
  }
960

961
  pLogBuf->lastDuration = 0;
3,207✔
962

963
  if (start < end) {
3,207!
964
    TAOS_UNUSED(taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf) + start, pollSize));
3,207✔
965
  } else {
966
    int32_t tsize = LOG_BUF_SIZE(pLogBuf) - start;
×
967
    TAOS_UNUSED(taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf) + start, tsize));
×
968

969
    TAOS_UNUSED(taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf), end));
×
970
  }
971

972
  dbgWN++;
3,207✔
973
  dbgWSize += pollSize;
3,207✔
974

975
  if (pollSize < pLogBuf->minBuffSize) {
3,207!
976
    dbgSmallWN++;
3,207✔
977
    if (pLogBuf->writeInterval < LOG_MAX_INTERVAL) {
3,207!
978
      pLogBuf->writeInterval += LOG_INTERVAL_STEP;
×
979
    }
980
  } else if (pollSize > LOG_BUF_SIZE(pLogBuf) / 3) {
×
981
    dbgBigWN++;
×
982
    pLogBuf->writeInterval = LOG_MIN_INTERVAL;
×
983
  } else if (pollSize > LOG_BUF_SIZE(pLogBuf) / 4) {
×
984
    if (pLogBuf->writeInterval > LOG_MIN_INTERVAL) {
×
985
      pLogBuf->writeInterval -= LOG_INTERVAL_STEP;
×
986
    }
987
  }
988

989
  LOG_BUF_START(pLogBuf) = (LOG_BUF_START(pLogBuf) + pollSize) % LOG_BUF_SIZE(pLogBuf);
3,207✔
990

991
  start = LOG_BUF_START(pLogBuf);
3,207✔
992
  end = LOG_BUF_END(pLogBuf);
3,207✔
993

994
  pollSize = taosGetLogRemainSize(pLogBuf, start, end);
3,207✔
995
  if (pollSize < pLogBuf->minBuffSize) {
3,207!
996
    return;
3,207✔
997
  }
998

999
  pLogBuf->writeInterval = 0;
×
1000
}
1001

1002
static void *taosAsyncOutputLog(void *param) {
8,172✔
1003
  SLogBuff *pLogBuf = (SLogBuff *)tsLogObj.logHandle;
8,172✔
1004
  SLogBuff *pSlowBuf = (SLogBuff *)tsLogObj.slowHandle;
8,172✔
1005

1006
  setThreadName("log");
8,172✔
1007
  int32_t count = 0;
8,172✔
1008
  int32_t updateCron = 0;
8,172✔
1009
  int32_t writeInterval = 0;
8,172✔
1010

1011
  while (1) {
1012
    if (pSlowBuf) {
9,046,339✔
1013
      writeInterval = TMIN(pLogBuf->writeInterval, pSlowBuf->writeInterval);
2,321,732✔
1014
    } else {
1015
      writeInterval = pLogBuf->writeInterval;
6,724,607✔
1016
    }
1017
    count += writeInterval;
9,046,339✔
1018
    updateCron++;
9,046,339✔
1019
    taosMsleep(writeInterval);
9,046,339✔
1020
    if (count > 1000) {
9,046,338✔
1021
      TAOS_UNUSED(osUpdate());
217,149✔
1022
      count = 0;
217,149✔
1023
    }
1024

1025
    // Polling the buffer
1026
    taosWriteLog(pLogBuf);
9,046,338✔
1027
    if (pSlowBuf) taosWriteSlowLog(pSlowBuf);
9,046,338✔
1028

1029
    if (pLogBuf->stop || (pSlowBuf && pSlowBuf->stop)) {
9,046,338!
1030
      pLogBuf->lastDuration = LOG_MAX_WAIT_MSEC;
8,171✔
1031
      taosWriteLog(pLogBuf);
8,171✔
1032
      if (pSlowBuf) taosWriteSlowLog(pSlowBuf);
8,171✔
1033
      break;
8,171✔
1034
    }
1035
  }
1036

1037
  return NULL;
8,171✔
1038
}
1039

1040
bool taosAssertDebug(bool condition, const char *file, int32_t line, bool core, const char *format, ...) {
×
1041
  if (condition) return false;
×
1042

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

1049
  va_list argpointer;
1050
  va_start(argpointer, format);
×
1051
  len = len + vsnprintf(buffer + len, LOG_MAX_LINE_BUFFER_SIZE - len, format, argpointer);
×
1052
  va_end(argpointer);
×
1053
  buffer[len++] = '\n';
×
1054
  buffer[len] = 0;
×
1055
  taosPrintLogImp(1, 255, buffer, len);
×
1056

1057
  taosPrintLog(flags, level, dflag, "tAssert at file %s:%d exit:%d", file, line, tsAssert);
×
1058
  taosPrintTrace(flags, level, dflag, -1);
×
1059

1060
  if (tsAssert || core) {
×
1061
    taosCloseLog();
×
1062
    taosMsleep(300);
×
1063

1064
#ifdef NDEBUG
1065
    abort();
1066
#else
1067
    assert(0);
×
1068
#endif
1069
  }
1070

1071
  return true;
×
1072
}
1073

1074
void taosLogCrashInfo(char *nodeType, char *pMsg, int64_t msgLen, int signum, void *sigInfo) {
×
1075
  const char *flags = "UTL FATAL ";
×
1076
  ELogLevel   level = DEBUG_FATAL;
×
1077
  int32_t     dflag = 255;
×
1078
  char        filepath[PATH_MAX] = {0};
×
1079
  TdFilePtr   pFile = NULL;
×
1080

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

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

1090
    if (taosLockFile(pFile) < 0) {
×
1091
      taosPrintLog(flags, level, dflag, "failed to lock file:%s since %s", filepath, terrstr());
×
1092
      goto _return;
×
1093
    }
1094

1095
    int64_t writeSize = taosWriteFile(pFile, &msgLen, sizeof(msgLen));
×
1096
    if (sizeof(msgLen) != writeSize) {
×
1097
      TAOS_UNUSED(taosUnLockFile(pFile));
×
1098
      taosPrintLog(flags, level, dflag, "failed to write len to file:%s,%p wlen:%" PRId64 " tlen:%lu since %s",
×
1099
                   filepath, pFile, writeSize, sizeof(msgLen), terrstr());
1100
      goto _return;
×
1101
    }
1102

1103
    writeSize = taosWriteFile(pFile, pMsg, msgLen);
×
1104
    if (msgLen != writeSize) {
×
1105
      TAOS_UNUSED(taosUnLockFile(pFile));
×
1106
      taosPrintLog(flags, level, dflag, "failed to write file:%s,%p wlen:%" PRId64 " tlen:%" PRId64 " since %s",
×
1107
                   filepath, pFile, writeSize, msgLen, terrstr());
1108
      goto _return;
×
1109
    }
1110

1111
    TAOS_UNUSED(taosUnLockFile(pFile));
×
1112
  }
1113

1114
_return:
×
1115

1116
  if (pFile) (void)taosCloseFile(&pFile);
×
1117

1118
  taosPrintLog(flags, level, dflag, "crash signal is %d", signum);
×
1119

1120
#ifdef _TD_DARWIN_64
1121
  taosPrintTrace(flags, level, dflag, 4);
1122
#elif !defined(WINDOWS)
1123
  taosPrintLog(flags, level, dflag, "sender PID:%d cmdline:%s", ((siginfo_t *)sigInfo)->si_pid,
×
1124
               taosGetCmdlineByPID(((siginfo_t *)sigInfo)->si_pid));
1125
  taosPrintTrace(flags, level, dflag, 3);
×
1126
#else
1127
  taosPrintTrace(flags, level, dflag, 8);
1128
#endif
1129

1130
  taosMemoryFree(pMsg);
×
1131
}
×
1132

1133
void taosReadCrashInfo(char *filepath, char **pMsg, int64_t *pMsgLen, TdFilePtr *pFd) {
×
1134
  const char *flags = "UTL FATAL ";
×
1135
  ELogLevel   level = DEBUG_FATAL;
×
1136
  int32_t     dflag = 255;
×
1137
  TdFilePtr   pFile = NULL;
×
1138
  bool        truncateFile = false;
×
1139
  char       *buf = NULL;
×
1140

1141
  if (NULL == *pFd) {
×
1142
    int64_t filesize = 0;
×
1143
    if (taosStatFile(filepath, &filesize, NULL, NULL) < 0) {
×
1144
      if (TAOS_SYSTEM_ERROR(ENOENT) == terrno) {
×
1145
        return;
×
1146
      }
1147

1148
      taosPrintLog(flags, level, dflag, "failed to stat file:%s since %s", filepath, terrstr());
×
1149
      return;
×
1150
    }
1151

1152
    if (filesize <= 0) {
×
1153
      return;
×
1154
    }
1155

1156
    pFile = taosOpenFile(filepath, TD_FILE_READ | TD_FILE_WRITE);
×
1157
    if (pFile == NULL) {
×
1158
      if (ENOENT == errno) {
×
1159
        return;
×
1160
      }
1161

1162
      taosPrintLog(flags, level, dflag, "failed to open file:%s since %s", filepath, terrstr());
×
1163
      return;
×
1164
    }
1165

1166
    TAOS_UNUSED(taosLockFile(pFile));
×
1167
  } else {
1168
    pFile = *pFd;
×
1169
  }
1170

1171
  int64_t msgLen = 0;
×
1172
  int64_t readSize = taosReadFile(pFile, &msgLen, sizeof(msgLen));
×
1173
  if (sizeof(msgLen) != readSize) {
×
1174
    truncateFile = true;
×
1175
    if (readSize < 0) {
×
1176
      taosPrintLog(flags, level, dflag, "failed to read len from file:%s,%p wlen:%" PRId64 " tlen:%lu since %s",
×
1177
                   filepath, pFile, readSize, sizeof(msgLen), terrstr());
1178
    }
1179
    goto _return;
×
1180
  }
1181

1182
  buf = taosMemoryMalloc(msgLen);
×
1183
  if (NULL == buf) {
×
1184
    taosPrintLog(flags, level, dflag, "failed to malloc buf, size:%" PRId64, msgLen);
×
1185
    goto _return;
×
1186
  }
1187

1188
  readSize = taosReadFile(pFile, buf, msgLen);
×
1189
  if (msgLen != readSize) {
×
1190
    truncateFile = true;
×
1191
    taosPrintLog(flags, level, dflag, "failed to read file:%s,%p wlen:%" PRId64 " tlen:%" PRId64 " since %s", filepath,
×
1192
                 pFile, readSize, msgLen, terrstr());
1193
    goto _return;
×
1194
  }
1195

1196
  *pMsg = buf;
×
1197
  *pMsgLen = msgLen;
×
1198
  *pFd = pFile;
×
1199

1200
  return;
×
1201

1202
_return:
×
1203

1204
  if (truncateFile) {
×
1205
    TAOS_UNUSED(taosFtruncateFile(pFile, 0));
×
1206
  }
1207
  TAOS_UNUSED(taosUnLockFile(pFile));
×
1208
  TAOS_UNUSED(taosCloseFile(&pFile));
×
1209
  taosMemoryFree(buf);
×
1210

1211
  *pMsg = NULL;
×
1212
  *pMsgLen = 0;
×
1213
  *pFd = NULL;
×
1214
}
1215

1216
void taosReleaseCrashLogFile(TdFilePtr pFile, bool truncateFile) {
×
1217
  if (truncateFile) {
×
1218
    TAOS_UNUSED(taosFtruncateFile(pFile, 0));
×
1219
  }
1220

1221
  TAOS_UNUSED(taosUnLockFile(pFile));
×
1222
  TAOS_UNUSED(taosCloseFile(&pFile));
×
1223
}
×
1224

1225
#ifdef NDEBUG
1226
bool taosAssertRelease(bool condition) {
1227
  if (condition) return false;
1228

1229
  const char *flags = "UTL FATAL ";
1230
  ELogLevel   level = DEBUG_FATAL;
1231
  int32_t     dflag = 255;  // tsLogEmbedded ? 255 : uDebugFlag
1232

1233
  taosPrintLog(flags, level, dflag, "tAssert called in release mode, exit:%d", tsAssert);
1234
  taosPrintTrace(flags, level, dflag, 0);
1235

1236
  if (tsAssert) {
1237
    taosMsleep(300);
1238
    abort();
1239
  }
1240

1241
  return true;
1242
}
1243
#endif
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