Skip to content

Commit

Permalink
FileSystem: Add non-blocking option to POSIXLock
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Dec 3, 2024
1 parent d93c713 commit 04e472d
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 14 deletions.
43 changes: 31 additions & 12 deletions src/common/file_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2788,55 +2788,66 @@ bool FileSystem::SetPathCompression(const char* path, bool enable)
return false;
}

static bool SetLock(int fd, bool lock)
static bool SetLock(int fd, bool lock, bool block, Error* error)
{
// We want to lock the whole file.
const off_t offs = lseek(fd, 0, SEEK_CUR);
if (offs < 0)
{
ERROR_LOG("lseek({}) failed: {}", fd, errno);
if (error)
error->SetErrno("lseek() failed: ", errno);
else
ERROR_LOG("lseek({}) failed: {}", fd, errno);
return false;
}

if (offs != 0 && lseek(fd, 0, SEEK_SET) < 0)
{
ERROR_LOG("lseek({}, 0) failed: {}", fd, errno);
if (error)
error->SetErrno("lseek(0) failed: ", errno);
else
ERROR_LOG("lseek({}, 0) failed: {}", fd, errno);
return false;
}

// bloody signals...
bool res;
for (;;)
{
res = (lockf(fd, lock ? F_LOCK : F_ULOCK, 0) == 0);
res = (lockf(fd, lock ? (block ? F_TLOCK : F_LOCK) : F_ULOCK, 0) == 0);
if (!res && errno == EINTR)
continue;
else
break;
}

if (!res)
{
if (error)
error->SetErrno("lockf() failed: ", errno);
else
ERROR_LOG("lockf() for {} failed: {}", lock ? "lock" : "unlock", errno);
}

if (lseek(fd, offs, SEEK_SET) < 0)
Panic("Repositioning file descriptor after lock failed.");

if (!res)
ERROR_LOG("lockf() for {} failed: {}", lock ? "lock" : "unlock", errno);

return res;
}

FileSystem::POSIXLock::POSIXLock() : m_fd(-1)
{
}

FileSystem::POSIXLock::POSIXLock(int fd) : m_fd(fd)
FileSystem::POSIXLock::POSIXLock(int fd, bool block, Error* error) : m_fd(fd)
{
if (!SetLock(m_fd, true))
if (!SetLock(m_fd, true, block, error))
m_fd = -1;
}

FileSystem::POSIXLock::POSIXLock(std::FILE* fp) : m_fd(fileno(fp))
FileSystem::POSIXLock::POSIXLock(std::FILE* fp, bool block, Error* error) : m_fd(fileno(fp))
{
if (!SetLock(m_fd, true))
if (!SetLock(m_fd, true, block, error))
m_fd = -1;
}

Expand All @@ -2846,9 +2857,17 @@ FileSystem::POSIXLock::POSIXLock(POSIXLock&& move)
}

FileSystem::POSIXLock::~POSIXLock()
{
Unlock();
}

void FileSystem::POSIXLock::Unlock()
{
if (m_fd >= 0)
SetLock(m_fd, false);
{
SetLock(m_fd, false, true, nullptr);
m_fd = -1;
}
}

FileSystem::POSIXLock& FileSystem::POSIXLock::operator=(POSIXLock&& move)
Expand Down
7 changes: 5 additions & 2 deletions src/common/file_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,18 @@ class POSIXLock
{
public:
POSIXLock();
POSIXLock(int fd);
POSIXLock(std::FILE* fp);
POSIXLock(int fd, bool block = true, Error* error = nullptr);
POSIXLock(std::FILE* fp, bool block = true, Error* error = nullptr);
POSIXLock(POSIXLock&& move);
POSIXLock(const POSIXLock&) = delete;
~POSIXLock();

POSIXLock& operator=(POSIXLock&& move);
POSIXLock& operator=(const POSIXLock&) = delete;

ALWAYS_INLINE bool IsLocked() const { return (m_fd >= 0); }
void Unlock();

private:
int m_fd;
};
Expand Down

0 comments on commit 04e472d

Please sign in to comment.