homework-jianmu/source/os/src/osSysinfo.c

1161 lines
31 KiB
C

/*
* 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/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "taoserror.h"
#if defined(CUS_NAME) || defined(CUS_PROMPT) || defined(CUS_EMAIL)
#include "cus_name.h"
#endif
#define PROCESS_ITEM 12
#define UUIDLEN37 37
typedef struct {
uint64_t user;
uint64_t nice;
uint64_t system;
uint64_t idle;
} SysCpuInfo;
typedef struct {
uint64_t utime; // user time
uint64_t stime; // kernel time
uint64_t cutime; // all user time
uint64_t cstime; // all dead time
} ProcCpuInfo;
#ifdef WINDOWS
/*
* windows implementation
*/
#if (_WIN64)
#include <iphlpapi.h>
#include <mswsock.h>
#include <psapi.h>
#include <stdio.h>
#include <windows.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Mswsock.lib ")
#endif
#include <objbase.h>
#pragma warning(push)
#pragma warning(disable : 4091)
#include <DbgHelp.h>
#pragma warning(pop)
LONG WINAPI FlCrashDump(PEXCEPTION_POINTERS ep) {
typedef BOOL(WINAPI * FxMiniDumpWriteDump)(IN HANDLE hProcess, IN DWORD ProcessId, IN HANDLE hFile,
IN MINIDUMP_TYPE DumpType,
IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
HMODULE dll = LoadLibrary("dbghelp.dll");
if (dll == NULL) return EXCEPTION_CONTINUE_SEARCH;
FxMiniDumpWriteDump mdwd = (FxMiniDumpWriteDump)(GetProcAddress(dll, "MiniDumpWriteDump"));
if (mdwd == NULL) {
FreeLibrary(dll);
return EXCEPTION_CONTINUE_SEARCH;
}
TCHAR path[MAX_PATH];
DWORD len = GetModuleFileName(NULL, path, _countof(path));
path[len - 3] = 'd';
path[len - 2] = 'm';
path[len - 1] = 'p';
HANDLE file = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
MINIDUMP_EXCEPTION_INFORMATION mei;
mei.ThreadId = GetCurrentThreadId();
mei.ExceptionPointers = ep;
mei.ClientPointers = FALSE;
(*mdwd)(GetCurrentProcess(), GetCurrentProcessId(), file, MiniDumpWithHandleData, &mei, NULL, NULL);
CloseHandle(file);
FreeLibrary(dll);
return EXCEPTION_CONTINUE_SEARCH;
}
LONG WINAPI exceptionHandler(LPEXCEPTION_POINTERS exception);
#elif defined(_TD_DARWIN_64)
#include <errno.h>
#include <libproc.h>
#include <sys/sysctl.h>
#include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
#include <CoreFoundation/CFString.h>
#include <stdio.h>
#else
#include <argp.h>
#include <linux/sysctl.h>
#include <sys/file.h>
#include <sys/resource.h>
#include <sys/statvfs.h>
#include <sys/syscall.h>
#include <sys/utsname.h>
#include <unistd.h>
static pid_t tsProcId;
static char tsSysNetFile[] = "/proc/net/dev";
static char tsSysCpuFile[] = "/proc/stat";
static char tsProcCpuFile[25] = {0};
static char tsProcMemFile[25] = {0};
static char tsProcIOFile[25] = {0};
static void taosGetProcIOnfos() {
tsPageSizeKB = sysconf(_SC_PAGESIZE) / 1024;
tsOpenMax = sysconf(_SC_OPEN_MAX);
tsStreamMax = TMAX(sysconf(_SC_STREAM_MAX), 0);
tsProcId = (pid_t)syscall(SYS_gettid);
snprintf(tsProcMemFile, sizeof(tsProcMemFile), "/proc/%d/status", tsProcId);
snprintf(tsProcCpuFile, sizeof(tsProcCpuFile), "/proc/%d/stat", tsProcId);
snprintf(tsProcIOFile, sizeof(tsProcIOFile), "/proc/%d/io", tsProcId);
}
#endif
static int32_t taosGetSysCpuInfo(SysCpuInfo *cpuInfo) {
#ifdef WINDOWS
FILETIME pre_idleTime = {0};
FILETIME pre_kernelTime = {0};
FILETIME pre_userTime = {0};
FILETIME idleTime;
FILETIME kernelTime;
FILETIME userTime;
bool res = GetSystemTimes(&idleTime, &kernelTime, &userTime);
if (res) {
cpuInfo->idle = CompareFileTime(&pre_idleTime, &idleTime);
cpuInfo->system = CompareFileTime(&pre_kernelTime, &kernelTime);
cpuInfo->user = CompareFileTime(&pre_userTime, &userTime);
cpuInfo->nice = 0;
}
#elif defined(DARWIN)
cpuInfo->idle = 0;
cpuInfo->system = 0;
cpuInfo->user = 0;
cpuInfo->nice = 0;
#else
TdFilePtr pFile = taosOpenFile(tsSysCpuFile, TD_FILE_READ | TD_FILE_STREAM);
if (pFile == NULL) {
return -1;
}
char line[1024];
ssize_t bytes = taosGetsFile(pFile, sizeof(line), line);
if (bytes < 0) {
taosCloseFile(&pFile);
return -1;
}
char cpu[10] = {0};
sscanf(line, "%s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, cpu, &cpuInfo->user, &cpuInfo->nice, &cpuInfo->system,
&cpuInfo->idle);
taosCloseFile(&pFile);
#endif
return 0;
}
static int32_t taosGetProcCpuInfo(ProcCpuInfo *cpuInfo) {
#ifdef WINDOWS
FILETIME pre_krnlTm = {0};
FILETIME pre_usrTm = {0};
FILETIME creatTm, exitTm, krnlTm, usrTm;
if (GetThreadTimes(GetCurrentThread(), &creatTm, &exitTm, &krnlTm, &usrTm)) {
cpuInfo->stime = CompareFileTime(&pre_krnlTm, &krnlTm);
cpuInfo->utime = CompareFileTime(&pre_usrTm, &usrTm);
cpuInfo->cutime = 0;
cpuInfo->cstime = 0;
}
#elif defined(DARWIN)
cpuInfo->stime = 0;
cpuInfo->utime = 0;
cpuInfo->cutime = 0;
cpuInfo->cstime = 0;
#else
TdFilePtr pFile = taosOpenFile(tsProcCpuFile, TD_FILE_READ | TD_FILE_STREAM);
if (pFile == NULL) {
return -1;
}
char line[1024] = {0};
ssize_t bytes = taosGetsFile(pFile, sizeof(line), line);
if (bytes < 0) {
taosCloseFile(&pFile);
return -1;
}
for (int i = 0, blank = 0; line[i] != 0; ++i) {
if (line[i] == ' ') blank++;
if (blank == PROCESS_ITEM) {
sscanf(line + i + 1, "%" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, &cpuInfo->utime, &cpuInfo->stime,
&cpuInfo->cutime, &cpuInfo->cstime);
break;
}
}
taosCloseFile(&pFile);
#endif
return 0;
}
bool taosCheckSystemIsLittleEnd() {
union check {
int16_t i;
char ch[2];
} c;
c.i = 1;
return c.ch[0] == 1;
}
void taosGetSystemInfo() {
#ifdef WINDOWS
taosGetCpuCores(&tsNumOfCores);
taosGetTotalMemory(&tsTotalMemoryKB);
taosGetCpuUsage(NULL, NULL);
#elif defined(_TD_DARWIN_64)
long physical_pages = sysconf(_SC_PHYS_PAGES);
long page_size = sysconf(_SC_PAGESIZE);
tsTotalMemoryKB = physical_pages * page_size / 1024;
tsPageSizeKB = page_size / 1024;
tsNumOfCores = sysconf(_SC_NPROCESSORS_ONLN);
#else
taosGetProcIOnfos();
taosGetCpuCores(&tsNumOfCores);
taosGetTotalMemory(&tsTotalMemoryKB);
taosGetCpuUsage(NULL, NULL);
taosGetCpuInstructions(&tsSSE42Enable, &tsAVXEnable, &tsAVX2Enable, &tsFMAEnable);
#endif
}
int32_t taosGetEmail(char *email, int32_t maxLen) {
#ifdef WINDOWS
// ASSERT(0);
#elif defined(_TD_DARWIN_64)
#ifdef CUS_PROMPT
const char *filepath = "/usr/local/"CUS_PROMPT"/email";
#else
const char *filepath = "/usr/local/taos/email";
#endif // CUS_PROMPT
TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ);
if (pFile == NULL) return false;
if (taosReadFile(pFile, (void *)email, maxLen) < 0) {
taosCloseFile(&pFile);
return -1;
}
taosCloseFile(&pFile);
return 0;
#else
#ifdef CUS_PROMPT
const char *filepath = "/usr/local/"CUS_PROMPT"/email";
#else
const char *filepath = "/usr/local/taos/email";
#endif // CUS_PROMPT
TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ);
if (pFile == NULL) return false;
if (taosReadFile(pFile, (void *)email, maxLen) < 0) {
taosCloseFile(&pFile);
return -1;
}
taosCloseFile(&pFile);
return 0;
#endif
}
#ifdef WINDOWS
bool getWinVersionReleaseName(char *releaseName, int32_t maxLen) {
TCHAR szFileName[MAX_PATH];
DWORD dwHandle;
DWORD dwLen;
LPVOID lpData;
UINT uLen;
VS_FIXEDFILEINFO *pFileInfo;
GetWindowsDirectory(szFileName, MAX_PATH);
wsprintf(szFileName, L"%s%s", szFileName, L"\\explorer.exe");
dwLen = GetFileVersionInfoSize(szFileName, &dwHandle);
if (dwLen == 0) {
return false;
}
lpData = malloc(dwLen);
if (lpData == NULL) return false;
if (!GetFileVersionInfo(szFileName, dwHandle, dwLen, lpData)) {
free(lpData);
return false;
}
if (!VerQueryValue(lpData, L"\\", (LPVOID *)&pFileInfo, &uLen)) {
free(lpData);
return false;
}
snprintf(releaseName, maxLen, "Windows %d.%d", HIWORD(pFileInfo->dwProductVersionMS),
LOWORD(pFileInfo->dwProductVersionMS));
free(lpData);
return true;
}
#endif
int32_t taosGetOsReleaseName(char *releaseName, char* sName, char* ver, int32_t maxLen) {
#ifdef WINDOWS
if (!getWinVersionReleaseName(releaseName, maxLen)) {
snprintf(releaseName, maxLen, "Windows");
}
if(sName) snprintf(sName, maxLen, "Windows");
return 0;
#elif defined(_TD_DARWIN_64)
char osversion[32];
size_t osversion_len = sizeof(osversion) - 1;
int osversion_name[] = { CTL_KERN, KERN_OSRELEASE };
if(sName) snprintf(sName, maxLen, "macOS");
if (sysctl(osversion_name, 2, osversion, &osversion_len, NULL, 0) == -1) {
return -1;
}
uint32_t major, minor;
if (sscanf(osversion, "%u.%u", &major, &minor) != 2) {
return -1;
}
if (major >= 20) {
major -= 9; // macOS 11 and newer
sprintf(releaseName, "macOS %u.%u", major, minor);
} else {
major -= 4; // macOS 10.1.1 and newer
sprintf(releaseName, "macOS 10.%d.%d", major, minor);
}
return 0;
#else
char line[1024];
char *dest = NULL;
size_t size = 0;
int32_t code = -1;
int32_t cnt = 0;
TdFilePtr pFile = taosOpenFile("/etc/os-release", TD_FILE_READ | TD_FILE_STREAM);
if (pFile == NULL) return code;
while ((size = taosGetsFile(pFile, sizeof(line), line)) != -1) {
line[size - 1] = '\0';
if (strncmp(line, "NAME", 4) == 0) {
dest = sName;
} else if (strncmp(line, "PRETTY_NAME", 11) == 0) {
dest = releaseName;
} else if (strncmp(line, "VERSION_ID", 10) == 0) {
dest = ver;
} else {
continue;
}
if (!dest) continue;
const char *p = strchr(line, '=') + 1;
if (*p == '"') {
p++;
line[size - 2] = 0;
}
tstrncpy(dest, p, maxLen);
if (++cnt >= 3) {
code = 0;
break;
}
}
taosCloseFile(&pFile);
return code;
#endif
}
int32_t taosGetCpuInfo(char *cpuModel, int32_t maxLen, float *numOfCores) {
#ifdef WINDOWS
char value[100];
DWORD bufferSize = sizeof(value);
RegGetValue(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", "ProcessorNameString",
RRF_RT_ANY, NULL, (PVOID)&value, &bufferSize);
tstrncpy(cpuModel, value, maxLen);
SYSTEM_INFO si;
memset(&si, 0, sizeof(SYSTEM_INFO));
GetSystemInfo(&si);
*numOfCores = si.dwNumberOfProcessors;
return 0;
#elif defined(_TD_DARWIN_64)
char buf[16];
int32_t done = 0;
int32_t code = -1;
TdCmdPtr pCmd = taosOpenCmd("sysctl -n machdep.cpu.brand_string");
if (pCmd == NULL) return code;
if (taosGetsCmd(pCmd, maxLen, cpuModel) > 0) {
code = 0;
done |= 1;
}
int endPos = strlen(cpuModel)-1;
if (cpuModel[endPos] == '\n') {
cpuModel[endPos] = '\0';
}
taosCloseCmd(&pCmd);
pCmd = taosOpenCmd("sysctl -n machdep.cpu.core_count");
if (pCmd == NULL) return code;
memset(buf, 0, sizeof(buf));
if (taosGetsCmd(pCmd, sizeof(buf) - 1, buf) > 0) {
code = 0;
done |= 2;
*numOfCores = atof(buf);
}
taosCloseCmd(&pCmd);
return code;
#else
char line[1024] = {0};
size_t size = 0;
int32_t done = 0;
int32_t code = -1;
float coreCount = 0;
TdFilePtr pFile = taosOpenFile("/proc/cpuinfo", TD_FILE_READ | TD_FILE_STREAM);
if (pFile == NULL) return code;
while (done != 3 && (size = taosGetsFile(pFile, sizeof(line), line)) != -1) {
line[size - 1] = '\0';
if (((done & 1) == 0) && strncmp(line, "model name", 10) == 0) {
const char *v = strchr(line, ':') + 2;
tstrncpy(cpuModel, v, maxLen);
code = 0;
done |= 1;
} else if (((done & 2) == 0) && strncmp(line, "cpu cores", 9) == 0) {
const char *v = strchr(line, ':') + 2;
*numOfCores = atof(v);
done |= 2;
}
if (strncmp(line, "processor", 9) == 0) coreCount += 1;
}
taosCloseFile(&pFile);
if (code != 0 && (done & 1) == 0) {
TdFilePtr pFile1 = taosOpenFile("/proc/device-tree/model", TD_FILE_READ | TD_FILE_STREAM);
if (pFile1 != NULL) {
ssize_t bytes = taosGetsFile(pFile1, maxLen, cpuModel);
taosCloseFile(&pFile);
if (bytes > 0) {
code = 0;
done |= 1;
}
}
}
if (code != 0 && (done & 1) == 0) {
TdCmdPtr pCmd = taosOpenCmd("uname -a");
if (pCmd == NULL) return code;
if (taosGetsCmd(pCmd, maxLen, cpuModel) > 0) {
code = 0;
done |= 1;
}
taosCloseCmd(&pCmd);
}
if ((done & 2) == 0) {
*numOfCores = coreCount;
done |= 2;
}
return code;
#endif
}
int32_t taosGetCpuCores(float *numOfCores) {
#ifdef WINDOWS
SYSTEM_INFO info;
GetSystemInfo(&info);
*numOfCores = info.dwNumberOfProcessors;
return 0;
#elif defined(_TD_DARWIN_64)
*numOfCores = sysconf(_SC_NPROCESSORS_ONLN);
return 0;
#else
*numOfCores = sysconf(_SC_NPROCESSORS_ONLN);
return 0;
#endif
}
void taosGetCpuUsage(double *cpu_system, double *cpu_engine) {
static int64_t lastSysUsed = 0;
static int64_t lastSysTotal = 0;
static int64_t lastProcTotal = 0;
static int64_t curSysUsed = 0;
static int64_t curSysTotal = 0;
static int64_t curProcTotal = 0;
if (cpu_system != NULL) *cpu_system = 0;
if (cpu_engine != NULL) *cpu_engine = 0;
SysCpuInfo sysCpu = {0};
ProcCpuInfo procCpu = {0};
if (taosGetSysCpuInfo(&sysCpu) == 0 && taosGetProcCpuInfo(&procCpu) == 0) {
curSysUsed = sysCpu.user + sysCpu.nice + sysCpu.system;
curSysTotal = curSysUsed + sysCpu.idle;
curProcTotal = procCpu.utime + procCpu.stime + procCpu.cutime + procCpu.cstime;
if (curSysTotal - lastSysTotal > 0 && curSysUsed >= lastSysUsed && curProcTotal >= lastProcTotal) {
if (cpu_system != NULL) {
*cpu_system = (curSysUsed - lastSysUsed) / (double)(curSysTotal - lastSysTotal) * 100;
}
if (cpu_engine != NULL) {
*cpu_engine = (curProcTotal - lastProcTotal) / (double)(curSysTotal - lastSysTotal) * 100;
}
}
lastSysUsed = curSysUsed;
lastSysTotal = curSysTotal;
lastProcTotal = curProcTotal;
}
}
#define __cpuid_fix(level, a, b, c, d) \
__asm__("xor %%ecx, %%ecx\n" \
"cpuid\n" \
: "=a"(a), "=b"(b), "=c"(c), "=d"(d) \
: "0"(level))
// todo add for windows and mac
int32_t taosGetCpuInstructions(char* sse42, char* avx, char* avx2, char* fma) {
#ifdef WINDOWS
#elif defined(_TD_DARWIN_64)
#else
#ifdef _TD_X86_
// Since the compiler is not support avx/avx2 instructions, the global variables always need to be
// set to be false
//#if __AVX__ || __AVX2__
// tsSIMDBuiltins = true;
//#else
// tsSIMDBuiltins = false;
//#endif
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
int32_t ret = __get_cpuid(1, &eax, &ebx, &ecx, &edx);
if (ret == 0) {
return -1; // failed to get the cpuid info
}
*sse42 = (char) ((ecx & bit_SSE4_2) == bit_SSE4_2);
*avx = (char) ((ecx & bit_AVX) == bit_AVX);
*fma = (char) ((ecx & bit_FMA) == bit_FMA);
// work around a bug in GCC.
// Ref to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77756
__cpuid_fix(7u, eax, ebx, ecx, edx);
*avx2 = (char) ((ebx & bit_AVX2) == bit_AVX2);
#endif // _TD_X86_
#endif
return 0;
}
int32_t taosGetTotalMemory(int64_t *totalKB) {
#ifdef WINDOWS
MEMORYSTATUSEX memsStat;
memsStat.dwLength = sizeof(memsStat);
if (!GlobalMemoryStatusEx(&memsStat)) {
return -1;
}
*totalKB = memsStat.ullTotalPhys / 1024;
return 0;
#elif defined(_TD_DARWIN_64)
return 0;
#else
*totalKB = (int64_t)(sysconf(_SC_PHYS_PAGES) * tsPageSizeKB);
return 0;
#endif
}
int32_t taosGetProcMemory(int64_t *usedKB) {
#ifdef WINDOWS
unsigned bytes_used = 0;
#if defined(_WIN64) && defined(_MSC_VER)
PROCESS_MEMORY_COUNTERS pmc;
HANDLE cur_proc = GetCurrentProcess();
if (GetProcessMemoryInfo(cur_proc, &pmc, sizeof(pmc))) {
bytes_used = (unsigned)(pmc.WorkingSetSize + pmc.PagefileUsage);
}
#endif
*usedKB = bytes_used / 1024;
return 0;
#elif defined(_TD_DARWIN_64)
*usedKB = 0;
return 0;
#else
TdFilePtr pFile = taosOpenFile(tsProcMemFile, TD_FILE_READ | TD_FILE_STREAM);
if (pFile == NULL) {
// printf("open file:%s failed", tsProcMemFile);
return -1;
}
ssize_t bytes = 0;
char line[1024] = {0};
while (!taosEOFFile(pFile)) {
bytes = taosGetsFile(pFile, sizeof(line), line);
if (bytes < 0) {
break;
}
if (strstr(line, "VmRSS:") != NULL) {
break;
}
}
char tmp[10];
sscanf(line, "%s %" PRId64, tmp, usedKB);
taosCloseFile(&pFile);
return 0;
#endif
}
int32_t taosGetSysMemory(int64_t *usedKB) {
#ifdef WINDOWS
MEMORYSTATUSEX memsStat;
memsStat.dwLength = sizeof(memsStat);
if (!GlobalMemoryStatusEx(&memsStat)) {
return -1;
}
int64_t nMemFree = memsStat.ullAvailPhys / 1024;
int64_t nMemTotal = memsStat.ullTotalPhys / 1024.0;
*usedKB = nMemTotal - nMemFree;
return 0;
#elif defined(_TD_DARWIN_64)
*usedKB = 0;
return 0;
#else
*usedKB = sysconf(_SC_AVPHYS_PAGES) * tsPageSizeKB;
return 0;
#endif
}
int32_t taosGetDiskSize(char *dataDir, SDiskSize *diskSize) {
#if defined(WINDOWS)
unsigned _int64 i64FreeBytesToCaller;
unsigned _int64 i64TotalBytes;
unsigned _int64 i64FreeBytes;
BOOL fResult = GetDiskFreeSpaceExA(dataDir, (PULARGE_INTEGER)&i64FreeBytesToCaller, (PULARGE_INTEGER)&i64TotalBytes,
(PULARGE_INTEGER)&i64FreeBytes);
if (fResult) {
diskSize->total = (int64_t)(i64TotalBytes);
diskSize->avail = (int64_t)(i64FreeBytesToCaller);
diskSize->used = (int64_t)(i64TotalBytes - i64FreeBytes);
return 0;
} else {
// printf("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno));
// terrno = TAOS_SYSTEM_ERROR(errno);
return -1;
}
#elif defined(_TD_DARWIN_64)
struct statvfs info;
if (statvfs(dataDir, &info)) {
// printf("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno));
// terrno = TAOS_SYSTEM_ERROR(errno);
return -1;
} else {
diskSize->total = info.f_blocks * info.f_frsize;
diskSize->avail = info.f_bavail * info.f_frsize;
diskSize->used = (info.f_blocks - info.f_bfree) * info.f_frsize;
return 0;
}
#else
struct statvfs info;
if (statvfs(dataDir, &info)) {
// terrno = TAOS_SYSTEM_ERROR(errno);
return -1;
} else {
diskSize->total = info.f_blocks * info.f_frsize;
diskSize->avail = info.f_bavail * info.f_frsize;
diskSize->used = diskSize->total - diskSize->avail;
return 0;
}
#endif
}
int32_t taosGetProcIO(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int64_t *write_bytes) {
#ifdef WINDOWS
IO_COUNTERS io_counter;
if (GetProcessIoCounters(GetCurrentProcess(), &io_counter)) {
if (rchars) *rchars = io_counter.ReadTransferCount;
if (wchars) *wchars = io_counter.WriteTransferCount;
if (read_bytes) *read_bytes = 0;
if (write_bytes) *write_bytes = 0;
return 0;
}
return -1;
#elif defined(_TD_DARWIN_64)
if (rchars) *rchars = 0;
if (wchars) *wchars = 0;
if (read_bytes) *read_bytes = 0;
if (write_bytes) *write_bytes = 0;
return 0;
#else
TdFilePtr pFile = taosOpenFile(tsProcIOFile, TD_FILE_READ | TD_FILE_STREAM);
if (pFile == NULL) return -1;
ssize_t bytes = 0;
char line[1024] = {0};
char tmp[24];
int readIndex = 0;
while (!taosEOFFile(pFile)) {
bytes = taosGetsFile(pFile, sizeof(line), line);
if (bytes < 10) {
break;
}
if (strstr(line, "rchar:") != NULL) {
sscanf(line, "%s %" PRId64, tmp, rchars);
readIndex++;
} else if (strstr(line, "wchar:") != NULL) {
sscanf(line, "%s %" PRId64, tmp, wchars);
readIndex++;
} else if (strstr(line, "read_bytes:") != NULL) { // read_bytes
sscanf(line, "%s %" PRId64, tmp, read_bytes);
readIndex++;
} else if (strstr(line, "write_bytes:") != NULL) { // write_bytes
sscanf(line, "%s %" PRId64, tmp, write_bytes);
readIndex++;
} else {
}
if (readIndex >= 4) break;
}
taosCloseFile(&pFile);
if (readIndex < 4) {
return -1;
}
return 0;
#endif
}
void taosGetProcIODelta(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int64_t *write_bytes) {
static int64_t last_rchars = 0;
static int64_t last_wchars = 0;
static int64_t last_read_bytes = 0;
static int64_t last_write_bytes = 0;
static int64_t cur_rchars = 0;
static int64_t cur_wchars = 0;
static int64_t cur_read_bytes = 0;
static int64_t cur_write_bytes = 0;
if (taosGetProcIO(&cur_rchars, &cur_wchars, &cur_read_bytes, &cur_write_bytes) == 0) {
*rchars = cur_rchars - last_rchars;
*wchars = cur_wchars - last_wchars;
*read_bytes = cur_read_bytes - last_read_bytes;
*write_bytes = cur_write_bytes - last_write_bytes;
last_rchars = cur_rchars;
last_wchars = cur_wchars;
last_read_bytes = cur_read_bytes;
last_write_bytes = cur_write_bytes;
} else {
*rchars = 0;
*wchars = 0;
*read_bytes = 0;
*write_bytes = 0;
}
}
int32_t taosGetCardInfo(int64_t *receive_bytes, int64_t *transmit_bytes) {
#ifdef WINDOWS
*receive_bytes = 0;
*transmit_bytes = 0;
return 0;
#elif defined(_TD_DARWIN_64)
*receive_bytes = 0;
*transmit_bytes = 0;
return 0;
#else
TdFilePtr pFile = taosOpenFile(tsSysNetFile, TD_FILE_READ | TD_FILE_STREAM);
if (pFile == NULL) return -1;
ssize_t _bytes = 0;
char line[1024];
while (!taosEOFFile(pFile)) {
int64_t o_rbytes = 0;
int64_t rpackts = 0;
int64_t o_tbytes = 0;
int64_t tpackets = 0;
int64_t nouse1 = 0;
int64_t nouse2 = 0;
int64_t nouse3 = 0;
int64_t nouse4 = 0;
int64_t nouse5 = 0;
int64_t nouse6 = 0;
char nouse0[200] = {0};
_bytes = taosGetsFile(pFile, sizeof(line), line);
if (_bytes < 0) {
break;
}
line[_bytes - 1] = 0;
if (strstr(line, "lo:") != NULL) {
continue;
}
sscanf(line,
"%s %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64
" %" PRId64,
nouse0, &o_rbytes, &rpackts, &nouse1, &nouse2, &nouse3, &nouse4, &nouse5, &nouse6, &o_tbytes, &tpackets);
*receive_bytes = o_rbytes;
*transmit_bytes = o_tbytes;
}
taosCloseFile(&pFile);
return 0;
#endif
}
void taosGetCardInfoDelta(int64_t *receive_bytes, int64_t *transmit_bytes) {
static int64_t last_receive_bytes = 0;
static int64_t last_transmit_bytes = 0;
static int64_t cur_receive_bytes = 0;
static int64_t cur_transmit_bytes = 0;
if (taosGetCardInfo(&cur_receive_bytes, &cur_transmit_bytes) == 0) {
*receive_bytes = cur_receive_bytes - last_receive_bytes;
*transmit_bytes = cur_transmit_bytes - last_transmit_bytes;
last_receive_bytes = cur_receive_bytes;
last_transmit_bytes = cur_transmit_bytes;
} else {
*receive_bytes = 0;
*transmit_bytes = 0;
}
}
void taosKillSystem() {
#ifdef WINDOWS
printf("function taosKillSystem, exit!");
exit(0);
#elif defined(_TD_DARWIN_64)
printf("function taosKillSystem, exit!");
exit(0);
#else
// SIGINT
printf("taosd will shut down soon");
kill(tsProcId, 2);
#endif
}
int32_t taosGetSystemUUID(char *uid, int32_t uidlen) {
#ifdef WINDOWS
GUID guid;
CoCreateGuid(&guid);
snprintf(uid, uidlen, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6],
guid.Data4[7]);
return 0;
#elif defined(_TD_DARWIN_64)
uuid_t uuid = {0};
char buf[UUIDLEN37];
memset(buf, 0, UUIDLEN37);
uuid_generate(uuid);
// it's caller's responsibility to make enough space for `uid`, that's 36-char + 1-null
uuid_unparse_lower(uuid, buf);
int n = snprintf(uid, uidlen, "%.*s", (int)sizeof(buf), buf); // though less performance, much safer
if (n >= uidlen) {
// target buffer is too small
return -1;
}
return 0;
#else
int len = 0;
// fd = open("/proc/sys/kernel/random/uuid", 0);
TdFilePtr pFile = taosOpenFile("/proc/sys/kernel/random/uuid", TD_FILE_READ);
if (pFile == NULL) {
return -1;
} else {
len = taosReadFile(pFile, uid, uidlen);
taosCloseFile(&pFile);
}
if (len >= 36) {
uid[36] = 0;
return 0;
}
return 0;
#endif
}
char *taosGetCmdlineByPID(int pid) {
#ifdef WINDOWS
ASSERT(0);
return "";
#elif defined(_TD_DARWIN_64)
static char cmdline[1024];
errno = 0;
if (proc_pidpath(pid, cmdline, sizeof(cmdline)) <= 0) {
fprintf(stderr, "PID is %d, %s", pid, strerror(errno));
return strerror(errno);
}
return cmdline;
#else
static char cmdline[1024];
sprintf(cmdline, "/proc/%d/cmdline", pid);
// int fd = open(cmdline, O_RDONLY);
TdFilePtr pFile = taosOpenFile(cmdline, TD_FILE_READ);
if (pFile != NULL) {
int n = taosReadFile(pFile, cmdline, sizeof(cmdline) - 1);
if (n < 0) n = 0;
if (n > 0 && cmdline[n - 1] == '\n') --n;
cmdline[n] = 0;
taosCloseFile(&pFile);
} else {
cmdline[0] = 0;
}
return cmdline;
#endif
}
void taosSetCoreDump(bool enable) {
if (!enable) return;
#ifdef WINDOWS
SetUnhandledExceptionFilter(exceptionHandler);
SetUnhandledExceptionFilter(&FlCrashDump);
#elif defined(_TD_DARWIN_64)
#else
// 1. set ulimit -c unlimited
struct rlimit rlim;
struct rlimit rlim_new;
if (getrlimit(RLIMIT_CORE, &rlim) == 0) {
#ifndef _ALPINE
// printf("the old unlimited para: rlim_cur=%" PRIu64 ", rlim_max=%" PRIu64, rlim.rlim_cur, rlim.rlim_max);
#else
// printf("the old unlimited para: rlim_cur=%llu, rlim_max=%llu", rlim.rlim_cur, rlim.rlim_max);
#endif
rlim_new.rlim_cur = RLIM_INFINITY;
rlim_new.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &rlim_new) != 0) {
// printf("set unlimited fail, error: %s", strerror(errno));
rlim_new.rlim_cur = rlim.rlim_max;
rlim_new.rlim_max = rlim.rlim_max;
(void)setrlimit(RLIMIT_CORE, &rlim_new);
}
}
if (getrlimit(RLIMIT_CORE, &rlim) == 0) {
#ifndef _ALPINE
// printf("the new unlimited para: rlim_cur=%" PRIu64 ", rlim_max=%" PRIu64, rlim.rlim_cur, rlim.rlim_max);
#else
// printf("the new unlimited para: rlim_cur=%llu, rlim_max=%llu", rlim.rlim_cur, rlim.rlim_max);
#endif
}
#ifndef _TD_ARM_
// 2. set the path for saving core file
struct __sysctl_args args;
int old_usespid = 0;
size_t old_len = 0;
int new_usespid = 1;
size_t new_len = sizeof(new_usespid);
int name[] = {CTL_KERN, KERN_CORE_USES_PID};
memset(&args, 0, sizeof(struct __sysctl_args));
args.name = name;
args.nlen = sizeof(name) / sizeof(name[0]);
args.oldval = &old_usespid;
args.oldlenp = &old_len;
args.newval = &new_usespid;
args.newlen = new_len;
old_len = sizeof(old_usespid);
#ifndef __loongarch64
if (syscall(SYS__sysctl, &args) == -1) {
// printf("_sysctl(kern_core_uses_pid) set fail: %s", strerror(errno));
}
#endif
// printf("The old core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid);
old_usespid = 0;
old_len = 0;
memset(&args, 0, sizeof(struct __sysctl_args));
args.name = name;
args.nlen = sizeof(name) / sizeof(name[0]);
args.oldval = &old_usespid;
args.oldlenp = &old_len;
old_len = sizeof(old_usespid);
#ifndef __loongarch64
if (syscall(SYS__sysctl, &args) == -1) {
// printf("_sysctl(kern_core_uses_pid) get fail: %s", strerror(errno));
}
#endif
// printf("The new core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid);
#endif
#endif
}
SysNameInfo taosGetSysNameInfo() {
#ifdef WINDOWS
SysNameInfo info = {0};
DWORD dwVersion = GetVersion();
char *tmp = NULL;
tmp = getenv("OS");
if (tmp != NULL) tstrncpy(info.sysname, tmp, sizeof(info.sysname));
tmp = getenv("COMPUTERNAME");
if (tmp != NULL) tstrncpy(info.nodename, tmp, sizeof(info.nodename));
sprintf_s(info.release, sizeof(info.release), "%d", dwVersion & 0x0F);
sprintf_s(info.version, sizeof(info.release), "%d", (dwVersion >> 8) & 0x0F);
tmp = getenv("PROCESSOR_ARCHITECTURE");
if (tmp != NULL) tstrncpy(info.machine, tmp, sizeof(info.machine));
return info;
#elif defined(_TD_DARWIN_64)
SysNameInfo info = {0};
struct utsname uts;
if (!uname(&uts)) {
tstrncpy(info.sysname, uts.sysname, sizeof(info.sysname));
tstrncpy(info.nodename, uts.nodename, sizeof(info.nodename));
tstrncpy(info.release, uts.release, sizeof(info.release));
tstrncpy(info.version, uts.version, sizeof(info.version));
tstrncpy(info.machine, uts.machine, sizeof(info.machine));
}
char localHostName[512];
taosGetlocalhostname(localHostName, 512);
TdCmdPtr pCmd = taosOpenCmd("scutil --get LocalHostName");
tstrncpy(info.nodename, localHostName, sizeof(info.nodename));
return info;
#else
SysNameInfo info = {0};
struct utsname uts;
if (!uname(&uts)) {
tstrncpy(info.sysname, uts.sysname, sizeof(info.sysname));
tstrncpy(info.nodename, uts.nodename, sizeof(info.nodename));
tstrncpy(info.release, uts.release, sizeof(info.release));
tstrncpy(info.version, uts.version, sizeof(info.version));
tstrncpy(info.machine, uts.machine, sizeof(info.machine));
}
return info;
#endif
}
bool taosCheckCurrentInDll() {
#ifdef WINDOWS
MEMORY_BASIC_INFORMATION mbi;
char path[PATH_MAX] = {0};
GetModuleFileName(
((VirtualQuery(taosCheckCurrentInDll, &mbi, sizeof(mbi)) != 0) ? (HMODULE)mbi.AllocationBase : NULL), path,
PATH_MAX);
int strLastIndex = strlen(path);
if ((path[strLastIndex - 3] == 'd' || path[strLastIndex - 3] == 'D') &&
(path[strLastIndex - 2] == 'l' || path[strLastIndex - 2] == 'L') &&
(path[strLastIndex - 1] == 'l' || path[strLastIndex - 1] == 'L')) {
return true;
}
return false;
#else
return false;
#endif
}
#ifdef _TD_DARWIN_64
int taosGetMaclocalhostnameByCommand(char *hostname, size_t maxLen) {
TdCmdPtr pCmd = taosOpenCmd("scutil --get LocalHostName");
if (pCmd != NULL) {
if (taosGetsCmd(pCmd, maxLen - 1, hostname) > 0) {
int len = strlen(hostname);
if (hostname[len - 1] == '\n') {
hostname[len - 1] = '\0';
}
return 0;
}
taosCloseCmd(&pCmd);
}
return -1;
}
int getMacLocalHostNameBySCD(char *hostname, size_t maxLen) {
SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR(""), NULL, NULL);
CFStringRef hostname_cfstr = SCDynamicStoreCopyLocalHostName(store);
if (hostname_cfstr != NULL) {
CFStringGetCString(hostname_cfstr, hostname, maxLen - 1, kCFStringEncodingMacRoman);
CFRelease(hostname_cfstr);
} else {
return -1;
}
CFRelease(store);
return 0;
}
#endif
int taosGetlocalhostname(char *hostname, size_t maxLen) {
#ifdef _TD_DARWIN_64
int res = getMacLocalHostNameBySCD(hostname, maxLen);
if (res != 0) {
return taosGetMaclocalhostnameByCommand(hostname, maxLen);
} else {
return 0;
}
#else
return gethostname(hostname, maxLen);
#endif
}