tlog.c 22.4 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);
B
Benguang Zhao 已提交
448
    if (tsAsyncLog && level != DEBUG_FATAL) {
S
slguan 已提交
449
      taosPushLogBuffer(tsLogObj.logHandle, buffer, len);
H
hzcheng 已提交
450
    } else {
451
      taosWriteFile(tsLogObj.logHandle->pFile, buffer, len);
B
Benguang Zhao 已提交
452 453 454
      if (level == DEBUG_FATAL) {
        taosFsyncFile(tsLogObj.logHandle->pFile);
      }
H
hzcheng 已提交
455 456
    }

S
slguan 已提交
457 458
    if (tsLogObj.maxLines > 0) {
      atomic_add_fetch_32(&tsLogObj.lines, 1);
S
Shengliang Guan 已提交
459 460 461
      if ((tsLogObj.lines > tsLogObj.maxLines) && (tsLogObj.openInProgress == 0)) {
        taosOpenNewLogFile();
      }
H
hzcheng 已提交
462 463 464
    }
  }

465
  if (dflag & DEBUG_SCREEN) {
466 467
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
S
Shengliang Guan 已提交
468
    write(1, buffer, (uint32_t)len);
469
#pragma GCC diagnostic pop
470
  }
H
hzcheng 已提交
471 472
}

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

S
Shengliang Guan 已提交
476 477
  char    buffer[LOG_MAX_LINE_BUFFER_SIZE];
  int32_t len = taosBuildLogHead(buffer, flags);
H
hzcheng 已提交
478

S
Shengliang Guan 已提交
479 480
  va_list argpointer;
  va_start(argpointer, format);
S
Shengliang Guan 已提交
481
  int32_t writeLen = len + vsnprintf(buffer + len, LOG_MAX_LINE_BUFFER_SIZE - len, format, argpointer);
S
Shengliang Guan 已提交
482
  va_end(argpointer);
H
hzcheng 已提交
483

S
Shengliang Guan 已提交
484 485 486
  if (writeLen > LOG_MAX_LINE_SIZE) writeLen = LOG_MAX_LINE_SIZE;
  buffer[writeLen++] = '\n';
  buffer[writeLen] = 0;
H
hzcheng 已提交
487

S
Shengliang Guan 已提交
488 489 490 491 492 493
  taosPrintLogImp(level, dflag, buffer, writeLen);

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

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

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

S
Shengliang Guan 已提交
503
  va_list argpointer;
H
hzcheng 已提交
504
  va_start(argpointer, format);
S
Shengliang Guan 已提交
505
  len += vsnprintf(buffer + len, LOG_MAX_LINE_DUMP_BUFFER_SIZE - len, format, argpointer);
H
hzcheng 已提交
506 507
  va_end(argpointer);

S
Shengliang Guan 已提交
508
  if (len > LOG_MAX_LINE_DUMP_SIZE) len = LOG_MAX_LINE_DUMP_SIZE;
H
hzcheng 已提交
509 510 511
  buffer[len++] = '\n';
  buffer[len] = 0;

S
Shengliang Guan 已提交
512
  taosPrintLogImp(level, dflag, buffer, len);
513
  taosMemoryFree(buffer);
S
Shengliang Guan 已提交
514
}
L
Liu Jicong 已提交
515

S
Shengliang Guan 已提交
516 517 518
void taosDumpData(unsigned char *msg, int32_t len) {
  if (!osLogSpaceAvailable()) return;
  taosUpdateLogNums(DEBUG_DUMP);
H
hzcheng 已提交
519

520
  char    temp[256] = {0};
S
Shengliang Guan 已提交
521 522 523 524 525 526 527 528 529 530 531
  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 已提交
532 533 534
    }
  }

S
Shengliang Guan 已提交
535 536 537
  temp[pos++] = '\n';

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

540 541 542 543
static void taosCloseLogByFd(TdFilePtr pFile) {
  if (pFile != NULL) {
    taosUnLockLogFile(pFile);
    taosCloseFile(&pFile);
H
hzcheng 已提交
544 545 546
  }
}

S
slguan 已提交
547
static SLogBuff *taosLogBuffNew(int32_t bufSize) {
548
  SLogBuff *pLogBuf = NULL;
H
hzcheng 已提交
549

550 551
  pLogBuf = taosMemoryCalloc(1, sizeof(SLogBuff));
  if (pLogBuf == NULL) return NULL;
H
hzcheng 已提交
552

553 554
  LOG_BUF_BUFFER(pLogBuf) = taosMemoryMalloc(bufSize);
  if (LOG_BUF_BUFFER(pLogBuf) == NULL) goto _err;
H
hzcheng 已提交
555

556 557 558 559
  LOG_BUF_START(pLogBuf) = LOG_BUF_END(pLogBuf) = 0;
  LOG_BUF_SIZE(pLogBuf) = bufSize;
  pLogBuf->minBuffSize = bufSize / 10;
  pLogBuf->stop = 0;
H
hzcheng 已提交
560

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

564
  return pLogBuf;
H
hzcheng 已提交
565 566

_err:
567 568
  taosMemoryFreeClear(LOG_BUF_BUFFER(pLogBuf));
  taosMemoryFreeClear(pLogBuf);
H
hzcheng 已提交
569 570 571
  return NULL;
}

572
static void taosCopyLogBuffer(SLogBuff *pLogBuf, int32_t start, int32_t end, const char *msg, int32_t msgLen) {
D
fix bug  
dapan1121 已提交
573
  if (start > end) {
574
    memcpy(LOG_BUF_BUFFER(pLogBuf) + end, msg, msgLen);
D
fix bug  
dapan1121 已提交
575
  } else {
576 577 578
    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 已提交
579
    } else {
580
      memcpy(LOG_BUF_BUFFER(pLogBuf) + end, msg, msgLen);
D
fix bug  
dapan1121 已提交
581 582
    }
  }
583
  LOG_BUF_END(pLogBuf) = (LOG_BUF_END(pLogBuf) + msgLen) % LOG_BUF_SIZE(pLogBuf);
D
fix bug  
dapan1121 已提交
584 585
}

586
static int32_t taosPushLogBuffer(SLogBuff *pLogBuf, const char *msg, int32_t msgLen) {
L
Liu Jicong 已提交
587 588 589
  int32_t        start = 0;
  int32_t        end = 0;
  int32_t        remainSize = 0;
D
fix bug  
dapan1121 已提交
590
  static int64_t lostLine = 0;
H
Haojun Liao 已提交
591
  char           tmpBuf[128] = {0};
L
Liu Jicong 已提交
592
  int32_t        tmpBufLen = 0;
H
hzcheng 已提交
593

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

596 597 598
  taosThreadMutexLock(&LOG_BUF_MUTEX(pLogBuf));
  start = LOG_BUF_START(pLogBuf);
  end = LOG_BUF_END(pLogBuf);
H
hzcheng 已提交
599

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

D
fix bug  
dapan1121 已提交
602
  if (lostLine > 0) {
H
Haojun Liao 已提交
603
    snprintf(tmpBuf, tListLen(tmpBuf), "...Lost %" PRId64 " lines here...\n", lostLine);
D
dapan1121 已提交
604
    tmpBufLen = (int32_t)strlen(tmpBuf);
D
fix bug  
dapan1121 已提交
605 606 607 608
  }

  if (remainSize <= msgLen || ((lostLine > 0) && (remainSize <= (msgLen + tmpBufLen)))) {
    lostLine++;
S
Shengliang Guan 已提交
609
    tsAsyncLogLostLines++;
610
    taosThreadMutexUnlock(&LOG_BUF_MUTEX(pLogBuf));
H
hzcheng 已提交
611 612 613
    return -1;
  }

D
fix bug  
dapan1121 已提交
614
  if (lostLine > 0) {
615
    taosCopyLogBuffer(pLogBuf, start, end, tmpBuf, tmpBufLen);
D
fix bug  
dapan1121 已提交
616
    lostLine = 0;
H
hzcheng 已提交
617
  }
D
fix bug  
dapan1121 已提交
618

619
  taosCopyLogBuffer(pLogBuf, LOG_BUF_START(pLogBuf), LOG_BUF_END(pLogBuf), msg, msgLen);
H
hzcheng 已提交
620

L
Liu Jicong 已提交
621
  // int32_t w = atomic_sub_fetch_32(&waitLock, 1);
D
fix bug  
dapan1121 已提交
622
  /*
623 624
  if (w <= 0 || ((remainSize - msgLen - tmpBufLen) < (LOG_BUF_SIZE(pLogBuf) * 4 /5))) {
    tsem_post(&(pLogBuf->buffNotEmpty));
D
fix bug  
dapan1121 已提交
625 626 627
    dbgPostN++;
  } else {
    dbgNoPostN++;
D
fix bug  
dapan1121 已提交
628
  }
D
fix bug  
dapan1121 已提交
629
  */
H
hzcheng 已提交
630

631
  taosThreadMutexUnlock(&LOG_BUF_MUTEX(pLogBuf));
H
hzcheng 已提交
632 633 634 635

  return 0;
}

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

639
  return rSize >= 0 ? rSize : LOG_BUF_SIZE(pLogBuf) + rSize;
D
fix bug  
dapan1121 已提交
640
}
H
hzcheng 已提交
641

642
static void taosWriteLog(SLogBuff *pLogBuf) {
D
fix bu  
dapan1121 已提交
643
  static int32_t lastDuration = 0;
L
Liu Jicong 已提交
644 645 646
  int32_t        remainChecked = 0;
  int32_t        start, end, pollSize;

D
fix bug  
dapan1121 已提交
647
  do {
D
fix bu  
dapan1121 已提交
648
    if (remainChecked == 0) {
649 650
      start = LOG_BUF_START(pLogBuf);
      end = LOG_BUF_END(pLogBuf);
D
fix bu  
dapan1121 已提交
651 652 653

      if (start == end) {
        dbgEmptyW++;
S
Shengliang Guan 已提交
654
        tsWriteInterval = LOG_MAX_INTERVAL;
D
fix bu  
dapan1121 已提交
655 656
        return;
      }
H
hzcheng 已提交
657

658 659
      pollSize = taosGetLogRemainSize(pLogBuf, start, end);
      if (pollSize < pLogBuf->minBuffSize) {
S
Shengliang Guan 已提交
660
        lastDuration += tsWriteInterval;
D
fix bug  
dapan1121 已提交
661
        if (lastDuration < LOG_MAX_WAIT_MSEC) {
D
fix bu  
dapan1121 已提交
662 663 664
          break;
        }
      }
D
fix bug  
dapan1121 已提交
665

D
fix bu  
dapan1121 已提交
666 667 668 669
      lastDuration = 0;
    }

    if (start < end) {
670
      taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf) + start, pollSize);
H
hzcheng 已提交
671
    } else {
672 673
      int32_t tsize = LOG_BUF_SIZE(pLogBuf) - start;
      taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf) + start, tsize);
D
fix bug  
dapan1121 已提交
674

675
      taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf), end);
H
hzcheng 已提交
676
    }
D
fix bug  
dapan1121 已提交
677 678

    dbgWN++;
L
Liu Jicong 已提交
679 680
    dbgWSize += pollSize;

681
    if (pollSize < pLogBuf->minBuffSize) {
D
fix bug  
dapan1121 已提交
682
      dbgSmallWN++;
S
Shengliang Guan 已提交
683 684
      if (tsWriteInterval < LOG_MAX_INTERVAL) {
        tsWriteInterval += LOG_INTERVAL_STEP;
D
fix bug  
dapan1121 已提交
685
      }
686
    } else if (pollSize > LOG_BUF_SIZE(pLogBuf) / 3) {
D
fix bug  
dapan1121 已提交
687
      dbgBigWN++;
S
Shengliang Guan 已提交
688
      tsWriteInterval = LOG_MIN_INTERVAL;
689
    } else if (pollSize > LOG_BUF_SIZE(pLogBuf) / 4) {
S
Shengliang Guan 已提交
690 691
      if (tsWriteInterval > LOG_MIN_INTERVAL) {
        tsWriteInterval -= LOG_INTERVAL_STEP;
D
fix bug  
dapan1121 已提交
692
      }
D
fix bug  
dapan1121 已提交
693 694
    }

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

697 698
    start = LOG_BUF_START(pLogBuf);
    end = LOG_BUF_END(pLogBuf);
D
fix bu  
dapan1121 已提交
699

700 701
    pollSize = taosGetLogRemainSize(pLogBuf, start, end);
    if (pollSize < pLogBuf->minBuffSize) {
D
fix bug  
dapan1121 已提交
702 703 704
      break;
    }

S
Shengliang Guan 已提交
705
    tsWriteInterval = LOG_MIN_INTERVAL;
D
fix bu  
dapan1121 已提交
706 707

    remainChecked = 1;
L
Liu Jicong 已提交
708
  } while (1);
H
hzcheng 已提交
709 710
}

S
slguan 已提交
711
static void *taosAsyncOutputLog(void *param) {
712
  SLogBuff *pLogBuf = (SLogBuff *)param;
H
Haojun Liao 已提交
713
  setThreadName("log");
wafwerar's avatar
wafwerar 已提交
714
  int32_t count = 0;
dengyihao's avatar
dengyihao 已提交
715
  int32_t updateCron = 0;
H
hzcheng 已提交
716
  while (1) {
wafwerar's avatar
wafwerar 已提交
717
    count += tsWriteInterval;
dengyihao's avatar
dengyihao 已提交
718
    updateCron++;
S
Shengliang Guan 已提交
719
    taosMsleep(tsWriteInterval);
wafwerar's avatar
wafwerar 已提交
720 721 722 723
    if (count > 1000) {
      osUpdate();
      count = 0;
    }
H
hzcheng 已提交
724 725

    // Polling the buffer
726
    taosWriteLog(pLogBuf);
H
hzcheng 已提交
727

dengyihao's avatar
dengyihao 已提交
728 729 730 731 732
    if (updateCron >= 3600 * 24 * 40 / 2) {
      taosUpdateDaylight();
      updateCron = 0;
    }

733
    if (pLogBuf->stop) break;
H
hzcheng 已提交
734 735 736 737
  }

  return NULL;
}
S
Shengliang Guan 已提交
738 739 740 741 742

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

746 747 748
  // srcFp = fopen(srcFileName, "r");
  TdFilePtr pSrcFile = taosOpenFile(srcFileName, TD_FILE_READ);
  if (pSrcFile == NULL) {
S
Shengliang Guan 已提交
749 750 751 752
    ret = -1;
    goto cmp_end;
  }

753
  TdFilePtr pFile = taosOpenFile(destFileName, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
754
  if (pFile == NULL) {
S
Shengliang Guan 已提交
755 756 757 758
    ret = -2;
    goto cmp_end;
  }

S
ulog  
Shengliang Guan 已提交
759 760 761 762 763 764 765 766 767 768 769
  //  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 已提交
770 771

cmp_end:
772 773
  if (pSrcFile) {
    taosCloseFile(&pSrcFile);
S
Shengliang Guan 已提交
774
  }
S
ulog  
Shengliang Guan 已提交
775 776 777
  //  if (dstFp) {
  //    gzclose(dstFp);
  //  }
wafwerar's avatar
wafwerar 已提交
778
  taosMemoryFree(data);
S
Shengliang Guan 已提交
779 780 781

  return ret;
}
S
Shengliang Guan 已提交
782

S
Shengliang Guan 已提交
783
bool taosAssert(bool condition, const char *file, int32_t line, const char *format, ...) {
S
Shengliang Guan 已提交
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
  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) {
    taosCloseLog();
    taosMsleep(300);

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

  return true;
}