Fix long shutdown of FileLog storage

Previously it was possible to wait up to
poll_directory_watch_events_backoff_max (default is 32000) on shutdown,
because it was not possible to stop poll of inotify.

Before (takes 3 seconds):

    2024.02.12 11:27:55.058192 [ 10134 ] {} <Trace> StorageFileLog (file_log): Waiting for cleanup
    2024.02.12 11:27:58.178021 [ 10271 ] {} <Trace> directory_watch: Execution took 7519 ms.

After:

    2024.02.12 11:33:29.722403 [ 15866 ] {} <Trace> StorageFileLog (file_log): Waiting for cleanup
    2024.02.12 11:33:29.722473 [ 15956 ] {} <Trace> directory_watch: Execution took 6399 ms.

Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
This commit is contained in:
Azat Khuzhin 2024-02-12 11:33:40 +01:00
parent 67bb3994ce
commit 67b73c3e49
2 changed files with 20 additions and 14 deletions

View File

@ -34,8 +34,8 @@ DirectoryWatcherBase::DirectoryWatcherBase(
if (!std::filesystem::is_directory(path))
throw Exception(ErrorCodes::BAD_FILE_TYPE, "Path {} is not a directory", path);
fd = inotify_init();
if (fd == -1)
inotify_fd = inotify_init();
if (inotify_fd == -1)
throw ErrnoException(ErrorCodes::IO_SETUP_ERROR, "Cannot initialize inotify");
watch_task = getContext()->getSchedulePool().createTask("directory_watch", [this] { watchFunc(); });
@ -56,7 +56,7 @@ void DirectoryWatcherBase::watchFunc()
if (eventMask() & DirectoryWatcherBase::DW_ITEM_MOVED_TO)
mask |= IN_MOVED_TO;
int wd = inotify_add_watch(fd, path.c_str(), mask);
int wd = inotify_add_watch(inotify_fd, path.c_str(), mask);
if (wd == -1)
{
owner.onError(Exception(ErrorCodes::IO_SETUP_ERROR, "Watch directory {} failed", path));
@ -65,16 +65,20 @@ void DirectoryWatcherBase::watchFunc()
std::string buffer;
buffer.resize(buffer_size);
pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN;
pollfd pfds[2];
/// inotify descriptor
pfds[0].fd = inotify_fd;
pfds[0].events = POLLIN;
// notifier
pfds[1].fd = event_pipe.fds_rw[0];
pfds[1].events = POLLIN;
while (!stopped)
{
const auto & settings = owner.storage.getFileLogSettings();
if (poll(&pfd, 1, static_cast<int>(milliseconds_to_wait)) > 0 && pfd.revents & POLLIN)
if (poll(pfds, 2, static_cast<int>(milliseconds_to_wait)) > 0 && pfds[0].revents & POLLIN)
{
milliseconds_to_wait = settings->poll_directory_watch_events_backoff_init.totalMilliseconds();
ssize_t n = read(fd, buffer.data(), buffer.size());
ssize_t n = read(inotify_fd, buffer.data(), buffer.size());
int i = 0;
if (n > 0)
{
@ -130,7 +134,7 @@ void DirectoryWatcherBase::watchFunc()
DirectoryWatcherBase::~DirectoryWatcherBase()
{
stop();
int err = ::close(fd);
int err = ::close(inotify_fd);
chassert(!err || errno == EINTR);
}
@ -143,6 +147,7 @@ void DirectoryWatcherBase::start()
void DirectoryWatcherBase::stop()
{
stopped = true;
::write(event_pipe.fds_rw[1], "\0", 1);
if (watch_task)
watch_task->deactivate();
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <Core/BackgroundSchedulePool.h>
#include <Common/PipeFDs.h>
#include <atomic>
#include <memory>
@ -85,10 +86,6 @@ public:
void watchFunc();
protected:
void start();
void stop();
private:
FileLogDirectoryWatcher & owner;
@ -102,7 +99,11 @@ private:
int event_mask;
uint64_t milliseconds_to_wait;
int fd;
int inotify_fd;
PipeFDs event_pipe;
void start();
void stop();
};
}