Re-factor Util::checkDiskSpace() into separate parts

We will later want to just to a disk space check for the file system a
file is on, without registering that file system for periodic checks.

Adapt callers to keep working like before.
This commit is contained in:
Tor Lillqvist 2016-09-30 12:05:36 +03:00
parent ec88a53072
commit 9511bbda71
3 changed files with 68 additions and 41 deletions

View file

@ -230,7 +230,7 @@ static void forkChildren(const int number)
if (number > 0)
{
Util::checkDiskSpace("");
Util::checkDiskSpaceOnRegisteredFileSystems();
const std::string aMessage = "spawn " + std::to_string(number) + "\n";
Log::debug("MasterToForKit: " + aMessage.substr(0, aMessage.length() - 1));
IoUtil::writeFIFO(LOOLWSD::ForKitWritePipe, aMessage);
@ -779,7 +779,7 @@ private:
Log::trace("Sending to Client [" + status + "].");
ws->sendFrame(status.data(), (int) status.size());
Util::checkDiskSpace("");
Util::checkDiskSpaceOnRegisteredFileSystems();
// Let messages flow
IoUtil::SocketProcessor(ws,
@ -1832,8 +1832,8 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
else if (ChildRoot[ChildRoot.size() - 1] != '/')
ChildRoot += '/';
Util::checkDiskSpace(ChildRoot);
Util::checkDiskSpace(Cache + "/.");
Util::registerFileSystemForDiskSpaceChecks(ChildRoot);
Util::registerFileSystemForDiskSpaceChecks(Cache + "/.");
if (FileServerRoot.empty())
FileServerRoot = Poco::Path(Application::instance().commandPath()).parent().parent().toString();

View file

@ -212,36 +212,44 @@ namespace Util
}
}
void checkDiskSpace(const std::string& path)
} // namespace Util
namespace
{
struct fs
{
static std::mutex mutex;
std::lock_guard<std::mutex> lock(mutex);
struct fs
fs(const std::string& p, dev_t d)
: path(p), dev(d)
{
fs(const std::string& p, dev_t d)
: path(p), dev(d)
{
}
}
fs(dev_t d)
: fs("", d)
{
}
std::string path;
dev_t dev;
};
struct fsComparator
fs(dev_t d)
: fs("", d)
{
bool operator() (const fs& lhs, const fs& rhs) const
{
return (lhs.dev < rhs.dev);
}
};
}
static std::set<fs, fsComparator> filesystems;
std::string path;
dev_t dev;
};
struct fsComparator
{
bool operator() (const fs& lhs, const fs& rhs) const
{
return (lhs.dev < rhs.dev);
}
};
static std::mutex fsmutex;
static std::set<fs, fsComparator> filesystems;
} // unnamed namespace
namespace Util
{
void registerFileSystemForDiskSpaceChecks(const std::string& path)
{
std::lock_guard<std::mutex> lock(fsmutex);
if (path != "")
{
@ -255,11 +263,16 @@ namespace Util
return;
filesystems.insert(fs(dirPath, s.st_dev));
}
}
void checkDiskSpaceOnRegisteredFileSystems()
{
std::lock_guard<std::mutex> lock(fsmutex);
static std::chrono::steady_clock::time_point lastCheck;
std::chrono::steady_clock::time_point now(std::chrono::steady_clock::now());
// Don't check disk space more often that once a minute
// Don't check more often that once a minute
if (std::chrono::duration_cast<std::chrono::seconds>(now - lastCheck).count() < 60)
return;
@ -267,13 +280,7 @@ namespace Util
for (auto& i: filesystems)
{
struct stat s;
struct statfs sfs;
if (stat(i.path.c_str(), &s) == -1 ||
statfs(i.path.c_str(), &sfs) == -1)
continue;
if (static_cast<double>(sfs.f_bavail) / sfs.f_blocks <= 0.05)
if (!checkDiskSpace(i.path))
{
alertAllUsersAndLog("File system of " + i.path + " dangerously low on disk space", "internal", "diskfull");
break;
@ -281,6 +288,18 @@ namespace Util
}
}
bool checkDiskSpace(const std::string& path)
{
assert(path != "");
struct statfs sfs;
if (statfs(path.c_str(), &sfs) == -1)
return true;
if (static_cast<double>(sfs.f_bavail) / sfs.f_blocks <= 0.05)
return false;
return true;
}
const char *signalName(const int signo)
{
switch (signo)

View file

@ -73,12 +73,20 @@ namespace Util
}
#endif
// Check disk space on a list of file systems. The list is initially empty, and each call to the
// function with a non-empty 'path' adds the file system that path is located on to the list, if
// not already there. If the free space on any of the file systems in question is below 5%, call
// Add the file system that 'path' is located on to a list of file systems that are periodically
// checked for available space. The list is initially empty.
void registerFileSystemForDiskSpaceChecks(const std::string& path);
// Perform the check. If the free space on any of the registered file systems is below 5%, call
// 'alertAllUsers("internal", "diskfull")'. The check will be made no more often than once a
// minute.
void checkDiskSpace(const std::string& path);
void checkDiskSpaceOnRegisteredFileSystems();
// Check disk space on a specific file system, the one where 'path' is located. This does not
// add that file system to the list used by 'registerFileSystemForDiskSpaceChecks'. If the free
// space on the file system is below 5%, return false, otherwise true. Note that this function
// does not call 'alertAllUsers'.
bool checkDiskSpace(const std::string& path);
/// Assert that a lock is already taken.
template <typename T>