mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-12 10:04:14 +02:00
Add lock module initialization.
Each call to lockAcquireP() passed enough information to initialize the lock system. This was somewhat inefficient and as locks become more complicated it will lead to more code duplication. Since a process can only take one type of lock it makes sense to do most of the initialization up front. Also reduce the log level of lockRelease() since it is only called at exit and the lock will be released in any case.
This commit is contained in:
parent
f1caecc4ff
commit
8ff956ad7e
@ -463,9 +463,7 @@ HRN_FORK_BEGIN()
|
||||
{
|
||||
HRN_FORK_CHILD_BEGIN()
|
||||
{
|
||||
TEST_RESULT_INT_NE(
|
||||
lockAcquireP(cfgOptionStr(cfgOptLockPath), STRDEF("stanza1"), STRDEF("999-ffffffff"), lockTypeBackup), -1,
|
||||
"create backup/expire lock");
|
||||
TEST_RESULT_INT_NE(lockAcquireP(), -1, "create backup/expire lock");
|
||||
|
||||
// Notify parent that lock has been acquired
|
||||
HRN_FORK_CHILD_NOTIFY_PUT();
|
||||
|
@ -530,9 +530,7 @@ HRN_FORK_BEGIN()
|
||||
{
|
||||
HRN_FORK_CHILD_BEGIN()
|
||||
{
|
||||
TEST_RESULT_INT_NE(
|
||||
lockAcquireP(cfgOptionStr(cfgOptLockPath), STRDEF("stanza1"), STRDEF("999-ffffffff"), lockTypeBackup), -1,
|
||||
"create backup/expire lock");
|
||||
TEST_RESULT_INT_NE(lockAcquireP(), -1, "create backup/expire lock");
|
||||
|
||||
// Notify parent that lock has been acquired
|
||||
HRN_FORK_CHILD_NOTIFY_PUT();
|
||||
|
@ -718,10 +718,7 @@ cmdArchiveGet(void)
|
||||
// If the WAL segment has not already been found then start the async process to get it. There's no point in
|
||||
// forking the async process off more than once so track that as well. Use an archive lock to prevent forking if
|
||||
// the async process was launched by another process.
|
||||
if (!forked && (!found || !queueFull) &&
|
||||
lockAcquireP(
|
||||
cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptStanza), cfgOptionStr(cfgOptExecId), cfgLockType(),
|
||||
.returnOnNoLock = true))
|
||||
if (!forked && (!found || !queueFull) && lockAcquireP(.returnOnNoLock = true))
|
||||
{
|
||||
// Get control info
|
||||
PgControl pgControl = pgControlFromFile(storagePg(), cfgOptionStrNull(cfgOptPgVersionForce));
|
||||
|
@ -361,10 +361,7 @@ cmdArchivePush(void)
|
||||
// If the WAL segment has not already been pushed then start the async process to push it. There's no point in
|
||||
// forking the async process off more than once so track that as well. Use an archive lock to prevent more than
|
||||
// one async process being launched.
|
||||
if (!pushed && !forked &&
|
||||
lockAcquireP(
|
||||
cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptStanza), cfgOptionStr(cfgOptExecId), cfgLockType(),
|
||||
.returnOnNoLock = true))
|
||||
if (!pushed && !forked && lockAcquireP(.returnOnNoLock = true))
|
||||
{
|
||||
// The async process should not output on the console at all
|
||||
KeyValue *optionReplace = kvNew();
|
||||
|
@ -77,8 +77,7 @@ cmdRemote(ProtocolServer *const server)
|
||||
lockStopTest();
|
||||
|
||||
// Acquire the lock
|
||||
lockAcquireP(
|
||||
cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptStanza), cfgOptionStr(cfgOptExecId), cfgLockType());
|
||||
lockAcquireP();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,18 +51,48 @@ Mem context and local variables
|
||||
static struct LockLocal
|
||||
{
|
||||
MemContext *memContext; // Mem context for locks
|
||||
LockType held; // Current lock type held
|
||||
const String *path; // Lock path
|
||||
const String *execId; // Process exec id
|
||||
const String *stanza; // Stanza
|
||||
LockType type; // Lock type
|
||||
bool held; // Is the lock being held?
|
||||
|
||||
struct
|
||||
{
|
||||
String *name; // Name of lock file
|
||||
int fd; // File descriptor for lock file
|
||||
} file[lockTypeAll];
|
||||
} lockLocal =
|
||||
} lockLocal;
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
FN_EXTERN void
|
||||
lockInit(const String *const path, const String *const execId, const String *const stanza, const LockType type)
|
||||
{
|
||||
.held = lockTypeNone,
|
||||
};
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(STRING, path);
|
||||
FUNCTION_LOG_PARAM(STRING, execId);
|
||||
FUNCTION_LOG_PARAM(ENUM, type);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(lockLocal.memContext == NULL);
|
||||
|
||||
// Allocate a mem context to hold lock info
|
||||
MEM_CONTEXT_BEGIN(memContextTop())
|
||||
{
|
||||
MEM_CONTEXT_NEW_BEGIN(Lock, .childQty = MEM_CONTEXT_QTY_MAX)
|
||||
{
|
||||
lockLocal.memContext = MEM_CONTEXT_NEW();
|
||||
lockLocal.path = strDup(path);
|
||||
lockLocal.execId = strDup(execId);
|
||||
lockLocal.stanza = strDup(stanza);
|
||||
lockLocal.type = type;
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
FN_EXTERN String *
|
||||
@ -257,7 +287,7 @@ lockWriteData(const LockType lockType, const LockWriteDataParam param)
|
||||
|
||||
jsonWriteObjectEnd(json);
|
||||
|
||||
if (lockType == lockTypeBackup && lockLocal.held != lockTypeNone)
|
||||
if (lockType == lockTypeBackup && lockLocal.held)
|
||||
{
|
||||
// Seek to beginning of backup lock file
|
||||
THROW_ON_SYS_ERROR_FMT(
|
||||
@ -391,59 +421,34 @@ lockAcquireFile(const String *const lockFile, const TimeMSec lockTimeout, const
|
||||
}
|
||||
|
||||
FN_EXTERN bool
|
||||
lockAcquire(
|
||||
const String *const lockPath, const String *const stanza, const String *const execId, const LockType lockType,
|
||||
const LockAcquireParam param)
|
||||
lockAcquire(const LockAcquireParam param)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(STRING, lockPath);
|
||||
FUNCTION_LOG_PARAM(STRING, stanza);
|
||||
FUNCTION_LOG_PARAM(STRING, execId);
|
||||
FUNCTION_LOG_PARAM(ENUM, lockType);
|
||||
FUNCTION_LOG_PARAM(TIMEMSEC, param.timeout);
|
||||
FUNCTION_LOG_PARAM(BOOL, param.returnOnNoLock);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(lockPath != NULL);
|
||||
ASSERT(stanza != NULL);
|
||||
ASSERT(execId != NULL);
|
||||
ASSERT(lockLocal.memContext != NULL);
|
||||
|
||||
bool result = true;
|
||||
|
||||
// Don't allow failures when locking more than one file. This makes cleanup difficult and there are no known use cases.
|
||||
ASSERT(!param.returnOnNoLock || lockType != lockTypeAll);
|
||||
ASSERT(!param.returnOnNoLock || lockLocal.type != lockTypeAll);
|
||||
|
||||
// Don't allow another lock if one is already held
|
||||
if (lockLocal.held != lockTypeNone)
|
||||
if (lockLocal.held)
|
||||
THROW(AssertError, "lock is already held by this process");
|
||||
|
||||
// Allocate a mem context to hold lock filenames if one does not already exist
|
||||
if (lockLocal.memContext == NULL)
|
||||
{
|
||||
MEM_CONTEXT_BEGIN(memContextTop())
|
||||
{
|
||||
MEM_CONTEXT_NEW_BEGIN(Lock, .childQty = MEM_CONTEXT_QTY_MAX)
|
||||
{
|
||||
lockLocal.memContext = MEM_CONTEXT_NEW();
|
||||
lockLocal.execId = strDup(execId);
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
|
||||
// Exec id should never change
|
||||
ASSERT(strEq(execId, lockLocal.execId));
|
||||
|
||||
// Lock files
|
||||
LockType lockMin = lockType == lockTypeAll ? lockTypeArchive : lockType;
|
||||
LockType lockMax = lockType == lockTypeAll ? (lockTypeAll - 1) : lockType;
|
||||
LockType lockMin = lockLocal.type == lockTypeAll ? lockTypeArchive : lockLocal.type;
|
||||
LockType lockMax = lockLocal.type == lockTypeAll ? (lockTypeAll - 1) : lockLocal.type;
|
||||
|
||||
for (LockType lockIdx = lockMin; lockIdx <= lockMax; lockIdx++)
|
||||
{
|
||||
MEM_CONTEXT_BEGIN(lockLocal.memContext)
|
||||
{
|
||||
lockLocal.file[lockIdx].name = strNewFmt("%s/%s", strZ(lockPath), strZ(lockFileName(stanza, lockIdx)));
|
||||
strFree(lockLocal.file[lockIdx].name);
|
||||
lockLocal.file[lockIdx].name = strNewFmt("%s/%s", strZ(lockLocal.path), strZ(lockFileName(lockLocal.stanza, lockIdx)));
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
@ -451,10 +456,8 @@ lockAcquire(
|
||||
|
||||
if (lockLocal.file[lockIdx].fd == -1)
|
||||
{
|
||||
// Free the lock context and reset lock data
|
||||
memContextFree(lockLocal.memContext);
|
||||
lockLocal = (struct LockLocal){.held = lockTypeNone};
|
||||
|
||||
// Free the lock
|
||||
lockLocal.held = false;
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
@ -464,7 +467,7 @@ lockAcquire(
|
||||
}
|
||||
|
||||
if (result)
|
||||
lockLocal.held = lockType;
|
||||
lockLocal.held = true;
|
||||
|
||||
FUNCTION_LOG_RETURN(BOOL, result);
|
||||
}
|
||||
@ -497,13 +500,13 @@ lockReleaseFile(const int lockFd, const String *const lockFile)
|
||||
FN_EXTERN bool
|
||||
lockRelease(bool failOnNoLock)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||
FUNCTION_LOG_PARAM(BOOL, failOnNoLock);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (lockLocal.held == lockTypeNone)
|
||||
if (!lockLocal.held)
|
||||
{
|
||||
if (failOnNoLock)
|
||||
THROW(AssertError, "no lock is held by this process");
|
||||
@ -511,8 +514,8 @@ lockRelease(bool failOnNoLock)
|
||||
else
|
||||
{
|
||||
// Release locks
|
||||
LockType lockMin = lockLocal.held == lockTypeAll ? lockTypeArchive : lockLocal.held;
|
||||
LockType lockMax = lockLocal.held == lockTypeAll ? (lockTypeAll - 1) : lockLocal.held;
|
||||
LockType lockMin = lockLocal.type == lockTypeAll ? lockTypeArchive : lockLocal.type;
|
||||
LockType lockMax = lockLocal.type == lockTypeAll ? (lockTypeAll - 1) : lockLocal.type;
|
||||
|
||||
for (LockType lockIdx = lockMin; lockIdx <= lockMax; lockIdx++)
|
||||
{
|
||||
@ -520,10 +523,8 @@ lockRelease(bool failOnNoLock)
|
||||
lockReleaseFile(lockLocal.file[lockIdx].fd, lockLocal.file[lockIdx].name);
|
||||
}
|
||||
|
||||
// Free the lock context and reset lock data
|
||||
memContextFree(lockLocal.memContext);
|
||||
lockLocal = (struct LockLocal){.held = lockTypeNone};
|
||||
|
||||
// Free the lock context
|
||||
lockLocal.held = false;
|
||||
result = true;
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,9 @@ Constants
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
// Initialize lock module
|
||||
FN_EXTERN void lockInit(const String *path, const String *execId, const String *stanza, LockType type);
|
||||
|
||||
// Acquire a lock type. This will involve locking one or more files on disk depending on the lock type. Most operations only take a
|
||||
// single lock (archive or backup), but the stanza commands all need to lock both.
|
||||
typedef struct LockAcquireParam
|
||||
@ -46,11 +49,10 @@ typedef struct LockAcquireParam
|
||||
bool returnOnNoLock; // Return when no lock acquired (rather than throw an error)
|
||||
} LockAcquireParam;
|
||||
|
||||
#define lockAcquireP(lockPath, stanza, execId, lockType, ...) \
|
||||
lockAcquire(lockPath, stanza, execId, lockType, (LockAcquireParam) {VAR_PARAM_INIT, __VA_ARGS__})
|
||||
#define lockAcquireP(...) \
|
||||
lockAcquire((LockAcquireParam) {VAR_PARAM_INIT, __VA_ARGS__})
|
||||
|
||||
FN_EXTERN bool lockAcquire(
|
||||
const String *lockPath, const String *stanza, const String *execId, LockType lockType, LockAcquireParam param);
|
||||
FN_EXTERN bool lockAcquire(LockAcquireParam param);
|
||||
|
||||
// Release a lock
|
||||
FN_EXTERN bool lockRelease(bool failOnNoLock);
|
||||
|
@ -501,9 +501,15 @@ cfgLoad(unsigned int argListSize, const char *argList[])
|
||||
// Begin the command
|
||||
cmdBegin();
|
||||
|
||||
// Acquire a lock if this command requires a lock
|
||||
if (cfgLockRequired() && !cfgCommandHelp())
|
||||
lockAcquireP(cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptStanza), cfgOptionStr(cfgOptExecId), cfgLockType());
|
||||
// Init lock module if this command can lock
|
||||
if (cfgLockType() != lockTypeNone && !cfgCommandHelp())
|
||||
{
|
||||
lockInit(cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptExecId), cfgOptionStr(cfgOptStanza), cfgLockType());
|
||||
|
||||
// Acquire a lock if this command requires a lock
|
||||
if (cfgLockRequired())
|
||||
lockAcquireP();
|
||||
}
|
||||
|
||||
// Update options that have complex rules
|
||||
cfgLoadUpdateOption();
|
||||
|
@ -401,6 +401,12 @@ unit:
|
||||
name: storageHelper
|
||||
shim:
|
||||
storage/helper: ~
|
||||
harness:
|
||||
name: lock
|
||||
shim:
|
||||
common/lock:
|
||||
function:
|
||||
- lockInit
|
||||
|
||||
coverage:
|
||||
- common/lock
|
||||
|
@ -29,7 +29,8 @@ hrnCmdBackup(void)
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
lockAcquireP(STR(testPath()), cfgOptionStr(cfgOptStanza), cfgOptionStr(cfgOptExecId), lockTypeBackup);
|
||||
lockInit(STR(testPath()), cfgOptionStr(cfgOptExecId), cfgOptionStr(cfgOptStanza), lockTypeBackup);
|
||||
lockAcquireP();
|
||||
|
||||
TRY_BEGIN()
|
||||
{
|
||||
|
@ -17,6 +17,7 @@ Harness for Loading Test Configurations
|
||||
|
||||
#include "common/harnessConfig.h"
|
||||
#include "common/harnessDebug.h"
|
||||
#include "common/harnessLock.h"
|
||||
#include "common/harnessLog.h"
|
||||
#include "common/harnessStorageHelper.h"
|
||||
#include "common/harnessTest.h"
|
||||
@ -99,6 +100,11 @@ hrnCfgLoad(ConfigCommand commandId, const StringList *argListParam, const HrnCfg
|
||||
if (cfgOptionValid(cfgOptExecId) && !cfgOptionTest(cfgOptExecId))
|
||||
cfgOptionSet(cfgOptExecId, cfgSourceParam, VARSTRDEF("1-test"));
|
||||
|
||||
if (cfgOptionTest(cfgOptExecId) && cfgOptionTest(cfgOptLockPath) && cfgOptionTest(cfgOptStanza))
|
||||
lockInit(cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptExecId), cfgOptionStr(cfgOptStanza), cfgLockType());
|
||||
else
|
||||
hrnLockUnInit();
|
||||
|
||||
FUNCTION_HARNESS_RETURN_VOID();
|
||||
}
|
||||
|
||||
|
45
test/src/common/harnessLock.c
Normal file
45
test/src/common/harnessLock.c
Normal file
@ -0,0 +1,45 @@
|
||||
/***********************************************************************************************************************************
|
||||
Lock Test Harness
|
||||
***********************************************************************************************************************************/
|
||||
#include "build.auto.h"
|
||||
|
||||
#include "common/harnessDebug.h"
|
||||
#include "common/harnessLock.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Include shimmed C modules
|
||||
***********************************************************************************************************************************/
|
||||
{[SHIM_MODULE]}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
FN_EXTERN void
|
||||
lockInit(const String *const path, const String *const execId, const String *const stanza, const LockType type)
|
||||
{
|
||||
FUNCTION_HARNESS_BEGIN();
|
||||
FUNCTION_HARNESS_PARAM(STRING, path);
|
||||
FUNCTION_HARNESS_PARAM(STRING, execId);
|
||||
FUNCTION_HARNESS_PARAM(STRING, stanza);
|
||||
FUNCTION_HARNESS_PARAM(ENUM, type);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
hrnLockUnInit();
|
||||
lockInit_SHIMMED(path, execId, stanza, type);
|
||||
|
||||
FUNCTION_HARNESS_RETURN_VOID();
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
FN_EXTERN void
|
||||
hrnLockUnInit(void)
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
// Free mem context it it exists
|
||||
if (lockLocal.memContext != NULL)
|
||||
{
|
||||
memContextFree(lockLocal.memContext);
|
||||
lockLocal = (struct LockLocal){0};
|
||||
}
|
||||
|
||||
FUNCTION_HARNESS_RETURN_VOID();
|
||||
}
|
15
test/src/common/harnessLock.h
Normal file
15
test/src/common/harnessLock.h
Normal file
@ -0,0 +1,15 @@
|
||||
/***********************************************************************************************************************************
|
||||
Lock Test Harness
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef TEST_COMMON_HARNESSLOCK_H
|
||||
#define TEST_COMMON_HARNESSLOCK_H
|
||||
|
||||
#include "common/lock.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
// Uninitialize lock module
|
||||
FN_EXTERN void hrnLockUnInit(void);
|
||||
|
||||
#endif
|
@ -725,11 +725,8 @@ testRun(void)
|
||||
{
|
||||
HRN_FORK_CHILD_BEGIN()
|
||||
{
|
||||
TEST_RESULT_VOID(
|
||||
lockAcquireP(
|
||||
cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptStanza), STRDEF("999-dededede"), cfgLockType(),
|
||||
.timeout = 30000, .returnOnNoLock = true),
|
||||
"acquire lock");
|
||||
lockInit(cfgOptionStr(cfgOptLockPath), STRDEF("999-dededede"), cfgOptionStr(cfgOptStanza), cfgLockType());
|
||||
TEST_RESULT_VOID(lockAcquireP(.timeout = 30000, .returnOnNoLock = true), "acquire lock");
|
||||
|
||||
// Notify parent that lock has been acquired
|
||||
HRN_FORK_CHILD_NOTIFY_PUT();
|
||||
|
@ -749,9 +749,8 @@ testRun(void)
|
||||
{
|
||||
HRN_FORK_CHILD_BEGIN()
|
||||
{
|
||||
lockAcquireP(
|
||||
cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptStanza), STRDEF("555-fefefefe"), cfgLockType(),
|
||||
.timeout = 30000, .returnOnNoLock = true);
|
||||
lockInit(cfgOptionStr(cfgOptLockPath), STRDEF("555-fefefefe"), cfgOptionStr(cfgOptStanza), cfgLockType());
|
||||
lockAcquireP(.timeout = 30000, .returnOnNoLock = true);
|
||||
|
||||
// Notify parent that lock has been acquired
|
||||
HRN_FORK_CHILD_NOTIFY_PUT();
|
||||
|
@ -2126,9 +2126,9 @@ testRun(void)
|
||||
uint64_t sizeProgress = 0;
|
||||
currentPercentComplete = 4567;
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
lockAcquireP(TEST_PATH_STR, cfgOptionStr(cfgOptStanza), cfgOptionStr(cfgOptExecId), lockTypeBackup),
|
||||
"acquire backup lock");
|
||||
lockInit(TEST_PATH_STR, cfgOptionStr(cfgOptExecId), cfgOptionStr(cfgOptStanza), lockTypeBackup);
|
||||
TEST_RESULT_VOID(lockAcquireP(), "acquire backup lock");
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
backupJobResult(
|
||||
manifest, STRDEF("host"), storageTest, strLstNew(), job, false, 0, &sizeProgress, ¤tPercentComplete),
|
||||
|
@ -253,11 +253,8 @@ testRun(void)
|
||||
{
|
||||
HRN_FORK_CHILD_BEGIN()
|
||||
{
|
||||
TEST_RESULT_BOOL(
|
||||
lockAcquireP(
|
||||
STRDEF(HRN_PATH "/lock"), cfgOptionStr(cfgOptStanza), cfgOptionStr(cfgOptExecId), lockTypeArchive,
|
||||
.timeout = 30000),
|
||||
true, "child process acquires lock");
|
||||
lockInit(STRDEF(HRN_PATH "/lock"), cfgOptionStr(cfgOptExecId), cfgOptionStr(cfgOptStanza), lockTypeArchive);
|
||||
TEST_RESULT_BOOL(lockAcquireP(.timeout = 30000), true, "child process acquires lock");
|
||||
|
||||
// Notify parent that lock has been acquired
|
||||
HRN_FORK_CHILD_NOTIFY_PUT();
|
||||
|
@ -107,8 +107,6 @@ testRun(void)
|
||||
" ERR_STACK_TRACE\n"
|
||||
" --------------------------------------------------------------------\n"
|
||||
"P00 INFO: archive-push:async command end: aborted with exception [122]\n"
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/src/common/lock::lockRelease: (failOnNoLock: false)\n"
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/src/common/lock::lockRelease: => false\n"
|
||||
"P00 DEBUG: " TEST_PGB_PATH "/src/command/exit::exitSafe: => 122");
|
||||
}
|
||||
TRY_END();
|
||||
|
@ -236,9 +236,8 @@ testRun(void)
|
||||
{
|
||||
HRN_FORK_CHILD_BEGIN()
|
||||
{
|
||||
TEST_RESULT_INT_NE(
|
||||
lockAcquireP(cfgOptionStr(cfgOptLockPath), STRDEF("stanza1"), STRDEF("999-ffffffff"), lockTypeBackup), -1,
|
||||
"create backup/expire lock");
|
||||
lockInit(cfgOptionStr(cfgOptLockPath), STRDEF("999-ffffffff"), STRDEF("stanza1"), lockTypeBackup);
|
||||
TEST_RESULT_INT_NE(lockAcquireP(), -1, "create backup/expire lock");
|
||||
|
||||
// Notify parent that lock has been acquired
|
||||
HRN_FORK_CHILD_NOTIFY_PUT();
|
||||
@ -429,9 +428,8 @@ testRun(void)
|
||||
{
|
||||
HRN_FORK_CHILD_BEGIN()
|
||||
{
|
||||
TEST_RESULT_INT_NE(
|
||||
lockAcquireP(cfgOptionStr(cfgOptLockPath), STRDEF("stanza1"), STRDEF("777-afafafaf"), lockTypeBackup), -1,
|
||||
"create backup/expire lock");
|
||||
lockInit(cfgOptionStr(cfgOptLockPath), STRDEF("777-afafafaf"), STRDEF("stanza1"), lockTypeBackup);
|
||||
TEST_RESULT_INT_NE(lockAcquireP(), -1, "create backup/expire lock");
|
||||
TEST_RESULT_VOID(lockWriteDataP(lockTypeBackup), "write lock data");
|
||||
|
||||
// Notify parent that lock has been acquired
|
||||
@ -1025,9 +1023,8 @@ testRun(void)
|
||||
{
|
||||
HRN_FORK_CHILD_BEGIN()
|
||||
{
|
||||
TEST_RESULT_INT_NE(
|
||||
lockAcquireP(cfgOptionStr(cfgOptLockPath), STRDEF("stanza2"), STRDEF("999-ffffffff"), lockTypeBackup), -1,
|
||||
"create backup/expire lock");
|
||||
lockInit(cfgOptionStr(cfgOptLockPath), STRDEF("999-ffffffff"), STRDEF("stanza2"), lockTypeBackup);
|
||||
TEST_RESULT_INT_NE(lockAcquireP(), -1, "create backup/expire lock");
|
||||
TEST_RESULT_VOID(lockWriteDataP(lockTypeBackup, .percentComplete = VARUINT(4545)), "write lock data");
|
||||
|
||||
// Notify parent that lock has been acquired
|
||||
@ -1465,9 +1462,8 @@ testRun(void)
|
||||
{
|
||||
HRN_FORK_CHILD_BEGIN()
|
||||
{
|
||||
TEST_RESULT_INT_NE(
|
||||
lockAcquireP(cfgOptionStr(cfgOptLockPath), STRDEF("stanza2"), STRDEF("999-ffffffff"), lockTypeBackup), -1,
|
||||
"create backup/expire lock");
|
||||
lockInit(cfgOptionStr(cfgOptLockPath), STRDEF("999-ffffffff"), STRDEF("stanza2"), lockTypeBackup);
|
||||
TEST_RESULT_INT_NE(lockAcquireP(), -1, "create backup/expire lock");
|
||||
TEST_RESULT_VOID(lockWriteDataP(lockTypeBackup, .percentComplete = VARUINT(5555)), "write lock data");
|
||||
|
||||
// Notify parent that lock has been acquired
|
||||
|
@ -158,53 +158,55 @@ testRun(void)
|
||||
TEST_RESULT_BOOL(lockRelease(false), false, "release when there is no lock");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
lockLocal.execId = STRDEF("1-test");
|
||||
lockInit(TEST_PATH_STR, STRDEF("1-test"), stanza, lockTypeArchive);
|
||||
|
||||
TEST_ASSIGN(lockFdTest, lockAcquireFile(archiveLockFile, 0, true), "archive lock by file");
|
||||
TEST_RESULT_BOOL(
|
||||
lockAcquireP(TEST_PATH_STR, stanza, STRDEF("2-test"), lockTypeArchive, .returnOnNoLock = true), false,
|
||||
"archive already locked");
|
||||
TEST_RESULT_BOOL(lockAcquireP(.returnOnNoLock = true), false, "archive already locked");
|
||||
TEST_ERROR_FMT(
|
||||
lockAcquireP(TEST_PATH_STR, stanza, STRDEF("2-test"), lockTypeArchive), LockAcquireError,
|
||||
lockAcquireP(), LockAcquireError,
|
||||
"unable to acquire lock on file '%s': Resource temporarily unavailable\n"
|
||||
"HINT: is another pgBackRest process running?",
|
||||
strZ(archiveLockFile));
|
||||
|
||||
lockLocal.type = lockTypeAll;
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
lockAcquireP(TEST_PATH_STR, stanza, STRDEF("2-test"), lockTypeAll), LockAcquireError,
|
||||
lockAcquireP(), LockAcquireError,
|
||||
"unable to acquire lock on file '%s': Resource temporarily unavailable\n"
|
||||
"HINT: is another pgBackRest process running?", strZ(archiveLockFile));
|
||||
TEST_RESULT_VOID(lockReleaseFile(lockFdTest, archiveLockFile), "release lock");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
lockLocal.execId = STRDEF("1-test");
|
||||
lockInit(TEST_PATH_STR, STRDEF("1-test"), stanza, lockTypeArchive);
|
||||
|
||||
TEST_RESULT_BOOL(lockAcquireP(TEST_PATH_STR, stanza, STRDEF("1-test"), lockTypeArchive), true, "archive lock");
|
||||
TEST_RESULT_BOOL(lockAcquireP(), true, "archive lock");
|
||||
TEST_RESULT_BOOL(storageExistsP(storageTest, archiveLockFile), true, "archive lock file was created");
|
||||
TEST_ERROR(
|
||||
lockAcquireP(TEST_PATH_STR, stanza, STRDEF("1-test"), lockTypeArchive, .returnOnNoLock = true), AssertError,
|
||||
"lock is already held by this process");
|
||||
TEST_ERROR(lockAcquireP(.returnOnNoLock = true), AssertError, "lock is already held by this process");
|
||||
TEST_RESULT_VOID(lockRelease(true), "release archive lock");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
lockLocal.execId = STRDEF("2-test");
|
||||
lockInit(TEST_PATH_STR, STRDEF("1-test"), stanza, lockTypeBackup);
|
||||
|
||||
TEST_ASSIGN(lockFdTest, lockAcquireFile(backupLockFile, 0, true), "backup lock by file");
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
lockAcquireP(TEST_PATH_STR, stanza, STRDEF("2-test"), lockTypeBackup), LockAcquireError,
|
||||
lockAcquireP(), LockAcquireError,
|
||||
"unable to acquire lock on file '%s': Resource temporarily unavailable\n"
|
||||
"HINT: is another pgBackRest process running?", strZ(backupLockFile));
|
||||
|
||||
lockLocal.type = lockTypeAll;
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
lockAcquireP(TEST_PATH_STR, stanza, STRDEF("2-test"), lockTypeAll), LockAcquireError,
|
||||
lockAcquireP(), LockAcquireError,
|
||||
"unable to acquire lock on file '%s': Resource temporarily unavailable\n"
|
||||
"HINT: is another pgBackRest process running?", strZ(backupLockFile));
|
||||
TEST_RESULT_VOID(lockReleaseFile(lockFdTest, archiveLockFile), "release archive lock");
|
||||
TEST_RESULT_VOID(lockReleaseFile(lockFdTest, backupLockFile), "release backup lock");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
lockLocal.execId = STRDEF("1-test");
|
||||
lockInit(TEST_PATH_STR, STRDEF("1-test"), stanza, lockTypeAll);
|
||||
|
||||
TEST_RESULT_BOOL(lockAcquireP(TEST_PATH_STR, stanza, STRDEF("1-test"), lockTypeAll), true, "all lock");
|
||||
TEST_RESULT_BOOL(lockAcquireP(), true, "all lock");
|
||||
TEST_RESULT_BOOL(storageExistsP(storageTest, archiveLockFile), true, "archive lock file was created");
|
||||
TEST_RESULT_BOOL(storageExistsP(storageTest, backupLockFile), true, "backup lock file was created");
|
||||
|
||||
@ -239,8 +241,8 @@ testRun(void)
|
||||
"verify percentComplete");
|
||||
|
||||
TEST_ERROR(
|
||||
lockAcquireP(TEST_PATH_STR, stanza, STRDEF("1-test"), lockTypeAll, .returnOnNoLock = true), AssertError,
|
||||
"assertion '!param.returnOnNoLock || lockType != lockTypeAll' failed");
|
||||
lockAcquireP(.returnOnNoLock = true), AssertError,
|
||||
"assertion '!param.returnOnNoLock || lockLocal.type != lockTypeAll' failed");
|
||||
TEST_RESULT_VOID(lockRelease(true), "release all locks");
|
||||
|
||||
TEST_RESULT_BOOL(storageExistsP(storageTest, archiveLockFile), false, "archive lock file was removed");
|
||||
@ -249,15 +251,16 @@ testRun(void)
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_TITLE("acquire lock on the same exec-id and release");
|
||||
|
||||
TEST_RESULT_BOOL(lockAcquireP(TEST_PATH_STR, stanza, STRDEF("1-test"), lockTypeBackup), true, "backup lock");
|
||||
lockInit(TEST_PATH_STR, STRDEF("1-test"), stanza, lockTypeBackup);
|
||||
|
||||
TEST_RESULT_BOOL(lockAcquireP(), true, "backup lock");
|
||||
|
||||
// Make it look there is no lock
|
||||
lockFdTest = lockLocal.file[lockTypeBackup].fd;
|
||||
String *lockFileTest = strDup(lockLocal.file[lockTypeBackup].name);
|
||||
lockLocal.held = lockTypeNone;
|
||||
lockLocal.held = false;
|
||||
|
||||
TEST_RESULT_BOOL(
|
||||
lockAcquireP(TEST_PATH_STR, stanza, STRDEF("1-test"), lockTypeBackup), true, "backup lock again");
|
||||
TEST_RESULT_BOOL(lockAcquireP(), true, "backup lock again");
|
||||
TEST_RESULT_VOID(lockRelease(true), "release backup lock");
|
||||
|
||||
// Release lock manually
|
||||
@ -281,10 +284,9 @@ testRun(void)
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_TITLE("execId && pid valid file");
|
||||
|
||||
const String *stanza = STRDEF("1-test");
|
||||
lockLocal.execId = STRDEF("1-test");
|
||||
lockInit(TEST_PATH_STR, STRDEF("1-test"), STRDEF("1-test"), lockTypeBackup);
|
||||
|
||||
TEST_RESULT_BOOL(lockAcquireP(TEST_PATH_STR, stanza, STRDEF("1-test"), lockTypeBackup), true, "backup lock");
|
||||
TEST_RESULT_BOOL(lockAcquireP(), true, "backup lock");
|
||||
TEST_RESULT_BOOL(storageExistsP(storageTest, lockLocal.file[lockTypeBackup].name), true, "backup lock file was created");
|
||||
|
||||
// Overwrite backup lock file with execId of 1-test and pid of 12345
|
||||
@ -317,7 +319,9 @@ testRun(void)
|
||||
{
|
||||
HRN_FORK_CHILD_BEGIN()
|
||||
{
|
||||
TEST_RESULT_BOOL(lockAcquireP(TEST_PATH_STR, STRDEF("test"), STRDEF("test"), lockTypeBackup), true, "acquire lock");
|
||||
lockInit(TEST_PATH_STR, STRDEF("1-test"), STRDEF("test"), lockTypeBackup);
|
||||
|
||||
TEST_RESULT_BOOL(lockAcquireP(), true, "acquire lock");
|
||||
|
||||
// Overwrite lock file with bogus data
|
||||
THROW_ON_SYS_ERROR_FMT(
|
||||
@ -361,7 +365,9 @@ testRun(void)
|
||||
{
|
||||
HRN_FORK_CHILD_BEGIN()
|
||||
{
|
||||
TEST_RESULT_BOOL(lockAcquireP(TEST_PATH_STR, STRDEF("test"), STRDEF("test"), lockTypeBackup), true, "acquire lock");
|
||||
lockInit(TEST_PATH_STR, STRDEF("1-test"), STRDEF("test"), lockTypeBackup);
|
||||
|
||||
TEST_RESULT_BOOL(lockAcquireP(), true, "acquire lock");
|
||||
|
||||
// Notify parent that lock has been acquired
|
||||
HRN_FORK_CHILD_NOTIFY_PUT();
|
||||
@ -380,7 +386,7 @@ testRun(void)
|
||||
TEST_ASSIGN(result, lockRead(TEST_PATH_STR, STRDEF("test"), lockTypeBackup), "lock read");
|
||||
|
||||
TEST_RESULT_BOOL(result.data.processId != 0, true, "check processId");
|
||||
TEST_RESULT_STR_Z(result.data.execId, "test", "check execId");
|
||||
TEST_RESULT_STR_Z(result.data.execId, "1-test", "check execId");
|
||||
|
||||
TEST_STORAGE_LIST(storageTest, NULL, "test-backup.lock\n");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user