diff --git a/doc/xml/release.xml b/doc/xml/release.xml
index 69cbf9ea2..f1e782610 100644
--- a/doc/xml/release.xml
+++ b/doc/xml/release.xml
@@ -27,6 +27,19 @@
Increase precision of percent complete logging for backup and restore.
+
+
+
+
+
+
+
+
+
+
+
+ Improve stop command to honor stanza option.
+
@@ -11411,6 +11424,11 @@
rachid-casa
+
+ ragaoua
+ ragaoua
+
+
Rakshitha-BR
Rakshitha-BR
diff --git a/src/command/control/stop.c b/src/command/control/stop.c
index 8cd4d707e..bccb4d8f2 100644
--- a/src/command/control/stop.c
+++ b/src/command/control/stop.c
@@ -59,11 +59,19 @@ cmdStop(void)
// Find each lock file and send term signals to the processes
for (unsigned int lockPathFileIdx = 0; lockPathFileIdx < strLstSize(lockPathFileList); lockPathFileIdx++)
{
- String *lockFile = strNewFmt("%s/%s", strZ(lockPath), strZ(strLstGet(lockPathFileList, lockPathFileIdx)));
+ const String *lockFile = strLstGet(lockPathFileList, lockPathFileIdx);
- // Skip any file that is not a lock file
- if (!strEndsWithZ(lockFile, LOCK_FILE_EXT))
+ // Skip any file that is not a lock file. Skip lock files for other stanzas if a stanza is provided.
+ if (!strEndsWithZ(lockFile, LOCK_FILE_EXT) ||
+ (cfgOptionTest(cfgOptStanza) &&
+ !strEq(lockFile, lockFileName(cfgOptionStr(cfgOptStanza), lockTypeArchive)) &&
+ !strEq(lockFile, lockFileName(cfgOptionStr(cfgOptStanza), lockTypeBackup))))
+ {
continue;
+ }
+
+ // Add path to the lock file
+ lockFile = strNewFmt("%s/%s", strZ(lockPath), strZ(lockFile));
// If we cannot open the lock file for any reason then warn and continue to next file
if ((fd = open(strZ(lockFile), O_RDONLY, 0)) == -1)
diff --git a/src/common/lock.c b/src/common/lock.c
index ada4118f5..f13048413 100644
--- a/src/common/lock.c
+++ b/src/common/lock.c
@@ -58,6 +58,18 @@ static struct LockLocal
.held = lockTypeNone,
};
+/**********************************************************************************************************************************/
+String *
+lockFileName(const String *const stanza, const LockType lockType)
+{
+ FUNCTION_TEST_BEGIN();
+ FUNCTION_TEST_PARAM(STRING, stanza);
+ FUNCTION_TEST_PARAM(ENUM, lockType);
+ FUNCTION_TEST_END();
+
+ FUNCTION_TEST_RETURN(strNewFmt("%s-%s" LOCK_FILE_EXT, strZ(stanza), lockTypeName[lockType]));
+}
+
/***********************************************************************************************************************************
Read contents of lock file
@@ -285,7 +297,7 @@ lockAcquire(
{
MEM_CONTEXT_BEGIN(lockLocal.memContext)
{
- lockLocal.file[lockIdx].name = strNewFmt("%s/%s-%s" LOCK_FILE_EXT, strZ(lockPath), strZ(stanza), lockTypeName[lockIdx]);
+ lockLocal.file[lockIdx].name = strNewFmt("%s/%s", strZ(lockPath), strZ(lockFileName(stanza, lockIdx)));
}
MEM_CONTEXT_END();
diff --git a/src/common/lock.h b/src/common/lock.h
index 0d9f1cb11..6dbfe8106 100644
--- a/src/common/lock.h
+++ b/src/common/lock.h
@@ -42,4 +42,7 @@ bool lockAcquire(
// Release a lock
bool lockRelease(bool failOnNoLock);
+// Build lock file name
+String *lockFileName(const String *stanza, LockType lockType);
+
#endif
diff --git a/test/define.yaml b/test/define.yaml
index 113526943..559f0c932 100644
--- a/test/define.yaml
+++ b/test/define.yaml
@@ -687,7 +687,7 @@ unit:
test:
# ----------------------------------------------------------------------------------------------------------------------------
- name: control
- total: 3
+ total: 4
coverage:
- command/control/common
diff --git a/test/src/module/command/controlTest.c b/test/src/module/command/controlTest.c
index d2098577d..6da70a5ee 100644
--- a/test/src/module/command/controlTest.c
+++ b/test/src/module/command/controlTest.c
@@ -139,16 +139,17 @@ testRun(void)
TEST_TITLE("unable to open lock file");
HRN_STORAGE_PUT_EMPTY(
- hrnStorage, "lock/bad" LOCK_FILE_EXT, .modeFile = 0222, .comment = "create a lock file that cannot be opened");
+ hrnStorage, "lock/db-archive" LOCK_FILE_EXT, .modeFile = 0222,
+ .comment = "create a lock file that cannot be opened");
TEST_RESULT_VOID(cmdStop(), "stanza, create stop file but unable to open lock file");
TEST_STORAGE_EXISTS(hrnStorage, "lock/db" STOP_FILE_EXT, .comment = "stanza stop file created");
- TEST_RESULT_LOG("P00 WARN: unable to open lock file " HRN_PATH "/lock/bad" LOCK_FILE_EXT);
+ TEST_RESULT_LOG("P00 WARN: unable to open lock file " HRN_PATH "/lock/db-archive" LOCK_FILE_EXT);
HRN_STORAGE_PATH_REMOVE(hrnStorage, "lock", .recurse = true, .errorOnMissing = true, .comment = "remove the lock path");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("lock file removal");
- HRN_STORAGE_PUT_EMPTY(hrnStorage, "lock/empty" LOCK_FILE_EXT, .comment = "create empty lock file");
+ HRN_STORAGE_PUT_EMPTY(hrnStorage, "lock/db-backup" LOCK_FILE_EXT, .comment = "create empty lock file");
TEST_RESULT_VOID(cmdStop(), "stanza, create stop file, force - empty lock file");
TEST_STORAGE_LIST(
hrnStorage, "lock", "db" STOP_FILE_EXT "\n",
@@ -158,13 +159,13 @@ testRun(void)
TEST_TITLE("empty lock file with another process lock, processId == NULL");
HRN_STORAGE_REMOVE(hrnStorage, "lock/db" STOP_FILE_EXT, .errorOnMissing = true, .comment = "remove stanza stop file");
- HRN_STORAGE_PUT_EMPTY(hrnStorage, "lock/empty" LOCK_FILE_EXT, .comment = "create empty lock file");
+ HRN_STORAGE_PUT_EMPTY(hrnStorage, "lock/db-backup" LOCK_FILE_EXT, .comment = "create empty lock file");
HRN_FORK_BEGIN()
{
HRN_FORK_CHILD_BEGIN()
{
- int lockFd = open(HRN_PATH "/lock/empty" LOCK_FILE_EXT, O_RDONLY, 0);
+ int lockFd = open(HRN_PATH "/lock/db-backup" LOCK_FILE_EXT, O_RDONLY, 0);
TEST_RESULT_BOOL(lockFd != -1, true, "file descriptor acquired");
TEST_RESULT_INT(flock(lockFd, LOCK_EX | LOCK_NB), 0, "lock the empty file");
@@ -200,13 +201,13 @@ testRun(void)
TEST_TITLE("not empty lock file with another process lock, processId size trimmed to 0");
HRN_STORAGE_REMOVE(hrnStorage, "lock/db" STOP_FILE_EXT, .errorOnMissing = true, .comment = "remove stanza stop file");
- HRN_STORAGE_PUT_Z(hrnStorage, "lock/empty" LOCK_FILE_EXT, " ", .comment = "create non-empty lock file");
+ HRN_STORAGE_PUT_Z(hrnStorage, "lock/db-backup" LOCK_FILE_EXT, " ", .comment = "create non-empty lock file");
HRN_FORK_BEGIN()
{
HRN_FORK_CHILD_BEGIN()
{
- int lockFd = open(HRN_PATH "/lock/empty" LOCK_FILE_EXT, O_RDONLY, 0);
+ int lockFd = open(HRN_PATH "/lock/db-backup" LOCK_FILE_EXT, O_RDONLY, 0);
TEST_RESULT_BOOL(lockFd != -1, true, "file descriptor acquired");
TEST_RESULT_INT(flock(lockFd, LOCK_EX | LOCK_NB), 0, "lock the non-empty file");
@@ -276,13 +277,13 @@ testRun(void)
TEST_TITLE("lock file with another process lock, processId is invalid");
HRN_STORAGE_REMOVE(hrnStorage, "lock/db" STOP_FILE_EXT, .errorOnMissing = true, .comment = "remove stanza stop file");
- HRN_STORAGE_PUT_Z(hrnStorage, "lock/badpid" LOCK_FILE_EXT, "-32768", .comment = "create lock file with invalid PID");
+ HRN_STORAGE_PUT_Z(hrnStorage, "lock/db-backup" LOCK_FILE_EXT, "-32768", .comment = "create lock file with invalid PID");
HRN_FORK_BEGIN()
{
HRN_FORK_CHILD_BEGIN()
{
- int lockFd = open(HRN_PATH "/lock/badpid" LOCK_FILE_EXT, O_RDONLY, 0);
+ int lockFd = open(HRN_PATH "/lock/db-backup" LOCK_FILE_EXT, O_RDONLY, 0);
TEST_RESULT_BOOL(lockFd != -1, true, "file descriptor acquired");
TEST_RESULT_INT(flock(lockFd, LOCK_EX | LOCK_NB), 0, "lock the badpid file");
@@ -293,7 +294,7 @@ testRun(void)
HRN_FORK_CHILD_NOTIFY_GET();
// Remove the file and close the file descriptor
- HRN_STORAGE_REMOVE(hrnStorage, "lock/badpid" LOCK_FILE_EXT);
+ HRN_STORAGE_REMOVE(hrnStorage, "lock/db-backup" LOCK_FILE_EXT);
close(lockFd);
}
HRN_FORK_CHILD_END();
@@ -316,5 +317,47 @@ testRun(void)
HRN_FORK_END();
}
+ // *****************************************************************************************************************************
+ if (testBegin("cmdStop(), force, no stanza/stanza"))
+ {
+ StringList *argList = strLstNew();
+ hrnCfgArgRawBool(argList, cfgOptForce, true);
+ HRN_CFG_LOAD(cfgCmdStop, argList);
+
+ // -------------------------------------------------------------------------------------------------------------------------
+ TEST_TITLE("no stanza, force stop = process all lock files, ignore non lock files");
+
+ HRN_STORAGE_PUT_EMPTY(hrnStorage, "lock/db-junk.txt", .comment = "create empty non lock file, s/b ignored");
+ HRN_STORAGE_PUT_Z(hrnStorage, "lock/db-backup" LOCK_FILE_EXT, " ", .comment = "create backup lock file for stanza");
+ HRN_STORAGE_PUT_EMPTY(hrnStorage, "lock/db-archive" LOCK_FILE_EXT, .comment = "create empty archive lock file for stanza");
+ HRN_STORAGE_PUT_Z(hrnStorage, "lock/db1-backup" LOCK_FILE_EXT, " ", .comment = "create non-empty lock file other stanza");
+
+ TEST_RESULT_VOID(cmdStop(), "no stanza, create stop file, ignore non lock file");
+ TEST_STORAGE_EXISTS(hrnStorage, "lock/all" STOP_FILE_EXT, .comment = "stanza stop file created");
+ TEST_STORAGE_LIST(
+ hrnStorage, "lock", "all" STOP_FILE_EXT "\n" "db-junk.txt\n", .comment = "stop file created, all lock files processed");
+ TEST_RESULT_LOG("");
+ HRN_STORAGE_PATH_REMOVE(hrnStorage, "lock", .recurse = true, .errorOnMissing = true, .comment = "remove the lock path");
+
+ // -------------------------------------------------------------------------------------------------------------------------
+ TEST_TITLE("stanza, force stop = process only stanza lock files, ignore other stanza lock files and other files");
+
+ hrnCfgArgRawZ(argList, cfgOptStanza, "db");
+ HRN_CFG_LOAD(cfgCmdStop, argList);
+
+ HRN_STORAGE_PUT_EMPTY(hrnStorage, "lock/db-junk.txt", .comment = "create empty non lock file, s/b ignored");
+ HRN_STORAGE_PUT_EMPTY(hrnStorage, "lock/db-archive" LOCK_FILE_EXT, .comment = "create stanza empty lock file");
+ HRN_STORAGE_PUT_Z(hrnStorage, "lock/db1-backup" LOCK_FILE_EXT, " ", .comment = "create other stanza non-empty lock file");
+ HRN_STORAGE_PUT_Z(hrnStorage, "lock/db-backup" LOCK_FILE_EXT, " ", .comment = "create stanza non-empty lock file");
+
+ TEST_RESULT_VOID(cmdStop(), "stanza, create stop file, ignore other stanza lock and other files");
+ TEST_STORAGE_EXISTS(hrnStorage, "lock/db" STOP_FILE_EXT, .comment = "stanza stop file created");
+ TEST_STORAGE_LIST(
+ hrnStorage, "lock", "db-junk.txt\ndb" STOP_FILE_EXT "\n" "db1-backup" LOCK_FILE_EXT "\n",
+ .comment = "stop file created, stanza lock file was removed, other stanza lock and other files remain");
+ TEST_RESULT_LOG("");
+ HRN_STORAGE_PATH_REMOVE(hrnStorage, "lock", .recurse = true, .errorOnMissing = true, .comment = "remove the lock path");
+ }
+
FUNCTION_HARNESS_RETURN_VOID();
}