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

taosdata / TDengine / #5034

24 Apr 2026 11:25AM UTC coverage: 73.058%. Remained the same
#5034

push

travis-ci

web-flow
merge: from main to 3.0 branch #35224

merge: from main to 3.0 branch[manual-only]

1336 of 1975 new or added lines in 48 files covered. (67.65%)

14149 existing lines in 164 files now uncovered.

275896 of 377640 relevant lines covered (73.06%)

132944440.29 hits per line

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

81.05
/source/os/src/osSysinfo.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 "os.h"
18
#include "taoserror.h"
19
#include "cus_name.h"
20

21
#define PROCESS_ITEM 12
22
#define UUIDLEN37 37
23

24
typedef struct {
25
  uint64_t user;
26
  uint64_t nice;
27
  uint64_t system;
28
  uint64_t idle;
29
  uint64_t wa;
30
  uint64_t hi;
31
  uint64_t si;
32
  uint64_t st;
33
  uint64_t guest;
34
  uint64_t guest_nice;
35
} SysCpuInfo;
36

37
typedef struct {
38
  uint64_t utime;   // user time
39
  uint64_t stime;   // kernel time
40
  uint64_t cutime;  // all user time
41
  uint64_t cstime;  // all dead time
42
} ProcCpuInfo;
43

44
#ifdef WINDOWS
45

46
/*
47
 * windows implementation
48
 */
49

50
#if (_WIN64)
51
#include <iphlpapi.h>
52
#include <mswsock.h>
53
#include <psapi.h>
54
#include <stdio.h>
55
#include <windows.h>
56
#include <ws2tcpip.h>
57
#pragma comment(lib, "Mswsock.lib ")
58
#endif
59

60
#include <objbase.h>
61
#include <signal.h>
62
#include <stdlib.h>
63

64
#pragma warning(push)
65
#pragma warning(disable : 4091)
66
#include <DbgHelp.h>
67
#pragma warning(pop)
68

69
// Write a single stack frame line to hFile.
70
// dbghelp functions are available via the statically-linked dbghelp.lib.
71
static void taosWinWriteOneFrame(HANDLE hFile, HANDLE hProcess, DWORD64 pc, DWORD idx) {
72
  char         symBuf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
73
  PSYMBOL_INFO pSym = (PSYMBOL_INFO)symBuf;
74
  pSym->SizeOfStruct = sizeof(SYMBOL_INFO);
75
  pSym->MaxNameLen   = MAX_SYM_NAME;
76

77
  DWORD64 symDisp = 0;
78
  char   *symName = (char *)"<unknown>";
79
  if (SymFromAddr(hProcess, pc, &symDisp, pSym)) {
80
    symName = pSym->Name;
81
  }
82

83
  IMAGEHLP_LINE64 li = {0};
84
  li.SizeOfStruct     = sizeof(IMAGEHLP_LINE64);
85
  DWORD lineDisp      = 0;
86

87
  char line[4096];
88
  int  n;
89
  if (SymGetLineFromAddr64(hProcess, pc, &lineDisp, &li)) {
90
    n = _snprintf_s(line, sizeof(line), _TRUNCATE, "#%-3lu 0x%016I64X  %s  (%s:%lu)\r\n",
91
                    (unsigned long)idx, pc, symName, li.FileName, (unsigned long)li.LineNumber);
92
  } else {
93
    n = _snprintf_s(line, sizeof(line), _TRUNCATE, "#%-3lu 0x%016I64X  %s\r\n",
94
                    (unsigned long)idx, pc, symName);
95
  }
96
  DWORD w = 0;
97
  if (n > 0) (void)WriteFile(hFile, line, (DWORD)n, &w, NULL);
98
}
99

100
// Walk the call stack from the exception context and write each frame to hFile.
101
static void taosWinWriteStackTrace(HANDLE hFile, PEXCEPTION_POINTERS ep) {
102
  HANDLE  hProcess = GetCurrentProcess();
103
  HANDLE  hThread  = GetCurrentThread();
104
  CONTEXT ctx      = *ep->ContextRecord; /* copy: StackWalk64 modifies it */
105

106
  SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
107
  SymInitialize(hProcess, NULL, TRUE);
108

109
  STACKFRAME64 sf   = {0};
110
  DWORD        mach;
111
#if defined(_M_X64)
112
  mach                = IMAGE_FILE_MACHINE_AMD64;
113
  sf.AddrPC.Offset    = ctx.Rip; sf.AddrPC.Mode    = AddrModeFlat;
114
  sf.AddrFrame.Offset = ctx.Rbp; sf.AddrFrame.Mode = AddrModeFlat;
115
  sf.AddrStack.Offset = ctx.Rsp; sf.AddrStack.Mode = AddrModeFlat;
116
#elif defined(_M_IX86)
117
  mach                = IMAGE_FILE_MACHINE_I386;
118
  sf.AddrPC.Offset    = ctx.Eip; sf.AddrPC.Mode    = AddrModeFlat;
119
  sf.AddrFrame.Offset = ctx.Ebp; sf.AddrFrame.Mode = AddrModeFlat;
120
  sf.AddrStack.Offset = ctx.Esp; sf.AddrStack.Mode = AddrModeFlat;
121
#elif defined(_M_ARM64)
122
  mach                = IMAGE_FILE_MACHINE_ARM64;
123
  sf.AddrPC.Offset    = ctx.Pc; sf.AddrPC.Mode    = AddrModeFlat;
124
  sf.AddrFrame.Offset = ctx.Fp; sf.AddrFrame.Mode = AddrModeFlat;
125
  sf.AddrStack.Offset = ctx.Sp; sf.AddrStack.Mode = AddrModeFlat;
126
#else
127
  SymCleanup(hProcess);
128
  return; /* unsupported architecture */
129
#endif
130

131
  static const char hdr[] = "=== Stack Trace ===\r\n";
132
  DWORD w = 0;
133
  (void)WriteFile(hFile, hdr, (DWORD)(sizeof(hdr) - 1), &w, NULL);
134

135
  for (DWORD i = 0; i < 128; i++) {
136
    if (!StackWalk64(mach, hProcess, hThread, &sf, (PVOID)&ctx,
137
                     NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
138
      break;
139
    if (sf.AddrPC.Offset == 0) break;
140
    taosWinWriteOneFrame(hFile, hProcess, sf.AddrPC.Offset, i);
141
  }
142
  SymCleanup(hProcess);
143
}
144

145
LONG WINAPI FlCrashDump(PEXCEPTION_POINTERS ep) {
146
  // Only handle fatal exceptions, let others pass through for vectored handler
147
  DWORD code = ep->ExceptionRecord->ExceptionCode;
148

149
  // Skip non-fatal exceptions (like breakpoints during debugging)
150
  if (code == EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP) {
151
    return EXCEPTION_CONTINUE_SEARCH;
152
  }
153
  
154
  typedef BOOL(WINAPI * FxMiniDumpWriteDump)(IN HANDLE hProcess, IN DWORD ProcessId, IN HANDLE hFile,
155
                                             IN MINIDUMP_TYPE                           DumpType,
156
                                             IN CONST PMINIDUMP_EXCEPTION_INFORMATION   ExceptionParam,
157
                                             IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
158
                                             IN CONST PMINIDUMP_CALLBACK_INFORMATION    CallbackParam);
159

160
  // ── 1. load dbghelp ──────────────────────────────────────────────────────
161
  HMODULE dll = LoadLibraryA("dbghelp.dll");
162
  if (dll == NULL) return EXCEPTION_CONTINUE_SEARCH;
163
  FxMiniDumpWriteDump mdwd = (FxMiniDumpWriteDump)(GetProcAddress(dll, "MiniDumpWriteDump"));
164
  if (mdwd == NULL) {
165
    FreeLibrary(dll);
166
    return EXCEPTION_CONTINUE_SEARCH;
167
  }
168

169
  // ── 2. build timestamped file paths next to the running executable ───────
170
  //      Keeping dumps beside the exe makes them easy to find.
171
  SYSTEMTIME st;
172
  GetLocalTime(&st);
173

174
  TdWchar exePath[MAX_PATH];
175
  DWORD   exeLen = GetModuleFileNameW(NULL, exePath, MAX_PATH);
176
  /* strip the executable filename, keep the trailing backslash */
177
  while (exeLen > 0 && exePath[exeLen - 1] != L'\\') exeLen--;
178
  exePath[exeLen] = L'\0';  /* exePath is now the directory with trailing '\' */
179

180
  TdWchar dmpPath[MAX_PATH];
181
  TdWchar logPath[MAX_PATH];
182
  _snwprintf_s(dmpPath, MAX_PATH, _TRUNCATE,
183
               L"%staosd_%04d%02d%02d_%02d%02d%02d.dmp",
184
               exePath, st.wYear, st.wMonth, st.wDay,
185
               st.wHour, st.wMinute, st.wSecond);
186
  _snwprintf_s(logPath, MAX_PATH, _TRUNCATE,
187
               L"%staosd_%04d%02d%02d_%02d%02d%02d_stack.log",
188
               exePath, st.wYear, st.wMonth, st.wDay,
189
               st.wHour, st.wMinute, st.wSecond);
190

191
  // ── 3. write MiniDump with comprehensive type ─────────────────────────────
192
  HANDLE dmpFile = CreateFileW(dmpPath, GENERIC_WRITE, 0, NULL,
193
                               CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
194
  if (dmpFile != INVALID_HANDLE_VALUE) {
195
    MINIDUMP_EXCEPTION_INFORMATION mei;
196
    mei.ThreadId          = GetCurrentThreadId();
197
    mei.ExceptionPointers = ep;
198
    mei.ClientPointers    = FALSE;
199

200
    MINIDUMP_TYPE dumpType = (MINIDUMP_TYPE)(
201
        MiniDumpWithDataSegs                    |  /* global/static variables     */
202
        MiniDumpWithProcessThreadData           |  /* all thread stacks + locals  */
203
        MiniDumpWithHandleData                  |  /* open handles                */
204
        MiniDumpWithIndirectlyReferencedMemory  |  /* memory pointed-to by locals */
205
        MiniDumpWithThreadInfo                  |  /* thread times, start addr    */
206
        MiniDumpWithFullMemoryInfo);               /* all VMAs (flags/state)      */
207
    // Keep process/thread data and indirectly referenced memory enabled
208
    // to capture more complete diagnostic information in the minidump
209

210
    (*mdwd)(GetCurrentProcess(), GetCurrentProcessId(), dmpFile,
211
            dumpType, &mei, NULL, NULL);
212
    CloseHandle(dmpFile);
213
  }
214

215
  // ── 4. write stack trace text log (usable without PDB on developer side) ──
216
  HANDLE logFile = CreateFileW(logPath, GENERIC_WRITE, 0, NULL,
217
                               CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
218
  if (logFile != INVALID_HANDLE_VALUE) {
219
    char  hdr[512];
220
    DWORD w = 0;
221
    int   n = _snprintf_s(hdr, sizeof(hdr), _TRUNCATE,
222
                          "ExceptionCode:    0x%08lX\r\n"
223
                          "ExceptionAddress: 0x%016I64X\r\n"
224
                          "ThreadId:         %lu\r\n"
225
                          "\r\n",
226
                          ep->ExceptionRecord->ExceptionCode,
227
                          (DWORD64)(ULONG_PTR)ep->ExceptionRecord->ExceptionAddress,
228
                          (unsigned long)GetCurrentThreadId());
229
    if (n > 0) (void)WriteFile(logFile, hdr, (DWORD)n, &w, NULL);
230
    taosWinWriteStackTrace(logFile, ep);
231
    CloseHandle(logFile);
232
  }
233

234
  FreeLibrary(dll);
235

236
  // Return EXCEPTION_EXECUTE_HANDLER to terminate the process after dump
237
  return EXCEPTION_EXECUTE_HANDLER;
238
}
239

240
// Vectored Exception Handler - called BEFORE SEH, can catch heap corruption
241
static LONG WINAPI FlVectoredExceptionHandler(PEXCEPTION_POINTERS ep) {
242
  DWORD code = ep->ExceptionRecord->ExceptionCode;
243

244
  // Only handle critical exceptions that would terminate the process
245
  // These exceptions may bypass SetUnhandledExceptionFilter in some cases
246
  if (code == 0xC0000374 ||  // STATUS_HEAP_CORRUPTION
247
      code == 0xC0000409 ||  // STATUS_STACK_BUFFER_OVERRUN (fast-fail)
248
      code == 0xC00000FD) {  // STATUS_STACK_OVERFLOW
249
    // Call FlCrashDump directly for these special exceptions
250
    (void)FlCrashDump(ep);
251
  }
252

253
  // Let other exceptions pass to normal SEH handling
254
  return EXCEPTION_CONTINUE_SEARCH;
255
}
256

257
// Helper function to generate dump without exception context (for CRT handlers)
258
static void FlCrashDumpNoException(const char* reason) {
259
  typedef BOOL(WINAPI * FxMiniDumpWriteDump)(IN HANDLE hProcess, IN DWORD ProcessId, IN HANDLE hFile,
260
                                             IN MINIDUMP_TYPE                           DumpType,
261
                                             IN CONST PMINIDUMP_EXCEPTION_INFORMATION   ExceptionParam,
262
                                             IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
263
                                             IN CONST PMINIDUMP_CALLBACK_INFORMATION    CallbackParam);
264

265
  HMODULE dll = LoadLibraryA("dbghelp.dll");
266
  if (dll == NULL) return;
267
  FxMiniDumpWriteDump mdwd = (FxMiniDumpWriteDump)(GetProcAddress(dll, "MiniDumpWriteDump"));
268
  if (mdwd == NULL) {
269
    FreeLibrary(dll);
270
    return;
271
  }
272

273
  SYSTEMTIME st;
274
  GetLocalTime(&st);
275

276
  TdWchar exePath[MAX_PATH];
277
  DWORD   exeLen = GetModuleFileNameW(NULL, exePath, MAX_PATH);
278
  while (exeLen > 0 && exePath[exeLen - 1] != L'\\') exeLen--;
279
  exePath[exeLen] = L'\0';
280

281
  TdWchar dmpPath[MAX_PATH];
282
  _snwprintf_s(dmpPath, MAX_PATH, _TRUNCATE,
283
               L"%staosd_%04d%02d%02d_%02d%02d%02d.dmp",
284
               exePath, st.wYear, st.wMonth, st.wDay,
285
               st.wHour, st.wMinute, st.wSecond);
286

287
  HANDLE dmpFile = CreateFileW(dmpPath, GENERIC_WRITE, 0, NULL,
288
                               CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
289
  if (dmpFile != INVALID_HANDLE_VALUE) {
290
    MINIDUMP_TYPE dumpType = (MINIDUMP_TYPE)(
291
        MiniDumpWithDataSegs | MiniDumpWithProcessThreadData |
292
        MiniDumpWithHandleData | MiniDumpWithThreadInfo | MiniDumpWithFullMemoryInfo);
293
    (*mdwd)(GetCurrentProcess(), GetCurrentProcessId(), dmpFile,
294
            dumpType, NULL, NULL, NULL);  // No exception info
295
    CloseHandle(dmpFile);
296
  }
297

298
  // Write reason to log file
299
  TdWchar logPath[MAX_PATH];
300
  _snwprintf_s(logPath, MAX_PATH, _TRUNCATE,
301
               L"%staosd_%04d%02d%02d_%02d%02d%02d_stack.log",
302
               exePath, st.wYear, st.wMonth, st.wDay,
303
               st.wHour, st.wMinute, st.wSecond);
304
  HANDLE logFile = CreateFileW(logPath, GENERIC_WRITE, 0, NULL,
305
                               CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
306
  if (logFile != INVALID_HANDLE_VALUE) {
307
    char msg[512];
308
    int n = _snprintf_s(msg, sizeof(msg), _TRUNCATE,
309
                        "CRT/Runtime Error: %s\r\nThreadId: %lu\r\n",
310
                        reason, (unsigned long)GetCurrentThreadId());
311
    DWORD w = 0;
312
    if (n > 0) WriteFile(logFile, msg, (DWORD)n, &w, NULL);
313
    CloseHandle(logFile);
314
  }
315

316
  FreeLibrary(dll);
317
}
318

319
// CRT invalid parameter handler
320
static void FlInvalidParameterHandler(const TdWchar* expression, const TdWchar* function,
321
                                       const TdWchar* file, unsigned int line, size_t reserved) {
322
  (void)expression; (void)function; (void)file; (void)line; (void)reserved;
323
  FlCrashDumpNoException("Invalid parameter detected in CRT function");
324
  _exit(3);
325
}
326

327
// CRT pure virtual call handler
328
static void FlPureCallHandler(void) {
329
  FlCrashDumpNoException("Pure virtual function call");
330
  _exit(3);
331
}
332

333
// abort() handler - called when abort() is invoked
334
static void FlAbortHandler(int sig) {
335
  (void)sig;
336
  FlCrashDumpNoException("abort() called");
337
  _exit(3);
338
}
339

340
#elif defined(_TD_DARWIN_64)
341

342
#include <errno.h>
343
#include <libproc.h>
344
#include <sys/sysctl.h>
345
#include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
346
#include <CoreFoundation/CFString.h>
347
#include <stdio.h>
348

349
#else
350

351
#include <argp.h>
352
#ifndef TD_ASTRA
353
#include <linux/sysctl.h>
354
#include <sys/file.h>
355
#include <sys/resource.h>
356
#include <sys/statvfs.h>
357
#include <sys/syscall.h>
358
#endif
359
#include <sys/utsname.h>
360
#include <unistd.h>
361

362
static pid_t tsProcId;
363
static char  tsSysNetFile[] = "/proc/net/dev";
364
static char  tsSysCpuFile[] = "/proc/stat";
365
static char  tsCpuPeriodFile[] = "/sys/fs/cgroup/cpu/cpu.cfs_period_us";
366
static char  tsCpuQuotaFile[] = "/sys/fs/cgroup/cpu/cpu.cfs_quota_us";
367
static char  tsProcCpuFile[25] = {0};
368
static char  tsProcMemFile[25] = {0};
369
static char  tsProcIOFile[25] = {0};
370

371
static void taosGetProcIOnfos() {
8,507,630✔
372
  tsPageSizeKB = sysconf(_SC_PAGESIZE) / 1024;
8,507,630✔
373
  tsOpenMax = sysconf(_SC_OPEN_MAX);
8,507,630✔
374
  tsStreamMax = TMAX(sysconf(_SC_STREAM_MAX), 0);
8,507,630✔
375
#ifndef TD_ASTRA
376
  tsProcId = (pid_t)syscall(SYS_gettid);
8,507,630✔
377

378
  (void)snprintf(tsProcMemFile, sizeof(tsProcMemFile), "/proc/%d/status", tsProcId);
8,507,630✔
379
  (void)snprintf(tsProcCpuFile, sizeof(tsProcCpuFile), "/proc/%d/stat", tsProcId);
8,507,630✔
380
  (void)snprintf(tsProcIOFile, sizeof(tsProcIOFile), "/proc/%d/io", tsProcId);
8,507,630✔
381
#endif
382
}
8,507,630✔
383
#endif
384

385
static int32_t taosGetSysCpuInfo(SysCpuInfo *cpuInfo) {
8,507,888✔
386
  int32_t code = 0;
8,507,888✔
387
#ifdef WINDOWS
388
  FILETIME pre_idleTime = {0};
389
  FILETIME pre_kernelTime = {0};
390
  FILETIME pre_userTime = {0};
391
  FILETIME idleTime;
392
  FILETIME kernelTime;
393
  FILETIME userTime;
394
  bool     res = GetSystemTimes(&idleTime, &kernelTime, &userTime);
395
  if (res) {
396
    cpuInfo->idle = CompareFileTime(&pre_idleTime, &idleTime);
397
    cpuInfo->system = CompareFileTime(&pre_kernelTime, &kernelTime);
398
    cpuInfo->user = CompareFileTime(&pre_userTime, &userTime);
399
    cpuInfo->nice = 0;
400
  }
401
#elif defined(DARWIN) || defined(TD_ASTRA)
402
  cpuInfo->idle = 0;
403
  cpuInfo->system = 0;
404
  cpuInfo->user = 0;
405
  cpuInfo->nice = 0;
406
#else
407
  TdFilePtr pFile = taosOpenFile(tsSysCpuFile, TD_FILE_READ | TD_FILE_STREAM);
8,507,888✔
408
  if (pFile == NULL) {
8,507,888✔
409
    return terrno;
×
410
  }
411

412
  char    line[1024];
2,888,603✔
413
  ssize_t bytes = taosGetsFile(pFile, sizeof(line), line);
8,507,888✔
414
  if (bytes < 0) {
8,507,888✔
415
    TAOS_SKIP_ERROR(taosCloseFile(&pFile));
×
416
    return terrno;
×
417
  }
418

419
  char cpu[10] = {0};
8,507,888✔
420
  code = sscanf(line,
8,507,888✔
421
         "%s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64
422
         " %" PRIu64,
423
         cpu, &cpuInfo->user, &cpuInfo->nice, &cpuInfo->system, &cpuInfo->idle, &cpuInfo->wa, &cpuInfo->hi,
424
         &cpuInfo->si, &cpuInfo->st, &cpuInfo->guest, &cpuInfo->guest_nice);
425
  if (EOF == code) {
8,507,888✔
426
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
427
    TAOS_SKIP_ERROR(taosCloseFile(&pFile));
×
428
    return terrno;
×
429
  }
430
  
431
  TAOS_SKIP_ERROR(taosCloseFile(&pFile));
8,507,888✔
432
#endif
433

434
  return 0;
8,507,888✔
435
}
436

437
static int32_t taosGetProcCpuInfo(ProcCpuInfo *cpuInfo) {
8,507,888✔
438
  int32_t code = 0;
8,507,888✔
439

440
#ifdef WINDOWS
441
  FILETIME pre_krnlTm = {0};
442
  FILETIME pre_usrTm = {0};
443
  FILETIME creatTm, exitTm, krnlTm, usrTm;
444

445
  if (GetThreadTimes(GetCurrentThread(), &creatTm, &exitTm, &krnlTm, &usrTm)) {
446
    cpuInfo->stime = CompareFileTime(&pre_krnlTm, &krnlTm);
447
    cpuInfo->utime = CompareFileTime(&pre_usrTm, &usrTm);
448
    cpuInfo->cutime = 0;
449
    cpuInfo->cstime = 0;
450
  }
451
#elif defined(DARWIN) || defined(TD_ASTRA)
452
  cpuInfo->stime = 0;
453
  cpuInfo->utime = 0;
454
  cpuInfo->cutime = 0;
455
  cpuInfo->cstime = 0;
456
#else
457
  TdFilePtr pFile = taosOpenFile(tsProcCpuFile, TD_FILE_READ | TD_FILE_STREAM);
8,507,888✔
458
  if (pFile == NULL) {
8,507,888✔
459
    return terrno;
202✔
460
  }
461

462
  char    line[1024] = {0};
8,507,686✔
463
  ssize_t bytes = taosGetsFile(pFile, sizeof(line), line);
8,507,686✔
464
  if (bytes < 0) {
8,507,686✔
465
    TAOS_SKIP_ERROR(taosCloseFile(&pFile));
×
466
    return code;
×
467
  }
468

469
  for (int i = 0, blank = 0; line[i] != 0; ++i) {
458,024,265✔
470
    if (line[i] == ' ') blank++;
458,024,265✔
471
    if (blank == PROCESS_ITEM) {
458,024,265✔
472
      code = sscanf(line + i + 1, "%" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, &cpuInfo->utime, &cpuInfo->stime,
8,507,686✔
473
             &cpuInfo->cutime, &cpuInfo->cstime);
474
      if (EOF == code) {
8,507,686✔
475
        terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
476
        return terrno;
×
477
      }
478
             
479
      break;
8,507,686✔
480
    }
481
  }
482

483
  TAOS_SKIP_ERROR(taosCloseFile(&pFile));
8,507,686✔
484
#endif
485

486
  return 0;
8,507,686✔
487
}
488

489
bool taosCheckSystemIsLittleEnd() {
1,360,960✔
490
  union check {
491
    int16_t i;
492
    char    ch[2];
493
  } c;
494
  c.i = 1;
1,360,960✔
495
  return c.ch[0] == 1;
1,360,960✔
496
}
497

498
void taosGetSystemInfo() {
8,507,630✔
499
#ifdef WINDOWS
500
  TAOS_SKIP_ERROR(taosGetCpuCores(&tsNumOfCores, false));
501
  TAOS_SKIP_ERROR(taosGetTotalMemory(&tsTotalMemoryKB));
502
  TAOS_SKIP_ERROR(taosGetCpuUsage(NULL, NULL));
503
#elif defined(_TD_DARWIN_64)
504
  long physical_pages = sysconf(_SC_PHYS_PAGES);
505
  long page_size = sysconf(_SC_PAGESIZE);
506
  tsTotalMemoryKB = physical_pages * page_size / 1024;
507
  tsPageSizeKB = page_size / 1024;
508
  tsNumOfCores = sysconf(_SC_NPROCESSORS_ONLN);
509
#elif defined(TD_ASTRA)
510
  taosGetProcIOnfos();
511
  TAOS_SKIP_ERROR(taosGetCpuCores(&tsNumOfCores, false));
512
  TAOS_SKIP_ERROR(taosGetTotalMemory(&tsTotalMemoryKB));
513
  TAOS_SKIP_ERROR(taosGetCpuUsage(NULL, NULL));
514
#else
515
  taosGetProcIOnfos();
8,507,630✔
516
  TAOS_SKIP_ERROR(taosGetCpuCores(&tsNumOfCores, false)); 
8,507,630✔
517
  TAOS_SKIP_ERROR(taosGetTotalMemory(&tsTotalMemoryKB));
8,507,630✔
518
  TAOS_SKIP_ERROR(taosGetCpuUsage(NULL, NULL));
8,507,630✔
519
  TAOS_SKIP_ERROR(taosGetCpuInstructions(&tsSSE42Supported, &tsAVXSupported, &tsAVX2Supported, &tsFMASupported, &tsAVX512Supported));
8,507,630✔
520
#endif
521
}
8,507,630✔
522

523
int32_t taosGetEmail(char *email, int32_t maxLen) {
481,453✔
524
  OS_PARAM_CHECK(email);
481,453✔
525
#ifdef WINDOWS
526
  return 0;
527
#elif defined(_TD_DARWIN_64)
528
#ifdef CUS_PROMPT
529
  const char *filepath = "/usr/local/"CUS_PROMPT"/email";
530
#else
531
  const char *filepath = "/usr/local/taos/email";
532
#endif  // CUS_PROMPT
533

534
  TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ);
535
  if (pFile == NULL) return false;
536

537
  if (taosReadFile(pFile, (void *)email, maxLen) < 0) {
538
    taosCloseFile(&pFile);
539
    return terrno;
540
  }
541

542
  taosCloseFile(&pFile);
543
  return 0;
544
#else
545
#ifdef CUS_PROMPT
546
  const char *filepath = "/usr/local/"CUS_PROMPT"/email";
481,251✔
547
#else
548
  const char *filepath = "/usr/local/taos/email";
549
#endif  // CUS_PROMPT
550

551
  TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ);
481,251✔
552
  if (pFile == NULL) return terrno;
481,251✔
553

554
  if (taosReadFile(pFile, (void *)email, maxLen) < 0) {
×
555
    int32_t code = terrno;
×
556
    TAOS_SKIP_ERROR(taosCloseFile(&pFile));
×
557
    return code;
×
558
  }
559

560
  TAOS_SKIP_ERROR(taosCloseFile(&pFile));
×
561
  
562
  return 0;
×
563
#endif
564
}
565

566
#ifdef WINDOWS
567
bool getWinVersionReleaseName(char *releaseName, int32_t maxLen) {
568
  if(releaseName == NULL) return false;
569
  TCHAR          szFileName[MAX_PATH];
570
  DWORD             dwHandle;
571
  DWORD             dwLen;
572
  LPVOID            lpData;
573
  UINT              uLen;
574
  VS_FIXEDFILEINFO *pFileInfo;
575

576
  int ret = GetWindowsDirectory(szFileName, MAX_PATH);
577
  if (ret == 0) {
578
    return false;
579
  }
580
  wsprintf(szFileName, L"%s%s", szFileName, L"\\explorer.exe");
581
  dwLen = GetFileVersionInfoSize(szFileName, &dwHandle);
582
  if (dwLen == 0) {
583
    return false;
584
  }
585

586
  lpData = malloc(dwLen);
587
  if (lpData == NULL) return false;
588
  if (!GetFileVersionInfo(szFileName, dwHandle, dwLen, lpData)) {
589
    free(lpData);
590
    return false;
591
  }
592

593
  if (!VerQueryValue(lpData, L"\\", (LPVOID *)&pFileInfo, &uLen)) {
594
    free(lpData);
595
    return false;
596
  }
597

598
  snprintf(releaseName, maxLen, "Windows %d.%d", HIWORD(pFileInfo->dwProductVersionMS),
599
           LOWORD(pFileInfo->dwProductVersionMS));
600
  free(lpData);
601
  return true;
602
}
603
#endif
604

605
int32_t taosGetOsReleaseName(char *releaseName, char* sName, char* ver, int32_t maxLen) {
569✔
606
  OS_PARAM_CHECK(releaseName);
569✔
607
#ifdef WINDOWS
608
  if (!getWinVersionReleaseName(releaseName, maxLen)) {
609
    snprintf(releaseName, maxLen, "Windows");
610
  }
611
  if(sName) snprintf(sName, maxLen, "Windows");
612
  return 0;
613
#elif defined(_TD_DARWIN_64)
614
  char osversion[32];
615
  size_t osversion_len = sizeof(osversion) - 1;
616
  int osversion_name[] = { CTL_KERN, KERN_OSRELEASE };
617

618
  if(sName) snprintf(sName, maxLen, "macOS");
619
  if (sysctl(osversion_name, 2, osversion, &osversion_len, NULL, 0) == -1) {
620
    return TAOS_SYSTEM_ERROR(ERRNO);
621
  }
622

623
  uint32_t major, minor;
624
  if (sscanf(osversion, "%u.%u", &major, &minor) == EOF) {
625
      return TAOS_SYSTEM_ERROR(ERRNO);
626
  }
627
  if (major >= 20) {
628
      major -= 9; // macOS 11 and newer
629
      snprintf(releaseName, maxLen, "macOS %u.%u", major, minor);
630
  } else {
631
      major -= 4; // macOS 10.1.1 and newer
632
      snprintf(releaseName, maxLen, "macOS 10.%d.%d", major, minor);
633
  }
634

635
  return 0;
636
#elif defined(TD_ASTRA) // TD_ASTRA_TODO
637
  if(sName) snprintf(sName, maxLen, "Astra");
638
  snprintf(releaseName, maxLen, "Astra");
639
  return 0;
640
#else
641
  char    line[1024];
165✔
642
  char   *dest = NULL;
367✔
643
  size_t  size = 0;
367✔
644
  int32_t code = 0;
367✔
645
  int32_t cnt = 0;
367✔
646

647
  TdFilePtr pFile = taosOpenFile("/etc/os-release", TD_FILE_READ | TD_FILE_STREAM);
367✔
648
  if (pFile == NULL) {
367✔
649
    return terrno;
×
650
  }
651

652
  while ((size = taosGetsFile(pFile, sizeof(line), line)) > 0) {
3,670✔
653
    line[size - 1] = '\0';
3,303✔
654
    if (strncmp(line, "NAME", 4) == 0) {
3,303✔
655
      dest = sName;
367✔
656
    } else if (strncmp(line, "PRETTY_NAME", 11) == 0) {
2,936✔
657
      dest = releaseName;
367✔
658
      code = 0;
367✔
659
    } else if (strncmp(line, "VERSION_ID", 10) == 0) {
2,569✔
660
      dest = ver;
367✔
661
    } else {
662
      continue;
2,202✔
663
    }
664
    if (!dest) continue;
1,101✔
665
    const char *p = strchr(line, '=') + 1;
367✔
666
    if (*p == '"') {
367✔
667
      p++;
367✔
668
      line[size - 2] = 0;
367✔
669
    }
670
    tstrncpy(dest, p, maxLen);
367✔
671

672
    if (++cnt >= 3) break;
367✔
673
  }
674

675
  TAOS_SKIP_ERROR(taosCloseFile(&pFile));
367✔
676
  return code;
367✔
677
#endif
678
}
679

680
int32_t taosGetCpuInfo(char *cpuModel, int32_t maxLen, float *numOfCores) {
771✔
681
  OS_PARAM_CHECK(cpuModel);
771✔
682
  OS_PARAM_CHECK(numOfCores);
569✔
683
#ifdef WINDOWS
684
  char  value[100];
685
  DWORD bufferSize = sizeof(value);
686
  LSTATUS ret = RegGetValue(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", "ProcessorNameString",
687
              RRF_RT_ANY, NULL, (PVOID)&value, &bufferSize);
688
  if (ret != ERROR_SUCCESS) {
689
    return TAOS_SYSTEM_ERROR(ret);
690
  }
691
  tstrncpy(cpuModel, value, maxLen);
692
  SYSTEM_INFO si;
693
  memset(&si, 0, sizeof(SYSTEM_INFO));
694
  GetSystemInfo(&si);
695
  *numOfCores = si.dwNumberOfProcessors;
696
  return 0;
697
#elif defined(_TD_DARWIN_64)
698
  char    buf[16];
699
  int32_t done = 0;
700
  int32_t code = -1;
701

702
  TdCmdPtr pCmd = taosOpenCmd("sysctl -n machdep.cpu.brand_string");
703
  if (pCmd == NULL) return code;
704
  if (taosGetsCmd(pCmd, maxLen, cpuModel) > 0) {
705
    code = 0;
706
    done |= 1;
707
  }
708
  int endPos = strlen(cpuModel)-1;
709
  if (cpuModel[endPos] == '\n') {
710
    cpuModel[endPos] = '\0';
711
  }
712
  taosCloseCmd(&pCmd);
713

714
  pCmd = taosOpenCmd("sysctl -n machdep.cpu.core_count");
715
  if (pCmd == NULL) return code;
716
  memset(buf, 0, sizeof(buf));
717
  if (taosGetsCmd(pCmd, sizeof(buf) - 1, buf) > 0) {
718
    code = 0;
719
    done |= 2;
720
    *numOfCores = taosStr2Float(buf, NULL);
721
  }
722
  taosCloseCmd(&pCmd);
723

724
  return code;
725
#elif defined(TD_ASTRA) // TD_ASTRA_TODO
726
  tstrncpy(cpuModel, "ft_2000_4", maxLen);
727
  TAOS_SKIP_ERROR(taosGetCpuCores(numOfCores, false));
728
  return 0;
729
#else
730
  char    line[1024] = {0};
367✔
731
  size_t  size = 0;
367✔
732
  int32_t done = 0;
367✔
733
  int32_t code = 0;
367✔
734
  float   coreCount = 0;
367✔
735

736
  TdFilePtr pFile = taosOpenFile("/proc/cpuinfo", TD_FILE_READ | TD_FILE_STREAM);
367✔
737
  if (pFile == NULL) return terrno;
367✔
738

739
  while (done != 3 && (size = taosGetsFile(pFile, sizeof(line), line)) > 0) {
5,138✔
740
    line[size - 1] = '\0';
4,771✔
741
    if (((done & 1) == 0) && strncmp(line, "model name", 10) == 0) {
4,771✔
742
      const char *v = strchr(line, ':') + 2;
367✔
743
      tstrncpy(cpuModel, v, maxLen);
367✔
744
      code = 0;
367✔
745
      done |= 1;
367✔
746
    } else if (((done & 2) == 0) && strncmp(line, "cpu cores", 9) == 0) {
4,404✔
747
      const char *v = strchr(line, ':') + 2;
367✔
748
      *numOfCores = taosStr2Float(v, NULL);
367✔
749
      done |= 2;
367✔
750
    }
751
    if (strncmp(line, "processor", 9) == 0) coreCount += 1;
4,771✔
752
  }
753

754
  TAOS_SKIP_ERROR(taosCloseFile(&pFile));
367✔
755

756
  if (code != 0 && (done & 1) == 0) {
367✔
757
    TdFilePtr pFile1 = taosOpenFile("/proc/device-tree/model", TD_FILE_READ | TD_FILE_STREAM);
×
758
    if (pFile1 != NULL) {
×
759
      ssize_t bytes = taosGetsFile(pFile1, maxLen, cpuModel);
×
760
      TAOS_SKIP_ERROR(taosCloseFile(&pFile));
×
761
      if (bytes > 0) {
×
762
        code = 0;
×
763
        done |= 1;
×
764
      }
765
    }
766
  }
767

768
  if (code != 0 && (done & 1) == 0) {
367✔
769
    TdCmdPtr pCmd = taosOpenCmd("uname -a");
×
770
    if (pCmd == NULL) {
×
771
      return terrno;
×
772
    }
773
    if (taosGetsCmd(pCmd, maxLen, cpuModel) > 0) {
×
774
      code = 0;
×
775
      done |= 1;
×
776
    }
777
    taosCloseCmd(&pCmd);
×
778
  }
779

780
  if ((done & 2) == 0) {
367✔
781
    *numOfCores = coreCount;
×
782
    done |= 2;
×
783
  }
784

785
  return code;
367✔
786
#endif
787
}
788

789
// Returns the container's CPU quota if successful, otherwise returns the physical CPU cores
790
static int32_t taosCntrGetCpuCores(float *numOfCores) {
9,196,862✔
791
#ifdef WINDOWS
792
  return TSDB_CODE_UNSUPPORT_OS;
793
#elif defined(_TD_DARWIN_64) || defined(TD_ASTRA)
794
  return TSDB_CODE_UNSUPPORT_OS;
795
#else
796
  TdFilePtr pFile = NULL;
9,196,862✔
797
  if (!(pFile = taosOpenFile(tsCpuQuotaFile, TD_FILE_READ | TD_FILE_STREAM))) {
9,196,862✔
798
    goto _sys;
×
799
  }
800
  char qline[32] = {0};
9,196,862✔
801
  if (taosGetsFile(pFile, sizeof(qline), qline) <= 0) {
9,196,862✔
802
    TAOS_SKIP_ERROR(taosCloseFile(&pFile));
×
803
    goto _sys;
×
804
  }
805
  
806
  TAOS_SKIP_ERROR(taosCloseFile(&pFile));
9,196,862✔
807
  float quota = taosStr2Float(qline, NULL);
9,196,862✔
808
  if (quota < 0) {
9,196,862✔
809
    goto _sys;
9,196,862✔
810
  }
811

812
  if (!(pFile = taosOpenFile(tsCpuPeriodFile, TD_FILE_READ | TD_FILE_STREAM))) {
×
813
    goto _sys;
×
814
  }
815
  
816
  char pline[32] = {0};
×
817
  if (taosGetsFile(pFile, sizeof(pline), pline) <= 0) {
×
818
    TAOS_SKIP_ERROR(taosCloseFile(&pFile));
×
819
    goto _sys;
×
820
  }
821
  
822
  TAOS_SKIP_ERROR(taosCloseFile(&pFile));
×
823

824
  float period = taosStr2Float(pline, NULL);
×
825
  float quotaCores = quota / period;
×
826
  float sysCores = sysconf(_SC_NPROCESSORS_ONLN);
×
827
  if (quotaCores < sysCores && quotaCores > 0) {
×
828
    *numOfCores = quotaCores;
×
829
  } else {
830
    *numOfCores = sysCores;
×
831
  }
832
  if(*numOfCores <= 0) {
×
833
    return TAOS_SYSTEM_ERROR(ERRNO);
×
834
  }
835
  goto _end;
×
836
  
837
_sys:
9,196,862✔
838
  *numOfCores = sysconf(_SC_NPROCESSORS_ONLN);
9,196,862✔
839
  if(*numOfCores <= 0) {
9,196,862✔
840
    return TAOS_SYSTEM_ERROR(ERRNO);
×
841
  }
842
  
843
_end:
9,196,862✔
844
  return 0;
9,196,862✔
845
  
846
#endif
847
}
848

849
int32_t taosGetCpuCores(float *numOfCores, bool physical) {
10,225,450✔
850
  OS_PARAM_CHECK(numOfCores);
10,225,450✔
851
#ifdef WINDOWS
852
  SYSTEM_INFO info;
853
  GetSystemInfo(&info);
854
  *numOfCores = info.dwNumberOfProcessors;
855
  return  0;
856
#elif defined(_TD_DARWIN_64)
857
  *numOfCores = sysconf(_SC_NPROCESSORS_ONLN);
858
  if(*numOfCores <= 0) {
859
    return TAOS_SYSTEM_ERROR(ERRNO);
860
  }
861
  return 0;
862
#elif defined(TD_ASTRA) // TD_ASTRA_TODO
863
  *numOfCores = 4;
864
  return 0;
865
#else
866
  if (physical) {
10,225,248✔
867
    *numOfCores = sysconf(_SC_NPROCESSORS_ONLN);
1,028,386✔
868
    if(*numOfCores <= 0) {
1,028,386✔
869
      return TAOS_SYSTEM_ERROR(ERRNO);
×
870
    }
871
  } else {
872
    int code= taosCntrGetCpuCores(numOfCores);
9,196,862✔
873
    if(code != 0) {
9,196,862✔
874
      return code;
×
875
    }
876
  }
877
  return 0;
10,225,248✔
878
#endif
879
}
880

881
int32_t taosGetCpuUsage(double *cpu_system, double *cpu_engine) {
8,507,888✔
882
  static int64_t lastSysUsed = -1;
883
  static int64_t lastSysTotal = -1;
884
  static int64_t lastProcTotal = -1;
885
  static int64_t curSysUsed = 0;
886
  static int64_t curSysTotal = 0;
887
  static int64_t curProcTotal = 0;
888

889
  if (cpu_system != NULL) *cpu_system = 0;
8,507,888✔
890
  if (cpu_engine != NULL) *cpu_engine = 0;
8,507,888✔
891

892
  SysCpuInfo  sysCpu = {0};
8,507,888✔
893
  ProcCpuInfo procCpu = {0};
8,507,888✔
894
  if (taosGetSysCpuInfo(&sysCpu) == 0 && taosGetProcCpuInfo(&procCpu) == 0) {
8,507,888✔
895
    curSysUsed = sysCpu.user + sysCpu.nice + sysCpu.system + sysCpu.wa + sysCpu.hi + sysCpu.si + sysCpu.st +
8,507,686✔
896
                 sysCpu.guest + sysCpu.guest_nice;
8,507,686✔
897
    curSysTotal = curSysUsed + sysCpu.idle;
8,507,686✔
898
    curProcTotal = procCpu.utime + procCpu.stime + procCpu.cutime + procCpu.cstime;
8,507,686✔
899

900
    if(lastSysUsed >= 0 && lastSysTotal >=0 && lastProcTotal >=0){
8,507,686✔
901
      if (curSysTotal - lastSysTotal > 0 && curSysUsed >= lastSysUsed && curProcTotal >= lastProcTotal) {
5,594,440✔
902
        if (cpu_system != NULL) {
1,545,380✔
903
          *cpu_system = (curSysUsed - lastSysUsed) / (double)(curSysTotal - lastSysTotal) * 100;
56✔
904
        }
905
        if (cpu_engine != NULL) {
1,545,380✔
906
          *cpu_engine = (curProcTotal - lastProcTotal) / (double)(curSysTotal - lastSysTotal) * 100;
56✔
907
        }
908
      }
909
    }
910

911
    lastSysUsed = curSysUsed;
8,507,686✔
912
    lastSysTotal = curSysTotal;
8,507,686✔
913
    lastProcTotal = curProcTotal;
8,507,686✔
914
  }
915
  return 0;
8,507,888✔
916
}
917

918
#define __cpuid_fix(level, a, b, c, d) \
919
              __asm__("xor %%ecx, %%ecx\n" \
920
                      "cpuid\n" \
921
                      : "=a"(a), "=b"(b), "=c"(c), "=d"(d) \
922
                      : "0"(level))
923

924
// todo add for windows and mac
925
int32_t taosGetCpuInstructions(char* sse42, char* avx, char* avx2, char* fma, char* avx512) {
8,507,630✔
926
#ifdef WINDOWS
927
#elif defined(_TD_DARWIN_64)
928
#else
929

930
#ifdef _TD_X86_
931
  // Since the compiler is not support avx/avx2 instructions, the global variables always need to be
932
  // set to be false
933
  uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
8,507,630✔
934

935
  int32_t ret = __get_cpuid(1, &eax, &ebx, &ecx, &edx);
8,507,630✔
936
  if (ret == 0) {
8,507,630✔
937
    return -1;  // failed to get the cpuid info
×
938
  }
939

940
  *sse42 = (char) ((ecx & bit_SSE4_2) == bit_SSE4_2);
8,507,630✔
941
  *avx   = (char) ((ecx & bit_AVX) == bit_AVX);
8,507,630✔
942
  *fma   = (char) ((ecx & bit_FMA) == bit_FMA);
8,507,630✔
943

944
  // work around a bug in GCC.
945
  // Ref to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77756
946
  __cpuid_fix(7u, eax, ebx, ecx, edx);
8,507,630✔
947
  *avx2 = (char) ((ebx & bit_AVX2) == bit_AVX2);
8,507,630✔
948
  *avx512 = (char)((ebx & bit_AVX512F) == bit_AVX512F);
8,507,630✔
949
#endif   // _TD_X86_
950
#endif
951

952
  return 0;
8,507,630✔
953
}
954

955
int32_t taosGetTotalMemory(int64_t *totalKB) {
9,180,304✔
956
  OS_PARAM_CHECK(totalKB);
9,180,304✔
957
#ifdef WINDOWS
958
  MEMORYSTATUSEX memsStat;
959
  memsStat.dwLength = sizeof(memsStat);
960
  if (!GlobalMemoryStatusEx(&memsStat)) {
961
    return TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
962
  }
963

964
  *totalKB = memsStat.ullTotalPhys / 1024;
965
  return 0;
966
#elif defined(_TD_DARWIN_64)
967
  return 0;
968
#elif defined(TD_ASTRA) // TD_ASTRA_TODO
969
  *totalKB = (int64_t)256 * 1024;
970
  return 0;
971
#else
972
  *totalKB = (int64_t)(sysconf(_SC_PHYS_PAGES) * tsPageSizeKB);
9,180,102✔
973
  if(*totalKB <= 0) {
9,180,102✔
974
    return TAOS_SYSTEM_ERROR(ERRNO);
×
975
  }
976
  return 0;
9,180,102✔
977
#endif
978
}
979

980
int32_t taosGetProcMemory(int64_t *usedKB) {
460✔
981
  OS_PARAM_CHECK(usedKB);
460✔
982
#ifdef WINDOWS
983
  unsigned bytes_used = 0;
984

985
#if defined(_WIN64) && defined(_MSC_VER)
986
  PROCESS_MEMORY_COUNTERS pmc;
987
  HANDLE                  cur_proc = GetCurrentProcess();
988

989
  if (GetProcessMemoryInfo(cur_proc, &pmc, sizeof(pmc))) {
990
    bytes_used = (unsigned)(pmc.WorkingSetSize + pmc.PagefileUsage);
991
  }
992
#endif
993

994
  *usedKB = bytes_used / 1024;
995
  return 0;
996
#elif defined(_TD_DARWIN_64) || defined(TD_ASTRA)
997
  *usedKB = 0;
998
  return 0;
999
#else
1000
  TdFilePtr pFile = taosOpenFile(tsProcMemFile, TD_FILE_READ | TD_FILE_STREAM);
258✔
1001
  if (pFile == NULL) {
258✔
1002
    // printf("open file:%s failed", tsProcMemFile);
1003
    return terrno;
202✔
1004
  }
1005

1006
  ssize_t bytes = 0;
56✔
1007
  char    line[1024] = {0};
56✔
1008
  while (!taosEOFFile(pFile)) {
1,232✔
1009
    bytes = taosGetsFile(pFile, sizeof(line), line);
1,232✔
1010
    if (bytes <= 0) {
1,232✔
1011
      break;
×
1012
    }
1013
    if (strstr(line, "VmRSS:") != NULL) {
1,232✔
1014
      break;
56✔
1015
    }
1016
  }
1017

1018
  char tmp[10];
56✔
1019
  (void)sscanf(line, "%s %" PRId64, tmp, usedKB);
56✔
1020

1021
  TAOS_SKIP_ERROR(taosCloseFile(&pFile));
56✔
1022
  
1023
  return 0;
56✔
1024
#endif
1025
}
1026

1027
int32_t taosGetSysAvailMemory(int64_t *availSize) {
2,147,483,647✔
1028
#ifdef WINDOWS
1029
  MEMORYSTATUSEX memsStat;
1030
  memsStat.dwLength = sizeof(memsStat);
1031
  if (!GlobalMemoryStatusEx(&memsStat)) {
1032
    return -1;
1033
  }
1034

1035
  int64_t nMemFree = memsStat.ullAvailPhys;
1036
  int64_t nMemTotal = memsStat.ullTotalPhys;
1037

1038
  *availSize = nMemTotal - nMemFree;
1039
  return 0;
1040
#elif defined(_TD_DARWIN_64) || defined(TD_ASTRA)
1041
  *availSize = 0;
1042
  return 0;
1043
#else
1044
  TdFilePtr pFile = taosOpenFile("/proc/meminfo", TD_FILE_READ | TD_FILE_STREAM);
2,147,483,647✔
1045
  if (pFile == NULL) {
2,147,483,647✔
1046
    return terrno;
×
1047
  }
1048

1049
  ssize_t bytes = 0;
2,147,483,647✔
1050
  char    line[128] = {0};
2,147,483,647✔
1051
  int32_t expectedSize = 13; //"MemAvailable:"
2,147,483,647✔
1052
  while (!taosEOFFile(pFile)) {
2,147,483,647✔
1053
    bytes = taosGetsFile(pFile, sizeof(line), line);
2,147,483,647✔
1054
    if (bytes < 0) {
2,147,483,647✔
1055
      break;
×
1056
    }
1057
    if (line[0] != 'M' && line[3] != 'A') {
2,147,483,647✔
1058
      line[0] = 0;
×
1059
      continue;
×
1060
    }
1061
    if (0 == strncmp(line, "MemAvailable:", expectedSize)) {
2,147,483,647✔
1062
      break;
2,147,483,647✔
1063
    }
1064
  }
1065

1066
  if (0 == line[0]) {
2,147,483,647✔
1067
    return TSDB_CODE_UNSUPPORT_OS;
×
1068
  }
1069
  
1070
  char tmp[32];
2,147,483,647✔
1071
  (void)sscanf(line, "%s %" PRId64, tmp, availSize);
2,147,483,647✔
1072

1073
  *availSize *= 1024;
2,147,483,647✔
1074
  
1075
  (void)taosCloseFile(&pFile);
2,147,483,647✔
1076
  return 0;
2,147,483,647✔
1077
#endif
1078
}
1079

1080
static void taosGetMemValue(char* line, char* key, int64_t* value){
3,870✔
1081
  if(value == NULL) return;
3,870✔
1082
  *value = 0;
3,870✔
1083
  if(line == NULL || line[0] == '\0') return;
3,870✔
1084

1085
  char *colon_pos = strchr(line, ':');
3,870✔
1086
  if (colon_pos != NULL) {
3,870✔
1087
    *colon_pos = '\0';
3,870✔
1088
    if(sscanf(line, "%s", key) != 1){
3,870✔
1089
      key[0] = '\0';
×
1090
    }
1091
    if (sscanf(colon_pos + 1, "%" PRId64, value) != 1) {
3,870✔
1092
      *value = 0;
×
1093
    }
1094
  }
1095
}
1096

1097
int32_t taosGetSysMemory(int64_t *usedKB, int64_t *freeKB, int64_t *cacheBufferKB) {
460✔
1098
  OS_PARAM_CHECK(usedKB);
460✔
1099
  OS_PARAM_CHECK(freeKB);
258✔
1100
  OS_PARAM_CHECK(cacheBufferKB);
258✔
1101
#ifdef WINDOWS
1102
  MEMORYSTATUSEX memsStat;
1103
  memsStat.dwLength = sizeof(memsStat);
1104
  if (!GlobalMemoryStatusEx(&memsStat)) {
1105
    return TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1106
  }
1107

1108
  int64_t nMemFree = memsStat.ullAvailPhys / 1024;
1109
  int64_t nMemTotal = memsStat.ullTotalPhys / 1024.0;
1110

1111
  *usedKB = nMemTotal - nMemFree;
1112
  *freeKB = nMemFree;
1113
  *cacheBufferKB = 0;
1114
  return 0;
1115
#elif defined(_TD_DARWIN_64) || defined(TD_ASTRA) // TD_ASTRA_TODO
1116
  *usedKB = 0;
1117
  *freeKB = 0;
1118
  *cacheBufferKB = 0;
1119
  return 0;
1120
#else
1121
  /*
1122
  *usedKB = sysconf(_SC_AVPHYS_PAGES) * tsPageSizeKB;
1123
  if(*usedKB <= 0) {
1124
    return TAOS_SYSTEM_ERROR(ERRNO);
1125
  }
1126
  */
1127
  TdFilePtr pFile = taosOpenFile("/proc/meminfo", TD_FILE_READ | TD_FILE_STREAM);
258✔
1128
  if (pFile == NULL) {
258✔
1129
    return terrno;
×
1130
  }
1131

1132
  char    line[1024] = {0};
258✔
1133
  char    key[1024] = {0};
258✔
1134
  int64_t  value = 0;
258✔
1135
  ssize_t bytes = 0;
258✔
1136

1137
  //MemTotal
1138
  int64_t total = 0;
258✔
1139

1140
  //MemFree
1141
  int64_t mfree = 0;
258✔
1142

1143
  //MemAvailable
1144
  int64_t available = 0;
258✔
1145

1146
  //Buffers
1147
  int64_t buffer = 0;
258✔
1148

1149
  //Cached
1150
  int64_t cached = 0;
258✔
1151

1152
  //SwapCached ,Active, Inactive, Active(anon), Inactive(anon), Active(file), Inactive(file), Unevictable, Mlocked, SwapTotal
1153

1154
  //SwapFree
1155
  int64_t swapFree = 0;
258✔
1156

1157
  //Dirty, Writeback, AnonPages, Mapped, Shmem, KReclaimable, Slab
1158

1159
  //SReclaimable
1160
  int64_t sReclaimable = 0;
258✔
1161

1162
  for(int32_t i=0; i < 30; i++){
7,998✔
1163
    bytes = taosGetsFile(pFile, sizeof(line), line);
7,740✔
1164
    if (bytes < 0) {
7,740✔
1165
      TAOS_SKIP_ERROR(taosCloseFile(&pFile));
×
1166
      return terrno;
×
1167
    }
1168
    if (line[0] != 'M' && line[0] != 'B' && line[0] != 'C' && line[0] != 'S') {
7,740✔
1169
      line[0] = 0;
3,870✔
1170
      continue;
3,870✔
1171
    }
1172
    taosGetMemValue(line, key, &value);
3,870✔
1173
    if(strncmp(key, "MemTotal", 1024) == 0) {total = value; continue;}
3,870✔
1174
    if(strncmp(key, "MemFree", 1024) == 0) {mfree = value; continue;}
3,612✔
1175
    if(strncmp(key, "MemAvailable", 1024) == 0) {available = value; continue;}
3,354✔
1176
    if(strncmp(key, "Buffers", 1024) == 0) {buffer = value; continue;}
3,096✔
1177
    if(strncmp(key, "Cached", 1024) == 0) {cached = value; continue;}
2,838✔
1178
    if(strncmp(key, "SwapFree", 1024) == 0) {swapFree = value; continue;}
2,580✔
1179
    if(strncmp(key, "SReclaimable", 1024) == 0) {sReclaimable = value; continue;}
2,322✔
1180
  }
1181

1182
  //free   Unused memory (MemFree and SwapFree in /proc/meminfo)
1183
  *freeKB = mfree;
258✔
1184
  //buffers Memory used by kernel buffers (Buffers in /proc/meminfo)
1185
  //cache  Memory used by the page cache and slabs (Cached and SReclaimable in /proc/meminfo)
1186
  *cacheBufferKB = buffer + cached + sReclaimable;
258✔
1187
  *usedKB = total - *freeKB - *cacheBufferKB;
258✔
1188
  
1189
  TAOS_SKIP_ERROR(taosCloseFile(&pFile));
258✔
1190
  return 0;
258✔
1191
#endif
1192
}
1193

1194
int32_t taosGetDiskSize(char *dataDir, SDiskSize *diskSize) {
678,238,981✔
1195
  OS_PARAM_CHECK(dataDir);
678,238,981✔
1196
  OS_PARAM_CHECK(diskSize);
678,238,779✔
1197
#if defined(WINDOWS)
1198
  unsigned _int64 i64FreeBytesToCaller;
1199
  unsigned _int64 i64TotalBytes;
1200
  unsigned _int64 i64FreeBytes;
1201

1202
  BOOL fResult = GetDiskFreeSpaceExA(dataDir, (PULARGE_INTEGER)&i64FreeBytesToCaller, (PULARGE_INTEGER)&i64TotalBytes,
1203
                                     (PULARGE_INTEGER)&i64FreeBytes);
1204
  if (fResult) {
1205
    diskSize->total = (int64_t)(i64TotalBytes);
1206
    diskSize->avail = (int64_t)(i64FreeBytesToCaller);
1207
    diskSize->used = (int64_t)(i64TotalBytes - i64FreeBytes);
1208
    return 0;
1209
  } else {
1210
    // printf("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(ERRNO));
1211
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1212
    return terrno;
1213
  }
1214
#elif defined(_TD_DARWIN_64)
1215
  struct statvfs info;
1216
  if (statvfs(dataDir, &info)) {
1217
    // printf("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(ERRNO));
1218
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
1219
    return terrno;
1220
  } else {
1221
    diskSize->total = info.f_blocks * info.f_frsize;
1222
    diskSize->avail = info.f_bavail * info.f_frsize;
1223
    diskSize->used = (info.f_blocks - info.f_bfree) * info.f_frsize;
1224
    return 0;
1225
  }
1226
#elif defined(TD_ASTRA)  // TD_ASTRA_TODO
1227
  //  if (-1 == ioctl(dataDir, FIOFSTATVFSGETBYNAME, &info)) { // TODO:try to check whether the API is available
1228
  //     terrno = TAOS_SYSTEM_ERROR(ERRNO);
1229
  //     return terrno;
1230
  diskSize->total = 100LL * 1024 * 1024 * 1024;
1231
  diskSize->avail = 50LL * 1024 * 1024 * 1024;
1232
  diskSize->used = 50LL * 1024 * 1024 * 1024;
1233
  //  } else {
1234
  //    diskSize->total = info.f_blocks * info.f_frsize;
1235
  //    diskSize->avail = info.f_bavail * info.f_frsize;
1236
  //    diskSize->used = diskSize->total - diskSize->avail;
1237
  //  }
1238
  return 0;
1239
#else
1240
  struct statvfs info;
673,884,899✔
1241
  if (-1 == statvfs(dataDir, &info)) {
678,238,577✔
1242
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1243
    return terrno;
×
1244
  } else {
1245
    diskSize->total = info.f_blocks * info.f_frsize;
678,239,258✔
1246
    diskSize->avail = info.f_bavail * info.f_frsize;
678,239,258✔
1247
    diskSize->used = diskSize->total - diskSize->avail;
678,239,258✔
1248
    
1249
    return 0;
678,239,258✔
1250
  }
1251
#endif
1252
}
1253

1254
int32_t taosGetProcIO(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int64_t *write_bytes) {
1,066✔
1255
  OS_PARAM_CHECK(rchars);
1,066✔
1256
  OS_PARAM_CHECK(wchars);
864✔
1257
  OS_PARAM_CHECK(read_bytes);
662✔
1258
  OS_PARAM_CHECK(write_bytes);
460✔
1259
#ifdef WINDOWS
1260
  IO_COUNTERS io_counter;
1261
  if (GetProcessIoCounters(GetCurrentProcess(), &io_counter)) {
1262
    *rchars = io_counter.ReadTransferCount;
1263
    *wchars = io_counter.WriteTransferCount;
1264
    *read_bytes = 0;
1265
    *write_bytes = 0;
1266
    return 0;
1267
  }
1268
  return TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1269
#elif defined(_TD_DARWIN_64) || defined(TD_ASTRA)
1270
  *rchars = 0;
1271
  *wchars = 0;
1272
  *read_bytes = 0;
1273
  *write_bytes = 0;
1274
  return 0;
1275
#else
1276
  TdFilePtr pFile = taosOpenFile(tsProcIOFile, TD_FILE_READ | TD_FILE_STREAM);
258✔
1277
  if (pFile == NULL) {
258✔
1278
    return terrno;
202✔
1279
  }
1280

1281
  ssize_t bytes = 0;
56✔
1282
  char    line[1024] = {0};
56✔
1283
  char    tmp[24];
56✔
1284
  int     readIndex = 0;
56✔
1285

1286
  while (!taosEOFFile(pFile)) {
336✔
1287
    bytes = taosGetsFile(pFile, sizeof(line), line);
336✔
1288
    if (bytes < 10) {
336✔
1289
      break;
×
1290
    }
1291
    if (strstr(line, "rchar:") != NULL) {
336✔
1292
      (void)sscanf(line, "%s %" PRId64, tmp, rchars);
56✔
1293
      readIndex++;
56✔
1294
    } else if (strstr(line, "wchar:") != NULL) {
280✔
1295
      (void)sscanf(line, "%s %" PRId64, tmp, wchars);
56✔
1296
      readIndex++;
56✔
1297
    } else if (strstr(line, "read_bytes:") != NULL) {  // read_bytes
224✔
1298
      (void)sscanf(line, "%s %" PRId64, tmp, read_bytes);
56✔
1299
      readIndex++;
56✔
1300
    } else if (strstr(line, "write_bytes:") != NULL) {  // write_bytes
168✔
1301
      (void)sscanf(line, "%s %" PRId64, tmp, write_bytes);
56✔
1302
      readIndex++;
56✔
1303
    } else {
1304
    }
1305

1306
    if (readIndex >= 4) break;
336✔
1307
  }
1308

1309
  TAOS_SKIP_ERROR(taosCloseFile(&pFile));
56✔
1310

1311
  if (readIndex < 4) {
56✔
1312
    return -1;
×
1313
  }
1314

1315
  return 0;
56✔
1316
#endif
1317
}
1318

1319
int32_t taosGetProcIODelta(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int64_t *write_bytes) {
1,268✔
1320
  if (rchars == NULL || wchars == NULL || read_bytes == NULL || write_bytes == NULL) {
1,268✔
1321
    return TSDB_CODE_INVALID_PARA;
1,010✔
1322
  }
1323
  static int64_t last_rchars = -1;
1324
  static int64_t last_wchars = -1;
1325
  static int64_t last_read_bytes = -1;
1326
  static int64_t last_write_bytes = -1;
1327
  static int64_t cur_rchars = 0;
1328
  static int64_t cur_wchars = 0;
1329
  static int64_t cur_read_bytes = 0;
1330
  static int64_t cur_write_bytes = 0;
1331
  int32_t code = taosGetProcIO(&cur_rchars, &cur_wchars, &cur_read_bytes, &cur_write_bytes);
258✔
1332
  if (code == 0) {
258✔
1333
    if(last_rchars >=0 && last_wchars >=0 && last_read_bytes >=0 && last_write_bytes >= 0){
56✔
1334
      *rchars = cur_rchars - last_rchars;
×
1335
      *wchars = cur_wchars - last_wchars;
×
1336
      *read_bytes = cur_read_bytes - last_read_bytes;
×
1337
      *write_bytes = cur_write_bytes - last_write_bytes;
×
1338
    }
1339
    else{
1340
      *rchars = 0;
56✔
1341
      *wchars = 0;
56✔
1342
      *read_bytes = 0;
56✔
1343
      *write_bytes = 0;
56✔
1344
    }
1345
    last_rchars = cur_rchars;
56✔
1346
    last_wchars = cur_wchars;
56✔
1347
    last_read_bytes = cur_read_bytes;
56✔
1348
    last_write_bytes = cur_write_bytes;
56✔
1349
  } else {
1350
    return code;
202✔
1351
  }
1352
  return 0;
56✔
1353
}
1354
void taosSetDefaultProcIODelta(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int64_t *write_bytes) {
×
1355
  if(rchars) *rchars = 0;
×
1356
  if(wchars) *wchars = 0;
×
1357
  if(read_bytes) *read_bytes = 0;
×
1358
  if(write_bytes) *write_bytes = 0;
×
1359
}
×
1360

1361
int32_t taosGetCardInfo(int64_t *receive_bytes, int64_t *transmit_bytes) {
662✔
1362
  OS_PARAM_CHECK(receive_bytes);
662✔
1363
  OS_PARAM_CHECK(transmit_bytes);
460✔
1364
  *receive_bytes = 0;
258✔
1365
  *transmit_bytes = 0;
258✔
1366

1367
#ifdef WINDOWS
1368
  return 0;
1369
#elif defined(_TD_DARWIN_64) || defined(TD_ASTRA)
1370
  return 0;
1371
#else
1372
  TdFilePtr pFile = taosOpenFile(tsSysNetFile, TD_FILE_READ | TD_FILE_STREAM);
258✔
1373
  if (pFile == NULL) {
258✔
1374
    return terrno;
×
1375
  }
1376

1377
  ssize_t _bytes = 0;
258✔
1378
  char    line[1024];
56✔
1379

1380
  while (!taosEOFFile(pFile)) {
1,290✔
1381
    int64_t o_rbytes = 0;
1,290✔
1382
    int64_t rpackts = 0;
1,290✔
1383
    int64_t o_tbytes = 0;
1,290✔
1384
    int64_t tpackets = 0;
1,290✔
1385
    int64_t nouse1 = 0;
1,290✔
1386
    int64_t nouse2 = 0;
1,290✔
1387
    int64_t nouse3 = 0;
1,290✔
1388
    int64_t nouse4 = 0;
1,290✔
1389
    int64_t nouse5 = 0;
1,290✔
1390
    int64_t nouse6 = 0;
1,290✔
1391
    char    nouse0[200] = {0};
1,290✔
1392

1393
    _bytes = taosGetsFile(pFile, sizeof(line), line);
1,290✔
1394
    if (_bytes <= 0) {
1,290✔
1395
      break;
258✔
1396
    }
1397

1398
    line[_bytes - 1] = 0;
1,032✔
1399

1400
    if (strstr(line, "lo:") != NULL) {
1,032✔
1401
      continue;
258✔
1402
    }
1403

1404
    (void)sscanf(line,
774✔
1405
           "%s %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64
1406
           " %" PRId64,
1407
           nouse0, &o_rbytes, &rpackts, &nouse1, &nouse2, &nouse3, &nouse4, &nouse5, &nouse6, &o_tbytes, &tpackets);
1408
    *receive_bytes += o_rbytes;
774✔
1409
    *transmit_bytes += o_tbytes;
774✔
1410
  }
1411

1412
  TAOS_SKIP_ERROR(taosCloseFile(&pFile));
258✔
1413

1414
  return 0;
258✔
1415
#endif
1416
}
1417

1418
int32_t taosGetCardInfoDelta(int64_t *receive_bytes, int64_t *transmit_bytes) {
864✔
1419
  OS_PARAM_CHECK(receive_bytes);
864✔
1420
  OS_PARAM_CHECK(transmit_bytes);
460✔
1421
  static int64_t last_receive_bytes = -1;
1422
  static int64_t last_transmit_bytes = -1;
1423
  int64_t cur_receive_bytes = 0;
258✔
1424
  int64_t cur_transmit_bytes = 0;
258✔
1425
  int32_t code = taosGetCardInfo(&cur_receive_bytes, &cur_transmit_bytes);
258✔
1426
  if (code == 0) {
258✔
1427
    if(last_receive_bytes >= 0 && last_transmit_bytes >= 0){
258✔
1428
      *receive_bytes = cur_receive_bytes - last_receive_bytes;
×
1429
      *transmit_bytes = cur_transmit_bytes - last_transmit_bytes;
×
1430
    }
1431
    else{
1432
      *receive_bytes = 0;
258✔
1433
      *transmit_bytes = 0;
258✔
1434
    }
1435

1436
    last_receive_bytes = cur_receive_bytes;
258✔
1437
    last_transmit_bytes = cur_transmit_bytes;
258✔
1438
  } else {
1439
    return code;
×
1440
  }
1441
  return 0;
258✔
1442
}
1443
void taosSetDefaultCardInfoDelta(int64_t *receive_bytes, int64_t *transmit_bytes) {
×
1444
  if (receive_bytes) *receive_bytes = 0;
×
1445
  if (transmit_bytes) *transmit_bytes = 0;
×
1446
}
×
1447

1448
#if 0
1449
void taosKillSystem() {
1450
#ifdef WINDOWS
1451
  printf("function taosKillSystem, exit!");
1452
  exit(0);
1453
#elif defined(_TD_DARWIN_64) || defined(TD_ASTRA)
1454
  printf("function taosKillSystem, exit!");
1455
  exit(0);
1456
#else
1457
  // SIGINT
1458
  (void)printf("%sd will shut down soon", CUS_PROMPT);
1459
  (void)kill(tsProcId, 2);
1460
#endif
1461
}
1462
#endif
1463

1464
#define UUIDLEN (36)
1465
int32_t taosGetSystemUUIDLimit36(char *uid, int32_t uidlen) {
256,340,580✔
1466
  OS_PARAM_CHECK(uid);
256,340,580✔
1467
#ifdef WINDOWS
1468
  GUID guid;
1469
  HRESULT h = CoCreateGuid(&guid);
1470
  if (h != S_OK) {
1471
    return TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1472
  }
1473
  (void)snprintf(uid, uidlen, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", guid.Data1, guid.Data2, guid.Data3,
1474
           guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6],
1475
           guid.Data4[7]);
1476

1477
  return 0;
1478
#elif defined(_TD_DARWIN_64)
1479
  uuid_t uuid = {0};
1480
  char   buf[UUIDLEN37];
1481
  memset(buf, 0, UUIDLEN37);
1482
  uuid_generate(uuid);
1483
  // it's caller's responsibility to make enough space for `uid`, that's 36-char + 1-null
1484
  uuid_unparse_lower(uuid, buf);
1485
  (void)snprintf(uid, uidlen, "%.*s", (int)sizeof(buf), buf);
1486
  return 0;
1487
#elif defined(TD_ASTRA)
1488
  const char *template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
1489
  const char *hex_chars = "0123456789abcdef";
1490
  int32_t     len = uidlen > 36 ? 36 : uidlen;
1491

1492
  for (int32_t i = 0; i < len; i++) {
1493
    if (template[i] == 'x') {
1494
      uid[i] = hex_chars[taosRand() & 15];
1495
    } else if (template[i] == 'y') {
1496
      uid[i] = hex_chars[(taosRand() & 3) + 8];  // 8, 9, a, or b
1497
    } else {
1498
      uid[i] = template[i];
1499
    }
1500
  }
1501
  if (len >= 0) {
1502
    uid[len] = 0;
1503
  }
1504

1505
  return 0;
1506
#else
1507
  int64_t len = 0;
256,340,378✔
1508

1509
  // fd = open("/proc/sys/kernel/random/uuid", 0);
1510
  TdFilePtr pFile = taosOpenFile("/proc/sys/kernel/random/uuid", TD_FILE_READ);
256,340,378✔
1511
  if (pFile == NULL) {
255,417,427✔
1512
    return terrno;
×
1513
  } else {
1514
    len = taosReadFile(pFile, uid, uidlen);
255,417,427✔
1515
    TAOS_SKIP_ERROR(taosCloseFile(&pFile));
256,079,387✔
1516
    if (len < 0) {
255,678,548✔
1517
      return terrno;
×
1518
    }
1519
  }
1520
  if (len >= UUIDLEN + 1) {
255,678,548✔
1521
    uid[len - 1] = 0;
255,327,728✔
1522
  } else {
1523
    uid[uidlen - 1] = 0;
350,820✔
1524
  }
1525

1526
  return 0;
255,750,060✔
1527
#endif
1528
}
1529

1530
int32_t taosGetSystemUUIDLen(char *uid, int32_t uidlen) {
350,214✔
1531
  if (uid == NULL || uidlen <= 0) {
350,214✔
1532
    return TSDB_CODE_APP_ERROR;
404✔
1533
  }
1534
  int num = (uidlen % UUIDLEN == 0) ? (uidlen / UUIDLEN) : (uidlen / UUIDLEN + 1);
349,810✔
1535
  int left = uidlen;
349,810✔
1536
  for (int i = 0; i < num; ++i) {
1,048,622✔
1537
    int32_t code = taosGetSystemUUIDLimit36(uid + i * UUIDLEN, left);
698,812✔
1538
    if (code != 0) {
698,812✔
1539
      return code;
×
1540
    }
1541
    left -= UUIDLEN;
698,812✔
1542
  }
1543
  return TSDB_CODE_SUCCESS;
349,810✔
1544
}
1545

1546
char *taosGetCmdlineByPID(int pid) {
689,975✔
1547
#ifdef WINDOWS
1548
  return "";
1549
#elif defined(_TD_DARWIN_64)
1550
  static char cmdline[1024];
1551
  SET_ERRNO(0);
1552

1553
  if (proc_pidpath(pid, cmdline, sizeof(cmdline)) <= 0) {
1554
    fprintf(stderr, "PID is %d, %s", pid, strerror(ERRNO));
1555
    return strerror(ERRNO);
1556
  }
1557

1558
  return cmdline;
1559
#elif defined(TD_ASTRA)
1560
  return "";
1561
#else
1562
  static char cmdline[1024];
1563
  (void)snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid);
689,975✔
1564

1565
  // int fd = open(cmdline, O_RDONLY);
1566
  TdFilePtr pFile = taosOpenFile(cmdline, TD_FILE_READ);
689,975✔
1567
  if (pFile != NULL) {
689,975✔
1568
    int n = taosReadFile(pFile, cmdline, sizeof(cmdline) - 1);
369,263✔
1569
    if (n < 0) n = 0;
369,263✔
1570

1571
    if (n > 0 && cmdline[n - 1] == '\n') --n;
369,263✔
1572

1573
    cmdline[n] = 0;
369,263✔
1574

1575
    TAOS_SKIP_ERROR(taosCloseFile(&pFile));
369,263✔
1576
  } else {
1577
    cmdline[0] = 0;
320,712✔
1578
  }
1579

1580
  return cmdline;
689,975✔
1581
#endif
1582
}
1583

1584
int64_t taosGetOsUptime() {
1,269,522✔
1585
#ifdef WINDOWS
1586
#elif defined(_TD_DARWIN_64) || defined(TD_ASTRA)
1587
#else
1588
  struct sysinfo info;
1,267,681✔
1589
  if (-1 == sysinfo(&info)) {
1,269,522✔
1590
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1591
    return terrno;
×
1592
  }
1593
  
1594
  return (int64_t)info.uptime * 1000;
1,269,522✔
1595
  
1596
#endif
1597
  return 0;
1598
}
1599

1600
void taosSetCoreDump(bool enable) {
3,425,626✔
1601
  if (!enable) return;
3,425,626✔
1602
#ifdef WINDOWS
1603
  /* Register vectored exception handler FIRST - it runs before SEH and can
1604
   * catch heap corruption (STATUS_HEAP_CORRUPTION 0xC0000374) which may
1605
   * bypass SetUnhandledExceptionFilter in some cases. */
1606
  AddVectoredExceptionHandler(1, FlVectoredExceptionHandler);
1607
  
1608
  /* Also set the unhandled exception filter for normal crashes */
1609
  SetUnhandledExceptionFilter(&FlCrashDump);
1610
  
1611
  /* Register CRT handlers for various runtime errors */
1612
  _set_invalid_parameter_handler(FlInvalidParameterHandler);
1613
  _set_purecall_handler(FlPureCallHandler);
1614
  
1615
  /* Handle abort() calls */
1616
  signal(SIGABRT, FlAbortHandler);
1617
  
1618
#elif defined(_TD_DARWIN_64) || defined(TD_ASTRA)
1619
#else
1620
  // 1. set ulimit -c unlimited
1621
  struct rlimit rlim;
3,401,484✔
1622
  struct rlimit rlim_new;
3,401,484✔
1623
  if (getrlimit(RLIMIT_CORE, &rlim) == 0) {
3,424,584✔
1624
#ifndef _ALPINE
1625
    // printf("the old unlimited para: rlim_cur=%" PRIu64 ", rlim_max=%" PRIu64, rlim.rlim_cur, rlim.rlim_max);
1626
#else
1627
    // printf("the old unlimited para: rlim_cur=%llu, rlim_max=%llu", rlim.rlim_cur, rlim.rlim_max);
1628
#endif
1629
    rlim_new.rlim_cur = RLIM_INFINITY;
3,424,584✔
1630
    rlim_new.rlim_max = RLIM_INFINITY;
3,424,584✔
1631
    if (setrlimit(RLIMIT_CORE, &rlim_new) != 0) {
3,424,584✔
1632
      // printf("set unlimited fail, error: %s", strerror(ERRNO));
1633
      rlim_new.rlim_cur = rlim.rlim_max;
×
1634
      rlim_new.rlim_max = rlim.rlim_max;
×
1635
      (void)setrlimit(RLIMIT_CORE, &rlim_new);
×
1636
    }
1637
  }
1638

1639
  if (getrlimit(RLIMIT_CORE, &rlim) == 0) {
3,424,584✔
1640
#ifndef _ALPINE
1641
    // printf("the new unlimited para: rlim_cur=%" PRIu64 ", rlim_max=%" PRIu64, rlim.rlim_cur, rlim.rlim_max);
1642
#else
1643
    // printf("the new unlimited para: rlim_cur=%llu, rlim_max=%llu", rlim.rlim_cur, rlim.rlim_max);
1644
#endif
1645
  }
1646

1647
#ifndef _TD_ARM_
1648
  // 2. set the path for saving core file
1649
  struct __sysctl_args args;
3,401,484✔
1650

1651
  int    old_usespid = 0;
3,424,584✔
1652
  size_t old_len = 0;
3,424,584✔
1653
  int    new_usespid = 1;
3,424,584✔
1654
  size_t new_len = sizeof(new_usespid);
3,424,584✔
1655

1656
  int name[] = {CTL_KERN, KERN_CORE_USES_PID};
3,424,584✔
1657

1658
  (void)memset(&args, 0, sizeof(struct __sysctl_args));
3,424,584✔
1659
  args.name = name;
3,424,584✔
1660
  args.nlen = sizeof(name) / sizeof(name[0]);
3,424,584✔
1661
  args.oldval = &old_usespid;
3,424,584✔
1662
  args.oldlenp = &old_len;
3,424,584✔
1663
  args.newval = &new_usespid;
3,424,584✔
1664
  args.newlen = new_len;
3,424,584✔
1665

1666
  old_len = sizeof(old_usespid);
3,424,584✔
1667

1668
#ifndef __loongarch64
1669
  if (syscall(SYS__sysctl, &args) == -1) {
3,424,584✔
1670
    // printf("_sysctl(kern_core_uses_pid) set fail: %s", strerror(ERRNO));
1671
  }
1672
#endif
1673

1674
  // printf("The old core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid);
1675

1676
  old_usespid = 0;
3,424,584✔
1677
  old_len = 0;
3,424,584✔
1678
  (void)memset(&args, 0, sizeof(struct __sysctl_args));
3,424,584✔
1679
  args.name = name;
3,424,584✔
1680
  args.nlen = sizeof(name) / sizeof(name[0]);
3,424,584✔
1681
  args.oldval = &old_usespid;
3,424,584✔
1682
  args.oldlenp = &old_len;
3,424,584✔
1683

1684
  old_len = sizeof(old_usespid);
3,424,584✔
1685

1686
#ifndef __loongarch64
1687
  if (syscall(SYS__sysctl, &args) == -1) {
3,424,584✔
1688
    // printf("_sysctl(kern_core_uses_pid) get fail: %s", strerror(ERRNO));
1689
  }
1690
#endif
1691

1692
  // printf("The new core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid);
1693
#endif
1694
#endif
1695
}
1696

1697
SysNameInfo taosGetSysNameInfo() {
2,910,747✔
1698
#ifdef WINDOWS
1699
  SysNameInfo info = {0};
1700
  DWORD       dwVersion = GetVersion();
1701

1702
  char *tmp = NULL;
1703
  tmp = getenv("OS");
1704
  if (tmp != NULL) tstrncpy(info.sysname, tmp, sizeof(info.sysname));
1705
  tmp = getenv("COMPUTERNAME");
1706
  if (tmp != NULL) tstrncpy(info.nodename, tmp, sizeof(info.nodename));
1707
  sprintf_s(info.release, sizeof(info.release), "%d", dwVersion & 0x0F);
1708
  sprintf_s(info.version, sizeof(info.release), "%d", (dwVersion >> 8) & 0x0F);
1709
  tmp = getenv("PROCESSOR_ARCHITECTURE");
1710
  if (tmp != NULL) tstrncpy(info.machine, tmp, sizeof(info.machine));
1711

1712
  return info;
1713
#elif defined(_TD_DARWIN_64)
1714
  SysNameInfo info = {0};
1715

1716
  struct utsname uts;
1717
  if (!uname(&uts)) {
1718
    tstrncpy(info.sysname, uts.sysname, sizeof(info.sysname));
1719
    tstrncpy(info.nodename, uts.nodename, sizeof(info.nodename));
1720
    tstrncpy(info.release, uts.release, sizeof(info.release));
1721
    tstrncpy(info.version, uts.version, sizeof(info.version));
1722
    tstrncpy(info.machine, uts.machine, sizeof(info.machine));
1723
  }
1724

1725
  char     localHostName[512];
1726
  TAOS_SKIP_ERROR(taosGetlocalhostname(localHostName, 512));
1727
  TdCmdPtr pCmd = taosOpenCmd("scutil --get LocalHostName");
1728
  tstrncpy(info.nodename, localHostName, sizeof(info.nodename));
1729

1730
  return info;
1731
#else
1732
  SysNameInfo info = {0};
2,910,747✔
1733
  struct utsname uts;
2,888,459✔
1734
  if (!uname(&uts)) {
2,910,747✔
1735
    tstrncpy(info.sysname, uts.sysname, sizeof(info.sysname));
2,910,747✔
1736
    tstrncpy(info.nodename, uts.nodename, sizeof(info.nodename));
2,910,747✔
1737
    tstrncpy(info.release, uts.release, sizeof(info.release));
2,910,747✔
1738
    tstrncpy(info.version, uts.version, sizeof(info.version));
2,910,747✔
1739
    tstrncpy(info.machine, uts.machine, sizeof(info.machine));
2,910,747✔
1740
  } else {
1741
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1742
  }
1743

1744
  return info;
2,910,747✔
1745
#endif
1746
}
1747

1748
bool taosCheckCurrentInDll() {
1,556,827✔
1749
#ifdef WINDOWS
1750
  MEMORY_BASIC_INFORMATION mbi;
1751
  char                     path[PATH_MAX] = {0};
1752
  GetModuleFileName(
1753
      ((VirtualQuery(taosCheckCurrentInDll, &mbi, sizeof(mbi)) != 0) ? (HMODULE)mbi.AllocationBase : NULL), path,
1754
      PATH_MAX);
1755
  int strLastIndex = strlen(path);
1756
  if ((path[strLastIndex - 3] == 'd' || path[strLastIndex - 3] == 'D') &&
1757
      (path[strLastIndex - 2] == 'l' || path[strLastIndex - 2] == 'L') &&
1758
      (path[strLastIndex - 1] == 'l' || path[strLastIndex - 1] == 'L')) {
1759
    return true;
1760
  }
1761
  return false;
1762
#else
1763
  return false;
1,556,827✔
1764
#endif
1765
}
1766

1767
#ifdef _TD_DARWIN_64
1768
int32_t taosGetMaclocalhostnameByCommand(char *hostname, size_t maxLen) {
1769
  TdCmdPtr pCmd = taosOpenCmd("scutil --get LocalHostName");
1770
  if (pCmd != NULL) {
1771
    if (taosGetsCmd(pCmd, maxLen - 1, hostname) > 0) {
1772
      int len = strlen(hostname);
1773
      if (hostname[len - 1] == '\n') {
1774
        hostname[len - 1] = '\0';
1775
      }
1776
      return 0;
1777
    }
1778
    taosCloseCmd(&pCmd);
1779
  }
1780
  return TAOS_SYSTEM_ERROR(ERRNO);
1781
}
1782

1783
int32_t getMacLocalHostNameBySCD(char *hostname, size_t maxLen) {
1784
  SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR(""), NULL, NULL);
1785
  CFStringRef       hostname_cfstr = SCDynamicStoreCopyLocalHostName(store);
1786
  if (hostname_cfstr != NULL) {
1787
    CFStringGetCString(hostname_cfstr, hostname, maxLen - 1, kCFStringEncodingMacRoman);
1788
    CFRelease(hostname_cfstr);
1789
  } else {
1790
    return -1;
1791
  }
1792
  CFRelease(store);
1793
  return 0;
1794
}
1795
#endif
1796

1797
int32_t taosGetlocalhostname(char *hostname, size_t maxLen) {
27,046,149✔
1798
  OS_PARAM_CHECK(hostname);
27,046,149✔
1799
#ifdef _TD_DARWIN_64
1800
  int res = getMacLocalHostNameBySCD(hostname, maxLen);
1801
  if (res != 0) {
1802
    return taosGetMaclocalhostnameByCommand(hostname, maxLen);
1803
  } else {
1804
    return 0;
1805
  }
1806
#else
1807
  int r = gethostname(hostname, maxLen);
27,045,947✔
1808
  if (-1 == r) {
27,045,947✔
UNCOV
1809
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
1810
    return terrno;
×
1811
  }
1812
  return r;
27,045,947✔
1813
#endif
1814
}
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