FileSystem: Add non-blocking option to POSIXLock

This commit is contained in:
Stenzek 2024-12-03 17:10:54 +10:00
parent d93c713fb7
commit 04e472d088
No known key found for this signature in database
2 changed files with 36 additions and 14 deletions

View File

@ -2788,19 +2788,25 @@ bool FileSystem::SetPathCompression(const char* path, bool enable)
return false; 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. // We want to lock the whole file.
const off_t offs = lseek(fd, 0, SEEK_CUR); const off_t offs = lseek(fd, 0, SEEK_CUR);
if (offs < 0) 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; return false;
} }
if (offs != 0 && lseek(fd, 0, SEEK_SET) < 0) 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; return false;
} }
@ -2808,19 +2814,24 @@ static bool SetLock(int fd, bool lock)
bool res; bool res;
for (;;) 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) if (!res && errno == EINTR)
continue; continue;
else else
break; 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) if (lseek(fd, offs, SEEK_SET) < 0)
Panic("Repositioning file descriptor after lock failed."); Panic("Repositioning file descriptor after lock failed.");
if (!res)
ERROR_LOG("lockf() for {} failed: {}", lock ? "lock" : "unlock", errno);
return res; return res;
} }
@ -2828,15 +2839,15 @@ 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; 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; m_fd = -1;
} }
@ -2846,9 +2857,17 @@ FileSystem::POSIXLock::POSIXLock(POSIXLock&& move)
} }
FileSystem::POSIXLock::~POSIXLock() FileSystem::POSIXLock::~POSIXLock()
{
Unlock();
}
void FileSystem::POSIXLock::Unlock()
{ {
if (m_fd >= 0) if (m_fd >= 0)
SetLock(m_fd, false); {
SetLock(m_fd, false, true, nullptr);
m_fd = -1;
}
} }
FileSystem::POSIXLock& FileSystem::POSIXLock::operator=(POSIXLock&& move) FileSystem::POSIXLock& FileSystem::POSIXLock::operator=(POSIXLock&& move)

View File

@ -160,8 +160,8 @@ class POSIXLock
{ {
public: public:
POSIXLock(); POSIXLock();
POSIXLock(int fd); POSIXLock(int fd, bool block = true, Error* error = nullptr);
POSIXLock(std::FILE* fp); POSIXLock(std::FILE* fp, bool block = true, Error* error = nullptr);
POSIXLock(POSIXLock&& move); POSIXLock(POSIXLock&& move);
POSIXLock(const POSIXLock&) = delete; POSIXLock(const POSIXLock&) = delete;
~POSIXLock(); ~POSIXLock();
@ -169,6 +169,9 @@ public:
POSIXLock& operator=(POSIXLock&& move); POSIXLock& operator=(POSIXLock&& move);
POSIXLock& operator=(const POSIXLock&) = delete; POSIXLock& operator=(const POSIXLock&) = delete;
ALWAYS_INLINE bool IsLocked() const { return (m_fd >= 0); }
void Unlock();
private: private:
int m_fd; int m_fd;
}; };