Path where lock files are stored.
diff --git a/doc/xml/release.xml b/doc/xml/release.xml
index 139018f35..0c602d507 100644
--- a/doc/xml/release.xml
+++ b/doc/xml/release.xml
@@ -57,6 +57,10 @@
TCP keep-alive options are configurable.
+
+ Add io-timeout option.
+
+
diff --git a/src/command/repo/put.c b/src/command/repo/put.c
index bb6e6d52d..eb2503597 100644
--- a/src/command/repo/put.c
+++ b/src/command/repo/put.c
@@ -88,7 +88,7 @@ cmdStoragePut(void)
MEM_CONTEXT_TEMP_BEGIN()
{
- storagePutProcess(ioHandleReadNew(STRDEF("stdin"), STDIN_FILENO, IO_TIMEOUT_DEFAULT));
+ storagePutProcess(ioHandleReadNew(STRDEF("stdin"), STDIN_FILENO, ioTimeoutMs()));
}
MEM_CONTEXT_TEMP_END();
diff --git a/src/common/io/io.c b/src/common/io/io.c
index b9da76b94..f71c34228 100644
--- a/src/common/io/io.c
+++ b/src/common/io/io.c
@@ -19,6 +19,9 @@ should set their buffer size using ioBufferSize() but there may be cases where a
static size_t bufferSize = (8 * IO_BUFFER_BLOCK_SIZE);
+// I/O timeout in milliseconds
+static TimeMSec timeoutMs = 60000;
+
/**********************************************************************************************************************************/
size_t
ioBufferSize(void)
@@ -39,6 +42,26 @@ ioBufferSizeSet(size_t bufferSizeParam)
FUNCTION_TEST_RETURN_VOID();
}
+/**********************************************************************************************************************************/
+TimeMSec
+ioTimeoutMs(void)
+{
+ FUNCTION_TEST_VOID();
+ FUNCTION_TEST_RETURN(timeoutMs);
+}
+
+void
+ioTimeoutMsSet(TimeMSec timeoutMsParam)
+{
+ FUNCTION_TEST_BEGIN();
+ FUNCTION_TEST_PARAM(TIME_MSEC, timeoutMsParam);
+ FUNCTION_TEST_END();
+
+ timeoutMs = timeoutMsParam;
+
+ FUNCTION_TEST_RETURN_VOID();
+}
+
/**********************************************************************************************************************************/
Buffer *
ioReadBuf(IoRead *read)
diff --git a/src/common/io/io.h b/src/common/io/io.h
index 99d6558ed..7930902b3 100644
--- a/src/common/io/io.h
+++ b/src/common/io/io.h
@@ -9,11 +9,7 @@ Common IO functions.
#include
#include
-
-/***********************************************************************************************************************************
-Default IO timeout to use when nothing else is configured
-***********************************************************************************************************************************/
-#define IO_TIMEOUT_DEFAULT 60000
+#include
/***********************************************************************************************************************************
Functions
@@ -31,4 +27,9 @@ Getters/Setters
size_t ioBufferSize(void);
void ioBufferSizeSet(size_t bufferSize);
+// I/O timeout in milliseconds. Used to timeout on connections and read/write operations. Note that an *entire* read/write operation
+// does not need to take place within this timeout but at least some progress needs to be made, even if it is only a byte.
+TimeMSec ioTimeoutMs(void);
+void ioTimeoutMsSet(TimeMSec timeout);
+
#endif
diff --git a/src/config/config.auto.c b/src/config/config.auto.c
index df048a83e..f3bc46000 100644
--- a/src/config/config.auto.c
+++ b/src/config/config.auto.c
@@ -310,6 +310,7 @@ STRING_EXTERN(CFGOPT_FILTER_STR, CFGOPT_FILTE
STRING_EXTERN(CFGOPT_FORCE_STR, CFGOPT_FORCE);
STRING_EXTERN(CFGOPT_HOST_ID_STR, CFGOPT_HOST_ID);
STRING_EXTERN(CFGOPT_IGNORE_MISSING_STR, CFGOPT_IGNORE_MISSING);
+STRING_EXTERN(CFGOPT_IO_TIMEOUT_STR, CFGOPT_IO_TIMEOUT);
STRING_EXTERN(CFGOPT_LINK_ALL_STR, CFGOPT_LINK_ALL);
STRING_EXTERN(CFGOPT_LINK_MAP_STR, CFGOPT_LINK_MAP);
STRING_EXTERN(CFGOPT_LOCK_PATH_STR, CFGOPT_LOCK_PATH);
@@ -686,6 +687,14 @@ static ConfigOptionData configOptionData[CFG_OPTION_TOTAL] = CONFIG_OPTION_LIST
CONFIG_OPTION_DEFINE_ID(cfgDefOptIgnoreMissing)
)
+ //------------------------------------------------------------------------------------------------------------------------------
+ CONFIG_OPTION
+ (
+ CONFIG_OPTION_NAME(CFGOPT_IO_TIMEOUT)
+ CONFIG_OPTION_INDEX(0)
+ CONFIG_OPTION_DEFINE_ID(cfgDefOptIoTimeout)
+ )
+
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
diff --git a/src/config/config.auto.h b/src/config/config.auto.h
index 4d0c34a47..22dab5024 100644
--- a/src/config/config.auto.h
+++ b/src/config/config.auto.h
@@ -107,6 +107,8 @@ Option constants
STRING_DECLARE(CFGOPT_HOST_ID_STR);
#define CFGOPT_IGNORE_MISSING "ignore-missing"
STRING_DECLARE(CFGOPT_IGNORE_MISSING_STR);
+#define CFGOPT_IO_TIMEOUT "io-timeout"
+ STRING_DECLARE(CFGOPT_IO_TIMEOUT_STR);
#define CFGOPT_LINK_ALL "link-all"
STRING_DECLARE(CFGOPT_LINK_ALL_STR);
#define CFGOPT_LINK_MAP "link-map"
@@ -416,7 +418,7 @@ Option constants
#define CFGOPT_TYPE "type"
STRING_DECLARE(CFGOPT_TYPE_STR);
-#define CFG_OPTION_TOTAL 181
+#define CFG_OPTION_TOTAL 182
/***********************************************************************************************************************************
Command enum
@@ -477,6 +479,7 @@ typedef enum
cfgOptForce,
cfgOptHostId,
cfgOptIgnoreMissing,
+ cfgOptIoTimeout,
cfgOptLinkAll,
cfgOptLinkMap,
cfgOptLockPath,
diff --git a/src/config/define.auto.c b/src/config/define.auto.c
index 5244f2904..f4c1b7892 100644
--- a/src/config/define.auto.c
+++ b/src/config/define.auto.c
@@ -1377,6 +1377,53 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
)
)
+ // -----------------------------------------------------------------------------------------------------------------------------
+ CFGDEFDATA_OPTION
+ (
+ CFGDEFDATA_OPTION_NAME("io-timeout")
+ CFGDEFDATA_OPTION_REQUIRED(true)
+ CFGDEFDATA_OPTION_SECTION(cfgDefSectionGlobal)
+ CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeFloat)
+ CFGDEFDATA_OPTION_INTERNAL(false)
+
+ CFGDEFDATA_OPTION_INDEX_TOTAL(1)
+ CFGDEFDATA_OPTION_SECURE(false)
+
+ CFGDEFDATA_OPTION_HELP_SECTION("general")
+ CFGDEFDATA_OPTION_HELP_SUMMARY("I/O timeout.")
+ CFGDEFDATA_OPTION_HELP_DESCRIPTION
+ (
+ "Timeout used for connections and read/write operations.\n"
+ "\n"
+ "Note that the entire read/write operation does not need to complete within this timeout but some progress must be "
+ "made, even if it is only a single byte."
+ )
+
+ CFGDEFDATA_OPTION_COMMAND_LIST
+ (
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchiveGet)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchivePush)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdBackup)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdCheck)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdInfo)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRepoCreate)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRepoGet)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRepoLs)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRepoPut)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRepoRm)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRestore)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaCreate)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaDelete)
+ CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaUpgrade)
+ )
+
+ CFGDEFDATA_OPTION_OPTIONAL_LIST
+ (
+ CFGDEFDATA_OPTION_OPTIONAL_ALLOW_RANGE(0.1, 3600)
+ CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("60")
+ )
+ )
+
// -----------------------------------------------------------------------------------------------------------------------------
CFGDEFDATA_OPTION
(
diff --git a/src/config/define.auto.h b/src/config/define.auto.h
index c4e13cb1c..362bad7ea 100644
--- a/src/config/define.auto.h
+++ b/src/config/define.auto.h
@@ -79,6 +79,7 @@ typedef enum
cfgDefOptForce,
cfgDefOptHostId,
cfgDefOptIgnoreMissing,
+ cfgDefOptIoTimeout,
cfgDefOptLinkAll,
cfgDefOptLinkMap,
cfgDefOptLockPath,
diff --git a/src/config/load.c b/src/config/load.c
index d2bb573d6..76d3e22ec 100644
--- a/src/config/load.c
+++ b/src/config/load.c
@@ -350,6 +350,10 @@ cfgLoad(unsigned int argListSize, const char *argList[])
if (cfgOptionValid(cfgOptBufferSize))
ioBufferSizeSet(cfgOptionUInt(cfgOptBufferSize));
+ // Set IO timeout
+ if (cfgOptionValid(cfgOptIoTimeout))
+ ioTimeoutMsSet((TimeMSec)(cfgOptionDbl(cfgOptIoTimeout) * MSEC_PER_SEC));
+
// Open the log file if this command logs to a file
cfgLoadLogFile();
diff --git a/src/config/parse.auto.c b/src/config/parse.auto.c
index fafb51554..ca14bb19c 100644
--- a/src/config/parse.auto.c
+++ b/src/config/parse.auto.c
@@ -328,6 +328,18 @@ static const struct option optionList[] =
.val = PARSE_OPTION_FLAG | cfgOptIgnoreMissing,
},
+ // io-timeout option
+ // -----------------------------------------------------------------------------------------------------------------------------
+ {
+ .name = CFGOPT_IO_TIMEOUT,
+ .has_arg = required_argument,
+ .val = PARSE_OPTION_FLAG | cfgOptIoTimeout,
+ },
+ {
+ .name = "reset-" CFGOPT_IO_TIMEOUT,
+ .val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | cfgOptIoTimeout,
+ },
+
// link-all option
// -----------------------------------------------------------------------------------------------------------------------------
{
@@ -2443,6 +2455,7 @@ static const ConfigOption optionResolveOrder[] =
cfgOptFilter,
cfgOptHostId,
cfgOptIgnoreMissing,
+ cfgOptIoTimeout,
cfgOptLinkAll,
cfgOptLinkMap,
cfgOptLockPath,
diff --git a/src/storage/helper.c b/src/storage/helper.c
index 7fa13b1e7..15a5d793f 100644
--- a/src/storage/helper.c
+++ b/src/storage/helper.c
@@ -6,6 +6,7 @@ Storage Helper
#include
#include "common/debug.h"
+#include "common/io/io.h"
#include "common/memContext.h"
#include "common/regExp.h"
#include "config/define.h"
@@ -383,7 +384,7 @@ storageRepoGet(const String *type, bool write)
strEqZ(cfgOptionStr(cfgOptRepoS3UriStyle), STORAGE_S3_URI_STYLE_HOST) ? storageS3UriStyleHost : storageS3UriStylePath,
cfgOptionStr(cfgOptRepoS3Region), cfgOptionStr(cfgOptRepoS3Key), cfgOptionStr(cfgOptRepoS3KeySecret),
cfgOptionTest(cfgOptRepoS3Token) ? cfgOptionStr(cfgOptRepoS3Token) : NULL, STORAGE_S3_PARTSIZE_MIN,
- STORAGE_S3_DELETE_MAX, host, port, STORAGE_S3_TIMEOUT_DEFAULT, cfgOptionBool(cfgOptRepoS3VerifyTls),
+ STORAGE_S3_DELETE_MAX, host, port, ioTimeoutMs(), cfgOptionBool(cfgOptRepoS3VerifyTls),
cfgOptionTest(cfgOptRepoS3CaFile) ? cfgOptionStr(cfgOptRepoS3CaFile) : NULL,
cfgOptionTest(cfgOptRepoS3CaPath) ? cfgOptionStr(cfgOptRepoS3CaPath) : NULL);
}
diff --git a/src/storage/s3/storage.h b/src/storage/s3/storage.h
index af0bee3c0..78bcb0f9b 100644
--- a/src/storage/s3/storage.h
+++ b/src/storage/s3/storage.h
@@ -27,7 +27,6 @@ typedef enum
/***********************************************************************************************************************************
Defaults
***********************************************************************************************************************************/
-#define STORAGE_S3_TIMEOUT_DEFAULT 60000
#define STORAGE_S3_PARTSIZE_MIN ((size_t)5 * 1024 * 1024)
#define STORAGE_S3_DELETE_MAX 1000
diff --git a/test/src/module/command/helpTest.c b/test/src/module/command/helpTest.c
index 079ef3fe0..f1e328e61 100644
--- a/test/src/module/command/helpTest.c
+++ b/test/src/module/command/helpTest.c
@@ -157,6 +157,7 @@ testRun(void)
" --config-path base path of pgBackRest configuration files\n"
" [default=/etc/pgbackrest]\n"
" --delta restore or backup using checksums [default=n]\n"
+ " --io-timeout i/O timeout [default=60]\n"
" --lock-path path where lock files are stored\n"
" [default=/tmp/pgbackrest]\n"
" --neutral-umask use a neutral umask [default=y]\n"
diff --git a/test/src/module/common/ioTest.c b/test/src/module/common/ioTest.c
index aa867b5fe..915e3b5f8 100644
--- a/test/src/module/common/ioTest.c
+++ b/test/src/module/common/ioTest.c
@@ -249,11 +249,15 @@ testRun(void)
FUNCTION_HARNESS_VOID();
// *****************************************************************************************************************************
- if (testBegin("ioBufferSize() and ioBufferSizeSet()"))
+ if (testBegin("ioBufferSize()/ioBufferSizeSet() and ioTimeoutMs()/ioTimeoutMsSet()"))
{
TEST_RESULT_UINT(ioBufferSize(), 65536, "check initial buffer size");
TEST_RESULT_VOID(ioBufferSizeSet(16384), "set buffer size");
TEST_RESULT_UINT(ioBufferSize(), 16384, "check buffer size");
+
+ TEST_RESULT_UINT(ioTimeoutMs(), 60000, "check initial timeout ms");
+ TEST_RESULT_VOID(ioTimeoutMsSet(77777), "set timeout ms");
+ TEST_RESULT_UINT(ioTimeoutMs(), 77777, "check timeout ms");
}
// *****************************************************************************************************************************
diff --git a/test/src/module/config/loadTest.c b/test/src/module/config/loadTest.c
index 6a4f34a59..402003cd1 100644
--- a/test/src/module/config/loadTest.c
+++ b/test/src/module/config/loadTest.c
@@ -360,6 +360,7 @@ testRun(void)
TEST_RESULT_VOID(cfgLoad(strLstSize(argList), strLstPtr(argList)), "load config and don't set umask");
TEST_RESULT_BOOL(socketLocal.init, true, " check socketLocal.init");
TEST_RESULT_BOOL(socketLocal.keepAlive, false, " check socketLocal.keepAlive");
+ TEST_RESULT_UINT(ioTimeoutMs(), 60000, " check io timeout");
// Set a distinct umask value and test that the umask is reset by configLoad since default for neutral-umask=y
// -------------------------------------------------------------------------------------------------------------------------
@@ -369,11 +370,13 @@ testRun(void)
strLstAdd(argList, strNew("--log-level-console=off"));
strLstAdd(argList, strNew("--log-level-stderr=off"));
strLstAdd(argList, strNew("--log-level-file=off"));
+ strLstAdd(argList, strNew("--io-timeout=95.5"));
strLstAdd(argList, strNew("archive-get"));
umask(0111);
TEST_RESULT_VOID(cfgLoad(strLstSize(argList), strLstPtr(argList)), "load config for neutral-umask");
TEST_RESULT_INT(umask(0111), 0000, " umask was reset");
+ TEST_RESULT_UINT(ioTimeoutMs(), 95500, " check io timeout");
// Set a distinct umask value and test that the umask is not reset by configLoad with option --no-neutral-umask
// -------------------------------------------------------------------------------------------------------------------------