356 lines
6.9 KiB
C++
356 lines
6.9 KiB
C++
|
#include "referer.h"
|
||
|
|
||
|
|
||
|
#include "log_util.h"
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// refer
|
||
|
refer::refer() : ref_(1)
|
||
|
{
|
||
|
on_born();
|
||
|
}
|
||
|
refer::~refer()
|
||
|
{
|
||
|
on_dead();
|
||
|
}
|
||
|
|
||
|
void refer::on_born(void)
|
||
|
{}
|
||
|
void refer::on_dead(void)
|
||
|
{}
|
||
|
|
||
|
int32_t refer::add_ref(void)
|
||
|
{
|
||
|
LOCKER lock(mutex_);
|
||
|
|
||
|
return ++ref_;
|
||
|
}
|
||
|
int32_t refer::release(void)
|
||
|
{
|
||
|
int32_t ref = 0;
|
||
|
|
||
|
{
|
||
|
LOCKER lock(mutex_);
|
||
|
ref = --ref_;
|
||
|
}
|
||
|
|
||
|
if (ref == 0)
|
||
|
delete this;
|
||
|
|
||
|
return ref;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// chronograph
|
||
|
#include <sys/time.h>
|
||
|
|
||
|
|
||
|
chronograph::chronograph()
|
||
|
{
|
||
|
reset();
|
||
|
}
|
||
|
chronograph::~chronograph()
|
||
|
{}
|
||
|
|
||
|
bool chronograph::now(struct timeval* tv)
|
||
|
{
|
||
|
struct timezone tz = { 0 };
|
||
|
|
||
|
return gettimeofday(tv, &tz) == 0;
|
||
|
}
|
||
|
bool chronograph::now(uint64_t* seconds, uint64_t* u_seconds)
|
||
|
{
|
||
|
struct timeval tv = { 0 };
|
||
|
struct timezone tz = { 0 };
|
||
|
|
||
|
if (gettimeofday(&tv, &tz) == 0)
|
||
|
{
|
||
|
if (seconds)
|
||
|
*seconds = tv.tv_sec;
|
||
|
if (u_seconds)
|
||
|
*u_seconds = tv.tv_usec;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
std::string chronograph::now(bool with_ms/*whether with milliseconds*/) // return '2022-11-30 10:38:42.123', no '.123' if with_ms was false
|
||
|
{
|
||
|
struct timeval tv = { 0 };
|
||
|
|
||
|
if (!chronograph::now(&tv))
|
||
|
return "";
|
||
|
|
||
|
char buf[40] = { 0 };
|
||
|
time_t t = tv.tv_sec;
|
||
|
struct tm* l = localtime(&t);
|
||
|
|
||
|
if (with_ms)
|
||
|
sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%06d", l->tm_year + 1900, l->tm_mon + 1, l->tm_mday
|
||
|
, l->tm_hour, l->tm_min, l->tm_sec, tv.tv_usec);
|
||
|
else
|
||
|
sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", l->tm_year + 1900, l->tm_mon + 1, l->tm_mday
|
||
|
, l->tm_hour, l->tm_min, l->tm_sec);
|
||
|
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
uint64_t chronograph::elapse_s(void)
|
||
|
{
|
||
|
struct timeval tv = { 0 };
|
||
|
|
||
|
chronograph::now(&tv);
|
||
|
|
||
|
return tv.tv_sec - bgn_.tv_sec;
|
||
|
}
|
||
|
uint64_t chronograph::elapse_ms(void)
|
||
|
{
|
||
|
struct timeval tv = { 0 };
|
||
|
uint64_t dif = 0;
|
||
|
|
||
|
chronograph::now(&tv);
|
||
|
dif = SEC_2_MS(tv.tv_sec - bgn_.tv_sec);
|
||
|
dif += tv.tv_usec / MSEC_2_US(1);
|
||
|
dif -= bgn_.tv_usec / MSEC_2_US(1);
|
||
|
|
||
|
return dif;
|
||
|
}
|
||
|
uint64_t chronograph::elapse_us(void)
|
||
|
{
|
||
|
struct timeval tv = { 0 };
|
||
|
uint64_t dif = 0;
|
||
|
|
||
|
chronograph::now(&tv);
|
||
|
dif = SEC_2_US(tv.tv_sec - bgn_.tv_sec);
|
||
|
dif += tv.tv_usec;
|
||
|
dif -= bgn_.tv_usec;
|
||
|
|
||
|
return dif;
|
||
|
}
|
||
|
void chronograph::reset()
|
||
|
{
|
||
|
chronograph::now(&bgn_);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// sys utility
|
||
|
#include <dirent.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
namespace sys_util
|
||
|
{
|
||
|
static bool find_module(const char* path, void* param)
|
||
|
{
|
||
|
std::string* para = (std::string*)param;
|
||
|
|
||
|
if (para[0].empty())
|
||
|
{
|
||
|
para[1] = path;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
const char* name = strrchr(path, '/');
|
||
|
if (name++ == nullptr)
|
||
|
name = path;
|
||
|
if (strstr(name, para[0].c_str()))
|
||
|
{
|
||
|
para[1] = path;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int32_t enum_modules(bool(*on_found)(const char* path_module_name, void* param),// return false to stop enumeratin
|
||
|
void* param, // user defined data, passed into callback on_found
|
||
|
unsigned pid // process id, -1 is self
|
||
|
) // return errno
|
||
|
{
|
||
|
char path[128] = { 0 };
|
||
|
|
||
|
if (pid == -1)
|
||
|
pid = getpid();
|
||
|
sprintf(path, "/proc/%u/map_files/", pid);
|
||
|
|
||
|
return enum_files(path, on_found, param, false);
|
||
|
}
|
||
|
|
||
|
int32_t enum_files(const char* dir, // dir path
|
||
|
bool(*on_found)(const char* path_name, void* param), // return false to stop enumeratin
|
||
|
void* param // user defined data, passed into callback on_found
|
||
|
, bool recursive
|
||
|
) // return errno
|
||
|
{
|
||
|
int32_t ret = 0;
|
||
|
DIR* pdir = nullptr;
|
||
|
struct dirent* ent = nullptr;
|
||
|
|
||
|
pdir = opendir(dir);
|
||
|
if (!pdir)
|
||
|
return errno;
|
||
|
|
||
|
while ((ent = readdir(pdir)))
|
||
|
{
|
||
|
if (ent->d_type & DT_DIR)
|
||
|
{
|
||
|
if (recursive)
|
||
|
{
|
||
|
if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, ".."))
|
||
|
{
|
||
|
std::string sub(dir);
|
||
|
sub += "/";
|
||
|
sub += ent->d_name;
|
||
|
ret = enum_files(sub.c_str(), on_found, param, recursive);
|
||
|
if (ret == 0x5e17)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
std::string file(dir);
|
||
|
|
||
|
file += "/";
|
||
|
file += ent->d_name;
|
||
|
if (!on_found(read_link(file.c_str()).c_str(), param))
|
||
|
{
|
||
|
ret = 0x5e17;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
closedir(pdir);
|
||
|
|
||
|
return ret == 0x5e17 ? 0 : ret;
|
||
|
}
|
||
|
|
||
|
std::string get_module_path(const char* module_name, unsigned pid) // get module full path, nullptr is for main-exe
|
||
|
{
|
||
|
std::string param[] = { module_name ? module_name : "", "" };
|
||
|
|
||
|
enum_modules(find_module, param, pid);
|
||
|
|
||
|
return param[1];
|
||
|
}
|
||
|
std::string read_link(const char* lnk)
|
||
|
{
|
||
|
char path[512] = { 0 };
|
||
|
|
||
|
readlink(lnk, path, sizeof(path) - 1);
|
||
|
|
||
|
return path;
|
||
|
}
|
||
|
size_t get_page_size(void)
|
||
|
{
|
||
|
size_t size = sysconf(_SC_PAGESIZE);
|
||
|
|
||
|
if (size < 1024 || (size & 0x0fe0000ff)) // nKB && < 16MB
|
||
|
size = getpagesize();
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
bool create_folder(const char* dir)
|
||
|
{
|
||
|
return mkdir(dir, S_IREAD | S_IWRITE | S_IEXEC) == 0 || errno == EEXIST;
|
||
|
}
|
||
|
|
||
|
int32_t get_memory_info(uint64_t* total, uint64_t* available)
|
||
|
{
|
||
|
if(!total && !available)
|
||
|
return 0;
|
||
|
|
||
|
char line[128] = {0};
|
||
|
FILE *src = fopen("/proc/meminfo", "rb");
|
||
|
int32_t count = total && available ? 2 : 1;
|
||
|
unsigned long val = 0;
|
||
|
|
||
|
if(!src)
|
||
|
return log_cls::log_when_err(-1, "fopen('/proc/meminfo', 'rb')", LOG_LEVEL_FATAL);
|
||
|
|
||
|
while(fgets(line, sizeof(line) - 1, src))
|
||
|
{
|
||
|
if(sscanf(line, "MemTotal: %ld", &val))
|
||
|
{
|
||
|
if(total)
|
||
|
{
|
||
|
*total = val * 1024;
|
||
|
if(--count == 0)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else if(sscanf(line, "MemFree: %ld", &val))
|
||
|
{
|
||
|
if(available)
|
||
|
{
|
||
|
*available = val * 1024;
|
||
|
if(--count == 0)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fclose(src);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
std::string format_readable_bytes(uint64_t bytes)
|
||
|
{
|
||
|
std::string str("\0", 80);
|
||
|
|
||
|
if(bytes >= SIZE_GB(1))
|
||
|
{
|
||
|
double v = bytes * 1.0f / (SIZE_GB(1));
|
||
|
size_t pos = 0;
|
||
|
|
||
|
sprintf(&str[0], "%.2fGB", v);
|
||
|
pos = str.find(".");
|
||
|
while(pos > 3)
|
||
|
{
|
||
|
pos -= 3;
|
||
|
str.insert(pos, ",");
|
||
|
}
|
||
|
}
|
||
|
else if(bytes >= SIZE_MB(1))
|
||
|
{
|
||
|
double v = bytes * 1.0f / (SIZE_MB(1));
|
||
|
sprintf(&str[0], "%.2fMB", v);
|
||
|
}
|
||
|
else if(bytes >= SIZE_KB(1))
|
||
|
{
|
||
|
double v = bytes * 1.0f / (SIZE_KB(1));
|
||
|
sprintf(&str[0], "%.2fKB", v);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sprintf(&str[0], "%uB", (unsigned)bytes);
|
||
|
}
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
}
|
||
|
|