Skip to content
Snippets Groups Projects
Commit 03b84df8 authored by Rob Swindell's avatar Rob Swindell :speech_balloon:
Browse files

Add/use xp_lockfile() to support blocking file range/region lock acquisition

Under heavy loads, I've found periodic non-blocking lock attempts just aren't
reliable enough: in particular, on Vertrauen, the guest user account record
in the user.tab file gets read and written-to A LOT (updating stats), and
under heavy loads (especially with hundreds of web client sessions), I'd get
timeouts attempting to lock the guest record in the user.tab (after about a
minute of periodic retries) - so let's just block "forever" to get the user
record lock (or until signaled or notified of a deadlock). With this change,
I've not had any user.tab lock errors or apparent deadlocks.

Let the underlying OS/filesystem handle queuing and deadlock detection,
when supported. lock() still behaves as before: non-blocking lock attempt.
parent b422688e
No related branches found
No related tags found
No related merge requests found
...@@ -283,12 +283,7 @@ bool lockuserdat(int file, unsigned user_number) ...@@ -283,12 +283,7 @@ bool lockuserdat(int file, unsigned user_number)
off_t offset = userdatoffset(user_number); off_t offset = userdatoffset(user_number);
unsigned attempt=0; return xp_lockfile(file, offset, USER_RECORD_LINE_LEN, /* block: */true) == 0;
while(attempt < LOOP_USERDAT && lock(file, offset, USER_RECORD_LINE_LEN) == -1) {
attempt++;
RETRY_DELAY(attempt);
}
return attempt < LOOP_USERDAT;
} }
bool unlockuserdat(int file, unsigned user_number) bool unlockuserdat(int file, unsigned user_number)
......
...@@ -83,13 +83,15 @@ off_t filelength(int fd) ...@@ -83,13 +83,15 @@ off_t filelength(int fd)
#if defined F_OFD_SETLK #if defined F_OFD_SETLK
#undef F_SETLK #undef F_SETLK
#define F_SETLK F_OFD_SETLK #define F_SETLK F_OFD_SETLK
#undef F_SETLKW
#define F_SETLKW F_OFD_SETLKW
#else #else
#warning Linux OFD locks not enabled! #warning Linux OFD locks not enabled!
#endif #endif
#endif #endif
/* Sets a lock on a portion of a file */ /* Sets a lock on a portion of a file */
int lock(int fd, off_t pos, off_t len) int xp_lockfile(int fd, off_t pos, off_t len, bool block)
{ {
#if defined USE_FCNTL_LOCKS #if defined USE_FCNTL_LOCKS
struct flock alock = {0}; struct flock alock = {0};
...@@ -106,12 +108,15 @@ int lock(int fd, off_t pos, off_t len) ...@@ -106,12 +108,15 @@ int lock(int fd, off_t pos, off_t len)
alock.l_start = pos; alock.l_start = pos;
alock.l_len = (int)len; alock.l_len = (int)len;
int result = fcntl(fd, F_SETLK, &alock); int result = fcntl(fd, block ? F_SETLKW : F_SETLK, &alock);
if(result == -1 && errno != EINVAL) if(result == -1 && errno != EINVAL)
return -1; return -1;
#elif !defined(__QNX__) && !defined(__solaris__) #elif !defined(__QNX__) && !defined(__solaris__)
int op = LOCK_EX;
if(!block)
op |= LOCK_NB;
/* use flock (doesn't work over NFS) */ /* use flock (doesn't work over NFS) */
if(flock(fd,LOCK_EX|LOCK_NB)!=0 && errno != EOPNOTSUPP) if(flock(fd, op) != 0 && errno != EOPNOTSUPP)
return(-1); return(-1);
#endif #endif
return(0); return(0);
...@@ -244,7 +249,7 @@ int sopen(const char *fn, int sh_access, int share, ...) ...@@ -244,7 +249,7 @@ int sopen(const char *fn, int sh_access, int share, ...)
#define LK_UNLCK LK_UNLOCK #define LK_UNLCK LK_UNLOCK
#endif #endif
int lock(int file, off_t offset, off_t size) int xp_lockfile(int file, off_t offset, off_t size, bool block)
{ {
int i; int i;
off_t pos; off_t pos;
...@@ -252,7 +257,9 @@ int lock(int file, off_t offset, off_t size) ...@@ -252,7 +257,9 @@ int lock(int file, off_t offset, off_t size)
pos=tell(file); pos=tell(file);
if(offset!=pos) if(offset!=pos)
(void)lseek(file, offset, SEEK_SET); (void)lseek(file, offset, SEEK_SET);
i=_locking(file,LK_NBLCK,(long)size); do {
i = _locking(file, block ? LK_LOCK : LK_NBLCK, (long)size);
} while(block && i != 0 && errno = EDEADLOCK);
if(offset!=pos) if(offset!=pos)
(void)lseek(file, pos, SEEK_SET); (void)lseek(file, pos, SEEK_SET);
return(i); return(i);
...@@ -274,6 +281,11 @@ int unlock(int file, off_t offset, off_t size) ...@@ -274,6 +281,11 @@ int unlock(int file, off_t offset, off_t size)
#endif /* !__unix__ && (_MSC_VER || __MINGW32__ || __DMC__) */ #endif /* !__unix__ && (_MSC_VER || __MINGW32__ || __DMC__) */
int lock(int fd, off_t pos, off_t len)
{
return xp_lockfile(fd, pos, len, /* block */false);
}
#if defined(_WIN32 ) #if defined(_WIN32 )
static size_t static size_t
p2roundup(size_t n) p2roundup(size_t n)
......
...@@ -156,6 +156,7 @@ extern "C" { ...@@ -156,6 +156,7 @@ extern "C" {
#endif #endif
#if !defined(__BORLANDC__) && !defined(__WATCOMC__) #if !defined(__BORLANDC__) && !defined(__WATCOMC__)
DLLEXPORT int xp_lockfile(int fd, off_t pos, off_t len, bool block);
DLLEXPORT int lock(int fd, off_t pos, off_t len); DLLEXPORT int lock(int fd, off_t pos, off_t len);
DLLEXPORT int unlock(int fd, off_t pos, off_t len); DLLEXPORT int unlock(int fd, off_t pos, off_t len);
#endif #endif
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment