Skip to content

Commit

Permalink
Adapt to the changes in the file locking API in libntech
Browse files Browse the repository at this point in the history
File locking in libntech is now a bit more abstract and
versatile.
  • Loading branch information
vpodzime committed Oct 21, 2019
1 parent faab54a commit b5ee6a3
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 60 deletions.
32 changes: 14 additions & 18 deletions cf-check/repair.c
Expand Up @@ -106,24 +106,22 @@ int repair_lmdb_file(const char *file, int fd_tstamp)
int ret;
char *dest_file = StringFormat("%s"REPAIR_FILE_EXTENSION, file);

/* Used to keep track of whether the repair timestamp file was opened
* locally. */
int local_fd_tstamp = -1;
FileLock lock = EMPTY_FILE_LOCK;
if (fd_tstamp == -1)
{
char *tstamp_file = StringFormat("%s.repaired", file);
fd_tstamp = safe_open(tstamp_file, O_CREAT|O_RDWR);
int lock_ret = ExclusiveFileLockPath(&lock, tstamp_file, true); /* wait=true */
free(tstamp_file);
local_fd_tstamp = fd_tstamp;
}
if (!ExclusiveLockFileCheck(fd_tstamp) && ExclusiveLockFile(fd_tstamp, true) == -1)
{
/* Should never happen because we tried to wait for the lock. */
Log(LOG_LEVEL_ERR,
"Failed to acquire lock for the '%s' DB repair timestamp file",
file);
ret = -1;
goto cleanup;
if (lock_ret < 0)
{
/* Should never happen because we tried to wait for the lock. */
Log(LOG_LEVEL_ERR,
"Failed to acquire lock for the '%s' DB repair timestamp file",
file);
ret = -1;
goto cleanup;
}
fd_tstamp = lock.fd;
}
pid_t child_pid = fork();
if (child_pid == 0)
Expand Down Expand Up @@ -205,11 +203,9 @@ int repair_lmdb_file(const char *file, int fd_tstamp)
}
cleanup:
free(dest_file);
if (local_fd_tstamp != -1)
if (lock.fd != -1)
{
/* Also releases file locks on the timestamp file if we opened it
* locally. */
close(local_fd_tstamp);
ExclusiveFileUnlock(&lock, true); /* close=true */
}
return ret;
}
Expand Down
2 changes: 1 addition & 1 deletion libntech
38 changes: 12 additions & 26 deletions libpromises/dbm_api.c
Expand Up @@ -37,8 +37,8 @@
#include <time.h> /* time() */


static int DBPathLock(const char *filename);
static void DBPathUnLock(int fd);
static bool DBPathLock(FileLock *lock, const char *filename);
static void DBPathUnLock(FileLock *lock);
static void DBPathMoveBroken(const char *filename);

struct DBHandle_
Expand Down Expand Up @@ -379,9 +379,8 @@ bool OpenDBInstance(DBHandle **dbp, dbid id, DBHandle *handle)
}
if (handle->refcount == 0)
{
int lock_fd = DBPathLock(handle->filename);

if(lock_fd != -1)
FileLock lock = EMPTY_FILE_LOCK;
if (DBPathLock(&lock, handle->filename))
{
handle->open_tstamp = time(NULL);
handle->priv = DBPrivOpenDB(handle->filename, id);
Expand All @@ -396,7 +395,7 @@ bool OpenDBInstance(DBHandle **dbp, dbid id, DBHandle *handle)
}
}

DBPathUnLock(lock_fd);
DBPathUnLock(&lock);
}

if (handle->priv)
Expand Down Expand Up @@ -613,42 +612,29 @@ bool DeleteDBCursor(DBCursor *cursor)
return true;
}

static int DBPathLock(const char *filename)
static bool DBPathLock(FileLock *lock, const char *filename)
{
char *filename_lock;
if (xasprintf(&filename_lock, "%s.lock", filename) == -1)
{
ProgrammingError("Unable to construct lock database filename for file %s", filename);
}

int fd = open(filename_lock, O_CREAT | O_RDWR, 0666);

if(fd == -1)
{
Log(LOG_LEVEL_ERR, "Unable to open database lock file '%s'. (flock: %s)", filename_lock, GetErrorStr());
free(filename_lock);
return -1;
}

if (ExclusiveLockFile(fd, true) == -1)
if (ExclusiveFileLockPath(lock, filename_lock, true) != 0)
{
Log(LOG_LEVEL_ERR, "Unable to lock database lock file '%s'. (fcntl(F_SETLK): %s)", filename_lock, GetErrorStr());
Log(LOG_LEVEL_ERR, "Unable to lock database lock file '%s'.", filename_lock);
free(filename_lock);
close(fd);
return -1;
return false;
}

free(filename_lock);

return fd;
return true;
}

static void DBPathUnLock(int fd)
static void DBPathUnLock(FileLock *lock)
{
if(ExclusiveUnlockFile(fd) != 0)
{
Log(LOG_LEVEL_ERR, "Could not close db lock-file. (close: %s)", GetErrorStr());
}
ExclusiveFileUnlock(lock, true);
}

static void DBPathMoveBroken(const char *filename)
Expand Down
28 changes: 13 additions & 15 deletions libpromises/dbm_lmdb.c
Expand Up @@ -311,6 +311,8 @@ static void HandleLMDBCorruption(MDB_env *env, const char *msg)

exit(EC_CORRUPTION_REPAIR_FAILED);
}
FileLock tstamp_lock = { .fd = fd_tstamp };

int fd_db_lock = safe_open(db_lock_file, O_CREAT|O_RDWR);
if (fd_db_lock == -1)
{
Expand All @@ -323,20 +325,17 @@ static void HandleLMDBCorruption(MDB_env *env, const char *msg)

exit(EC_CORRUPTION_REPAIR_FAILED);
}
FileLock db_lock = { .fd = fd_db_lock };

int ret;
bool handle_corruption = true;

/* Make sure we are not holding the DB's lock (potentially needed by some
* other process for the repair) to avoid deadlocks. */
if (ExclusiveLockFileCheck(fd_db_lock))
{
Log(LOG_LEVEL_DEBUG, "Releasing lock on the '%s' DB", lmdb_file);
ExclusiveUnlockFile(fd_db_lock); /* closes fd_db_lock (TODO: fix) */
fd_db_lock = safe_open(db_lock_file, O_CREAT|O_RDWR);
}
Log(LOG_LEVEL_DEBUG, "Releasing lock on the '%s' DB", lmdb_file);
ExclusiveFileUnlock(&db_lock, false); /* close=false */

ret = SharedLockFile(fd_tstamp, true);
ret = SharedFileLock(&tstamp_lock, true);
if (ret == 0)
{
if (RepairedAfterOpen(lmdb_file, fd_tstamp))
Expand All @@ -346,8 +345,7 @@ static void HandleLMDBCorruption(MDB_env *env, const char *msg)
* it would just open the new (repaired) LMDB file. */
handle_corruption = false;
}
SharedUnlockFile(fd_tstamp); /* closes fd_tstamp (TODO: fix) */
fd_tstamp = safe_open(tstamp_file, O_CREAT|O_RDWR);
SharedFileUnlock(&tstamp_lock, false);
}
else
{
Expand Down Expand Up @@ -376,8 +374,8 @@ static void HandleLMDBCorruption(MDB_env *env, const char *msg)
* contents of the timestamp file again below, while holding the EXCLUSIVE
* lock. */

ret = ExclusiveLockFile(fd_tstamp, true);
if (ret == -1)
ret = ExclusiveFileLock(&tstamp_lock, true);
if (ret != 0)
{
/* should never happen (we tried to wait), but if it does, just
* terminate because doing the repair without the lock could be
Expand All @@ -399,7 +397,7 @@ static void HandleLMDBCorruption(MDB_env *env, const char *msg)

/* 1. Acquire the lock for the DB to prevent more processes trying to use
* it while it is corrupted (wait till the lock is available). */
while (ExclusiveLockFile(fd_db_lock, false) == -1)
while (ExclusiveFileLock(&db_lock, false) == -1)
{
/* busy wait to do the logging */
Log(LOG_LEVEL_INFO, "Waiting for the lock on the '%s' DB",
Expand Down Expand Up @@ -443,14 +441,14 @@ static void HandleLMDBCorruption(MDB_env *env, const char *msg)
/* 4. Make the repaired DB available for others. Also release the locks
* in the opposite order in which they were acquired to avoid
* deadlocks. */
if (ExclusiveUnlockFile(fd_db_lock) != 0)
if (ExclusiveFileUnlock(&db_lock, true) != 0)
{
Log(LOG_LEVEL_ERR, "Failed to release the acquired lock for '%s'",
db_lock_file);
}

/* 5. Signal that the repair is done (also closes fd_tstamp). */
if (ExclusiveUnlockFile(fd_tstamp) != 0)
if (ExclusiveFileUnlock(&tstamp_lock, true) != 0)
{
Log(LOG_LEVEL_ERR, "Failed to release the acquired lock for '%s'",
tstamp_file);
Expand All @@ -460,7 +458,7 @@ static void HandleLMDBCorruption(MDB_env *env, const char *msg)
free(db_lock_file);
free(tstamp_file);
/* fd_db_lock and fd_tstamp are already closed by the calls to
* ExclusiveUnlockFile above. */
* ExclusiveFileUnlock above. */

if (repair_successful)
{
Expand Down

0 comments on commit b5ee6a3

Please sign in to comment.