You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-29 08:21:15 +03:00
MCOL-5500 This patch adds cgroup v2 support with some sanity checks for (#2849)
values reported by cgroups v1
This commit is contained in:
@ -18,8 +18,10 @@
|
|||||||
#include "cgroupconfigurator.h"
|
#include "cgroupconfigurator.h"
|
||||||
#include "configcpp.h"
|
#include "configcpp.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
#include <charconv>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
|
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
@ -77,9 +79,8 @@ CGroupConfigurator::CGroupConfigurator()
|
|||||||
else
|
else
|
||||||
cGroupDefined = true;
|
cGroupDefined = true;
|
||||||
|
|
||||||
totalMemory = 0;
|
ifstream v2Check("/sys/fs/cgroup/cgroup.controllers");
|
||||||
totalSwap = 0;
|
cGroupVersion_ = (v2Check) ? v2 : v1;
|
||||||
printedWarning = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CGroupConfigurator::~CGroupConfigurator()
|
CGroupConfigurator::~CGroupConfigurator()
|
||||||
@ -88,9 +89,16 @@ CGroupConfigurator::~CGroupConfigurator()
|
|||||||
|
|
||||||
uint32_t CGroupConfigurator::getNumCoresFromCGroup()
|
uint32_t CGroupConfigurator::getNumCoresFromCGroup()
|
||||||
{
|
{
|
||||||
ostringstream filename_os;
|
ostringstream filenameOs;
|
||||||
filename_os << "/sys/fs/cgroup/cpuset/" << cGroupName << "/cpus";
|
if (cGroupVersion_ == v1)
|
||||||
string filename = filename_os.str();
|
{
|
||||||
|
filenameOs << "/sys/fs/cgroup/cpuset/" << cGroupName << "/cpuset.cpus";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filenameOs << "/sys/fs/cgroup/" << cGroupName << "/cpuset.cpus";
|
||||||
|
}
|
||||||
|
string filename = filenameOs.str();
|
||||||
|
|
||||||
ifstream in(filename.c_str());
|
ifstream in(filename.c_str());
|
||||||
string cpusString;
|
string cpusString;
|
||||||
@ -141,7 +149,7 @@ uint32_t CGroupConfigurator::getNumCoresFromCGroup()
|
|||||||
first = last + 1;
|
first = last + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cout << "found " << cpus << " CPUS in the string " << cpusString << endl;
|
cout << "found " << cpus << " CPUS in the string " << cpusString << endl;
|
||||||
return cpus;
|
return cpus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +163,7 @@ uint32_t CGroupConfigurator::getNumCoresFromProc()
|
|||||||
uint32_t CGroupConfigurator::getNumCores()
|
uint32_t CGroupConfigurator::getNumCores()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Detect if InfiniDB is in a C-Group
|
Detect if MCS is in a C-Group
|
||||||
- get the group ID
|
- get the group ID
|
||||||
If not, get the number of cores from /proc
|
If not, get the number of cores from /proc
|
||||||
*/
|
*/
|
||||||
@ -171,7 +179,7 @@ uint32_t CGroupConfigurator::getNumCores()
|
|||||||
ret = getNumCoresFromProc();
|
ret = getNumCoresFromProc();
|
||||||
}
|
}
|
||||||
|
|
||||||
// cout << "There are " << ret << " cores available" << endl;
|
cout << "There are " << ret << " cores available" << endl;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,11 +196,11 @@ uint64_t CGroupConfigurator::getTotalMemory()
|
|||||||
{
|
{
|
||||||
ret = getTotalMemoryFromCGroup();
|
ret = getTotalMemoryFromCGroup();
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0 || ret == std::numeric_limits<uint64_t>::max())
|
||||||
ret = getTotalMemoryFromProc();
|
ret = getTotalMemoryFromProc();
|
||||||
}
|
}
|
||||||
|
|
||||||
// cout << "Total mem available is " << ret << endl;
|
cout << "Total mem available is " << ret << endl;
|
||||||
totalMemory = ret;
|
totalMemory = ret;
|
||||||
return totalMemory;
|
return totalMemory;
|
||||||
}
|
}
|
||||||
@ -201,23 +209,11 @@ uint64_t CGroupConfigurator::getTotalMemoryFromProc()
|
|||||||
{
|
{
|
||||||
size_t memTot;
|
size_t memTot;
|
||||||
|
|
||||||
#if defined(__FreeBSD__)
|
|
||||||
string cmd("sysctl -a | awk '/realmem/ {print int(($2+1023)/1024);}'");
|
|
||||||
FILE* cmdPipe;
|
|
||||||
char input[80];
|
|
||||||
cmdPipe = popen(cmd.c_str(), "r");
|
|
||||||
input[0] = '\0';
|
|
||||||
fgets(input, 80, cmdPipe);
|
|
||||||
input[79] = '\0';
|
|
||||||
pclose(cmdPipe);
|
|
||||||
memTot = atoi(input);
|
|
||||||
#else
|
|
||||||
ifstream in("/proc/meminfo");
|
ifstream in("/proc/meminfo");
|
||||||
string x;
|
string x;
|
||||||
|
|
||||||
in >> x;
|
in >> x;
|
||||||
in >> memTot;
|
in >> memTot;
|
||||||
#endif
|
|
||||||
|
|
||||||
// memTot is now in KB, convert to bytes
|
// memTot is now in KB, convert to bytes
|
||||||
memTot *= 1024;
|
memTot *= 1024;
|
||||||
@ -227,40 +223,61 @@ uint64_t CGroupConfigurator::getTotalMemoryFromProc()
|
|||||||
|
|
||||||
uint64_t CGroupConfigurator::getTotalMemoryFromCGroup()
|
uint64_t CGroupConfigurator::getTotalMemoryFromCGroup()
|
||||||
{
|
{
|
||||||
ifstream in;
|
std::string memLimitStr;
|
||||||
uint64_t ret;
|
uint64_t memLimit = std::numeric_limits<uint64_t>::max();
|
||||||
ostringstream os;
|
ostringstream os;
|
||||||
string filename;
|
|
||||||
|
|
||||||
os << "/sys/fs/cgroup/memory/" << cGroupName << "/memory.limit_in_bytes";
|
if (cGroupVersion_ == v1)
|
||||||
filename = os.str();
|
{
|
||||||
|
os << "/sys/fs/cgroup/memory/" << cGroupName << "/memory.limit_in_bytes";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << "/sys/fs/cgroup/" << cGroupName << "/memory.max";
|
||||||
|
}
|
||||||
|
string filename = os.str();
|
||||||
|
|
||||||
in.open(filename.c_str());
|
ifstream in(filename.c_str());
|
||||||
|
|
||||||
if (!in)
|
if (!in)
|
||||||
RETURN_NO_GROUP(0);
|
RETURN_NO_GROUP(0);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
in >> ret;
|
in >> memLimitStr;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
RETURN_READ_ERROR(0);
|
RETURN_READ_ERROR(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
if (cGroupVersion_ == v2 && memLimitStr == "max")
|
||||||
|
{
|
||||||
|
return std::numeric_limits<uint64_t>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [ch, ec] = std::from_chars(memLimitStr.c_str(), memLimitStr.c_str() + memLimitStr.size(), memLimit);
|
||||||
|
if (ec != std::errc())
|
||||||
|
{
|
||||||
|
return std::numeric_limits<uint64_t>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cGroupVersion_ == v1)
|
||||||
|
{
|
||||||
|
return std::min(getTotalMemoryFromProc(), memLimit);
|
||||||
|
}
|
||||||
|
return memLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t CGroupConfigurator::getFreeMemory()
|
uint64_t CGroupConfigurator::getFreeMemory()
|
||||||
{
|
{
|
||||||
uint64_t ret;
|
uint64_t ret;
|
||||||
|
|
||||||
if (!cGroupDefined)
|
if (!cGroupDefined)
|
||||||
ret = getFreeMemoryFromProc();
|
ret = getFreeMemoryFromProc();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint64_t usage = getMemUsageFromCGroup();
|
uint64_t usage = getMemUsageFromCGroup();
|
||||||
|
cout << "usage " << usage << endl;
|
||||||
|
|
||||||
if (usage == 0)
|
if (usage == 0)
|
||||||
ret = getFreeMemoryFromProc();
|
ret = getFreeMemoryFromProc();
|
||||||
@ -268,20 +285,26 @@ uint64_t CGroupConfigurator::getFreeMemory()
|
|||||||
ret = getTotalMemory() - usage;
|
ret = getTotalMemory() - usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cout << "free memory = " << ret << endl;
|
cout << "free memory = " << ret << endl;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t CGroupConfigurator::getMemUsageFromCGroup()
|
uint64_t CGroupConfigurator::getMemUsageFromCGroup()
|
||||||
{
|
{
|
||||||
uint64_t ret = 0;
|
|
||||||
bool found = false;
|
|
||||||
char oneline[80];
|
char oneline[80];
|
||||||
|
|
||||||
if (memUsageFilename.empty())
|
if (memUsageFilename.empty())
|
||||||
{
|
{
|
||||||
ostringstream filename;
|
ostringstream filename;
|
||||||
filename << "/sys/fs/cgroup/memory/" << cGroupName << "/memory.stat";
|
if (cGroupVersion_ == v1)
|
||||||
|
{
|
||||||
|
memStatePrefix = "rss ";
|
||||||
|
filename << "/sys/fs/cgroup/memory/" << cGroupName << "/memory.stat";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memStatePrefix = "anon ";
|
||||||
|
filename << "/sys/fs/cgroup/" << cGroupName << "/memory.stat";
|
||||||
|
}
|
||||||
memUsageFilename = filename.str();
|
memUsageFilename = filename.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,14 +316,13 @@ uint64_t CGroupConfigurator::getMemUsageFromCGroup()
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (in && !found)
|
while (in)
|
||||||
{
|
{
|
||||||
in.getline(oneline, 80);
|
in.getline(oneline, 80);
|
||||||
|
|
||||||
if (strncmp(oneline, "rss", 2) == 0)
|
if (strncmp(oneline, memStatePrefix.c_str(), memStatePrefix.size() - 1) == 0)
|
||||||
{
|
{
|
||||||
ret = atoll(&oneline[3]);
|
return atoll(&oneline[memStatePrefix.size()]);
|
||||||
found = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,7 +331,7 @@ uint64_t CGroupConfigurator::getMemUsageFromCGroup()
|
|||||||
RETURN_READ_ERROR(0);
|
RETURN_READ_ERROR(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t CGroupConfigurator::getFreeMemoryFromProc()
|
uint64_t CGroupConfigurator::getFreeMemoryFromProc()
|
||||||
@ -320,10 +342,6 @@ uint64_t CGroupConfigurator::getFreeMemoryFromProc()
|
|||||||
uint64_t memTotal = 0;
|
uint64_t memTotal = 0;
|
||||||
uint64_t memAvailable = 0;
|
uint64_t memAvailable = 0;
|
||||||
|
|
||||||
#if defined(__FreeBSD__)
|
|
||||||
// FreeBSD is not supported, no optimization.
|
|
||||||
memAvailable = 0;
|
|
||||||
#else
|
|
||||||
ifstream in("/proc/meminfo");
|
ifstream in("/proc/meminfo");
|
||||||
string x;
|
string x;
|
||||||
|
|
||||||
@ -354,137 +372,9 @@ uint64_t CGroupConfigurator::getFreeMemoryFromProc()
|
|||||||
memAvailable = memFree + buffers + cached;
|
memAvailable = memFree + buffers + cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// amount available for application
|
// amount available for application
|
||||||
memAvailable *= 1024;
|
memAvailable *= 1024;
|
||||||
return memAvailable;
|
return memAvailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t CGroupConfigurator::getTotalSwapSpace()
|
|
||||||
{
|
|
||||||
int64_t ret;
|
|
||||||
|
|
||||||
if (totalSwap != 0)
|
|
||||||
return totalSwap;
|
|
||||||
|
|
||||||
if (!cGroupDefined)
|
|
||||||
ret = getTotalSwapFromSysinfo();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = getTotalMemAndSwapFromCGroup();
|
|
||||||
|
|
||||||
// if no limit is set in the cgroup, the file contains maxint64. Use sysinfo in that case.
|
|
||||||
if (ret == -1 || ret == numeric_limits<int64_t>::max())
|
|
||||||
ret = getTotalSwapFromSysinfo();
|
|
||||||
else
|
|
||||||
ret -= getTotalMemory();
|
|
||||||
}
|
|
||||||
|
|
||||||
// cout << "total swap=" << ret << endl;
|
|
||||||
totalSwap = ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t CGroupConfigurator::getTotalSwapFromSysinfo()
|
|
||||||
{
|
|
||||||
struct sysinfo si;
|
|
||||||
|
|
||||||
sysinfo(&si);
|
|
||||||
return si.totalswap;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t CGroupConfigurator::getTotalMemAndSwapFromCGroup()
|
|
||||||
{
|
|
||||||
int64_t ret;
|
|
||||||
ifstream in;
|
|
||||||
string filename;
|
|
||||||
ostringstream os;
|
|
||||||
|
|
||||||
os << "/sys/fs/cgroup/memory/" << cGroupName << "/memory.memsw.limit_in_bytes";
|
|
||||||
filename = os.str();
|
|
||||||
in.open(filename.c_str());
|
|
||||||
|
|
||||||
if (!in)
|
|
||||||
RETURN_NO_GROUP(-1);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
in >> ret;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
RETURN_READ_ERROR(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t CGroupConfigurator::getSwapInUse()
|
|
||||||
{
|
|
||||||
int64_t ret;
|
|
||||||
|
|
||||||
if (!cGroupDefined)
|
|
||||||
ret = getSwapInUseFromSysinfo();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = getSwapInUseFromCGroup();
|
|
||||||
|
|
||||||
if (ret == -1)
|
|
||||||
ret = getSwapInUseFromSysinfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
// cout << "current swap in use=" << ret << endl;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t CGroupConfigurator::getSwapInUseFromCGroup()
|
|
||||||
{
|
|
||||||
int64_t ret = -1;
|
|
||||||
ifstream in;
|
|
||||||
bool found = false;
|
|
||||||
char oneline[80];
|
|
||||||
|
|
||||||
if (usedSwapFilename.empty())
|
|
||||||
{
|
|
||||||
ostringstream os;
|
|
||||||
os << "/sys/fs/cgroup/memory/" << cGroupName << "/memory.stat";
|
|
||||||
usedSwapFilename = os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
string& filename = usedSwapFilename;
|
|
||||||
in.open(filename.c_str());
|
|
||||||
|
|
||||||
if (!in)
|
|
||||||
RETURN_NO_GROUP(-1);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (in && !found)
|
|
||||||
{
|
|
||||||
in.getline(oneline, 80);
|
|
||||||
|
|
||||||
if (strncmp(oneline, "swap", 4) == 0)
|
|
||||||
{
|
|
||||||
ret = atoll(&oneline[5]);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
RETURN_READ_ERROR(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t CGroupConfigurator::getSwapInUseFromSysinfo()
|
|
||||||
{
|
|
||||||
struct sysinfo si;
|
|
||||||
|
|
||||||
sysinfo(&si);
|
|
||||||
return si.totalswap - si.freeswap;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
@ -31,14 +31,17 @@ namespace utils
|
|||||||
class CGroupConfigurator
|
class CGroupConfigurator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum CGroupVersions
|
||||||
|
{
|
||||||
|
v1,
|
||||||
|
v2,
|
||||||
|
};
|
||||||
CGroupConfigurator();
|
CGroupConfigurator();
|
||||||
virtual ~CGroupConfigurator();
|
virtual ~CGroupConfigurator();
|
||||||
|
|
||||||
uint32_t getNumCores();
|
uint32_t getNumCores();
|
||||||
uint64_t getTotalMemory();
|
uint64_t getTotalMemory();
|
||||||
uint64_t getFreeMemory();
|
uint64_t getFreeMemory();
|
||||||
uint64_t getTotalSwapSpace();
|
|
||||||
uint64_t getSwapInUse();
|
|
||||||
|
|
||||||
bool usingCGroup()
|
bool usingCGroup()
|
||||||
{
|
{
|
||||||
@ -52,20 +55,16 @@ class CGroupConfigurator
|
|||||||
uint64_t getTotalMemoryFromCGroup();
|
uint64_t getTotalMemoryFromCGroup();
|
||||||
uint64_t getFreeMemoryFromProc();
|
uint64_t getFreeMemoryFromProc();
|
||||||
uint64_t getMemUsageFromCGroup();
|
uint64_t getMemUsageFromCGroup();
|
||||||
uint64_t getTotalSwapFromSysinfo();
|
|
||||||
int64_t getTotalMemAndSwapFromCGroup();
|
|
||||||
uint64_t getSwapInUseFromSysinfo();
|
|
||||||
int64_t getSwapInUseFromCGroup();
|
|
||||||
|
|
||||||
std::string memUsageFilename;
|
|
||||||
std::string usedSwapFilename;
|
|
||||||
|
|
||||||
std::string cGroupName;
|
std::string cGroupName;
|
||||||
|
std::string memUsageFilename;
|
||||||
|
std::string memStatePrefix;
|
||||||
bool cGroupDefined;
|
bool cGroupDefined;
|
||||||
config::Config* config;
|
config::Config* config;
|
||||||
uint64_t totalMemory;
|
uint64_t totalMemory = 0;
|
||||||
uint64_t totalSwap;
|
uint64_t totalSwap = 0;
|
||||||
bool printedWarning;
|
bool printedWarning = false;
|
||||||
|
enum CGroupVersions cGroupVersion_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
Reference in New Issue
Block a user