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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return false;
}

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

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

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

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

A
Alex Duan 已提交
211
  (void)taosRenameFile(oldName, fileName);
212

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

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

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

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

S
Shengliang Guan 已提交
233
  taosUmaskFile(0);
H
hzcheng 已提交
234

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

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

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

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

H
hzcheng 已提交
257 258 259
  return NULL;
}

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

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

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

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

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

  return 0;
}

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

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

  taosOpenNewLogFile();
289
  (void)taosRemoveFile(lastName);
H
hzcheng 已提交
290

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return 0;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

574
  return pLogBuf;
H
hzcheng 已提交
575 576

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

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

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

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

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

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

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

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

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

629
  taosCopyLogBuffer(pLogBuf, LOG_BUF_START(pLogBuf), LOG_BUF_END(pLogBuf), msg, msgLen);
H
hzcheng 已提交
630

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

641
  taosThreadMutexUnlock(&LOG_BUF_MUTEX(pLogBuf));
H
hzcheng 已提交
642 643 644 645

  return 0;
}

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

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

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

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

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

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

D
fix bu  
dapan1121 已提交
676 677 678 679
      lastDuration = 0;
    }

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

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

    dbgWN++;
L
Liu Jicong 已提交
689 690
    dbgWSize += pollSize;

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

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

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

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

S
Shengliang Guan 已提交
715
    tsWriteInterval = LOG_MIN_INTERVAL;
D
fix bu  
dapan1121 已提交
716 717

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

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

    // Polling the buffer
736
    taosWriteLog(pLogBuf);
H
hzcheng 已提交
737

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

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

  return NULL;
}
S
Shengliang Guan 已提交
748 749 750 751 752

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

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

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

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

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

  return ret;
}
S
Shengliang Guan 已提交
792

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

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

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

  taosPrintLog(flags, level, dflag, "tAssert at file %s:%d exit:%d", file, line, tsAssert);
  taosPrintTrace(flags, level, dflag);

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

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

  return true;
}