mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-03-03 14:52:21 +02:00
Add stack trace macros to all functions.
Low-level functions only include stack trace in test builds while higher-level functions ship with stack trace built-in. Stack traces include all parameters passed to the function but production builds only create the parameter list when the log level is set high enough, i.e. debug or trace depending on the function.
This commit is contained in:
parent
abb9651f4c
commit
52bc073234
@ -25,6 +25,10 @@
|
||||
</release-improvement-list>
|
||||
|
||||
<release-development-list>
|
||||
<release-item>
|
||||
<p>Add stack trace macros to all functions. Low-level functions only include stack trace in test builds while higher-level functions ship with stack trace built-in. Stack traces include all parameters passed to the function but production builds only create the parameter list when the log level is set high enough, i.e. <id>debug</id> or <id>trace</id> depending on the function.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<p>Build <path>libc</path> using links rather than referencing the C files in <path>src</path> directly. The C library builds with different options which should not be reused for the C binary or vice versa.</p>
|
||||
</release-item>
|
||||
|
@ -15,7 +15,10 @@ use ExtUtils::MakeMaker;
|
||||
use File::Basename qw(dirname);
|
||||
|
||||
use lib dirname($0) . '/lib';
|
||||
use lib dirname($0) . '/build/lib';
|
||||
|
||||
use pgBackRest::LibCAuto;
|
||||
use pgBackRestLibC::BuildParam;
|
||||
|
||||
####################################################################################################################################
|
||||
# Storage object to use for all file operations
|
||||
@ -77,6 +80,7 @@ my @stryCFile =
|
||||
'cipher/cipher.c',
|
||||
'cipher/random.c',
|
||||
'command/command.c',
|
||||
'common/debug.c',
|
||||
'common/encode.c',
|
||||
'common/encode/base64.c',
|
||||
'common/error.c',
|
||||
@ -86,7 +90,9 @@ my @stryCFile =
|
||||
'common/log.c',
|
||||
'common/memContext.c',
|
||||
'common/regExp.c',
|
||||
'common/stackTrace.c',
|
||||
'common/time.c',
|
||||
'common/type/convert.c',
|
||||
'common/type/buffer.c',
|
||||
'common/type/keyValue.c',
|
||||
'common/type/list.c',
|
||||
@ -142,15 +148,7 @@ WriteMakefile
|
||||
VERSION_FROM => 'lib/' . BACKREST_NAME . '/LibC.pm',
|
||||
AUTHOR => 'David Steele <david@pgbackrest.org>',
|
||||
|
||||
CCFLAGS => join(' ', qw(
|
||||
-Wfatal-errors -Wall -Wextra -Wwrite-strings -Wno-clobbered -Wno-missing-field-initializers
|
||||
-o $@
|
||||
-std=c99
|
||||
-D_FILE_OFFSET_BITS=64
|
||||
-funroll-loops
|
||||
-ftree-vectorize
|
||||
$(CFLAGS)
|
||||
)),
|
||||
CCFLAGS => join(' ', buildParamCCAll()),
|
||||
|
||||
INC => join(' ', qw(
|
||||
-I.
|
||||
|
46
libc/build/lib/pgBackRestLibC/BuildParam.pm
Normal file
46
libc/build/lib/pgBackRestLibC/BuildParam.pm
Normal file
@ -0,0 +1,46 @@
|
||||
####################################################################################################################################
|
||||
# Parameters used by LibC builds
|
||||
####################################################################################################################################
|
||||
package pgBackRestLibC::BuildParam;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => qw(all);
|
||||
use Carp qw(confess);
|
||||
use English '-no_match_vars';
|
||||
|
||||
use Exporter qw(import);
|
||||
our @EXPORT = qw();
|
||||
|
||||
####################################################################################################################################
|
||||
# All CC params used for a debug build
|
||||
####################################################################################################################################
|
||||
sub buildParamCCDebug
|
||||
{
|
||||
return qw(
|
||||
-Wfatal-errors -Wall -Wextra -Wwrite-strings -Wno-clobbered -Wno-missing-field-initializers
|
||||
-o $@
|
||||
-std=c99
|
||||
-D_FILE_OFFSET_BITS=64
|
||||
$(CFLAGS));
|
||||
}
|
||||
|
||||
push @EXPORT, qw(buildParamCCDebug);
|
||||
|
||||
####################################################################################################################################
|
||||
# All CC params used for a production build
|
||||
####################################################################################################################################
|
||||
sub buildParamCCAll
|
||||
{
|
||||
my @stryParams = buildParamCCDebug;
|
||||
|
||||
push(@stryParams, qw(
|
||||
-DNDEBUG
|
||||
-funroll-loops
|
||||
-ftree-vectorize));
|
||||
|
||||
return @stryParams;
|
||||
}
|
||||
|
||||
push @EXPORT, qw(buildParamCCAll);
|
||||
|
||||
1;
|
@ -59,17 +59,20 @@ SRCS = \
|
||||
command/archive/push/push.c \
|
||||
command/help/help.c \
|
||||
command/command.c \
|
||||
common/fork.c \
|
||||
common/debug.c \
|
||||
common/error.c \
|
||||
common/exit.c \
|
||||
common/fork.c \
|
||||
common/io/handle.c \
|
||||
common/ini.c \
|
||||
common/lock.c \
|
||||
common/log.c \
|
||||
common/memContext.c \
|
||||
common/regExp.c \
|
||||
common/stackTrace.c \
|
||||
common/time.c \
|
||||
common/type/buffer.c \
|
||||
common/type/convert.c \
|
||||
common/type/keyValue.c \
|
||||
common/type/list.c \
|
||||
common/type/string.c \
|
||||
|
@ -6,6 +6,7 @@ Block Cipher
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "cipher/block.h"
|
||||
#include "cipher/random.h"
|
||||
@ -45,6 +46,18 @@ New block encrypt/decrypt object
|
||||
CipherBlock *
|
||||
cipherBlockNew(CipherMode mode, const char *cipherName, const unsigned char *pass, size_t passSize, const char *digestName)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, mode);
|
||||
FUNCTION_DEBUG_PARAM(STRINGZ, cipherName);
|
||||
FUNCTION_DEBUG_PARAM(UCHARP, pass);
|
||||
FUNCTION_DEBUG_PARAM(SIZE, passSize);
|
||||
FUNCTION_DEBUG_PARAM(STRINGZ, digestName);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(cipherName != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(pass != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(passSize > 0);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Only need to init once.
|
||||
if (!cipherIsInit())
|
||||
cipherInit();
|
||||
@ -90,7 +103,7 @@ cipherBlockNew(CipherMode mode, const char *cipherName, const unsigned char *pas
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_DEBUG_RESULT(CIPHER_BLOCK, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -99,6 +112,13 @@ Determine how large the destination buffer should be
|
||||
size_t
|
||||
cipherBlockProcessSize(CipherBlock *this, size_t sourceSize)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(CIPHER_BLOCK, this);
|
||||
FUNCTION_DEBUG_PARAM(SIZE, sourceSize);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Destination size is source size plus one extra block
|
||||
size_t destinationSize = sourceSize + EVP_MAX_BLOCK_LENGTH;
|
||||
|
||||
@ -106,7 +126,7 @@ cipherBlockProcessSize(CipherBlock *this, size_t sourceSize)
|
||||
if (this->mode == cipherModeEncrypt && !this->saltDone)
|
||||
destinationSize += CIPHER_BLOCK_MAGIC_SIZE + PKCS5_SALT_LEN;
|
||||
|
||||
return destinationSize;
|
||||
FUNCTION_DEBUG_RESULT(SIZE, destinationSize);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -115,6 +135,17 @@ Encrypt/decrypt data
|
||||
size_t
|
||||
cipherBlockProcess(CipherBlock *this, const unsigned char *source, size_t sourceSize, unsigned char *destination)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(CIPHER_BLOCK, this);
|
||||
FUNCTION_DEBUG_PARAM(UCHARP, source);
|
||||
FUNCTION_DEBUG_PARAM(SIZE, sourceSize);
|
||||
FUNCTION_DEBUG_PARAM(UCHARP, destination);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(source != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(destination != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Actual destination size
|
||||
size_t destinationSize = 0;
|
||||
|
||||
@ -212,7 +243,7 @@ cipherBlockProcess(CipherBlock *this, const unsigned char *source, size_t source
|
||||
}
|
||||
|
||||
// Return actual destination size
|
||||
return destinationSize;
|
||||
FUNCTION_DEBUG_RESULT(SIZE, destinationSize);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -221,6 +252,14 @@ Flush the remaining data
|
||||
size_t
|
||||
cipherBlockFlush(CipherBlock *this, unsigned char *destination)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(CIPHER_BLOCK, this);
|
||||
FUNCTION_DEBUG_PARAM(UCHARP, destination);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(destination != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Actual destination size
|
||||
size_t destinationSize = 0;
|
||||
|
||||
@ -233,7 +272,7 @@ cipherBlockFlush(CipherBlock *this, unsigned char *destination)
|
||||
THROW(CipherError, "unable to flush");
|
||||
|
||||
// Return actual destination size
|
||||
return destinationSize;
|
||||
FUNCTION_DEBUG_RESULT(SIZE, destinationSize);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -242,10 +281,18 @@ Free memory
|
||||
void
|
||||
cipherBlockFree(CipherBlock *this)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(CIPHER_BLOCK, this);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Free cipher context
|
||||
if (this->cipherContext)
|
||||
EVP_CIPHER_CTX_cleanup(this->cipherContext);
|
||||
|
||||
// Free mem context
|
||||
memContextFree(this->memContext);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -21,4 +21,12 @@ size_t cipherBlockProcess(CipherBlock *this, const unsigned char *source, size_t
|
||||
size_t cipherBlockFlush(CipherBlock *this, unsigned char *destination);
|
||||
void cipherBlockFree(CipherBlock *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_CIPHER_BLOCK_TYPE \
|
||||
CipherBlock *
|
||||
#define FUNCTION_DEBUG_CIPHER_BLOCK_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "CipherBlock", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -6,6 +6,7 @@ Cipher General Init and Free
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "cipher/cipher.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Flag to indicate if OpenSSL has already been initialized
|
||||
@ -18,6 +19,8 @@ Initialize ciphers
|
||||
void
|
||||
cipherInit()
|
||||
{
|
||||
FUNCTION_DEBUG_VOID(logLevelTrace);
|
||||
|
||||
if (!cipherInitDone)
|
||||
{
|
||||
ERR_load_crypto_strings();
|
||||
@ -25,6 +28,8 @@ cipherInit()
|
||||
|
||||
cipherInitDone = true;
|
||||
}
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -33,23 +38,6 @@ Have the ciphers been initialized?
|
||||
bool
|
||||
cipherIsInit()
|
||||
{
|
||||
return cipherInitDone;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Free ciphers
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
cipherFree()
|
||||
{
|
||||
if (cipherInitDone)
|
||||
{
|
||||
FIPS_mode_set(0);
|
||||
EVP_cleanup();
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
ERR_remove_thread_state(NULL);
|
||||
ERR_free_strings();
|
||||
|
||||
cipherInitDone = false;
|
||||
}
|
||||
FUNCTION_TEST_VOID();
|
||||
FUNCTION_TEST_RESULT(BOOL, cipherInitDone);
|
||||
}
|
||||
|
@ -20,6 +20,5 @@ Functions
|
||||
***********************************************************************************************************************************/
|
||||
void cipherInit();
|
||||
bool cipherIsInit();
|
||||
void cipherFree();
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,8 @@ Cipher
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "cipher/random.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Generate random bytes
|
||||
@ -11,5 +13,15 @@ Generate random bytes
|
||||
void
|
||||
randomBytes(unsigned char *buffer, size_t size)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(UCHARP, buffer);
|
||||
FUNCTION_DEBUG_PARAM(SIZE, size);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(buffer != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(size > 0);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
RAND_bytes(buffer, (int)size);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ Archive Push Command
|
||||
|
||||
#include "command/archive/common.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/log.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/wait.h"
|
||||
@ -19,6 +20,12 @@ Check for ok/error status files in the spool in/out directory
|
||||
bool
|
||||
archiveAsyncStatus(ArchiveMode archiveMode, const String *walSegment, bool confessOnError)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, archiveMode);
|
||||
FUNCTION_DEBUG_PARAM(STRING, walSegment);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, confessOnError);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -98,7 +105,7 @@ archiveAsyncStatus(ArchiveMode archiveMode, const String *walSegment, bool confe
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -107,10 +114,16 @@ Get the next WAL segment given a WAL segment and WAL segment size
|
||||
String *
|
||||
walSegmentNext(const String *walSegment, size_t walSegmentSize, uint pgVersion)
|
||||
{
|
||||
ASSERT_DEBUG(walSegment != NULL);
|
||||
ASSERT_DEBUG(strSize(walSegment) == 24);
|
||||
ASSERT_DEBUG(UINT32_MAX % walSegmentSize == walSegmentSize - 1);
|
||||
ASSERT_DEBUG(pgVersion >= PG_VERSION_11 || walSegmentSize == 16 * 1024 * 1024);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, walSegment);
|
||||
FUNCTION_DEBUG_PARAM(SIZE, walSegmentSize);
|
||||
FUNCTION_DEBUG_PARAM(UINT, pgVersion);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(walSegment != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(strSize(walSegment) == 24);
|
||||
FUNCTION_DEBUG_ASSERT(UINT32_MAX % walSegmentSize == walSegmentSize - 1);
|
||||
FUNCTION_DEBUG_ASSERT(pgVersion >= PG_VERSION_11 || walSegmentSize == 16 * 1024 * 1024);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Extract WAL parts
|
||||
uint32_t timeline = 0;
|
||||
@ -141,7 +154,7 @@ walSegmentNext(const String *walSegment, size_t walSegmentSize, uint pgVersion)
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return strNewFmt("%08X%08X%08X", timeline, major, minor);
|
||||
FUNCTION_DEBUG_RESULT(STRING, strNewFmt("%08X%08X%08X", timeline, major, minor));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -150,7 +163,13 @@ Build a list of WAL segments based on a beginning WAL and number of WAL in the r
|
||||
StringList *
|
||||
walSegmentRange(const String *walSegmentBegin, size_t walSegmentSize, uint pgVersion, uint range)
|
||||
{
|
||||
ASSERT_DEBUG(range > 0);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STRING, walSegmentBegin);
|
||||
FUNCTION_DEBUG_PARAM(SIZE, walSegmentSize);
|
||||
FUNCTION_DEBUG_PARAM(UINT, pgVersion);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(range > 0);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
StringList *result = NULL;
|
||||
|
||||
@ -177,5 +196,5 @@ walSegmentRange(const String *walSegmentBegin, size_t walSegmentSize, uint pgVer
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(STRING_LIST, result);
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ Archive Get Command
|
||||
|
||||
#include "command/archive/common.h"
|
||||
#include "command/command.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/fork.h"
|
||||
#include "common/log.h"
|
||||
#include "common/memContext.h"
|
||||
@ -23,6 +25,16 @@ Clean the queue and prepare a list of WAL segments that the async process should
|
||||
static StringList *
|
||||
queueNeed(const String *walSegment, bool found, size_t queueSize, size_t walSegmentSize, uint pgVersion)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STRING, walSegment);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, found);
|
||||
FUNCTION_DEBUG_PARAM(SIZE, queueSize);
|
||||
FUNCTION_DEBUG_PARAM(SIZE, walSegmentSize);
|
||||
FUNCTION_DEBUG_PARAM(UINT, pgVersion);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(walSegment != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
StringList *result = strLstNew();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -76,7 +88,7 @@ queueNeed(const String *walSegment, bool found, size_t queueSize, size_t walSegm
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(STRING_LIST, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -85,6 +97,8 @@ Push a WAL segment to the repository
|
||||
int
|
||||
cmdArchiveGet()
|
||||
{
|
||||
FUNCTION_DEBUG_VOID(logLevelDebug);
|
||||
|
||||
int result = 1;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -98,9 +112,9 @@ cmdArchiveGet()
|
||||
THROW(ParamRequiredError, "WAL segment to get required");
|
||||
|
||||
if (strLstSize(commandParam) == 1)
|
||||
THROW(ParamRequiredError, "Path to copy WAL segment required");
|
||||
THROW(ParamRequiredError, "path to copy WAL segment required");
|
||||
|
||||
THROW(ParamRequiredError, "extra parameters found");
|
||||
THROW(ParamInvalidError, "extra parameters found");
|
||||
}
|
||||
|
||||
// Get the segment name
|
||||
@ -270,5 +284,5 @@ cmdArchiveGet()
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(INT, result);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ Archive Push Command
|
||||
|
||||
#include "command/archive/common.h"
|
||||
#include "command/command.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/fork.h"
|
||||
#include "common/log.h"
|
||||
#include "common/memContext.h"
|
||||
@ -20,6 +21,8 @@ Push a WAL segment to the repository
|
||||
void
|
||||
cmdArchivePush()
|
||||
{
|
||||
FUNCTION_DEBUG_VOID(logLevelDebug);
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// Make sure there is a parameter to retrieve the WAL segment from
|
||||
@ -123,4 +126,6 @@ cmdArchivePush()
|
||||
THROW(AssertError, "archive-push in C does not support synchronous mode");
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -4,25 +4,23 @@ Common Command Routines
|
||||
#include <string.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/log.h"
|
||||
#include "common/memContext.h"
|
||||
#include "config/config.h"
|
||||
#include "version.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Debug Asserts
|
||||
***********************************************************************************************************************************/
|
||||
// The command must be set
|
||||
#define ASSERT_DEBUG_COMMAND_SET() \
|
||||
ASSERT_DEBUG(cfgCommand() != cfgCmdNone)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Begin the command
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
cmdBegin(bool logOption)
|
||||
{
|
||||
ASSERT_DEBUG_COMMAND_SET();
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, logOption);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(cfgCommand() != cfgCmdNone);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// This is fairly expensive log message to generate so skip it if it won't be output
|
||||
if (logWill(cfgLogLevelDefault()))
|
||||
@ -134,10 +132,12 @@ cmdBegin(bool logOption)
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ANY(cfgLogLevelDefault(), 0, strPtr(info));
|
||||
LOG(cfgLogLevelDefault(), 0, strPtr(info));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
}
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -146,8 +146,13 @@ End the command
|
||||
void
|
||||
cmdEnd(int code, const String *errorMessage)
|
||||
{
|
||||
ASSERT_DEBUG_COMMAND_SET();
|
||||
ASSERT_DEBUG(code == 0 || errorMessage != NULL);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(INT, code);
|
||||
FUNCTION_DEBUG_PARAM(STRING, errorMessage);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(cfgCommand() != cfgCmdNone);
|
||||
FUNCTION_DEBUG_ASSERT(code == 0 || errorMessage != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Skip this log message if it won't be output. It's not too expensive but since we skipped cmdBegin(), may as well.
|
||||
if (logWill(cfgLogLevelDefault()))
|
||||
@ -162,8 +167,10 @@ cmdEnd(int code, const String *errorMessage)
|
||||
else
|
||||
strCat(info, strPtr(errorMessage));
|
||||
|
||||
LOG_ANY(cfgLogLevelDefault(), 0, strPtr(info));
|
||||
LOG(cfgLogLevelDefault(), 0, strPtr(info));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
}
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ Help Command
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/io/handle.h"
|
||||
#include "common/memContext.h"
|
||||
#include "config/config.h"
|
||||
@ -22,6 +24,16 @@ Helper function for helpRender() to make output look good on a console
|
||||
static String *
|
||||
helpRenderText(const String *text, size_t indent, bool indentFirst, size_t length)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, text);
|
||||
FUNCTION_DEBUG_PARAM(SIZE, indent);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, indentFirst);
|
||||
FUNCTION_DEBUG_PARAM(SIZE, length);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(text != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(length > 0);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
String *result = strNew("");
|
||||
|
||||
// Split the text into paragraphs
|
||||
@ -54,7 +66,7 @@ helpRenderText(const String *text, size_t indent, bool indentFirst, size_t lengt
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(STRING, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -63,6 +75,10 @@ Helper function for helpRender() to output values as strings
|
||||
static String *
|
||||
helpRenderValue(const Variant *value)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(VARIANT, value);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
String *result = NULL;
|
||||
|
||||
if (value != NULL)
|
||||
@ -109,7 +125,7 @@ helpRenderValue(const Variant *value)
|
||||
result = varStrForce(value);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(STRING, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -118,6 +134,8 @@ Render help to a string
|
||||
static String *
|
||||
helpRender()
|
||||
{
|
||||
FUNCTION_DEBUG_VOID(logLevelDebug);
|
||||
|
||||
String *result = strNew(PGBACKREST_NAME " " PGBACKREST_VERSION);
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -358,7 +376,7 @@ helpRender()
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(STRING, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -367,9 +385,13 @@ Render help and output to stdout
|
||||
void
|
||||
cmdHelp()
|
||||
{
|
||||
FUNCTION_DEBUG_VOID(logLevelDebug);
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
ioHandleWriteOneStr(STDOUT_FILENO, helpRender());
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -10,10 +10,12 @@ Assert Routines
|
||||
For very important asserts that are shipped with the production code
|
||||
***********************************************************************************************************************************/
|
||||
#define ASSERT(condition) \
|
||||
{ \
|
||||
if (!(condition)) \
|
||||
THROW_FMT(AssertError, "assertion '%s' failed", #condition); \
|
||||
}
|
||||
do \
|
||||
{ \
|
||||
if (!(condition)) \
|
||||
THROW_FMT(AssertError, "assertion '%s' failed", #condition); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Used for assertions that should only be run when debugging. Ideal for conditions that need to be tested during development but
|
||||
@ -21,10 +23,12 @@ be too expensive to ship with the production code.
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef NDEBUG
|
||||
#define ASSERT_DEBUG(condition) \
|
||||
{ \
|
||||
if (!(condition)) \
|
||||
THROW_FMT(AssertError, "debug assertion '%s' failed", #condition); \
|
||||
}
|
||||
do \
|
||||
{ \
|
||||
if (!(condition)) \
|
||||
THROW_FMT(AssertError, "debug assertion '%s' failed", #condition); \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
#define ASSERT_DEBUG(condition)
|
||||
#endif
|
||||
|
47
src/common/debug.c
Normal file
47
src/common/debug.c
Normal file
@ -0,0 +1,47 @@
|
||||
/***********************************************************************************************************************************
|
||||
Debug Routines
|
||||
***********************************************************************************************************************************/
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert object to a zero-terminated string for logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
objToLog(const void *object, const char *objectName, char *buffer, size_t bufferSize)
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
if (object == NULL)
|
||||
result = (size_t)snprintf(buffer, bufferSize, "null");
|
||||
else
|
||||
result = (size_t)snprintf(buffer, bufferSize, "{%s}", objectName);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert pointer to a zero-terminated string for logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
ptrToLog(const void *pointer, const char *pointerName, char *buffer, size_t bufferSize)
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
if (pointer == NULL)
|
||||
result = (size_t)snprintf(buffer, bufferSize, "null");
|
||||
else
|
||||
result = (size_t)snprintf(buffer, bufferSize, "(%s)", pointerName);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert zero-terminated string for logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
strzToLog(const char *string, char *buffer, size_t bufferSize)
|
||||
{
|
||||
return (size_t)snprintf(buffer, bufferSize, string == NULL ? "%s" : "\"%s\"", string == NULL ? "null" : string);
|
||||
}
|
@ -4,6 +4,9 @@ Debug Routines
|
||||
#ifndef COMMON_DEBUG_H
|
||||
#define COMMON_DEBUG_H
|
||||
|
||||
#include "common/stackTrace.h"
|
||||
#include "common/type/convert.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
NDEBUG indicates to C library routines that debugging is off -- set a more readable flag to use when debugging is on
|
||||
***********************************************************************************************************************************/
|
||||
@ -21,4 +24,294 @@ Extern variables that are needed for unit testing
|
||||
static
|
||||
#endif
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Base function debugging macros
|
||||
|
||||
In debug mode parameters will always be recorded in the stack trace while in production mode they will only be recorded when the log
|
||||
level is set to debug or trace.
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_LEVEL() \
|
||||
FUNCTION_DEBUG_logLevel
|
||||
|
||||
#ifdef DEBUG
|
||||
#define FUNCTION_DEBUG_BEGIN_BASE(logLevel) \
|
||||
LogLevel FUNCTION_DEBUG_LEVEL() = STACK_TRACE_PUSH(logLevel); \
|
||||
\
|
||||
{ \
|
||||
stackTraceParamLog();
|
||||
|
||||
#define FUNCTION_DEBUG_END_BASE() \
|
||||
LOG_WILL(FUNCTION_DEBUG_LEVEL(), 0, "(%s)", stackTraceParam()); \
|
||||
}
|
||||
|
||||
#define FUNCTION_DEBUG_PARAM_BASE_BEGIN() \
|
||||
stackTraceTestStop() \
|
||||
|
||||
#define FUNCTION_DEBUG_PARAM_BASE_END() \
|
||||
stackTraceTestStart()
|
||||
#else
|
||||
#define FUNCTION_DEBUG_BEGIN_BASE(logLevel) \
|
||||
LogLevel FUNCTION_DEBUG_LEVEL() = STACK_TRACE_PUSH(logLevel); \
|
||||
\
|
||||
if (logWill(FUNCTION_DEBUG_LEVEL())) \
|
||||
{ \
|
||||
stackTraceParamLog()
|
||||
|
||||
#define FUNCTION_DEBUG_END_BASE() \
|
||||
LOG(FUNCTION_DEBUG_LEVEL(), 0, "(%s)", stackTraceParam()); \
|
||||
}
|
||||
|
||||
#define FUNCTION_DEBUG_PARAM_BASE_BEGIN()
|
||||
#define FUNCTION_DEBUG_PARAM_BASE_END()
|
||||
#endif
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
General purpose function debugging macros
|
||||
|
||||
FUNCTION_DEBUG_VOID() is provided as a shortcut for functions that have no parameters.
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_BEGIN(logLevel) \
|
||||
FUNCTION_DEBUG_BEGIN_BASE(logLevel)
|
||||
|
||||
#define FUNCTION_DEBUG_END() \
|
||||
FUNCTION_DEBUG_END_BASE()
|
||||
|
||||
#define FUNCTION_DEBUG_VOID(logLevel) \
|
||||
FUNCTION_DEBUG_BEGIN_BASE(logLevel); \
|
||||
FUNCTION_DEBUG_END_BASE()
|
||||
|
||||
#define FUNCTION_DEBUG_PARAM(typeMacroPrefix, param) \
|
||||
FUNCTION_DEBUG_PARAM_BASE_BEGIN(); \
|
||||
stackTraceParamAdd(FUNCTION_DEBUG_##typeMacroPrefix##_FORMAT(param, stackTraceParamBuffer(#param), STACK_TRACE_PARAM_MAX)); \
|
||||
FUNCTION_DEBUG_PARAM_BASE_END()
|
||||
|
||||
#define FUNCTION_DEBUG_PARAM_PTR(typeName, param) \
|
||||
FUNCTION_DEBUG_PARAM_BASE_BEGIN(); \
|
||||
stackTraceParamAdd(ptrToLog(param, typeName, stackTraceParamBuffer(#param), STACK_TRACE_PARAM_MAX )); \
|
||||
FUNCTION_DEBUG_PARAM_BASE_END()
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions and macros to render various data types
|
||||
***********************************************************************************************************************************/
|
||||
size_t objToLog(const void *object, const char *objectName, char *buffer, size_t bufferSize);
|
||||
size_t ptrToLog(const void *pointer, const char *pointerName, char *buffer, size_t bufferSize);
|
||||
size_t strzToLog(const char *string, char *buffer, size_t bufferSize);
|
||||
|
||||
#define FUNCTION_DEBUG_BOOL_TYPE \
|
||||
bool
|
||||
#define FUNCTION_DEBUG_BOOL_FORMAT(value, buffer, bufferSize) \
|
||||
cvtBoolToZ(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_BOOLP_TYPE \
|
||||
bool *
|
||||
#define FUNCTION_DEBUG_BOOLP_FORMAT(value, buffer, bufferSize) \
|
||||
ptrToLog(value, "bool *", buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_CHARP_TYPE \
|
||||
char *
|
||||
#define FUNCTION_DEBUG_CHARP_FORMAT(value, buffer, bufferSize) \
|
||||
ptrToLog(value, "char *", buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_CONST_CHARPP_TYPE \
|
||||
const char **
|
||||
#define FUNCTION_DEBUG_CONST_CHARPP_FORMAT(value, buffer, bufferSize) \
|
||||
ptrToLog(value, "char **", buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_CHARPY_TYPE \
|
||||
char *[]
|
||||
#define FUNCTION_DEBUG_CHARPY_FORMAT(value, buffer, bufferSize) \
|
||||
ptrToLog(value, "char *[]", buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_DOUBLE_TYPE \
|
||||
double
|
||||
#define FUNCTION_DEBUG_DOUBLE_FORMAT(value, buffer, bufferSize) \
|
||||
cvtDoubleToZ(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_DOUBLEP_TYPE \
|
||||
double *
|
||||
#define FUNCTION_DEBUG_DOUBLEP_FORMAT(value, buffer, bufferSize) \
|
||||
ptrToLog(value, "double *", buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_INT_TYPE \
|
||||
int
|
||||
#define FUNCTION_DEBUG_INT_FORMAT(value, buffer, bufferSize) \
|
||||
cvtIntToZ(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_INTP_TYPE \
|
||||
int *
|
||||
#define FUNCTION_DEBUG_INTP_FORMAT(value, buffer, bufferSize) \
|
||||
ptrToLog(value, "int *", buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_INT64_TYPE \
|
||||
int64_t
|
||||
#define FUNCTION_DEBUG_INT64_FORMAT(value, buffer, bufferSize) \
|
||||
cvtInt64ToZ(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_ENUM_TYPE \
|
||||
unsigned int
|
||||
#define FUNCTION_DEBUG_ENUM_FORMAT(value, buffer, bufferSize) \
|
||||
FUNCTION_DEBUG_UINT_FORMAT(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_FUNCTIONP_FORMAT(value, buffer, bufferSize) \
|
||||
ptrToLog(value == NULL ? NULL : (void *)1, "function *", buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_MODE_TYPE \
|
||||
mode_t
|
||||
#define FUNCTION_DEBUG_MODE_FORMAT(value, buffer, bufferSize) \
|
||||
cvtModeToZ(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_UCHARP_TYPE \
|
||||
unsigned char *
|
||||
#define FUNCTION_DEBUG_UCHARP_FORMAT(value, buffer, bufferSize) \
|
||||
ptrToLog(value, "unsigned char *", buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_SIZE_TYPE \
|
||||
size_t
|
||||
#define FUNCTION_DEBUG_SIZE_FORMAT(value, buffer, bufferSize) \
|
||||
cvtSizeToZ(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_UINT_TYPE \
|
||||
unsigned int
|
||||
#define FUNCTION_DEBUG_UINT_FORMAT(value, buffer, bufferSize) \
|
||||
cvtUIntToZ(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_UINT16_TYPE \
|
||||
uint16_t
|
||||
#define FUNCTION_DEBUG_UINT16_FORMAT(value, buffer, bufferSize) \
|
||||
FUNCTION_DEBUG_UINT_FORMAT(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_UINT32_TYPE \
|
||||
uint32_t
|
||||
#define FUNCTION_DEBUG_UINT32_FORMAT(value, buffer, bufferSize) \
|
||||
FUNCTION_DEBUG_UINT_FORMAT(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_UINT64_TYPE \
|
||||
uint64_t
|
||||
#define FUNCTION_DEBUG_UINT64_FORMAT(value, buffer, bufferSize) \
|
||||
cvtUInt64ToZ(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_VOIDP_TYPE \
|
||||
void *
|
||||
#define FUNCTION_DEBUG_VOIDP_FORMAT(value, buffer, bufferSize) \
|
||||
ptrToLog(value, "void *", buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_VOIDPP_TYPE \
|
||||
void **
|
||||
#define FUNCTION_DEBUG_VOIDPP_FORMAT(value, buffer, bufferSize) \
|
||||
ptrToLog(value, "void **", buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_STRINGZ_TYPE \
|
||||
const char *
|
||||
#define FUNCTION_DEBUG_STRINGZ_FORMAT(value, buffer, bufferSize) \
|
||||
strzToLog(value, buffer, bufferSize)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Assert function to be used with function debugging
|
||||
|
||||
The assert statement is compiled into production code but only runs when the log level >= debug
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_ASSERT(condition) \
|
||||
do \
|
||||
{ \
|
||||
if (!(condition)) \
|
||||
THROW_FMT(AssertError, "function debug assertion '%s' failed", #condition); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros to return function results (or void)
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_RESULT(typeMacroPrefix, result) \
|
||||
do \
|
||||
{ \
|
||||
FUNCTION_DEBUG_##typeMacroPrefix##_TYPE FUNCTION_DEBUG_RESULT_result = result; \
|
||||
\
|
||||
STACK_TRACE_POP(); \
|
||||
\
|
||||
if (logWill(FUNCTION_DEBUG_LEVEL())) \
|
||||
{ \
|
||||
char buffer[STACK_TRACE_PARAM_MAX]; \
|
||||
\
|
||||
FUNCTION_DEBUG_##typeMacroPrefix##_FORMAT(FUNCTION_DEBUG_RESULT_result, buffer, sizeof(buffer)); \
|
||||
LOG(FUNCTION_DEBUG_LEVEL(), 0, "=> %s", buffer); \
|
||||
} \
|
||||
\
|
||||
return FUNCTION_DEBUG_RESULT_result; \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define FUNCTION_DEBUG_RESULT_VOID() \
|
||||
do \
|
||||
{ \
|
||||
STACK_TRACE_POP(); \
|
||||
\
|
||||
LOG_WILL(FUNCTION_DEBUG_LEVEL(), 0, "=> void"); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Function Test Macros
|
||||
|
||||
In debug builds these macros will update the stack trace with function names and parameters but not log. In production builds all
|
||||
test macros are compiled out.
|
||||
***********************************************************************************************************************************/
|
||||
#ifdef DEBUG
|
||||
#define FUNCTION_TEST_BEGIN() \
|
||||
if (stackTraceTest()) \
|
||||
{ \
|
||||
STACK_TRACE_PUSH(logLevelDebug); \
|
||||
stackTraceParamLog()
|
||||
|
||||
#define FUNCTION_TEST_PARAM(typeMacroPrefix, param) \
|
||||
FUNCTION_DEBUG_PARAM(typeMacroPrefix, param)
|
||||
|
||||
#define FUNCTION_TEST_PARAM_PTR(typeName, param) \
|
||||
FUNCTION_DEBUG_PARAM_PTR(typeName, param)
|
||||
|
||||
#define FUNCTION_TEST_END() \
|
||||
}
|
||||
|
||||
#define FUNCTION_TEST_VOID() \
|
||||
FUNCTION_TEST_BEGIN(); \
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
#define FUNCTION_TEST_ASSERT(condition) \
|
||||
do \
|
||||
{ \
|
||||
if (!(condition)) \
|
||||
THROW_FMT(AssertError, "function test assertion '%s' failed", #condition); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define FUNCTION_TEST_RESULT(typeMacroPrefix, result) \
|
||||
do \
|
||||
{ \
|
||||
FUNCTION_DEBUG_##typeMacroPrefix##_TYPE FUNCTION_DEBUG_RESULT_result = result; \
|
||||
\
|
||||
if (stackTraceTest()) \
|
||||
STACK_TRACE_POP(); \
|
||||
\
|
||||
return FUNCTION_DEBUG_RESULT_result; \
|
||||
} \
|
||||
while(0);
|
||||
|
||||
#define FUNCTION_TEST_RESULT_VOID() \
|
||||
do \
|
||||
{ \
|
||||
if (stackTraceTest()) \
|
||||
STACK_TRACE_POP(); \
|
||||
} \
|
||||
while(0);
|
||||
#else
|
||||
#define FUNCTION_TEST_BEGIN()
|
||||
#define FUNCTION_TEST_PARAM(typeMacroPrefix, param)
|
||||
#define FUNCTION_TEST_PARAM_PTR(typeName, param)
|
||||
#define FUNCTION_TEST_END()
|
||||
#define FUNCTION_TEST_VOID()
|
||||
#define FUNCTION_TEST_ASSERT(condition)
|
||||
#define FUNCTION_TEST_RESULT(typeMacroPrefix, result) \
|
||||
return result
|
||||
#define FUNCTION_TEST_RESULT_VOID()
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -6,6 +6,7 @@ Binary to String Encode/Decode
|
||||
|
||||
#include "common/encode.h"
|
||||
#include "common/encode/base64.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -20,10 +21,19 @@ Encode binary data to a printable string
|
||||
void
|
||||
encodeToStr(EncodeType encodeType, const unsigned char *source, size_t sourceSize, char *destination)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, encodeType);
|
||||
FUNCTION_TEST_PARAM(UCHARP, source);
|
||||
FUNCTION_TEST_PARAM(SIZE, sourceSize);
|
||||
FUNCTION_TEST_PARAM(CHARP, destination);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (encodeType == encodeBase64)
|
||||
encodeToStrBase64(source, sourceSize, destination);
|
||||
else
|
||||
ENCODE_TYPE_INVALID_ERROR(encodeType);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -32,6 +42,11 @@ Size of the string returned by encodeToStr()
|
||||
size_t
|
||||
encodeToStrSize(EncodeType encodeType, size_t sourceSize)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, encodeType);
|
||||
FUNCTION_TEST_PARAM(SIZE, sourceSize);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
size_t destinationSize = 0;
|
||||
|
||||
if (encodeType == encodeBase64)
|
||||
@ -39,7 +54,7 @@ encodeToStrSize(EncodeType encodeType, size_t sourceSize)
|
||||
else
|
||||
ENCODE_TYPE_INVALID_ERROR(encodeType);
|
||||
|
||||
return destinationSize;
|
||||
FUNCTION_TEST_RESULT(SIZE, destinationSize);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -48,10 +63,18 @@ Decode a string to binary data
|
||||
void
|
||||
decodeToBin(EncodeType encodeType, const char *source, unsigned char *destination)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, encodeType);
|
||||
FUNCTION_TEST_PARAM(CHARP, source);
|
||||
FUNCTION_TEST_PARAM(UCHARP, destination);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (encodeType == encodeBase64)
|
||||
decodeToBinBase64(source, destination);
|
||||
else
|
||||
ENCODE_TYPE_INVALID_ERROR(encodeType);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -60,6 +83,11 @@ Size of the binary data returned by decodeToBin()
|
||||
size_t
|
||||
decodeToBinSize(EncodeType encodeType, const char *source)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, encodeType);
|
||||
FUNCTION_TEST_PARAM(CHARP, source);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
size_t destinationSize = 0;
|
||||
|
||||
if (encodeType == encodeBase64)
|
||||
@ -67,7 +95,7 @@ decodeToBinSize(EncodeType encodeType, const char *source)
|
||||
else
|
||||
ENCODE_TYPE_INVALID_ERROR(encodeType);
|
||||
|
||||
return destinationSize;
|
||||
FUNCTION_TEST_RESULT(SIZE, destinationSize);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -76,6 +104,11 @@ Check that the encoded string is valid
|
||||
bool
|
||||
decodeToBinValid(EncodeType encodeType, const char *source)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, encodeType);
|
||||
FUNCTION_TEST_PARAM(CHARP, source);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool valid = true;
|
||||
|
||||
TRY_BEGIN()
|
||||
@ -88,7 +121,7 @@ decodeToBinValid(EncodeType encodeType, const char *source)
|
||||
}
|
||||
TRY_END();
|
||||
|
||||
return valid;
|
||||
FUNCTION_TEST_RESULT(BOOL, valid);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -97,8 +130,15 @@ Validate the encoded string
|
||||
void
|
||||
decodeToBinValidate(EncodeType encodeType, const char *source)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, encodeType);
|
||||
FUNCTION_TEST_PARAM(CHARP, source);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (encodeType == encodeBase64)
|
||||
decodeToBinValidateBase64(source);
|
||||
else
|
||||
ENCODE_TYPE_INVALID_ERROR(encodeType);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ Base64 Binary to String Encode/Decode
|
||||
#include <string.h>
|
||||
|
||||
#include "common/encode/base64.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -14,6 +15,15 @@ static const char encodeBase64Lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkl
|
||||
void
|
||||
encodeToStrBase64(const unsigned char *source, size_t sourceSize, char *destination)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UCHARP, source);
|
||||
FUNCTION_TEST_PARAM(SIZE, sourceSize);
|
||||
FUNCTION_TEST_PARAM(CHARP, destination);
|
||||
|
||||
FUNCTION_TEST_ASSERT(source != NULL);
|
||||
FUNCTION_TEST_ASSERT(destination != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
unsigned int destinationIdx = 0;
|
||||
|
||||
// Encode the string from three bytes to four characters
|
||||
@ -56,6 +66,8 @@ encodeToStrBase64(const unsigned char *source, size_t sourceSize, char *destinat
|
||||
|
||||
// Zero-terminate the string
|
||||
destination[destinationIdx] = 0;
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -64,6 +76,10 @@ Size of the destination param required by encodeToStrBase64() minus space for th
|
||||
size_t
|
||||
encodeToStrSizeBase64(size_t sourceSize)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(SIZE, sourceSize);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Calculate how many groups of three are in the source
|
||||
size_t encodeGroupTotal = sourceSize / 3;
|
||||
|
||||
@ -72,7 +88,7 @@ encodeToStrSizeBase64(size_t sourceSize)
|
||||
encodeGroupTotal++;
|
||||
|
||||
// Four characters are needed to encode each group
|
||||
return encodeGroupTotal * 4;
|
||||
FUNCTION_TEST_RESULT(SIZE, encodeGroupTotal * 4);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -101,6 +117,11 @@ static const int decodeBase64Lookup[256] =
|
||||
void
|
||||
decodeToBinBase64(const char *source, unsigned char *destination)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(CHARP, source);
|
||||
FUNCTION_TEST_PARAM(UCHARP, destination);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Validate encoded string
|
||||
decodeToBinValidateBase64(source);
|
||||
|
||||
@ -127,6 +148,8 @@ decodeToBinBase64(const char *source, unsigned char *destination)
|
||||
(((decodeBase64Lookup[(int)source[sourceIdx + 2]] << 6) & 0xc0) | decodeBase64Lookup[(int)source[sourceIdx + 3]]);
|
||||
}
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -135,6 +158,10 @@ Size of the destination param required by decodeToBinBase64()
|
||||
size_t
|
||||
decodeToBinSizeBase64(const char *source)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(CHARP, source);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Validate encoded string
|
||||
decodeToBinValidateBase64(source);
|
||||
|
||||
@ -152,7 +179,7 @@ decodeToBinSizeBase64(const char *source)
|
||||
destinationSize--;
|
||||
}
|
||||
|
||||
return destinationSize;
|
||||
FUNCTION_TEST_RESULT(SIZE, destinationSize);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -161,6 +188,10 @@ Validate the encoded string
|
||||
void
|
||||
decodeToBinValidateBase64(const char *source)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(CHARP, source);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Check for the correct length
|
||||
size_t sourceSize = strlen(source);
|
||||
|
||||
@ -188,4 +219,6 @@ decodeToBinValidateBase64(const char *source)
|
||||
THROW_FMT(FormatError, "base64 invalid character found at position %u", sourceIdx);
|
||||
}
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ Error Handler
|
||||
#include <string.h>
|
||||
|
||||
#include "common/error.h"
|
||||
#include "common/stackTrace.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Represents an error type
|
||||
@ -38,7 +39,7 @@ typedef enum {errorStateBegin, errorStateTry, errorStateCatch, errorStateFinal,
|
||||
/***********************************************************************************************************************************
|
||||
Track error handling
|
||||
***********************************************************************************************************************************/
|
||||
struct
|
||||
static struct
|
||||
{
|
||||
// Array of jump buffers
|
||||
jmp_buf jumpList[ERROR_TRY_MAX];
|
||||
@ -57,8 +58,10 @@ struct
|
||||
{
|
||||
const ErrorType *errorType; // Error type
|
||||
const char *fileName; // Source file where the error occurred
|
||||
const char *functionName; // Function where the error occurred
|
||||
int fileLine; // Source file line where the error occurred
|
||||
const char *message; // Description of the error
|
||||
const char *stackTrace; // Stack trace
|
||||
} error;
|
||||
} errorContext;
|
||||
|
||||
@ -75,6 +78,7 @@ The temp buffer is required because the error message being passed might be the
|
||||
|
||||
static char messageBuffer[ERROR_MESSAGE_BUFFER_SIZE];
|
||||
static char messageBufferTemp[ERROR_MESSAGE_BUFFER_SIZE];
|
||||
static char stackTraceBuffer[ERROR_MESSAGE_BUFFER_SIZE];
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Error type code
|
||||
@ -128,6 +132,14 @@ errorTypeParent(const ErrorType *errorType)
|
||||
return errorType->parentType;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get the depth of the current try statement (0 if none)
|
||||
***********************************************************************************************************************************/
|
||||
unsigned int errorTryDepth()
|
||||
{
|
||||
return (unsigned int)errorContext.tryTotal;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Does the child error type extend the parent error type?
|
||||
***********************************************************************************************************************************/
|
||||
@ -177,6 +189,15 @@ errorFileName()
|
||||
return errorContext.error.fileName;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Error function name
|
||||
***********************************************************************************************************************************/
|
||||
const char *
|
||||
errorFunctionName()
|
||||
{
|
||||
return errorContext.error.functionName;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Error file line number
|
||||
***********************************************************************************************************************************/
|
||||
@ -204,6 +225,15 @@ errorName()
|
||||
return errorTypeName(errorType());
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Error stack trace
|
||||
***********************************************************************************************************************************/
|
||||
const char *
|
||||
errorStackTrace()
|
||||
{
|
||||
return errorContext.error.stackTrace;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Is this error an instance of the error type?
|
||||
***********************************************************************************************************************************/
|
||||
@ -265,11 +295,11 @@ errorInternalJump()
|
||||
Begin the try block
|
||||
***********************************************************************************************************************************/
|
||||
bool
|
||||
errorInternalTry(const char *fileName, int fileLine)
|
||||
errorInternalTry(const char *fileName, const char *functionName, int fileLine)
|
||||
{
|
||||
// If try total has been exceeded then throw an error
|
||||
if (errorContext.tryTotal >= ERROR_TRY_MAX)
|
||||
errorInternalThrowFmt(&AssertError, fileName, fileLine, "too many nested try blocks");
|
||||
errorInternalThrowFmt(&AssertError, fileName, functionName, fileLine, "too many nested try blocks");
|
||||
|
||||
// Increment try total
|
||||
errorContext.tryTotal++;
|
||||
@ -315,6 +345,9 @@ errorInternalProcess(bool catch)
|
||||
errorContext.tryList[errorContext.tryTotal].uncaught = false;
|
||||
return true;
|
||||
}
|
||||
// Else if just entering error state clean up the stack
|
||||
else if (errorContext.tryList[errorContext.tryTotal].state == errorStateTry)
|
||||
stackTraceClean(errorTryDepth());
|
||||
|
||||
// Increment the state
|
||||
errorContext.tryList[errorContext.tryTotal].state++;
|
||||
@ -345,23 +378,34 @@ errorInternalProcess(bool catch)
|
||||
Throw an error
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
errorInternalThrow(const ErrorType *errorType, const char *fileName, int fileLine, const char *message)
|
||||
errorInternalThrow(const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *message)
|
||||
{
|
||||
// Setup error data
|
||||
errorContext.error.errorType = errorType;
|
||||
errorContext.error.fileName = fileName;
|
||||
errorContext.error.functionName = functionName;
|
||||
errorContext.error.fileLine = fileLine;
|
||||
|
||||
// Assign message to the error
|
||||
strcpy(messageBuffer, message);
|
||||
errorContext.error.message = (const char *)messageBuffer;
|
||||
|
||||
// Generate the stack trace for the error
|
||||
if (stackTraceToZ(
|
||||
stackTraceBuffer, sizeof(stackTraceBuffer), fileName, functionName, (unsigned int)fileLine) >= sizeof(stackTraceBuffer))
|
||||
{
|
||||
// Indicate that the stack trace was truncated
|
||||
}
|
||||
|
||||
errorContext.error.stackTrace = (const char *)stackTraceBuffer;
|
||||
|
||||
// Propogate the error
|
||||
errorInternalPropagate();
|
||||
}
|
||||
|
||||
void
|
||||
errorInternalThrowFmt(const ErrorType *errorType, const char *fileName, int fileLine, const char *format, ...)
|
||||
errorInternalThrowFmt(
|
||||
const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *format, ...)
|
||||
{
|
||||
// Format message
|
||||
va_list argument;
|
||||
@ -369,39 +413,26 @@ errorInternalThrowFmt(const ErrorType *errorType, const char *fileName, int file
|
||||
vsnprintf(messageBufferTemp, ERROR_MESSAGE_BUFFER_SIZE - 1, format, argument);
|
||||
va_end(argument);
|
||||
|
||||
errorInternalThrow(errorType, fileName, fileLine, messageBufferTemp);
|
||||
errorInternalThrow(errorType, fileName, functionName, fileLine, messageBufferTemp);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Throw a system error
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
errorInternalThrowSys(int errNo, const ErrorType *errorType, const char *fileName, int fileLine, const char *message)
|
||||
errorInternalThrowSys(
|
||||
int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *message)
|
||||
{
|
||||
// Setup error data
|
||||
errorContext.error.errorType = errorType;
|
||||
errorContext.error.fileName = fileName;
|
||||
errorContext.error.fileLine = fileLine;
|
||||
|
||||
// Append the system message
|
||||
// Format message with system message appended
|
||||
snprintf(messageBufferTemp, ERROR_MESSAGE_BUFFER_SIZE - 1, "%s: [%d] %s", message, errNo, strerror(errNo));
|
||||
|
||||
// Assign message to the error
|
||||
strcpy(messageBuffer, messageBufferTemp);
|
||||
errorContext.error.message = (const char *)messageBuffer;
|
||||
|
||||
// Propogate the error
|
||||
errorInternalPropagate();
|
||||
errorInternalThrow(errorType, fileName, functionName, fileLine, messageBufferTemp);
|
||||
}
|
||||
|
||||
void
|
||||
errorInternalThrowSysFmt(int errNo, const ErrorType *errorType, const char *fileName, int fileLine, const char *format, ...)
|
||||
errorInternalThrowSysFmt(
|
||||
int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *format, ...)
|
||||
{
|
||||
// Setup error data
|
||||
errorContext.error.errorType = errorType;
|
||||
errorContext.error.fileName = fileName;
|
||||
errorContext.error.fileLine = fileLine;
|
||||
|
||||
// Format message
|
||||
va_list argument;
|
||||
va_start(argument, format);
|
||||
@ -411,10 +442,5 @@ errorInternalThrowSysFmt(int errNo, const ErrorType *errorType, const char *file
|
||||
// Append the system message
|
||||
snprintf(messageBufferTemp + messageSize, ERROR_MESSAGE_BUFFER_SIZE - 1 - messageSize, ": [%d] %s", errNo, strerror(errNo));
|
||||
|
||||
// Assign message to the error
|
||||
strcpy(messageBuffer, messageBufferTemp);
|
||||
errorContext.error.message = (const char *)messageBuffer;
|
||||
|
||||
// Propogate the error
|
||||
errorInternalPropagate();
|
||||
errorInternalThrow(errorType, fileName, functionName, fileLine, messageBufferTemp);
|
||||
}
|
||||
|
@ -68,10 +68,17 @@ Functions to get information about the current error
|
||||
const ErrorType *errorType();
|
||||
int errorCode();
|
||||
const char *errorFileName();
|
||||
const char *errorFunctionName();
|
||||
int errorFileLine();
|
||||
bool errorInstanceOf(const ErrorType *errorTypeTest);
|
||||
const char *errorMessage();
|
||||
const char *errorName();
|
||||
bool errorInstanceOf(const ErrorType *errorTypeTest);
|
||||
const char *errorStackTrace();
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions to get information about the try stack
|
||||
***********************************************************************************************************************************/
|
||||
unsigned int errorTryDepth();
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Begin a block where errors can be thrown
|
||||
@ -79,7 +86,7 @@ Begin a block where errors can be thrown
|
||||
#define TRY_BEGIN() \
|
||||
do \
|
||||
{ \
|
||||
if (errorInternalTry(__FILE__, __LINE__) && setjmp(*errorInternalJump()) >= 0) \
|
||||
if (errorInternalTry(__FILE__, __func__, __LINE__) && setjmp(*errorInternalJump()) >= 0) \
|
||||
{ \
|
||||
while (errorInternalProcess(false)) \
|
||||
if (errorInternalStateTry())
|
||||
@ -118,39 +125,39 @@ error information to stderr.
|
||||
The seldom used "THROWP" variants allow an error to be thrown with a pointer to the error type.
|
||||
***********************************************************************************************************************************/
|
||||
#define THROW(errorType, message) \
|
||||
errorInternalThrow(&errorType, __FILE__, __LINE__, message)
|
||||
errorInternalThrow(&errorType, __FILE__, __func__, __LINE__, message)
|
||||
#define THROW_FMT(errorType, ...) \
|
||||
errorInternalThrowFmt(&errorType, __FILE__, __LINE__, __VA_ARGS__)
|
||||
errorInternalThrowFmt(&errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
||||
#define THROWP(errorType, message) \
|
||||
errorInternalThrow(errorType, __FILE__, __LINE__, message)
|
||||
errorInternalThrow(errorType, __FILE__, __func__, __LINE__, message)
|
||||
#define THROWP_FMT(errorType, ...) \
|
||||
errorInternalThrowFmt(errorType, __FILE__, __LINE__, __VA_ARGS__)
|
||||
errorInternalThrowFmt(errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
||||
|
||||
#define THROW_CODE(errorCode, message) \
|
||||
errorInternalThrow(errorTypeFromCode(errorCode), __FILE__, __LINE__, message)
|
||||
errorInternalThrow(errorTypeFromCode(errorCode), __FILE__, __func__, __LINE__, message)
|
||||
#define THROW_CODE_FMT(errorCode, ...) \
|
||||
errorInternalThrowFmt(errorTypeFromCode(errorCode), __FILE__, __LINE__, __VA_ARGS__)
|
||||
errorInternalThrowFmt(errorTypeFromCode(errorCode), __FILE__, __func__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Throw an error when a system call fails
|
||||
***********************************************************************************************************************************/
|
||||
#define THROW_SYS_ERROR(errorType, message) \
|
||||
errorInternalThrowSys(errno, &errorType, __FILE__, __LINE__, message)
|
||||
errorInternalThrowSys(errno, &errorType, __FILE__, __func__, __LINE__, message)
|
||||
#define THROW_SYS_ERROR_FMT(errorType, ...) \
|
||||
errorInternalThrowSysFmt(errno, &errorType, __FILE__, __LINE__, __VA_ARGS__)
|
||||
errorInternalThrowSysFmt(errno, &errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
||||
#define THROWP_SYS_ERROR(errorType, message) \
|
||||
errorInternalThrowSys(errno, errorType, __FILE__, __LINE__, message)
|
||||
errorInternalThrowSys(errno, errorType, __FILE__, __func__, __LINE__, message)
|
||||
#define THROWP_SYS_ERROR_FMT(errorType, ...) \
|
||||
errorInternalThrowSysFmt(errno, errorType, __FILE__, __LINE__, __VA_ARGS__)
|
||||
errorInternalThrowSysFmt(errno, errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
||||
|
||||
#define THROW_SYS_ERROR_CODE(errNo, errorType, message) \
|
||||
errorInternalThrowSys(errNo, &errorType, __FILE__, __LINE__, message)
|
||||
errorInternalThrowSys(errNo, &errorType, __FILE__, __func__, __LINE__, message)
|
||||
#define THROW_SYS_ERROR_CODE_FMT(errNo, errorType, ...) \
|
||||
errorInternalThrowSysFmt(errNo, &errorType, __FILE__, __LINE__, __VA_ARGS__)
|
||||
errorInternalThrowSysFmt(errNo, &errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
||||
#define THROWP_SYS_ERROR_CODE(errNo, errorType, message) \
|
||||
errorInternalThrowSys(errNo, errorType, __FILE__, __LINE__, message)
|
||||
errorInternalThrowSys(errNo, errorType, __FILE__, __func__, __LINE__, message)
|
||||
#define THROWP_SYS_ERROR_CODE_FMT(errNo, errorType, ...) \
|
||||
errorInternalThrowSysFmt(errNo, errorType, __FILE__, __LINE__, __VA_ARGS__)
|
||||
errorInternalThrowSysFmt(errNo, errorType, __FILE__, __func__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Rethrow the current error
|
||||
@ -163,7 +170,7 @@ Internal functions
|
||||
|
||||
These functions are used by the macros to implement the error handler and should never be called independently.
|
||||
***********************************************************************************************************************************/
|
||||
bool errorInternalTry(const char *fileName, int fileLine);
|
||||
bool errorInternalTry(const char *fileName, const char *functionName, int fileLine);
|
||||
jmp_buf *errorInternalJump();
|
||||
bool errorInternalStateTry();
|
||||
bool errorInternalStateCatch(const ErrorType *errorTypeCatch);
|
||||
@ -171,14 +178,24 @@ bool errorInternalStateFinal();
|
||||
bool errorInternalProcess(bool catch);
|
||||
void errorInternalPropagate() __attribute__((__noreturn__));
|
||||
void errorInternalThrow(
|
||||
const ErrorType *errorType, const char *fileName, int fileLine, const char *message) __attribute__((__noreturn__));
|
||||
const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *message)
|
||||
__attribute__((__noreturn__));
|
||||
void errorInternalThrowFmt(
|
||||
const ErrorType *errorType, const char *fileName, int fileLine, const char *format, ...)
|
||||
__attribute__((__noreturn__)) __attribute__((format(printf, 4, 5)));
|
||||
const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *format, ...)
|
||||
__attribute__((format(printf, 5, 6))) __attribute__((__noreturn__));
|
||||
void errorInternalThrowSys(
|
||||
int errNo, const ErrorType *errorType, const char *fileName, int fileLine, const char *message);
|
||||
int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *message)
|
||||
__attribute__((__noreturn__));
|
||||
void errorInternalThrowSysFmt(
|
||||
int errNo, const ErrorType *errorType, const char *fileName, int fileLine, const char *format, ...)
|
||||
__attribute__((format(printf, 5, 6)));
|
||||
int errNo, const ErrorType *errorType, const char *fileName, const char *functionName, int fileLine, const char *format, ...)
|
||||
__attribute__((format(printf, 6, 7))) __attribute__((__noreturn__));
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_ERROR_TYPE_TYPE \
|
||||
ErrorType *
|
||||
#define FUNCTION_DEBUG_ERROR_TYPE_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "ErrorType", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -5,6 +5,7 @@ Exit Routines
|
||||
#include <string.h>
|
||||
|
||||
#include "command/command.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
#include "common/exit.h"
|
||||
#include "common/lock.h"
|
||||
@ -18,6 +19,10 @@ Return signal names
|
||||
static const char *
|
||||
exitSignalName(int signalType)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INT, signalType);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
const char *name = NULL;
|
||||
|
||||
switch (signalType)
|
||||
@ -44,7 +49,7 @@ exitSignalName(int signalType)
|
||||
THROW(AssertError, "no name for signal none");
|
||||
}
|
||||
|
||||
return name;
|
||||
FUNCTION_TEST_RESULT(STRINGZ, name);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -53,7 +58,13 @@ Catch signals
|
||||
static void
|
||||
exitOnSignal(int signalType)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(INT, signalType);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
exit(exitSafe(errorTypeCode(&TermError), false, (SignalType)signalType));
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -62,9 +73,13 @@ Setup signal handlers
|
||||
void
|
||||
exitInit()
|
||||
{
|
||||
FUNCTION_DEBUG_VOID(logLevelTrace);
|
||||
|
||||
signal(SIGHUP, exitOnSignal);
|
||||
signal(SIGINT, exitOnSignal);
|
||||
signal(SIGTERM, exitOnSignal);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -73,12 +88,37 @@ Do cleanup and return result code
|
||||
int
|
||||
exitSafe(int result, bool error, SignalType signalType)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(INT, result);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, error);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, signalType);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Report error if one was thrown
|
||||
if (error)
|
||||
{
|
||||
// Don't log the error if it has already been logged by Perl
|
||||
if (strcmp(errorMessage(), PERL_EMBED_ERROR) != 0)
|
||||
LOG_ANY(errorCode() == errorTypeCode(&AssertError) ? logLevelAssert : logLevelError, errorCode(), errorMessage());
|
||||
{
|
||||
LogLevel logLevel = errorCode() == errorTypeCode(&AssertError) ? logLevelAssert : logLevelError;
|
||||
|
||||
// Assert errors always output a stack trace
|
||||
if (logLevel == logLevelAssert)
|
||||
LOG(logLevel, errorCode(), "%s\nSTACK TRACE:\n%s", errorMessage(), errorStackTrace());
|
||||
else
|
||||
{
|
||||
// Log just the error to non-debug levels
|
||||
LOG_INTERNAL(logLevel, LOG_LEVEL_MIN, logLevelDetail, errorCode(), errorMessage());
|
||||
|
||||
// Log the stack trace debug levels
|
||||
if (logWill(logLevelDebug))
|
||||
{
|
||||
LOG_INTERNAL(
|
||||
logLevel, logLevelDebug, LOG_LEVEL_MAX, errorCode(), "%s\nSTACK TRACE:\n%s", errorMessage(),
|
||||
errorStackTrace());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = errorCode();
|
||||
}
|
||||
@ -126,5 +166,5 @@ exitSafe(int result, bool error, SignalType signalType)
|
||||
}
|
||||
|
||||
// Return result - caller should immediate pass this result to exit()
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(INT, result);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ Fork Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -12,6 +13,8 @@ startup because the parent process may continue to run and perform work for some
|
||||
void
|
||||
forkDetach()
|
||||
{
|
||||
FUNCTION_DEBUG_VOID(logLevelTrace);
|
||||
|
||||
if (chdir("/") == -1) // {uncoverable - should never fail}
|
||||
THROW_SYS_ERROR(PathMissingError, "unable to change directory to '/'"); // {uncoverable+}
|
||||
|
||||
@ -26,4 +29,6 @@ forkDetach()
|
||||
|
||||
if (close(STDERR_FILENO) == -1) // {uncoverable - should never fail}
|
||||
THROW_SYS_ERROR(FileCloseError, "unable to close stderr"); // {uncoverable+}
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ Ini Handler
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/ini.h"
|
||||
#include "common/type/keyValue.h"
|
||||
@ -49,6 +50,16 @@ Internal function to get an ini value
|
||||
static const Variant *
|
||||
iniGetInternal(const Ini *this, const String *section, const String *key)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INI, this);
|
||||
FUNCTION_TEST_PARAM(STRING, section);
|
||||
FUNCTION_TEST_PARAM(STRING, key);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(section != NULL);
|
||||
FUNCTION_TEST_ASSERT(key != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
const Variant *result = NULL;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -62,7 +73,7 @@ iniGetInternal(const Ini *this, const String *section, const String *key)
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(CONST_VARIANT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -71,6 +82,16 @@ Get an ini value -- error if it does not exist
|
||||
const Variant *
|
||||
iniGet(const Ini *this, const String *section, const String *key)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INI, this);
|
||||
FUNCTION_TEST_PARAM(STRING, section);
|
||||
FUNCTION_TEST_PARAM(STRING, key);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(section != NULL);
|
||||
FUNCTION_TEST_ASSERT(key != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Get the value
|
||||
const Variant *result = iniGetInternal(this, section, key);
|
||||
|
||||
@ -79,6 +100,8 @@ iniGet(const Ini *this, const String *section, const String *key)
|
||||
THROW_FMT(FormatError, "section '%s', key '%s' does not exist", strPtr(section), strPtr(key));
|
||||
|
||||
return result;
|
||||
|
||||
FUNCTION_TEST_RESULT(CONST_VARIANT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -87,6 +110,17 @@ Get an ini value -- if it does not exist then return specified default
|
||||
const Variant *
|
||||
iniGetDefault(const Ini *this, const String *section, const String *key, Variant *defaultValue)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INI, this);
|
||||
FUNCTION_TEST_PARAM(STRING, section);
|
||||
FUNCTION_TEST_PARAM(STRING, key);
|
||||
FUNCTION_TEST_PARAM(VARIANT, defaultValue);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(section != NULL);
|
||||
FUNCTION_TEST_ASSERT(key != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Get the value
|
||||
const Variant *result = iniGetInternal(this, section, key);
|
||||
|
||||
@ -94,7 +128,7 @@ iniGetDefault(const Ini *this, const String *section, const String *key, Variant
|
||||
if (result == NULL)
|
||||
result = defaultValue;
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(CONST_VARIANT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -103,6 +137,14 @@ Get a list of keys for a section
|
||||
StringList *
|
||||
iniSectionKeyList(const Ini *this, const String *section)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INI, this);
|
||||
FUNCTION_TEST_PARAM(STRING, section);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(section != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
StringList *result = NULL;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -121,7 +163,7 @@ iniSectionKeyList(const Ini *this, const String *section)
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -130,6 +172,13 @@ Parse ini from a string
|
||||
void
|
||||
iniParse(Ini *this, const String *content)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INI, this);
|
||||
FUNCTION_TEST_PARAM(STRING, content);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
{
|
||||
kvFree(this->store);
|
||||
@ -195,6 +244,8 @@ iniParse(Ini *this, const String *content)
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_END()
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -203,6 +254,14 @@ Load ini from a file
|
||||
void
|
||||
iniLoad(Ini *this, const String *fileName)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INI, this);
|
||||
FUNCTION_TEST_PARAM(STRING, fileName);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(fileName != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
{
|
||||
// Set the filename
|
||||
@ -215,6 +274,8 @@ iniLoad(Ini *this, const String *fileName)
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
}
|
||||
MEM_CONTEXT_END()
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -223,6 +284,18 @@ Set an ini value
|
||||
void
|
||||
iniSet(Ini *this, const String *section, const String *key, const Variant *value)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INI, this);
|
||||
FUNCTION_TEST_PARAM(STRING, section);
|
||||
FUNCTION_TEST_PARAM(STRING, key);
|
||||
FUNCTION_TEST_PARAM(VARIANT, value);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(section != NULL);
|
||||
FUNCTION_TEST_ASSERT(key != NULL);
|
||||
FUNCTION_TEST_ASSERT(value != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
Variant *sectionKey = varNewStr(section);
|
||||
@ -234,6 +307,8 @@ iniSet(Ini *this, const String *section, const String *key, const Variant *value
|
||||
kvAdd(sectionKv, varNewStr(key), value);
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -242,5 +317,12 @@ Free the ini
|
||||
void
|
||||
iniFree(Ini *this)
|
||||
{
|
||||
memContextFree(this->memContext);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INI, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this != NULL)
|
||||
memContextFree(this->memContext);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -24,4 +24,12 @@ void iniSet(Ini *this, const String *section, const String *key, const Variant *
|
||||
|
||||
void iniFree(Ini *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_INI_TYPE \
|
||||
Ini *
|
||||
#define FUNCTION_DEBUG_INI_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "Ini", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -3,6 +3,7 @@ Handle IO
|
||||
***********************************************************************************************************************************/
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
#include "common/io/handle.h"
|
||||
|
||||
@ -12,6 +13,15 @@ Write a string to the specified handle
|
||||
void
|
||||
ioHandleWriteOneStr(int handle, const String *string)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(INT, handle);
|
||||
FUNCTION_DEBUG_PARAM(STRING, string);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(string != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
if (write(handle, strPtr(string), strSize(string)) != (int)strSize(string))
|
||||
THROW_SYS_ERROR_FMT(FileWriteError, "unable to write to %zu byte(s) to handle", strSize(string));
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ Lock Handler
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/io/handle.h"
|
||||
#include "common/lock.h"
|
||||
#include "common/memContext.h"
|
||||
@ -38,6 +39,12 @@ Acquire a lock using a file on the local filesystem
|
||||
static int
|
||||
lockAcquireFile(const String *lockFile, double lockTimeout, bool failOnNoLock)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, lockFile);
|
||||
FUNCTION_DEBUG_PARAM(DOUBLE, lockTimeout);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, failOnNoLock);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
int result = -1;
|
||||
|
||||
// Timeout can't be negative
|
||||
@ -112,7 +119,7 @@ lockAcquireFile(const String *lockFile, double lockTimeout, bool failOnNoLock)
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(INT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -121,6 +128,11 @@ Release the current lock
|
||||
static void
|
||||
lockReleaseFile(int lockHandle, const String *lockFile)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(INT, lockHandle);
|
||||
FUNCTION_DEBUG_PARAM(STRING, lockFile);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Can't release lock if there isn't one
|
||||
ASSERT_DEBUG(lockHandle != -1);
|
||||
|
||||
@ -128,6 +140,8 @@ lockReleaseFile(int lockHandle, const String *lockFile)
|
||||
// right before the delete which means the file locked by the other process will get deleted.
|
||||
storageRemoveNP(storageLocalWrite(), lockFile);
|
||||
close(lockHandle);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -139,6 +153,14 @@ backup), but the stanza commands all need to lock both.
|
||||
bool
|
||||
lockAcquire(const String *lockPath, const String *stanza, LockType lockType, double lockTimeout, bool failOnNoLock)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STRING, lockPath);
|
||||
FUNCTION_DEBUG_PARAM(STRING, stanza);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, lockType);
|
||||
FUNCTION_DEBUG_PARAM(DOUBLE, lockTimeout);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, failOnNoLock);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
// Don't allow failures when locking more than one file. This makes cleanup difficult and there are no known use cases.
|
||||
@ -186,7 +208,7 @@ lockAcquire(const String *lockPath, const String *stanza, LockType lockType, dou
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -196,6 +218,10 @@ and the master process won't try to free it.
|
||||
bool
|
||||
lockClear(bool failOnNoLock)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, failOnNoLock);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (lockTypeHeld == lockTypeNone)
|
||||
@ -216,7 +242,7 @@ lockClear(bool failOnNoLock)
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -225,6 +251,10 @@ Release a lock type
|
||||
bool
|
||||
lockRelease(bool failOnNoLock)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, failOnNoLock);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (lockTypeHeld == lockTypeNone)
|
||||
@ -248,5 +278,5 @@ lockRelease(bool failOnNoLock)
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(BOOL, result);
|
||||
}
|
||||
|
268
src/common/log.c
268
src/common/log.c
@ -36,25 +36,22 @@ static bool logFileBanner = false;
|
||||
DEBUG_UNIT_EXTERN bool logTimestamp = false;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Debug Asserts
|
||||
Test Asserts
|
||||
***********************************************************************************************************************************/
|
||||
#define ASSERT_DEBUG_MESSAGE_LOG_LEVEL_VALID(logLevel) \
|
||||
ASSERT_DEBUG(logLevel > logLevelOff)
|
||||
#define FUNCTION_TEST_ASSERT_LOG_LEVEL(logLevel) \
|
||||
FUNCTION_TEST_ASSERT(logLevel >= LOG_LEVEL_MIN && logLevel <= LOG_LEVEL_MAX)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Log buffer
|
||||
Log buffer -- used to format log header and message
|
||||
***********************************************************************************************************************************/
|
||||
#define LOG_BUFFER_SIZE 32768
|
||||
|
||||
char logBuffer[LOG_BUFFER_SIZE];
|
||||
char logFormat[LOG_BUFFER_SIZE];
|
||||
static char logBuffer[LOG_BUFFER_SIZE];
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert log level to string and vice versa
|
||||
***********************************************************************************************************************************/
|
||||
#define LOG_LEVEL_TOTAL 9
|
||||
#define LOG_LEVEL_TOTAL (LOG_LEVEL_MAX + 1)
|
||||
|
||||
const char *logLevelList[LOG_LEVEL_TOTAL] =
|
||||
static const char *logLevelList[LOG_LEVEL_TOTAL] =
|
||||
{
|
||||
"OFF",
|
||||
"ASSERT",
|
||||
@ -70,6 +67,12 @@ const char *logLevelList[LOG_LEVEL_TOTAL] =
|
||||
LogLevel
|
||||
logLevelEnum(const char *logLevel)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRINGZ, logLevel);
|
||||
|
||||
FUNCTION_TEST_ASSERT(logLevel != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
LogLevel result = logLevelOff;
|
||||
|
||||
// Search for the log level
|
||||
@ -81,16 +84,19 @@ logLevelEnum(const char *logLevel)
|
||||
if (result == LOG_LEVEL_TOTAL)
|
||||
THROW_FMT(AssertError, "log level '%s' not found", logLevel);
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(ENUM, result);
|
||||
}
|
||||
|
||||
const char *
|
||||
logLevelStr(LogLevel logLevel)
|
||||
{
|
||||
if (logLevel >= LOG_LEVEL_TOTAL)
|
||||
THROW_FMT(AssertError, "invalid log level '%u'", logLevel);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, logLevel);
|
||||
|
||||
return logLevelList[logLevel];
|
||||
FUNCTION_TEST_ASSERT(logLevel <= LOG_LEVEL_MAX);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRINGZ, logLevelList[logLevel]);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -99,10 +105,23 @@ Initialize the log system
|
||||
void
|
||||
logInit(LogLevel logLevelStdOutParam, LogLevel logLevelStdErrParam, LogLevel logLevelFileParam, bool logTimestampParam)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, logLevelStdOutParam);
|
||||
FUNCTION_TEST_PARAM(ENUM, logLevelStdErrParam);
|
||||
FUNCTION_TEST_PARAM(ENUM, logLevelFileParam);
|
||||
FUNCTION_TEST_PARAM(BOOL, logTimestampParam);
|
||||
|
||||
FUNCTION_TEST_ASSERT(logLevelStdOutParam <= LOG_LEVEL_MAX);
|
||||
FUNCTION_TEST_ASSERT(logLevelStdErrParam <= LOG_LEVEL_MAX);
|
||||
FUNCTION_TEST_ASSERT(logLevelFileParam <= LOG_LEVEL_MAX);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
logLevelStdOut = logLevelStdOutParam;
|
||||
logLevelStdErr = logLevelStdErrParam;
|
||||
logLevelFile = logLevelFileParam;
|
||||
logTimestamp = logTimestampParam;
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -111,6 +130,12 @@ Set the log file
|
||||
void
|
||||
logFileSet(const char *logFile)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRINGZ, logFile);
|
||||
|
||||
FUNCTION_TEST_ASSERT(logFile != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Close the file handle if it is already open
|
||||
if (logHandleFile != -1)
|
||||
{
|
||||
@ -133,6 +158,8 @@ logFileSet(const char *logFile)
|
||||
// Output the banner on first log message
|
||||
logFileBanner = false;
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -143,29 +170,69 @@ This is useful for log messages that are expensive to generate and should be ski
|
||||
static bool
|
||||
logWillFile(LogLevel logLevel)
|
||||
{
|
||||
ASSERT_DEBUG_MESSAGE_LOG_LEVEL_VALID(logLevel)
|
||||
return logLevel <= logLevelFile && logHandleFile != -1;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, logLevel);
|
||||
|
||||
FUNCTION_TEST_ASSERT_LOG_LEVEL(logLevel);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(ENUM, logLevel <= logLevelFile && logHandleFile != -1);
|
||||
}
|
||||
|
||||
static bool
|
||||
logWillStdErr(LogLevel logLevel)
|
||||
{
|
||||
ASSERT_DEBUG_MESSAGE_LOG_LEVEL_VALID(logLevel)
|
||||
return logLevel <= logLevelStdErr;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, logLevel);
|
||||
|
||||
FUNCTION_TEST_ASSERT_LOG_LEVEL(logLevel);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(ENUM, logLevel <= logLevelStdErr);
|
||||
}
|
||||
|
||||
static bool
|
||||
logWillStdOut(LogLevel logLevel)
|
||||
{
|
||||
ASSERT_DEBUG_MESSAGE_LOG_LEVEL_VALID(logLevel)
|
||||
return logLevel <= logLevelStdOut;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, logLevel);
|
||||
|
||||
FUNCTION_TEST_ASSERT_LOG_LEVEL(logLevel);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(ENUM, logLevel <= logLevelStdOut);
|
||||
}
|
||||
|
||||
bool
|
||||
logWill(LogLevel logLevel)
|
||||
{
|
||||
ASSERT_DEBUG_MESSAGE_LOG_LEVEL_VALID(logLevel)
|
||||
return logWillStdOut(logLevel) || logWillStdErr(logLevel) || logWillFile(logLevel);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, logLevel);
|
||||
|
||||
FUNCTION_TEST_ASSERT_LOG_LEVEL(logLevel);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, logWillStdOut(logLevel) || logWillStdErr(logLevel) || logWillFile(logLevel));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Determine if the log level is in the specified range
|
||||
***********************************************************************************************************************************/
|
||||
static bool
|
||||
logRange(LogLevel logLevel, LogLevel logRangeMin, LogLevel logRangeMax)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, logLevel);
|
||||
FUNCTION_TEST_PARAM(ENUM, logRangeMin);
|
||||
FUNCTION_TEST_PARAM(ENUM, logRangeMax);
|
||||
|
||||
FUNCTION_TEST_ASSERT_LOG_LEVEL(logLevel);
|
||||
FUNCTION_TEST_ASSERT_LOG_LEVEL(logRangeMin);
|
||||
FUNCTION_TEST_ASSERT_LOG_LEVEL(logRangeMax);
|
||||
FUNCTION_TEST_ASSERT(logRangeMin <= logRangeMax);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, logLevel >= logRangeMin && logLevel <= logRangeMax);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -174,17 +241,93 @@ Internal write function that handles errors
|
||||
static void
|
||||
logWrite(int handle, const char *message, size_t messageSize, const char *errorDetail)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INT, handle);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, message);
|
||||
FUNCTION_TEST_PARAM(SIZE, messageSize);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, errorDetail);
|
||||
|
||||
FUNCTION_TEST_ASSERT(handle != -1);
|
||||
FUNCTION_TEST_ASSERT(message != NULL);
|
||||
FUNCTION_TEST_ASSERT(messageSize != 0);
|
||||
FUNCTION_TEST_ASSERT(errorDetail != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if ((size_t)write(handle, message, messageSize) != messageSize)
|
||||
THROW_SYS_ERROR_FMT(FileWriteError, "unable to write %s", errorDetail);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Write out log message and indent subsequent lines
|
||||
***********************************************************************************************************************************/
|
||||
static void
|
||||
logWriteIndent(int handle, const char *message, size_t indentSize, const char *errorDetail)
|
||||
{
|
||||
// Indent buffer -- used to write out indent space without having to loop
|
||||
static const char indentBuffer[] = " ";
|
||||
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INT, handle);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, message);
|
||||
FUNCTION_TEST_PARAM(SIZE, indentSize);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, errorDetail);
|
||||
|
||||
FUNCTION_TEST_ASSERT(handle != -1);
|
||||
FUNCTION_TEST_ASSERT(message != NULL);
|
||||
FUNCTION_TEST_ASSERT(indentSize > 0 && indentSize < sizeof(indentBuffer));
|
||||
FUNCTION_TEST_ASSERT(errorDetail != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Indent all lines after the first
|
||||
const char *linefeedPtr = strchr(message, '\n');
|
||||
bool first = true;
|
||||
|
||||
while (linefeedPtr != NULL)
|
||||
{
|
||||
if (!first)
|
||||
logWrite(handle, indentBuffer, indentSize, errorDetail);
|
||||
else
|
||||
first = false;
|
||||
|
||||
logWrite(handle, message, (size_t)(linefeedPtr - message + 1), errorDetail);
|
||||
message += (size_t)(linefeedPtr - message + 1);
|
||||
|
||||
linefeedPtr = strchr(message, '\n');
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
General log function
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
logInternal(LogLevel logLevel, const char *fileName, const char *functionName, int code, const char *format, ...)
|
||||
logInternal(
|
||||
LogLevel logLevel, LogLevel logRangeMin, LogLevel logRangeMax, const char *fileName, const char *functionName, int code,
|
||||
const char *format, ...)
|
||||
{
|
||||
ASSERT_DEBUG_MESSAGE_LOG_LEVEL_VALID(logLevel)
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, logLevel);
|
||||
FUNCTION_TEST_PARAM(ENUM, logRangeMin);
|
||||
FUNCTION_TEST_PARAM(ENUM, logRangeMax);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, fileName);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, functionName);
|
||||
FUNCTION_TEST_PARAM(INT, code);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, format);
|
||||
|
||||
FUNCTION_TEST_ASSERT_LOG_LEVEL(logLevel);
|
||||
FUNCTION_TEST_ASSERT_LOG_LEVEL(logRangeMin);
|
||||
FUNCTION_TEST_ASSERT_LOG_LEVEL(logRangeMax);
|
||||
FUNCTION_TEST_ASSERT(logRangeMin <= logRangeMax);
|
||||
FUNCTION_TEST_ASSERT(fileName != NULL);
|
||||
FUNCTION_TEST_ASSERT(functionName != NULL);
|
||||
FUNCTION_TEST_ASSERT(
|
||||
(code == 0 && logLevel > logLevelError) || (logLevel == logLevelError && code != errorTypeCode(&AssertError)) ||
|
||||
(logLevel == logLevelAssert && code == errorTypeCode(&AssertError)));
|
||||
FUNCTION_TEST_ASSERT(format != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
size_t bufferPos = 0; // Current position in the buffer
|
||||
|
||||
@ -194,65 +337,43 @@ logInternal(LogLevel logLevel, const char *fileName, const char *functionName, i
|
||||
TimeMSec logTimeMSec = timeMSec();
|
||||
time_t logTimeSec = (time_t)(logTimeMSec / MSEC_PER_SEC);
|
||||
|
||||
bufferPos += strftime(logBuffer + bufferPos, LOG_BUFFER_SIZE - bufferPos, "%Y-%m-%d %H:%M:%S", localtime(&logTimeSec));
|
||||
bufferPos += strftime(logBuffer + bufferPos, sizeof(logBuffer) - bufferPos, "%Y-%m-%d %H:%M:%S", localtime(&logTimeSec));
|
||||
bufferPos += (size_t)snprintf(
|
||||
logBuffer + bufferPos, LOG_BUFFER_SIZE - bufferPos, ".%03d ", (int)(logTimeMSec % 1000));
|
||||
logBuffer + bufferPos, sizeof(logBuffer) - bufferPos, ".%03d ", (int)(logTimeMSec % 1000));
|
||||
}
|
||||
|
||||
// Add process and aligned log level
|
||||
bufferPos += (size_t)snprintf(
|
||||
logBuffer + bufferPos, LOG_BUFFER_SIZE - bufferPos, "P00 %*s: ", 6, logLevelStr(logLevel));
|
||||
bufferPos += (size_t)snprintf(logBuffer + bufferPos, sizeof(logBuffer) - bufferPos, "P00 %*s: ", 6, logLevelStr(logLevel));
|
||||
|
||||
// Position after the timestamp and process id for output to stderr
|
||||
size_t messageStdErrPos = bufferPos - strlen(logLevelStr(logLevel)) - 2;
|
||||
// When writing to stderr the timestamp, process, and log level alignment will be skipped
|
||||
char *logBufferStdErr = logBuffer + bufferPos - strlen(logLevelStr(logLevel)) - 2;
|
||||
|
||||
// Check that error code matches log level
|
||||
ASSERT_DEBUG(
|
||||
code == 0 || (logLevel == logLevelError && code != errorTypeCode(&AssertError)) ||
|
||||
(logLevel == logLevelAssert && code == errorTypeCode(&AssertError)));
|
||||
// Set the indent size -- this will need to be adjusted for stderr
|
||||
size_t indentSize = bufferPos;
|
||||
|
||||
// Add code
|
||||
// Add error code
|
||||
if (code != 0)
|
||||
bufferPos += (size_t)snprintf(logBuffer + bufferPos, LOG_BUFFER_SIZE - bufferPos, "[%03d]: ", code);
|
||||
bufferPos += (size_t)snprintf(logBuffer + bufferPos, sizeof(logBuffer) - bufferPos, "[%03d]: ", code);
|
||||
|
||||
// Add debug info
|
||||
if (logLevel >= logLevelDebug)
|
||||
{
|
||||
bufferPos += (size_t)snprintf(
|
||||
logBuffer + bufferPos, LOG_BUFFER_SIZE - bufferPos, "%s:%s(): ", fileName, functionName);
|
||||
}
|
||||
|
||||
// Format message
|
||||
va_list argumentList;
|
||||
va_start(argumentList, format);
|
||||
|
||||
if (logLevel <= logLevelStdErr || strchr(format, '\n') == NULL)
|
||||
bufferPos += (size_t)vsnprintf(logBuffer + bufferPos, LOG_BUFFER_SIZE - bufferPos, format, argumentList);
|
||||
else
|
||||
{
|
||||
vsnprintf(logFormat, LOG_BUFFER_SIZE, format, argumentList);
|
||||
|
||||
// Indent all lines after the first
|
||||
const char *formatPtr = logFormat;
|
||||
const char *linefeedPtr = strchr(logFormat, '\n');
|
||||
int indentSize = 12;
|
||||
|
||||
while (linefeedPtr != NULL)
|
||||
// Adding padding for debug and trace levels
|
||||
for (unsigned int paddingIdx = 0; paddingIdx < ((logLevel - logLevelDebug + 1) * 4); paddingIdx++)
|
||||
{
|
||||
strncpy(logBuffer + bufferPos, formatPtr, (size_t)(linefeedPtr - formatPtr + 1));
|
||||
bufferPos += (size_t)(linefeedPtr - formatPtr + 1);
|
||||
|
||||
formatPtr = linefeedPtr + 1;
|
||||
linefeedPtr = strchr(formatPtr, '\n');
|
||||
|
||||
for (int indentIdx = 0; indentIdx < indentSize; indentIdx++)
|
||||
logBuffer[bufferPos++] = ' ';
|
||||
logBuffer[bufferPos++] = ' ';
|
||||
indentSize++;
|
||||
}
|
||||
|
||||
strcpy(logBuffer + bufferPos, formatPtr);
|
||||
bufferPos += strlen(formatPtr);
|
||||
bufferPos += (size_t)snprintf(
|
||||
logBuffer + bufferPos, LOG_BUFFER_SIZE - bufferPos, "%.*s::%s: ", (int)strlen(fileName) - 2, fileName,
|
||||
functionName);
|
||||
}
|
||||
|
||||
// Format message -- this will need to be indented later
|
||||
va_list argumentList;
|
||||
va_start(argumentList, format);
|
||||
bufferPos += (size_t)vsnprintf(logBuffer + bufferPos, LOG_BUFFER_SIZE - bufferPos, format, argumentList);
|
||||
va_end(argumentList);
|
||||
|
||||
// Add linefeed
|
||||
@ -261,12 +382,15 @@ logInternal(LogLevel logLevel, const char *fileName, const char *functionName, i
|
||||
|
||||
// Determine where to log the message based on log-level-stderr
|
||||
if (logWillStdErr(logLevel))
|
||||
logWrite(logHandleStdErr, logBuffer + messageStdErrPos, bufferPos - messageStdErrPos, "log to stderr");
|
||||
else if (logWillStdOut(logLevel))
|
||||
logWrite(logHandleStdOut, logBuffer, bufferPos, "log to stdout");
|
||||
{
|
||||
if (logRange(logLevelStdErr, logRangeMin, logRangeMax))
|
||||
logWriteIndent(logHandleStdErr, logBufferStdErr, indentSize - (size_t)(logBufferStdErr - logBuffer), "log to stderr");
|
||||
}
|
||||
else if (logWillStdOut(logLevel) && logRange(logLevelStdOut, logRangeMin, logRangeMax))
|
||||
logWriteIndent(logHandleStdOut, logBuffer, indentSize, "log to stdout");
|
||||
|
||||
// Log to file
|
||||
if (logWillFile(logLevel))
|
||||
if (logWillFile(logLevel) && logRange(logLevelFile, logRangeMin, logRangeMax))
|
||||
{
|
||||
// If the banner has not been written
|
||||
if (!logFileBanner)
|
||||
@ -284,6 +408,8 @@ logInternal(LogLevel logLevel, const char *fileName, const char *functionName, i
|
||||
logFileBanner = true;
|
||||
}
|
||||
|
||||
logWrite(logHandleFile, logBuffer, bufferPos, "log to file");
|
||||
logWriteIndent(logHandleFile, logBuffer, indentSize, "log to file");
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -6,6 +6,13 @@ Log Handler
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Max size allowed for a single log message including header
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef LOG_BUFFER_SIZE
|
||||
#define LOG_BUFFER_SIZE ((size_t)(32 * 1024))
|
||||
#endif
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Log types
|
||||
***********************************************************************************************************************************/
|
||||
@ -22,6 +29,9 @@ typedef enum
|
||||
logLevelTrace,
|
||||
} LogLevel;
|
||||
|
||||
#define LOG_LEVEL_MIN logLevelAssert
|
||||
#define LOG_LEVEL_MAX logLevelTrace
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Expose internal data for unit testing/debugging
|
||||
***********************************************************************************************************************************/
|
||||
@ -53,27 +63,37 @@ Macros
|
||||
|
||||
Only call logInternal() if the message will be logged to one of the available outputs.
|
||||
***********************************************************************************************************************************/
|
||||
#define LOG_ANY(logLevel, code, ...) \
|
||||
#define LOG_INTERNAL(logLevel, logRangeMin, logRangeMax, code, ...) \
|
||||
logInternal(logLevel, logRangeMin, logRangeMax, __FILE__, __func__, code, __VA_ARGS__)
|
||||
|
||||
#define LOG(logLevel, code, ...) \
|
||||
LOG_INTERNAL(logLevel, LOG_LEVEL_MIN, LOG_LEVEL_MAX, code, __VA_ARGS__)
|
||||
|
||||
#define LOG_WILL(logLevel, code, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (logWill(logLevel)) \
|
||||
logInternal(logLevel, __FILE__, __func__, code, __VA_ARGS__); \
|
||||
}
|
||||
LOG(logLevel, code, __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define LOG_ASSERT(...) \
|
||||
LOG_ANY(logLevelAssert, errorTypeCode(&AssertError), __VA_ARGS__)
|
||||
LOG_WILL(logLevelAssert, errorTypeCode(&AssertError), __VA_ARGS__)
|
||||
#define LOG_ERROR(code, ...) \
|
||||
LOG_ANY(logLevelError, code, __VA_ARGS__)
|
||||
#define LOG_DEBUG(...) \
|
||||
LOG_ANY(logLevelDebug, 0, __VA_ARGS__)
|
||||
#define LOG_INFO(...) \
|
||||
LOG_ANY(logLevelInfo, 0, __VA_ARGS__)
|
||||
LOG_WILL(logLevelError, code, __VA_ARGS__)
|
||||
#define LOG_WARN(...) \
|
||||
LOG_ANY(logLevelWarn, 0, __VA_ARGS__)
|
||||
LOG_WILL(logLevelWarn, 0, __VA_ARGS__)
|
||||
#define LOG_INFO(...) \
|
||||
LOG_WILL(logLevelInfo, 0, __VA_ARGS__)
|
||||
#define LOG_DETAIL(...) \
|
||||
LOG_WILL(logLevelDetail, 0, __VA_ARGS__)
|
||||
#define LOG_TRACE(...) \
|
||||
LOG_WILL(logLevelTrace, 0, __VA_ARGS__)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Internal Functions
|
||||
***********************************************************************************************************************************/
|
||||
void logInternal(
|
||||
LogLevel logLevel, const char *fileName, const char *functionName, int code, const char *format, ...);
|
||||
LogLevel logLevel, LogLevel logRangeMin, LogLevel logRangeMax, const char *fileName, const char *functionName,
|
||||
int code, const char *format, ...);
|
||||
|
||||
#endif
|
||||
|
@ -5,6 +5,7 @@ Memory Context Manager
|
||||
#include <string.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
#include "common/memContext.h"
|
||||
|
||||
@ -64,6 +65,11 @@ Wrapper around malloc()
|
||||
static void *
|
||||
memAllocInternal(size_t size, bool zero)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
FUNCTION_TEST_PARAM(BOOL, zero);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Allocate memory
|
||||
void *buffer = malloc(size);
|
||||
|
||||
@ -76,7 +82,7 @@ memAllocInternal(size_t size, bool zero)
|
||||
memset(buffer, 0, size);
|
||||
|
||||
// Return the buffer
|
||||
return buffer;
|
||||
FUNCTION_TEST_RESULT(VOIDP, buffer);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -85,6 +91,15 @@ Wrapper around realloc()
|
||||
static void *
|
||||
memReAllocInternal(void *bufferOld, size_t sizeOld, size_t sizeNew, bool zeroNew)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VOIDP, bufferOld);
|
||||
FUNCTION_TEST_PARAM(SIZE, sizeOld);
|
||||
FUNCTION_TEST_PARAM(SIZE, sizeNew);
|
||||
FUNCTION_TEST_PARAM(BOOL, zeroNew);
|
||||
|
||||
FUNCTION_TEST_ASSERT(bufferOld != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Allocate memory
|
||||
void *bufferNew = realloc(bufferOld, sizeNew);
|
||||
|
||||
@ -97,7 +112,7 @@ memReAllocInternal(void *bufferOld, size_t sizeOld, size_t sizeNew, bool zeroNew
|
||||
memset((unsigned char *)bufferNew + sizeOld, 0, sizeNew - sizeOld);
|
||||
|
||||
// Return the buffer
|
||||
return bufferNew;
|
||||
FUNCTION_TEST_RESULT(VOIDP, bufferNew);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -106,12 +121,15 @@ Wrapper around free()
|
||||
static void
|
||||
memFreeInternal(void *buffer)
|
||||
{
|
||||
// Error if pointer is null
|
||||
if (buffer == NULL)
|
||||
THROW(MemoryError, "unable to free null pointer");
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VOIDP, buffer);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Free the buffer
|
||||
free(buffer);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -120,6 +138,13 @@ Find space for a new mem context
|
||||
static unsigned int
|
||||
memContextNewIndex(MemContext *memContext, bool allowFree)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, memContext);
|
||||
FUNCTION_TEST_PARAM(BOOL, allowFree);
|
||||
|
||||
FUNCTION_TEST_ASSERT(memContext != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Try to find space for the new context
|
||||
unsigned int contextIdx;
|
||||
|
||||
@ -160,7 +185,7 @@ memContextNewIndex(MemContext *memContext, bool allowFree)
|
||||
}
|
||||
}
|
||||
|
||||
return contextIdx;
|
||||
FUNCTION_TEST_RESULT(UINT, contextIdx);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -169,6 +194,12 @@ Create a new memory context
|
||||
MemContext *
|
||||
memContextNew(const char *name)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRINGZ, name);
|
||||
|
||||
FUNCTION_TEST_ASSERT(name != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Check context name length
|
||||
if (strlen(name) == 0 || strlen(name) > MEM_CONTEXT_NAME_SIZE)
|
||||
THROW_FMT(AssertError, "context name length must be > 0 and <= %d", MEM_CONTEXT_NAME_SIZE);
|
||||
@ -197,7 +228,7 @@ memContextNew(const char *name)
|
||||
this->contextParent = memContextCurrent();
|
||||
|
||||
// Return context
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(MEM_CONTEXT, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -206,6 +237,15 @@ Register a callback to be called just before the context is freed
|
||||
void
|
||||
memContextCallback(MemContext *this, void (*callbackFunction)(void *), void *callbackArgument)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, this);
|
||||
FUNCTION_TEST_PARAM(FUNCTIONP, callbackFunction);
|
||||
FUNCTION_TEST_PARAM(VOIDP, callbackArgument);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(callbackFunction != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Error if context is not active
|
||||
if (this->state != memContextStateActive)
|
||||
THROW(AssertError, "cannot assign callback to inactive context");
|
||||
@ -221,6 +261,8 @@ memContextCallback(MemContext *this, void (*callbackFunction)(void *), void *cal
|
||||
// Set callback function and argument
|
||||
this->callbackFunction = callbackFunction;
|
||||
this->callbackArgument = callbackArgument;
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -229,6 +271,11 @@ Allocate memory in the memory context and optionally zero it.
|
||||
static void *
|
||||
memContextAlloc(size_t size, bool zero)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
FUNCTION_TEST_PARAM(BOOL, zero);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Find space for the new allocation
|
||||
unsigned int allocIdx;
|
||||
|
||||
@ -270,7 +317,7 @@ memContextAlloc(size_t size, bool zero)
|
||||
memContextCurrent()->allocList[allocIdx].buffer = memAllocInternal(size, zero);
|
||||
|
||||
// Return buffer
|
||||
return memContextCurrent()->allocList[allocIdx].buffer;
|
||||
FUNCTION_TEST_RESULT(VOIDP, memContextCurrent()->allocList[allocIdx].buffer);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -279,9 +326,11 @@ Find a memory allocation
|
||||
static unsigned int
|
||||
memFind(const void *buffer)
|
||||
{
|
||||
// Error if buffer is null
|
||||
if (buffer == NULL)
|
||||
THROW(AssertError, "unable to find null allocation");
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VOIDP, buffer);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Find memory allocation
|
||||
unsigned int allocIdx;
|
||||
@ -294,7 +343,7 @@ memFind(const void *buffer)
|
||||
if (allocIdx == memContextCurrent()->allocListSize)
|
||||
THROW(AssertError, "unable to find allocation");
|
||||
|
||||
return allocIdx;
|
||||
FUNCTION_TEST_RESULT(UINT, allocIdx);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -303,7 +352,11 @@ Allocate zeroed memory in the memory context
|
||||
void *
|
||||
memNew(size_t size)
|
||||
{
|
||||
return memContextAlloc(size, true);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(VOIDP, memContextAlloc(size, true));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -312,6 +365,13 @@ Grow allocated memory without initializing the new portion
|
||||
void *
|
||||
memGrowRaw(const void *buffer, size_t size)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VOIDP, buffer);
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Find the allocation
|
||||
MemContextAlloc *alloc = &(memContextCurrent()->allocList[memFind(buffer)]);
|
||||
|
||||
@ -319,7 +379,7 @@ memGrowRaw(const void *buffer, size_t size)
|
||||
alloc->buffer = memReAllocInternal(alloc->buffer, alloc->size, size, false);
|
||||
alloc->size = (unsigned int)size;
|
||||
|
||||
return alloc->buffer;
|
||||
FUNCTION_TEST_RESULT(VOIDP, alloc->buffer);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -328,7 +388,11 @@ Allocate memory in the memory context without initializing it
|
||||
void *
|
||||
memNewRaw(size_t size)
|
||||
{
|
||||
return memContextAlloc(size, false);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(VOIDP, memContextAlloc(size, false));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -337,12 +401,20 @@ Free a memory allocation in the context
|
||||
void
|
||||
memFree(void *buffer)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VOIDP, buffer);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Find the allocation
|
||||
MemContextAlloc *alloc = &(memContextCurrent()->allocList[memFind(buffer)]);
|
||||
|
||||
// Free the buffer
|
||||
memFreeInternal(alloc->buffer);
|
||||
alloc->active = false;
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -353,6 +425,13 @@ This is generally used to move objects to a new context once they have been succ
|
||||
void
|
||||
memContextMove(MemContext *this, MemContext *parentNew)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, this);
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, parentNew);
|
||||
|
||||
FUNCTION_TEST_ASSERT(parentNew != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Only move if a valid mem context is provided
|
||||
if (this != NULL)
|
||||
{
|
||||
@ -382,6 +461,8 @@ memContextMove(MemContext *this, MemContext *parentNew)
|
||||
// Assign new parent
|
||||
this->contextParent = parentNew;
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -390,6 +471,12 @@ Switch to the specified context and return the old context
|
||||
MemContext *
|
||||
memContextSwitch(MemContext *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Error if context is not active
|
||||
if (this->state != memContextStateActive)
|
||||
THROW(AssertError, "cannot switch to inactive context");
|
||||
@ -397,7 +484,7 @@ memContextSwitch(MemContext *this)
|
||||
MemContext *memContextOld = memContextCurrent();
|
||||
contextCurrent = this;
|
||||
|
||||
return memContextOld;
|
||||
FUNCTION_TEST_RESULT(MEM_CONTEXT, memContextOld);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -406,7 +493,8 @@ Return the top context
|
||||
MemContext *
|
||||
memContextTop()
|
||||
{
|
||||
return &contextTop;
|
||||
FUNCTION_TEST_VOID();
|
||||
FUNCTION_TEST_RESULT(MEM_CONTEXT, &contextTop);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -415,7 +503,8 @@ Return the current context
|
||||
MemContext *
|
||||
memContextCurrent()
|
||||
{
|
||||
return contextCurrent;
|
||||
FUNCTION_TEST_VOID();
|
||||
FUNCTION_TEST_RESULT(MEM_CONTEXT, contextCurrent);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -424,11 +513,17 @@ Return the context name
|
||||
const char *
|
||||
memContextName(MemContext *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Error if context is not active
|
||||
if (this->state != memContextStateActive)
|
||||
THROW(AssertError, "cannot get name for inactive context");
|
||||
|
||||
return this->name;
|
||||
FUNCTION_TEST_RESULT(STRINGZ, this->name);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -437,62 +532,70 @@ memContextFree - free all memory used by the context and all child contexts
|
||||
void
|
||||
memContextFree(MemContext *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// If context is already freeing then return if memContextFree() is called again - this can happen in callbacks
|
||||
if (this->state == memContextStateFreeing)
|
||||
return;
|
||||
|
||||
// Current context cannot be freed unless it is top (top is never really freed, just the stuff under it)
|
||||
if (this == memContextCurrent() && this != memContextTop())
|
||||
THROW_FMT(AssertError, "cannot free current context '%s'", this->name);
|
||||
|
||||
// Error if context is not active
|
||||
if (this->state != memContextStateActive)
|
||||
THROW(AssertError, "cannot free inactive context");
|
||||
|
||||
// Free child contexts
|
||||
if (this->contextChildListSize > 0)
|
||||
for (unsigned int contextIdx = 0; contextIdx < this->contextChildListSize; contextIdx++)
|
||||
if (this->contextChildList[contextIdx] && this->contextChildList[contextIdx]->state == memContextStateActive)
|
||||
memContextFree(this->contextChildList[contextIdx]);
|
||||
|
||||
// Set state to freeing now that there are no child contexts. Child contexts might need to interact with their parent while
|
||||
// freeing so the parent needs to remain active until they are all gone.
|
||||
this->state = memContextStateFreeing;
|
||||
|
||||
// Execute callback if defined
|
||||
if (this->callbackFunction)
|
||||
this->callbackFunction(this->callbackArgument);
|
||||
|
||||
// Free child context allocations
|
||||
if (this->contextChildListSize > 0)
|
||||
if (this->state != memContextStateFreeing)
|
||||
{
|
||||
for (unsigned int contextIdx = 0; contextIdx < this->contextChildListSize; contextIdx++)
|
||||
if (this->contextChildList[contextIdx])
|
||||
memFreeInternal(this->contextChildList[contextIdx]);
|
||||
// Current context cannot be freed unless it is top (top is never really freed, just the stuff under it)
|
||||
if (this == memContextCurrent() && this != memContextTop())
|
||||
THROW_FMT(AssertError, "cannot free current context '%s'", this->name);
|
||||
|
||||
memFreeInternal(this->contextChildList);
|
||||
this->contextChildListSize = 0;
|
||||
}
|
||||
// Error if context is not active
|
||||
if (this->state != memContextStateActive)
|
||||
THROW(AssertError, "cannot free inactive context");
|
||||
|
||||
// Free memory allocations
|
||||
if (this->allocListSize > 0)
|
||||
{
|
||||
for (unsigned int allocIdx = 0; allocIdx < this->allocListSize; allocIdx++)
|
||||
// Free child contexts
|
||||
if (this->contextChildListSize > 0)
|
||||
for (unsigned int contextIdx = 0; contextIdx < this->contextChildListSize; contextIdx++)
|
||||
if (this->contextChildList[contextIdx] && this->contextChildList[contextIdx]->state == memContextStateActive)
|
||||
memContextFree(this->contextChildList[contextIdx]);
|
||||
|
||||
// Set state to freeing now that there are no child contexts. Child contexts might need to interact with their parent while
|
||||
// freeing so the parent needs to remain active until they are all gone.
|
||||
this->state = memContextStateFreeing;
|
||||
|
||||
// Execute callback if defined
|
||||
if (this->callbackFunction)
|
||||
this->callbackFunction(this->callbackArgument);
|
||||
|
||||
// Free child context allocations
|
||||
if (this->contextChildListSize > 0)
|
||||
{
|
||||
MemContextAlloc *alloc = &(this->allocList[allocIdx]);
|
||||
for (unsigned int contextIdx = 0; contextIdx < this->contextChildListSize; contextIdx++)
|
||||
if (this->contextChildList[contextIdx])
|
||||
memFreeInternal(this->contextChildList[contextIdx]);
|
||||
|
||||
if (alloc->active)
|
||||
memFreeInternal(alloc->buffer);
|
||||
memFreeInternal(this->contextChildList);
|
||||
this->contextChildListSize = 0;
|
||||
}
|
||||
|
||||
memFreeInternal(this->allocList);
|
||||
this->allocListSize = 0;
|
||||
// Free memory allocations
|
||||
if (this->allocListSize > 0)
|
||||
{
|
||||
for (unsigned int allocIdx = 0; allocIdx < this->allocListSize; allocIdx++)
|
||||
{
|
||||
MemContextAlloc *alloc = &(this->allocList[allocIdx]);
|
||||
|
||||
if (alloc->active)
|
||||
memFreeInternal(alloc->buffer);
|
||||
}
|
||||
|
||||
memFreeInternal(this->allocList);
|
||||
this->allocListSize = 0;
|
||||
}
|
||||
|
||||
// Make top context active again
|
||||
if (this == memContextTop())
|
||||
this->state = memContextStateActive;
|
||||
// Else reset the memory context so it can be reused
|
||||
else
|
||||
memset(this, 0, sizeof(MemContext));
|
||||
}
|
||||
|
||||
// Make top context active again
|
||||
if (this == memContextTop())
|
||||
this->state = memContextStateActive;
|
||||
// Else reset the memory context so it can be reused
|
||||
else
|
||||
memset(this, 0, sizeof(MemContext));
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -188,4 +188,12 @@ MEM_CONTEXT_TEMP_END();
|
||||
} \
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_MEM_CONTEXT_TYPE \
|
||||
MemContext *
|
||||
#define FUNCTION_DEBUG_MEM_CONTEXT_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "MemContext", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,7 @@ Regular Expression Handler
|
||||
#include <regex.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/regExp.h"
|
||||
|
||||
@ -22,9 +23,15 @@ Handle errors
|
||||
static void
|
||||
regExpError(int error)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INT, error);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
char buffer[4096];
|
||||
regerror(error, NULL, buffer, sizeof(buffer));
|
||||
THROW(FormatError, buffer);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -33,6 +40,12 @@ New regular expression handler
|
||||
RegExp *
|
||||
regExpNew(const String *expression)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, expression);
|
||||
|
||||
FUNCTION_TEST_ASSERT(expression != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
RegExp *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("RegExp")
|
||||
@ -54,7 +67,7 @@ regExpNew(const String *expression)
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(REGEXP, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -63,6 +76,14 @@ Match on a regular expression
|
||||
bool
|
||||
regExpMatch(RegExp *this, const String *string)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(REGEXP, this);
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(string != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Test for a match
|
||||
int result = regexec(&this->regExp, strPtr(string), 0, NULL, 0);
|
||||
|
||||
@ -70,7 +91,7 @@ regExpMatch(RegExp *this, const String *string)
|
||||
if (result != 0 && result != REG_NOMATCH) // {uncoverable - no error condition known}
|
||||
regExpError(result); // {+uncoverable}
|
||||
|
||||
return result == 0;
|
||||
FUNCTION_TEST_RESULT(BOOL, result == 0);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -79,11 +100,17 @@ Free regular expression
|
||||
void
|
||||
regExpFree(RegExp *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(REGEXP, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this != NULL)
|
||||
{
|
||||
regfree(&this->regExp);
|
||||
memContextFree(this->memContext);
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -92,6 +119,14 @@ Match a regular expression in one call for brevity
|
||||
bool
|
||||
regExpMatchOne(const String *expression, const String *string)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, expression);
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
|
||||
FUNCTION_TEST_ASSERT(expression != NULL);
|
||||
FUNCTION_TEST_ASSERT(string != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool result = false;
|
||||
RegExp *regExp = regExpNew(expression);
|
||||
|
||||
@ -105,5 +140,5 @@ regExpMatchOne(const String *expression, const String *string)
|
||||
}
|
||||
TRY_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
@ -20,4 +20,12 @@ void regExpFree(RegExp *this);
|
||||
|
||||
bool regExpMatchOne(const String *expression, const String *string);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_REGEXP_TYPE \
|
||||
RegExp *
|
||||
#define FUNCTION_DEBUG_REGEXP_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "RegExp", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
363
src/common/stackTrace.c
Normal file
363
src/common/stackTrace.c
Normal file
@ -0,0 +1,363 @@
|
||||
/***********************************************************************************************************************************
|
||||
Stack Trace Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WITH_BACKTRACE
|
||||
#include <backtrace.h>
|
||||
#include <backtrace-supported.h>
|
||||
#endif
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/error.h"
|
||||
#include "common/log.h"
|
||||
#include "common/stackTrace.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Max call stack depth
|
||||
***********************************************************************************************************************************/
|
||||
#define STACK_TRACE_MAX 128
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Track stack trace
|
||||
***********************************************************************************************************************************/
|
||||
static int stackSize = 0;
|
||||
|
||||
typedef struct StackTraceData
|
||||
{
|
||||
const char *fileName;
|
||||
const char *functionName;
|
||||
unsigned int fileLine;
|
||||
LogLevel functionLogLevel;
|
||||
unsigned int tryDepth;
|
||||
|
||||
char *param;
|
||||
size_t paramSize;
|
||||
bool paramOverflow;
|
||||
bool paramLog;
|
||||
} StackTraceData;
|
||||
|
||||
static StackTraceData stackTrace[STACK_TRACE_MAX];
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Buffer to hold function parameters
|
||||
***********************************************************************************************************************************/
|
||||
static char functionParamBuffer[32 * 1024];
|
||||
|
||||
struct backtrace_state *backTraceState = NULL;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Backtrace init and callbacks
|
||||
***********************************************************************************************************************************/
|
||||
#ifdef WITH_BACKTRACE
|
||||
|
||||
void
|
||||
stackTraceInit(const char *exe)
|
||||
{
|
||||
if (backTraceState == NULL)
|
||||
backTraceState = backtrace_create_state(exe, false, NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
backTraceCallback(void *data, uintptr_t pc, const char *filename, int lineno, const char *function)
|
||||
{
|
||||
(void)(data);
|
||||
(void)(pc);
|
||||
(void)(filename);
|
||||
(void)(function);
|
||||
|
||||
if (stackSize > 0)
|
||||
stackTrace[stackSize - 1].fileLine = (unsigned int)lineno;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
backTraceCallbackError(void *data, const char *msg, int errnum)
|
||||
{
|
||||
(void)data;
|
||||
(void)msg;
|
||||
(void)errnum;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Flag to enable/disable test function logging
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef NDEBUG
|
||||
|
||||
bool stackTraceTestFlag = true;
|
||||
|
||||
void
|
||||
stackTraceTestStart()
|
||||
{
|
||||
stackTraceTestFlag = true;
|
||||
}
|
||||
|
||||
void
|
||||
stackTraceTestStop()
|
||||
{
|
||||
stackTraceTestFlag = false;
|
||||
}
|
||||
|
||||
bool
|
||||
stackTraceTest()
|
||||
{
|
||||
return stackTraceTestFlag;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Push a new function onto the trace stack
|
||||
***********************************************************************************************************************************/
|
||||
LogLevel
|
||||
stackTracePush(const char *fileName, const char *functionName, LogLevel functionLogLevel)
|
||||
{
|
||||
ASSERT(stackSize < STACK_TRACE_MAX - 1);
|
||||
|
||||
// Get line number from backtrace if available
|
||||
#ifdef WITH_BACKTRACE
|
||||
backtrace_full(backTraceState, 2, backTraceCallback, backTraceCallbackError, NULL);
|
||||
#endif
|
||||
|
||||
// This struct could be holding old trace data so init to zero
|
||||
StackTraceData *data = &stackTrace[stackSize];
|
||||
memset(data, 0, sizeof(StackTraceData));
|
||||
|
||||
// Set function info
|
||||
data->fileName = fileName;
|
||||
data->functionName = functionName;
|
||||
data->tryDepth = errorTryDepth();
|
||||
|
||||
// Set param pointer
|
||||
if (stackSize == 0)
|
||||
{
|
||||
data->param = functionParamBuffer;
|
||||
data->functionLogLevel = functionLogLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
StackTraceData *dataPrior = &stackTrace[stackSize - 1];
|
||||
|
||||
data->param = dataPrior->param + dataPrior->paramSize + 1;
|
||||
|
||||
// Log level cannot be lower than the prior function
|
||||
if (functionLogLevel < dataPrior->functionLogLevel)
|
||||
data->functionLogLevel = dataPrior->functionLogLevel;
|
||||
else
|
||||
data->functionLogLevel = functionLogLevel;
|
||||
}
|
||||
|
||||
stackSize++;
|
||||
|
||||
return data->functionLogLevel;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get parameters for the top function on the stack
|
||||
***********************************************************************************************************************************/
|
||||
static const char *
|
||||
stackTraceParamIdx(int stackIdx)
|
||||
{
|
||||
ASSERT_DEBUG(stackSize > 0);
|
||||
ASSERT_DEBUG(stackIdx < stackSize);
|
||||
|
||||
StackTraceData *data = &stackTrace[stackIdx];
|
||||
|
||||
if (data->paramLog)
|
||||
{
|
||||
if (data->paramOverflow)
|
||||
return "!!! buffer overflow - parameters not available !!!";
|
||||
|
||||
if (data->paramSize == 0)
|
||||
return "void";
|
||||
|
||||
return data->param;
|
||||
}
|
||||
|
||||
return "debug log level required for parameters";
|
||||
}
|
||||
|
||||
const char *
|
||||
stackTraceParam()
|
||||
{
|
||||
return stackTraceParamIdx(stackSize - 1);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get the next location where a parameter can be added in the param buffer
|
||||
***********************************************************************************************************************************/
|
||||
char *
|
||||
stackTraceParamBuffer(const char *paramName)
|
||||
{
|
||||
ASSERT_DEBUG(stackSize > 0);
|
||||
|
||||
StackTraceData *data = &stackTrace[stackSize - 1];
|
||||
size_t paramNameSize = strlen(paramName);
|
||||
|
||||
// Make sure that adding this parameter will not overflow the buffer
|
||||
if ((size_t)(data->param - functionParamBuffer) + data->paramSize + paramNameSize + 4 >
|
||||
sizeof(functionParamBuffer) - (STACK_TRACE_PARAM_MAX * 2))
|
||||
{
|
||||
// Set overflow to true
|
||||
data->paramOverflow = true;
|
||||
|
||||
// There's no way to stop the parameter from being formatted so we reserve a space at the end where the format can safely
|
||||
// take place and not disturb the rest of the buffer. Hopefully overflows just won't happen but we need to be prepared in
|
||||
// case of runaway recursion or some other issue that fills the buffer because we don't want a segfault.
|
||||
return functionParamBuffer + sizeof(functionParamBuffer) - STACK_TRACE_PARAM_MAX;
|
||||
}
|
||||
|
||||
// Add a comma if a parameter is already in the list
|
||||
if (data->paramSize != 0)
|
||||
{
|
||||
data->param[data->paramSize++] = ',';
|
||||
data->param[data->paramSize++] = ' ';
|
||||
}
|
||||
|
||||
// Add the parameter name
|
||||
strcpy(data->param + data->paramSize, paramName);
|
||||
data->paramSize += paramNameSize;
|
||||
|
||||
// Add param/value separator
|
||||
data->param[data->paramSize++] = ':';
|
||||
data->param[data->paramSize++] = ' ';
|
||||
|
||||
return data->param + data->paramSize;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Add a parameter to the function on the top of the stack
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
stackTraceParamAdd(size_t bufferSize)
|
||||
{
|
||||
ASSERT_DEBUG(stackSize > 0);
|
||||
|
||||
StackTraceData *data = &stackTrace[stackSize - 1];
|
||||
|
||||
if (!data->paramOverflow)
|
||||
data->paramSize += bufferSize;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Mark that parameters are being logged -- it none appear then the function is void
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
stackTraceParamLog()
|
||||
{
|
||||
ASSERT_DEBUG(stackSize > 0);
|
||||
|
||||
stackTrace[stackSize - 1].paramLog = true;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Pop a function from the stack trace
|
||||
***********************************************************************************************************************************/
|
||||
#ifdef NDEBUG
|
||||
|
||||
void
|
||||
stackTracePop()
|
||||
{
|
||||
stackSize--;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
stackTracePop(const char *fileName, const char *functionName)
|
||||
{
|
||||
ASSERT_DEBUG(stackSize > 0);
|
||||
|
||||
stackSize--;
|
||||
|
||||
StackTraceData *data = &stackTrace[stackSize];
|
||||
|
||||
if (strcmp(data->fileName, fileName) != 0 || strcmp(data->functionName, functionName) != 0)
|
||||
THROW_FMT(AssertError, "popping %s:%s but expected %s:%s", fileName, functionName, data->fileName, data->functionName);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Stack trace format
|
||||
***********************************************************************************************************************************/
|
||||
static size_t
|
||||
stackTraceFmt(char *buffer, size_t bufferSize, size_t bufferUsed, const char *format, ...)
|
||||
{
|
||||
va_list argumentList;
|
||||
va_start(argumentList, format);
|
||||
int result = vsnprintf(
|
||||
buffer + bufferUsed, bufferUsed < bufferSize ? bufferSize - bufferUsed : 0, format, argumentList);
|
||||
va_end(argumentList);
|
||||
|
||||
return (size_t)result;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Generate the stack trace
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
stackTraceToZ(char *buffer, size_t bufferSize, const char *fileName, const char *functionName, unsigned int fileLine)
|
||||
{
|
||||
size_t result = 0;
|
||||
const char *param = "test build required for parameters";
|
||||
int stackIdx = stackSize - 1;
|
||||
|
||||
// If the current function passed in is the same as the top function on the stack then use the parameters for that function
|
||||
if (stackSize > 0 && strcmp(fileName, stackTrace[stackIdx].fileName) == 0 &&
|
||||
strcmp(functionName, stackTrace[stackIdx].functionName) == 0)
|
||||
{
|
||||
param = stackTraceParamIdx(stackSize - 1);
|
||||
stackIdx--;
|
||||
}
|
||||
|
||||
// Output the current function
|
||||
result = stackTraceFmt(
|
||||
buffer, bufferSize, 0, "%.*s:%s:%u:(%s)", (int)(strlen(fileName) - 2), fileName, functionName, fileLine, param);
|
||||
|
||||
// Output stack if there is anything on it
|
||||
if (stackIdx >= 0)
|
||||
{
|
||||
// If the function passed in was not at the top of the stack then some functions are missing
|
||||
if (stackIdx == stackSize - 1)
|
||||
result += stackTraceFmt(buffer, bufferSize, result, "\n ... function(s) ommitted ...");
|
||||
|
||||
// Output the rest of the stack
|
||||
for (; stackIdx >= 0; stackIdx--)
|
||||
{
|
||||
StackTraceData *data = &stackTrace[stackIdx];
|
||||
|
||||
result += stackTraceFmt(
|
||||
buffer, bufferSize, result, "\n%.*s:%s"
|
||||
|
||||
#ifdef WITH_BACKTRACE
|
||||
":%u"
|
||||
#endif
|
||||
":(%s)", (int)(strlen(data->fileName) - 2), data->fileName, data->functionName,
|
||||
|
||||
#ifdef WITH_BACKTRACE
|
||||
data->fileLine,
|
||||
#endif
|
||||
|
||||
stackTraceParamIdx(stackIdx));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Clean the stack at and below the try level
|
||||
|
||||
Called by the error to cleanup the stack when an exception occurs.
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
stackTraceClean(unsigned int tryDepth)
|
||||
{
|
||||
while (stackSize > 0 && stackTrace[stackSize - 1].tryDepth >= tryDepth)
|
||||
stackSize--;
|
||||
}
|
59
src/common/stackTrace.h
Normal file
59
src/common/stackTrace.h
Normal file
@ -0,0 +1,59 @@
|
||||
/***********************************************************************************************************************************
|
||||
Stack Trace Handler
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef COMMON_STACKTRACE_H
|
||||
#define COMMON_STACKTRACE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "common/log.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Maximum size of a single parameter (including NULL terminator)
|
||||
***********************************************************************************************************************************/
|
||||
#define STACK_TRACE_PARAM_MAX 256
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros to access internal functions
|
||||
***********************************************************************************************************************************/
|
||||
#define STACK_TRACE_PUSH(logLevel) \
|
||||
stackTracePush(__FILE__, __func__, logLevel)
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define STACK_TRACE_POP() \
|
||||
stackTracePop();
|
||||
#else
|
||||
#define STACK_TRACE_POP() \
|
||||
stackTracePop(__FILE__, __func__);
|
||||
#endif
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Internal Functions
|
||||
***********************************************************************************************************************************/
|
||||
#ifdef WITH_BACKTRACE
|
||||
void stackTraceInit(const char *exe);
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
void stackTraceTestStart();
|
||||
void stackTraceTestStop();
|
||||
bool stackTraceTest();
|
||||
#endif
|
||||
|
||||
LogLevel stackTracePush(const char *fileName, const char *functionName, LogLevel functionLogLevel);
|
||||
|
||||
#ifdef NDEBUG
|
||||
void stackTracePop();
|
||||
#else
|
||||
void stackTracePop(const char *fileName, const char *functionName);
|
||||
#endif
|
||||
|
||||
size_t stackTraceToZ(char *buffer, size_t bufferSize, const char *fileName, const char *functionName, unsigned int fileLine);
|
||||
void stackTraceParamLog();
|
||||
const char *stackTraceParam();
|
||||
char *stackTraceParamBuffer(const char *param);
|
||||
void stackTraceParamAdd(size_t bufferSize);
|
||||
|
||||
void stackTraceClean(unsigned int tryDepth);
|
||||
|
||||
#endif
|
@ -4,6 +4,7 @@ Time Management
|
||||
#include "stdio.h"
|
||||
#include "sys/time.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/time.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -17,9 +18,12 @@ Epoch time in milliseconds
|
||||
TimeMSec
|
||||
timeMSec()
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
struct timeval currentTime;
|
||||
gettimeofday(¤tTime, NULL);
|
||||
return ((TimeMSec)currentTime.tv_sec * MSEC_PER_SEC) + (TimeMSec)currentTime.tv_usec / MSEC_PER_USEC;
|
||||
|
||||
FUNCTION_TEST_RESULT(UINT64, ((TimeMSec)currentTime.tv_sec * MSEC_PER_SEC) + (TimeMSec)currentTime.tv_usec / MSEC_PER_USEC);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -28,8 +32,14 @@ Sleep for specified milliseconds
|
||||
void
|
||||
sleepMSec(TimeMSec sleepMSec)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UINT64, sleepMSec);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
struct timeval delay;
|
||||
delay.tv_sec = (time_t)(sleepMSec / MSEC_PER_SEC);
|
||||
delay.tv_usec = (time_t)(sleepMSec % MSEC_PER_SEC * 1000);
|
||||
select(0, NULL, NULL, NULL, &delay);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
/***********************************************************************************************************************************
|
||||
String Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/type/buffer.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -22,6 +24,10 @@ Create a new buffer
|
||||
Buffer *
|
||||
bufNew(size_t size)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
Buffer *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("Buffer")
|
||||
@ -37,7 +43,7 @@ bufNew(size_t size)
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(BUFFER, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -46,13 +52,18 @@ Create a new buffer from a C buffer
|
||||
Buffer *
|
||||
bufNewC(size_t size, const void *buffer)
|
||||
{
|
||||
// Create object
|
||||
Buffer *this = bufNew(size);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
FUNCTION_TEST_PARAM(VOIDP, buffer);
|
||||
|
||||
// Copy the data
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Create object and copy data
|
||||
Buffer *this = bufNew(size);
|
||||
memcpy(this->buffer, buffer, this->size);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(BUFFER, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -61,13 +72,19 @@ Create a new buffer from a string
|
||||
Buffer *
|
||||
bufNewStr(const String *string)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
|
||||
FUNCTION_TEST_ASSERT(string != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Create object
|
||||
Buffer *this = bufNew(strSize(string));
|
||||
|
||||
// Copy the data
|
||||
memcpy(this->buffer, strPtr(string), this->size);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(BUFFER, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -76,7 +93,12 @@ Append the contents of another buffer
|
||||
Buffer *
|
||||
bufCat(Buffer *this, const Buffer *cat)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(BUFFER, this);
|
||||
FUNCTION_TEST_PARAM(BUFFER, cat);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (cat != NULL && cat->size > 0)
|
||||
{
|
||||
@ -86,7 +108,7 @@ bufCat(Buffer *this, const Buffer *cat)
|
||||
memcpy(this->buffer + sizeOld, cat->buffer, cat->size);
|
||||
}
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(BUFFER, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -95,15 +117,20 @@ Are two buffers equal?
|
||||
bool
|
||||
bufEq(const Buffer *this, const Buffer *compare)
|
||||
{
|
||||
bool result = false;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(BUFFER, this);
|
||||
FUNCTION_TEST_PARAM(BUFFER, compare);
|
||||
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
ASSERT_DEBUG(compare != NULL);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(compare != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (this->size == compare->size)
|
||||
result = memcmp(this->buffer, compare->buffer, compare->size) == 0;
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -112,10 +139,17 @@ Move buffer to a new mem context
|
||||
Buffer *
|
||||
bufMove(Buffer *this, MemContext *parentNew)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(BUFFER, this);
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, parentNew);
|
||||
|
||||
FUNCTION_TEST_ASSERT(parentNew != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this != NULL)
|
||||
memContextMove(this->memContext, parentNew);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(BUFFER, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -124,7 +158,13 @@ Return buffer ptr
|
||||
unsigned char *
|
||||
bufPtr(const Buffer *this)
|
||||
{
|
||||
return this->buffer;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(BUFFER, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(UCHARP, this->buffer);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -133,6 +173,13 @@ Resize the buffer
|
||||
Buffer *
|
||||
bufResize(Buffer *this, size_t size)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(BUFFER, this);
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Only resize if it the new size is different
|
||||
if (this->size != size)
|
||||
{
|
||||
@ -167,7 +214,7 @@ bufResize(Buffer *this, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(BUFFER, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -176,7 +223,37 @@ Return buffer size
|
||||
size_t
|
||||
bufSize(const Buffer *this)
|
||||
{
|
||||
return this->size;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(BUFFER, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(SIZE, this->size);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert to a zero-terminated string for logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
bufToLog(const Buffer *this, char *buffer, size_t bufferSize)
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
String *string = NULL;
|
||||
|
||||
if (this == NULL)
|
||||
string = strNew("null");
|
||||
else
|
||||
string = strNewFmt("{size: %zu}", this->size);
|
||||
|
||||
result = (size_t)snprintf(buffer, bufferSize, "%s", strPtr(string));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -185,6 +262,12 @@ Free the buffer
|
||||
void
|
||||
bufFree(Buffer *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(BUFFER, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this != NULL)
|
||||
memContextFree(this->memContext);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -26,4 +26,14 @@ size_t bufSize(const Buffer *this);
|
||||
unsigned char *bufPtr(const Buffer *this);
|
||||
void bufFree(Buffer *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t bufToLog(const Buffer *this, char *buffer, size_t bufferSize);
|
||||
|
||||
#define FUNCTION_DEBUG_BUFFER_TYPE \
|
||||
Buffer *
|
||||
#define FUNCTION_DEBUG_BUFFER_FORMAT(value, buffer, bufferSize) \
|
||||
bufToLog(value, buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
266
src/common/type/convert.c
Normal file
266
src/common/type/convert.c
Normal file
@ -0,0 +1,266 @@
|
||||
/***********************************************************************************************************************************
|
||||
Convert Base Data Types
|
||||
***********************************************************************************************************************************/
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/type/convert.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert uint64 to zero-terminated string
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
cvtBoolToZ(bool value, char *buffer, size_t bufferSize)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(BOOL, value);
|
||||
FUNCTION_TEST_PARAM(CHARP, buffer);
|
||||
FUNCTION_TEST_PARAM(SIZE, bufferSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
size_t result = (size_t)snprintf(buffer, bufferSize, "%s", value ? "true" : "false");
|
||||
|
||||
if (result >= bufferSize)
|
||||
THROW(AssertError, "buffer overflow");
|
||||
|
||||
FUNCTION_TEST_RESULT(SIZE, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert double to zero-terminated string and vice versa
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
cvtDoubleToZ(double value, char *buffer, size_t bufferSize)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(DOUBLE, value);
|
||||
FUNCTION_TEST_PARAM(CHARP, buffer);
|
||||
FUNCTION_TEST_PARAM(SIZE, bufferSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Convert to a string
|
||||
size_t result = (size_t)snprintf(buffer, bufferSize, "%lf", value);
|
||||
|
||||
if (result >= bufferSize)
|
||||
THROW(AssertError, "buffer overflow");
|
||||
|
||||
// Any formatted double should be at least 8 characters, i.e. 0.000000
|
||||
ASSERT_DEBUG(strlen(buffer) >= 8);
|
||||
// Any formatted double should have a decimal point
|
||||
ASSERT_DEBUG(strchr(buffer, '.') != NULL);
|
||||
|
||||
// Strip off any final 0s and the decimal point if there are no non-zero digits after it
|
||||
char *end = buffer + strlen(buffer) - 1;
|
||||
|
||||
while (*end == '0' || *end == '.')
|
||||
{
|
||||
// It should not be possible to go past the beginning because format "%lf" will always write a decimal point
|
||||
ASSERT_DEBUG(end > buffer);
|
||||
|
||||
end--;
|
||||
|
||||
if (*(end + 1) == '.')
|
||||
break;
|
||||
}
|
||||
|
||||
// Zero terminate the string
|
||||
end[1] = 0;
|
||||
|
||||
// Return string length
|
||||
FUNCTION_TEST_RESULT(SIZE, (size_t)(end - buffer + 1));
|
||||
}
|
||||
|
||||
double
|
||||
cvtZToDouble(const char *value)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(CHARP, value);
|
||||
|
||||
FUNCTION_TEST_ASSERT(value != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
double result = 0;
|
||||
sscanf(value, "%lf", &result);
|
||||
|
||||
if (result == 0 && strcmp(value, "0") != 0)
|
||||
THROW_FMT(FormatError, "unable to convert string '%s' to double", value);
|
||||
|
||||
FUNCTION_TEST_RESULT(DOUBLE, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert int to zero-terminated string and vice versa
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
cvtIntToZ(int value, char *buffer, size_t bufferSize)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INT, value);
|
||||
FUNCTION_TEST_PARAM(CHARP, buffer);
|
||||
FUNCTION_TEST_PARAM(SIZE, bufferSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
size_t result = (size_t)snprintf(buffer, bufferSize, "%d", value);
|
||||
|
||||
if (result >= bufferSize)
|
||||
THROW(AssertError, "buffer overflow");
|
||||
|
||||
FUNCTION_TEST_RESULT(SIZE, result);
|
||||
}
|
||||
|
||||
int
|
||||
cvtZToInt(const char *value)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(CHARP, value);
|
||||
|
||||
FUNCTION_TEST_ASSERT(value != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
int result = atoi(value);
|
||||
|
||||
if (result == 0 && strcmp(value, "0") != 0)
|
||||
THROW_FMT(FormatError, "unable to convert string '%s' to int", value);
|
||||
|
||||
FUNCTION_TEST_RESULT(INT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert int64 to zero-terminated string and vice versa
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
cvtInt64ToZ(int64_t value, char *buffer, size_t bufferSize)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INT64, value);
|
||||
FUNCTION_TEST_PARAM(CHARP, buffer);
|
||||
FUNCTION_TEST_PARAM(SIZE, bufferSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
size_t result = (size_t)snprintf(buffer, bufferSize, "%" PRId64, value);
|
||||
|
||||
if (result >= bufferSize)
|
||||
THROW(AssertError, "buffer overflow");
|
||||
|
||||
FUNCTION_TEST_RESULT(SIZE, result);
|
||||
}
|
||||
|
||||
int64_t
|
||||
cvtZToInt64(const char *value)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(CHARP, value);
|
||||
|
||||
FUNCTION_TEST_ASSERT(value != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
int64_t result = atoll(value);
|
||||
|
||||
char buffer[32];
|
||||
snprintf(buffer, sizeof(buffer), "%" PRId64, result);
|
||||
|
||||
if (strcmp(value, buffer) != 0)
|
||||
THROW_FMT(FormatError, "unable to convert string '%s' to int64", value);
|
||||
|
||||
FUNCTION_TEST_RESULT(INT64, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert mode to zero-terminated string
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
cvtModeToZ(mode_t value, char *buffer, size_t bufferSize)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(MODE, value);
|
||||
FUNCTION_TEST_PARAM(CHARP, buffer);
|
||||
FUNCTION_TEST_PARAM(SIZE, bufferSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
size_t result = (size_t)snprintf(buffer, bufferSize, "%04o", value);
|
||||
|
||||
if (result >= bufferSize)
|
||||
THROW(AssertError, "buffer overflow");
|
||||
|
||||
FUNCTION_TEST_RESULT(SIZE, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert size to zero-terminated string
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
cvtSizeToZ(size_t value, char *buffer, size_t bufferSize)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(SIZE, value);
|
||||
FUNCTION_TEST_PARAM(CHARP, buffer);
|
||||
FUNCTION_TEST_PARAM(SIZE, bufferSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
size_t result = (size_t)snprintf(buffer, bufferSize, "%zu", value);
|
||||
|
||||
if (result >= bufferSize)
|
||||
THROW(AssertError, "buffer overflow");
|
||||
|
||||
FUNCTION_TEST_RESULT(SIZE, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert uint to zero-terminated string
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
cvtUIntToZ(unsigned int value, char *buffer, size_t bufferSize)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UINT, value);
|
||||
FUNCTION_TEST_PARAM(CHARP, buffer);
|
||||
FUNCTION_TEST_PARAM(SIZE, bufferSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
size_t result = (size_t)snprintf(buffer, bufferSize, "%u", value);
|
||||
|
||||
if (result >= bufferSize)
|
||||
THROW(AssertError, "buffer overflow");
|
||||
|
||||
FUNCTION_TEST_RESULT(SIZE, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert uint64 to zero-terminated string
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
cvtUInt64ToZ(uint64_t value, char *buffer, size_t bufferSize)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UINT64, value);
|
||||
FUNCTION_TEST_PARAM(CHARP, buffer);
|
||||
FUNCTION_TEST_PARAM(SIZE, bufferSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
size_t result = (size_t)snprintf(buffer, bufferSize, "%" PRIu64, value);
|
||||
|
||||
if (result >= bufferSize)
|
||||
THROW(AssertError, "buffer overflow");
|
||||
|
||||
FUNCTION_TEST_RESULT(SIZE, result);
|
||||
}
|
32
src/common/type/convert.h
Normal file
32
src/common/type/convert.h
Normal file
@ -0,0 +1,32 @@
|
||||
/***********************************************************************************************************************************
|
||||
Convert Base Data Types
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef COMMON_TYPE_CONVERT_H
|
||||
#define COMMON_TYPE_CONVERT_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
size_t cvtDoubleToZ(double value, char *buffer, size_t bufferSize);
|
||||
double cvtZToDouble(const char *value);
|
||||
|
||||
size_t cvtIntToZ(int value, char *buffer, size_t bufferSize);
|
||||
int cvtZToInt(const char *value);
|
||||
|
||||
size_t cvtInt64ToZ(int64_t value, char *buffer, size_t bufferSize);
|
||||
int64_t cvtZToInt64(const char *value);
|
||||
|
||||
size_t cvtModeToZ(mode_t value, char *buffer, size_t bufferSize);
|
||||
|
||||
size_t cvtSizeToZ(size_t value, char *buffer, size_t bufferSize);
|
||||
|
||||
size_t cvtUIntToZ(unsigned int value, char *buffer, size_t bufferSize);
|
||||
|
||||
size_t cvtUInt64ToZ(uint64_t value, char *buffer, size_t bufferSize);
|
||||
|
||||
size_t cvtBoolToZ(bool value, char *buffer, size_t bufferSize);
|
||||
|
||||
#endif
|
@ -3,6 +3,7 @@ Key Value Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include <limits.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/type/keyValue.h"
|
||||
#include "common/type/list.h"
|
||||
@ -38,9 +39,11 @@ Create a new key/value store
|
||||
KeyValue *
|
||||
kvNew()
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
KeyValue *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("keyValue")
|
||||
MEM_CONTEXT_NEW_BEGIN("KeyValue")
|
||||
{
|
||||
// Allocate state and set context
|
||||
this = memNew(sizeof(KeyValue));
|
||||
@ -52,7 +55,7 @@ kvNew()
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(KEY_VALUE, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -61,6 +64,12 @@ Duplicate key/value store
|
||||
KeyValue *
|
||||
kvDup(const KeyValue *source)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(KEY_VALUE, source);
|
||||
|
||||
FUNCTION_TEST_ASSERT(source != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
KeyValue *this = kvNew();
|
||||
|
||||
// Duplicate all key/values
|
||||
@ -79,7 +88,7 @@ kvDup(const KeyValue *source)
|
||||
|
||||
this->keyList = varLstDup(source->keyList);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(KEY_VALUE, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -88,23 +97,30 @@ Get key index if it exists
|
||||
static unsigned int
|
||||
kvGetIdx(const KeyValue *this, const Variant *key)
|
||||
{
|
||||
// Search for the key
|
||||
unsigned int listIdx = 0;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(KEY_VALUE, this);
|
||||
FUNCTION_TEST_PARAM(VARIANT, key);
|
||||
|
||||
for (; listIdx < lstSize(this->list); listIdx++)
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(key != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Search for the key
|
||||
unsigned int result = KEY_NOT_FOUND;
|
||||
|
||||
for (unsigned int listIdx = 0; listIdx < lstSize(this->list); listIdx++)
|
||||
{
|
||||
const KeyValuePair *pair = (const KeyValuePair *)lstGet(this->list, listIdx);
|
||||
|
||||
// Break if the key matches
|
||||
if (varEq(key, pair->key))
|
||||
{
|
||||
result = listIdx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If key was not found
|
||||
if (listIdx == lstSize(this->list))
|
||||
return KEY_NOT_FOUND;
|
||||
|
||||
return listIdx;
|
||||
FUNCTION_TEST_RESULT(UINT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -113,7 +129,13 @@ Get list of keys
|
||||
const VariantList *
|
||||
kvKeyList(const KeyValue *this)
|
||||
{
|
||||
return this->keyList;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(KEY_VALUE, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT_LIST, this->keyList);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -124,6 +146,15 @@ Handles the common logic for the external put functions. The correct mem context
|
||||
static void
|
||||
kvPutInternal(KeyValue *this, const Variant *key, Variant *value)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(KEY_VALUE, this);
|
||||
FUNCTION_TEST_PARAM(VARIANT, key);
|
||||
FUNCTION_TEST_PARAM(VARIANT, value);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(key != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Find the key
|
||||
unsigned int listIdx = kvGetIdx(this, key);
|
||||
|
||||
@ -151,6 +182,8 @@ kvPutInternal(KeyValue *this, const Variant *key, Variant *value)
|
||||
|
||||
pair->value = value;
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -159,13 +192,22 @@ Put key/value pair
|
||||
KeyValue *
|
||||
kvPut(KeyValue *this, const Variant *key, const Variant *value)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(KEY_VALUE, this);
|
||||
FUNCTION_TEST_PARAM(VARIANT, key);
|
||||
FUNCTION_TEST_PARAM(VARIANT, value);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(key != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
{
|
||||
kvPutInternal(this, key, varDup(value));
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(KEY_VALUE, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -174,6 +216,15 @@ Add value to key -- if the key does not exist then this works the same as kvPut(
|
||||
KeyValue *
|
||||
kvAdd(KeyValue *this, const Variant *key, const Variant *value)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(KEY_VALUE, this);
|
||||
FUNCTION_TEST_PARAM(VARIANT, key);
|
||||
FUNCTION_TEST_PARAM(VARIANT, value);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(key != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
{
|
||||
// Find the key
|
||||
@ -193,7 +244,7 @@ kvAdd(KeyValue *this, const Variant *key, const Variant *value)
|
||||
pair->value = varDup(value);
|
||||
else if (varType(pair->value) != varTypeVariantList)
|
||||
{
|
||||
Variant *valueList = varNewVarLstEmpty();
|
||||
Variant *valueList = varNewVarLst(varLstNew());
|
||||
varLstAdd(varVarLst(valueList), pair->value);
|
||||
varLstAdd(varVarLst(valueList), varDup(value));
|
||||
pair->value = valueList;
|
||||
@ -204,7 +255,7 @@ kvAdd(KeyValue *this, const Variant *key, const Variant *value)
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(KEY_VALUE, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -216,6 +267,14 @@ key/value store.
|
||||
KeyValue *
|
||||
kvPutKv(KeyValue *this, const Variant *key)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(KEY_VALUE, this);
|
||||
FUNCTION_TEST_PARAM(VARIANT, key);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(key != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
KeyValue *result = NULL;
|
||||
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
@ -227,7 +286,7 @@ kvPutKv(KeyValue *this, const Variant *key)
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(KEY_VALUE, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -236,6 +295,14 @@ Get a value using the key
|
||||
const Variant *
|
||||
kvGet(const KeyValue *this, const Variant *key)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(KEY_VALUE, this);
|
||||
FUNCTION_TEST_PARAM(VARIANT, key);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(key != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
Variant *result = NULL;
|
||||
|
||||
// Find the key
|
||||
@ -244,7 +311,7 @@ kvGet(const KeyValue *this, const Variant *key)
|
||||
if (listIdx != KEY_NOT_FOUND)
|
||||
result = ((KeyValuePair *)lstGet(this->list, listIdx))->value;
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(VARIANT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -253,6 +320,14 @@ Get a value as a list (even if there is only one value) using the key
|
||||
VariantList *
|
||||
kvGetList(const KeyValue *this, const Variant *key)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(KEY_VALUE, this);
|
||||
FUNCTION_TEST_PARAM(VARIANT, key);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(key != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
VariantList *result = NULL;
|
||||
|
||||
// Get the value
|
||||
@ -264,7 +339,7 @@ kvGetList(const KeyValue *this, const Variant *key)
|
||||
else
|
||||
result = varLstAdd(varLstNew(), varDup(value));
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(VARIANT_LIST, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -273,5 +348,12 @@ Free the string
|
||||
void
|
||||
kvFree(KeyValue *this)
|
||||
{
|
||||
memContextFree(this->memContext);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(KEY_VALUE, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this != NULL)
|
||||
memContextFree(this->memContext);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -24,4 +24,12 @@ const Variant *kvGet(const KeyValue *this, const Variant *key);
|
||||
VariantList *kvGetList(const KeyValue *this, const Variant *key);
|
||||
void kvFree(KeyValue *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_KEY_VALUE_TYPE \
|
||||
KeyValue *
|
||||
#define FUNCTION_DEBUG_KEY_VALUE_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "KeyValue", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -2,9 +2,11 @@
|
||||
List Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/type/list.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -25,6 +27,8 @@ Create a new list
|
||||
List *
|
||||
lstNew(size_t itemSize)
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
List *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("List")
|
||||
@ -36,8 +40,7 @@ lstNew(size_t itemSize)
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
// Return buffer
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(LIST, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -46,6 +49,14 @@ Add an item to the end of the list
|
||||
List *
|
||||
lstAdd(List *this, const void *item)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(LIST, this);
|
||||
FUNCTION_TEST_PARAM(VOIDP, item);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(item != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// If list size = max then allocate more space
|
||||
if (this->listSize == this->listSizeMax)
|
||||
{
|
||||
@ -70,8 +81,7 @@ lstAdd(List *this, const void *item)
|
||||
memcpy(this->list + (this->listSize * this->itemSize), item, this->itemSize);
|
||||
this->listSize++;
|
||||
|
||||
// Return list
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(LIST, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -80,12 +90,19 @@ Get an item from the list
|
||||
void *
|
||||
lstGet(const List *this, unsigned int listIdx)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(LIST, this);
|
||||
FUNCTION_TEST_PARAM(UINT, listIdx);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Ensure list index is in range
|
||||
if (listIdx >= this->listSize)
|
||||
THROW_FMT(AssertError, "cannot get index %u from list with %u value(s)", listIdx, this->listSize);
|
||||
|
||||
// Return pointer to list item
|
||||
return this->list + (listIdx * this->itemSize);
|
||||
FUNCTION_TEST_RESULT(VOIDP, this->list + (listIdx * this->itemSize));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -94,7 +111,13 @@ Return the memory context for this list
|
||||
MemContext *
|
||||
lstMemContext(const List *this)
|
||||
{
|
||||
return this->memContext;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(LIST, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(MEM_CONTEXT, this->memContext);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -103,10 +126,17 @@ Move the string list
|
||||
List *
|
||||
lstMove(List *this, MemContext *parentNew)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(LIST, this);
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, parentNew);
|
||||
|
||||
FUNCTION_TEST_ASSERT(parentNew != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this != NULL)
|
||||
memContextMove(this->memContext, parentNew);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(LIST, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -115,7 +145,13 @@ Return list size
|
||||
unsigned int
|
||||
lstSize(const List *this)
|
||||
{
|
||||
return this->listSize;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(LIST, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(UINT, this->listSize);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -124,9 +160,41 @@ List sort
|
||||
List *
|
||||
lstSort(List *this, int (*comparator)(const void *, const void*))
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(LIST, this);
|
||||
FUNCTION_TEST_PARAM(FUNCTIONP, comparator);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(comparator != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
qsort(this->list, this->listSize, this->itemSize, comparator);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(LIST, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert to a zero-terminated string for logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
lstToLog(const List *this, char *buffer, size_t bufferSize)
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
String *string = NULL;
|
||||
|
||||
if (this == NULL)
|
||||
string = strNew("null");
|
||||
else
|
||||
string = strNewFmt("{size: %u}", this->listSize);
|
||||
|
||||
result = (size_t)snprintf(buffer, bufferSize, "%s", strPtr(string));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -135,6 +203,12 @@ Free the string
|
||||
void
|
||||
lstFree(List *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(LIST, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this != NULL)
|
||||
memContextFree(this->memContext);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -29,4 +29,14 @@ unsigned int lstSize(const List *this);
|
||||
List *lstSort(List *this, int (*comparator)(const void *, const void*));
|
||||
void lstFree(List *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t lstToLog(const List *this, char *buffer, size_t bufferSize);
|
||||
|
||||
#define FUNCTION_DEBUG_LIST_TYPE \
|
||||
List *
|
||||
#define FUNCTION_DEBUG_LIST_FORMAT(value, buffer, bufferSize) \
|
||||
lstToLog(value, buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -8,6 +8,7 @@ String Handler
|
||||
#include <string.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/type/string.h"
|
||||
|
||||
@ -27,6 +28,12 @@ Create a new string from a zero-terminated string
|
||||
String *
|
||||
strNew(const char *string)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRINGZ, string);
|
||||
|
||||
FUNCTION_TEST_ASSERT(string != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Create object
|
||||
String *this = memNew(sizeof(String));
|
||||
this->memContext = memContextCurrent();
|
||||
@ -36,8 +43,7 @@ strNew(const char *string)
|
||||
this->buffer = memNewRaw(this->size + 1);
|
||||
strcpy(this->buffer, string);
|
||||
|
||||
// Return buffer
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -49,6 +55,12 @@ character will be used as a string.
|
||||
String *
|
||||
strNewBuf(const Buffer *buffer)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(BUFFER, buffer);
|
||||
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Create object
|
||||
String *this = memNew(sizeof(String));
|
||||
this->memContext = memContextCurrent();
|
||||
@ -59,8 +71,7 @@ strNewBuf(const Buffer *buffer)
|
||||
memcpy(this->buffer, (char *)bufPtr(buffer), this->size);
|
||||
this->buffer[this->size] = 0;
|
||||
|
||||
// Return buffer
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -69,6 +80,12 @@ Create a new string from a format string with parameters (i.e. sprintf)
|
||||
String *
|
||||
strNewFmt(const char *format, ...)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRINGZ, format);
|
||||
|
||||
FUNCTION_TEST_ASSERT(format != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Create object
|
||||
String *this = memNew(sizeof(String));
|
||||
this->memContext = memContextCurrent();
|
||||
@ -85,8 +102,7 @@ strNewFmt(const char *format, ...)
|
||||
vsnprintf(this->buffer, this->size + 1, format, argumentList);
|
||||
va_end(argumentList);
|
||||
|
||||
// Return buffer
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -97,6 +113,13 @@ The string may or may not be zero-terminated but we'll use that nomeclature sinc
|
||||
String *
|
||||
strNewN(const char *string, size_t size)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(CHARP, string);
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
|
||||
FUNCTION_TEST_ASSERT(string != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Create object
|
||||
String *this = memNew(sizeof(String));
|
||||
this->memContext = memContextCurrent();
|
||||
@ -108,7 +131,7 @@ strNewN(const char *string, size_t size)
|
||||
this->buffer[this->size] = 0;
|
||||
|
||||
// Return buffer
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -117,12 +140,18 @@ Return the file part of a string (i.e. everything after the last / or the entire
|
||||
String *
|
||||
strBase(const String *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
const char *end = this->buffer + this->size;
|
||||
|
||||
while (end > this->buffer && *(end - 1) != '/')
|
||||
end--;
|
||||
|
||||
return strNew(end);
|
||||
FUNCTION_TEST_RESULT(STRING, strNew(end));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -131,19 +160,35 @@ Does the string begin with the specified string?
|
||||
bool
|
||||
strBeginsWith(const String *this, const String *beginsWith)
|
||||
{
|
||||
return strBeginsWithZ(this, strPtr(beginsWith));
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(STRING, beginsWith);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(beginsWith != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, strBeginsWithZ(this, strPtr(beginsWith)));
|
||||
}
|
||||
|
||||
bool
|
||||
strBeginsWithZ(const String *this, const char *beginsWith)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, beginsWith);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(beginsWith != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool result = false;
|
||||
unsigned int beginsWithSize = (unsigned int)strlen(beginsWith);
|
||||
|
||||
if (this->size >= beginsWithSize)
|
||||
result = strncmp(strPtr(this), beginsWith, beginsWithSize) == 0;
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -152,6 +197,14 @@ Append a string
|
||||
String *
|
||||
strCat(String *this, const char *cat)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, cat);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(cat != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Determine length of string to append
|
||||
size_t sizeGrow = strlen(cat);
|
||||
|
||||
@ -165,7 +218,7 @@ strCat(String *this, const char *cat)
|
||||
strcpy(this->buffer + this->size, cat);
|
||||
this->size += sizeGrow;
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -174,6 +227,14 @@ Append a formatted string
|
||||
String *
|
||||
strCatFmt(String *this, const char *format, ...)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, format);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(format != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Determine how long the allocated string needs to be
|
||||
va_list argumentList;
|
||||
va_start(argumentList, format);
|
||||
@ -193,8 +254,7 @@ strCatFmt(String *this, const char *format, ...)
|
||||
|
||||
this->size += sizeGrow;
|
||||
|
||||
// Return buffer
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -203,13 +263,29 @@ C-style string compare
|
||||
int
|
||||
strCmp(const String *this, const String *compare)
|
||||
{
|
||||
return strcmp(strPtr(this), strPtr(compare));
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(STRING, compare);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(compare != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(INT, strcmp(strPtr(this), strPtr(compare)));
|
||||
}
|
||||
|
||||
int
|
||||
strCmpZ(const String *this, const char *compare)
|
||||
{
|
||||
return strcmp(strPtr(this), compare);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, compare);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(compare != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(INT, strcmp(strPtr(this), compare));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -218,12 +294,16 @@ Duplicate a string from an existing string
|
||||
String *
|
||||
strDup(const String *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
String *result = NULL;
|
||||
|
||||
if (this != NULL)
|
||||
result = strNew(strPtr(this));
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(STRING, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -232,19 +312,35 @@ Does the string end with the specified string?
|
||||
bool
|
||||
strEndsWith(const String *this, const String *endsWith)
|
||||
{
|
||||
return strEndsWithZ(this, strPtr(endsWith));
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(STRING, endsWith);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(endsWith != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, strEndsWithZ(this, strPtr(endsWith)));
|
||||
}
|
||||
|
||||
bool
|
||||
strEndsWithZ(const String *this, const char *endsWith)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, endsWith);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(endsWith != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool result = false;
|
||||
unsigned int endsWithSize = (unsigned int)strlen(endsWith);
|
||||
|
||||
if (this->size >= endsWithSize)
|
||||
result = strcmp(strPtr(this) + (this->size - endsWithSize), endsWith) == 0;
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -256,18 +352,34 @@ would need a call to strlen().
|
||||
bool
|
||||
strEq(const String *this, const String *compare)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(STRING, compare);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(compare != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (this->size == compare->size)
|
||||
result = strcmp(strPtr(this), strPtr(compare)) == 0;
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
bool
|
||||
strEqZ(const String *this, const char *compare)
|
||||
{
|
||||
return strcmp(strPtr(this), compare) == 0;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, compare);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(compare != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, strcmp(strPtr(this), compare) == 0);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -276,10 +388,16 @@ Upper-case the first letter
|
||||
String *
|
||||
strFirstUpper(String *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this->size > 0)
|
||||
this->buffer[0] = (char)toupper(this->buffer[0]);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -288,10 +406,16 @@ Lower-case the first letter
|
||||
String *
|
||||
strFirstLower(String *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this->size > 0)
|
||||
this->buffer[0] = (char)tolower(this->buffer[0]);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -300,11 +424,17 @@ Upper-case entire string
|
||||
String *
|
||||
strUpper(String *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this->size > 0)
|
||||
for (unsigned int idx = 0; idx <= this->size; idx++)
|
||||
this->buffer[idx] = (char)toupper(this->buffer[idx]);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -313,11 +443,17 @@ Upper-case entire string
|
||||
String *
|
||||
strLower(String *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this->size > 0)
|
||||
for (unsigned int idx = 0; idx <= this->size; idx++)
|
||||
this->buffer[idx] = (char)tolower(this->buffer[idx]);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -326,12 +462,19 @@ Return the path part of a string (i.e. everything before the last / or "" if the
|
||||
String *
|
||||
strPath(const String *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
const char *end = this->buffer + this->size;
|
||||
|
||||
while (end > this->buffer && *(end - 1) != '/')
|
||||
end--;
|
||||
|
||||
return strNewN(this->buffer, end - this->buffer <= 1 ? (size_t)(end - this->buffer) : (size_t)(end - this->buffer - 1));
|
||||
FUNCTION_TEST_RESULT(
|
||||
STRING, strNewN(this->buffer, end - this->buffer <= 1 ? (size_t)(end - this->buffer) : (size_t)(end - this->buffer - 1)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -340,12 +483,47 @@ Return string ptr
|
||||
const char *
|
||||
strPtr(const String *this)
|
||||
{
|
||||
const char *result = NULL;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
char *result = NULL;
|
||||
|
||||
if (this != NULL)
|
||||
result = (const char *)this->buffer;
|
||||
result = this->buffer;
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(CHARP, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Quote a string
|
||||
***********************************************************************************************************************************/
|
||||
String *
|
||||
strQuote(const String *this, const String *quote)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(STRING, quote);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(quote != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRING, strQuoteZ(this, strPtr(quote)));
|
||||
}
|
||||
|
||||
String *
|
||||
strQuoteZ(const String *this, const char *quote)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, quote);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(quote != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRING, strNewFmt("%s%s%s", quote, strPtr(this), quote));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -354,7 +532,15 @@ Return a substring given only the start position
|
||||
String *
|
||||
strSub(const String *this, size_t start)
|
||||
{
|
||||
return strSubN(this, start, this->size - start);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(SIZE, start);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(start < this->size);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRING, strSubN(this, start, this->size - start));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -363,10 +549,17 @@ Return a substring given the start position and size
|
||||
String *
|
||||
strSubN(const String *this, size_t start, size_t size)
|
||||
{
|
||||
ASSERT(start < this->size);
|
||||
ASSERT(start + size <= this->size);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(SIZE, start);
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
|
||||
return strNewN(this->buffer + start, size);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(start < this->size);
|
||||
FUNCTION_TEST_ASSERT(start + size <= this->size);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRING, strNewN(this->buffer + start, size));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -375,7 +568,13 @@ Return string size
|
||||
size_t
|
||||
strSize(const String *this)
|
||||
{
|
||||
return this->size;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(SIZE, this->size);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -384,6 +583,12 @@ Trim whitespace from the beginnning and end of a string
|
||||
String *
|
||||
strTrim(String *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Nothing to trim if size is zero
|
||||
if (this->size > 0)
|
||||
{
|
||||
@ -420,7 +625,7 @@ strTrim(String *this)
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -429,16 +634,23 @@ Return the index to the location of the the first occurrence of a character with
|
||||
int
|
||||
strChr(const String *this, char chr)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
int result = -1;
|
||||
|
||||
if (this->size > 0)
|
||||
{
|
||||
const char *ptr = strchr(this->buffer, chr);
|
||||
|
||||
if (ptr != NULL)
|
||||
result = (int)(ptr - this->buffer);
|
||||
result = (int)(ptr - this->buffer);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(INT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -447,9 +659,12 @@ Truncate the end of a string from the index provided to the current end (e.g. 12
|
||||
String *
|
||||
strTrunc(String *this, int idx)
|
||||
{
|
||||
// If the index position is outside the array boundaries then error
|
||||
if (idx < 0 || (size_t)idx > this->size)
|
||||
THROW_FMT(AssertError, "index passed is outside the string boundaries");
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(idx >= 0 && (size_t)idx <= this->size);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this->size > 0)
|
||||
{
|
||||
@ -465,7 +680,31 @@ strTrunc(String *this, int idx)
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert to a zero-terminated string for logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
strToLog(const String *this, char *buffer, size_t bufferSize)
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
String *string = NULL;
|
||||
|
||||
if (this == NULL)
|
||||
string = strNew("null");
|
||||
else
|
||||
string = strNewFmt("{\"%s\"}", strPtr(this));
|
||||
|
||||
result = (size_t)snprintf(buffer, bufferSize, "%s", strPtr(string));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -474,6 +713,10 @@ Free the string
|
||||
void
|
||||
strFree(String *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this != NULL)
|
||||
{
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
@ -483,4 +726,6 @@ strFree(String *this)
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ String *strUpper(String *this);
|
||||
String *strLower(String *this);
|
||||
String *strPath(const String *this);
|
||||
const char *strPtr(const String *this);
|
||||
String *strQuote(const String *this, const String *quote);
|
||||
String *strQuoteZ(const String *this, const char *quote);
|
||||
size_t strSize(const String *this);
|
||||
String *strSub(const String *this, size_t start);
|
||||
String *strSubN(const String *this, size_t start, size_t size);
|
||||
@ -46,4 +48,24 @@ String *strTrunc(String *this, int idx);
|
||||
|
||||
void strFree(String *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t strToLog(const String *this, char *buffer, size_t bufferSize);
|
||||
|
||||
#define FUNCTION_DEBUG_CONST_STRING_TYPE \
|
||||
const String *
|
||||
#define FUNCTION_DEBUG_CONST_STRING_FORMAT(value, buffer, bufferSize) \
|
||||
FUNCTION_DEBUG_STRING_FORMAT(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_STRING_TYPE \
|
||||
String *
|
||||
#define FUNCTION_DEBUG_STRING_FORMAT(value, buffer, bufferSize) \
|
||||
strToLog(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_STRINGP_TYPE \
|
||||
const String **
|
||||
#define FUNCTION_DEBUG_STRINGP_FORMAT(value, buffer, bufferSize) \
|
||||
ptrToLog(value, "String **", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -2,9 +2,12 @@
|
||||
String List Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/type/list.h"
|
||||
#include "common/type/stringList.h"
|
||||
@ -15,7 +18,8 @@ Wrapper for lstNew()
|
||||
StringList *
|
||||
strLstNew()
|
||||
{
|
||||
return (StringList *)lstNew(sizeof(String *));
|
||||
FUNCTION_TEST_VOID();
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, (StringList *)lstNew(sizeof(String *)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -24,7 +28,14 @@ Internal add -- the string must have been created in the list's mem context befo
|
||||
static StringList *
|
||||
strLstAddInternal(StringList *this, String *string)
|
||||
{
|
||||
return (StringList *)lstAdd((List *)this, &string);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, (StringList *)lstAdd((List *)this, &string));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -33,12 +44,28 @@ Split a string into a string list based on a delimiter
|
||||
StringList *
|
||||
strLstNewSplit(const String *string, const String *delimiter)
|
||||
{
|
||||
return strLstNewSplitZ(string, strPtr(delimiter));
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
FUNCTION_TEST_PARAM(STRING, delimiter);
|
||||
|
||||
FUNCTION_TEST_ASSERT(string != NULL);
|
||||
FUNCTION_TEST_ASSERT(delimiter != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, strLstNewSplitZ(string, strPtr(delimiter)));
|
||||
}
|
||||
|
||||
StringList *
|
||||
strLstNewSplitZ(const String *string, const char *delimiter)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, delimiter);
|
||||
|
||||
FUNCTION_TEST_ASSERT(string != NULL);
|
||||
FUNCTION_TEST_ASSERT(delimiter != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Create the list
|
||||
StringList *this = strLstNew();
|
||||
|
||||
@ -69,7 +96,7 @@ strLstNewSplitZ(const String *string, const char *delimiter)
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -81,12 +108,30 @@ breaking up test on spaces, for example.
|
||||
StringList *
|
||||
strLstNewSplitSize(const String *string, const String *delimiter, size_t size)
|
||||
{
|
||||
return strLstNewSplitSizeZ(string, strPtr(delimiter), size);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
FUNCTION_TEST_PARAM(STRING, delimiter);
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
|
||||
FUNCTION_TEST_ASSERT(string != NULL);
|
||||
FUNCTION_TEST_ASSERT(delimiter != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, strLstNewSplitSizeZ(string, strPtr(delimiter), size));
|
||||
}
|
||||
|
||||
StringList *
|
||||
strLstNewSplitSizeZ(const String *string, const char *delimiter, size_t size)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, delimiter);
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
|
||||
FUNCTION_TEST_ASSERT(string != NULL);
|
||||
FUNCTION_TEST_ASSERT(delimiter != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Create the list
|
||||
StringList *this = strLstNew();
|
||||
|
||||
@ -135,7 +180,7 @@ strLstNewSplitSizeZ(const String *string, const char *delimiter, size_t size)
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -144,6 +189,12 @@ New string list from a variant list -- all variants in the list must be type str
|
||||
StringList *
|
||||
strLstNewVarLst(const VariantList *sourceList)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT_LIST, sourceList);
|
||||
|
||||
FUNCTION_TEST_ASSERT(sourceList != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Create the list
|
||||
StringList *this = strLstNew();
|
||||
|
||||
@ -155,7 +206,7 @@ strLstNewVarLst(const VariantList *sourceList)
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -164,6 +215,12 @@ Duplicate a string list
|
||||
StringList *
|
||||
strLstDup(const StringList *sourceList)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, sourceList);
|
||||
|
||||
FUNCTION_TEST_ASSERT(sourceList != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Create the list
|
||||
StringList *this = strLstNew();
|
||||
|
||||
@ -175,7 +232,7 @@ strLstDup(const StringList *sourceList)
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -184,6 +241,13 @@ Does the specified string exist in the list?
|
||||
bool
|
||||
strLstExists(const StringList *this, const String *string)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (unsigned int listIdx = 0; listIdx < strLstSize(this); listIdx++)
|
||||
@ -195,12 +259,19 @@ strLstExists(const StringList *this, const String *string)
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
bool
|
||||
strLstExistsZ(const StringList *this, const char *cstring)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, cstring);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (unsigned int listIdx = 0; listIdx < strLstSize(this); listIdx++)
|
||||
@ -212,7 +283,7 @@ strLstExistsZ(const StringList *this, const char *cstring)
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -221,6 +292,13 @@ Wrapper for lstAdd()
|
||||
StringList *
|
||||
strLstAdd(StringList *this, const String *string)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
StringList *result = NULL;
|
||||
|
||||
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
|
||||
@ -229,7 +307,7 @@ strLstAdd(StringList *this, const String *string)
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -238,6 +316,13 @@ Add a zero-terminated string to the list
|
||||
StringList *
|
||||
strLstAddZ(StringList *this, const char *string)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, string);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
StringList *result = NULL;
|
||||
|
||||
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
|
||||
@ -246,7 +331,7 @@ strLstAddZ(StringList *this, const char *string)
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -255,7 +340,14 @@ Wrapper for lstGet()
|
||||
String *
|
||||
strLstGet(const StringList *this, unsigned int listIdx)
|
||||
{
|
||||
return *(String **)lstGet((List *)this, listIdx);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(UINT, listIdx);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRING, *(String **)lstGet((List *)this, listIdx));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -264,6 +356,33 @@ Join a list of strings into a single string using the specified separator
|
||||
String *
|
||||
strLstJoin(const StringList *this, const char *separator)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, separator);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(separator != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRING, strLstJoinQuote(this, separator, ""));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Join a list of strings into a single string using the specified separator and quote with specified quote character
|
||||
***********************************************************************************************************************************/
|
||||
String *
|
||||
strLstJoinQuote(const StringList *this, const char *separator, const char *quote)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, separator);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, quote);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(separator != NULL);
|
||||
FUNCTION_TEST_ASSERT(quote != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
String *join = strNew("");
|
||||
|
||||
for (unsigned int listIdx = 0; listIdx < strLstSize(this); listIdx++)
|
||||
@ -274,10 +393,10 @@ strLstJoin(const StringList *this, const char *separator)
|
||||
if (strLstGet(this, listIdx) == NULL)
|
||||
strCat(join, "[NULL]");
|
||||
else
|
||||
strCat(join, strPtr(strLstGet(this, listIdx)));
|
||||
strCatFmt(join, "%s%s%s", quote, strPtr(strLstGet(this, listIdx)), quote);
|
||||
}
|
||||
|
||||
return join;
|
||||
FUNCTION_TEST_RESULT(STRING, join);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -286,8 +405,16 @@ Move the string list
|
||||
StringList *
|
||||
strLstMove(StringList *this, MemContext *parentNew)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, parentNew);
|
||||
|
||||
FUNCTION_TEST_ASSERT(parentNew != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
lstMove((List *)this, parentNew);
|
||||
return this;
|
||||
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -297,6 +424,12 @@ this array, though it is OK to modify the array itself.
|
||||
const char **
|
||||
strLstPtr(const StringList *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
const char **list = memNew(strLstSize(this) * sizeof(char *));
|
||||
|
||||
for (unsigned int listIdx = 0; listIdx < strLstSize(this); listIdx++)
|
||||
@ -307,7 +440,7 @@ strLstPtr(const StringList *this)
|
||||
list[listIdx] = strPtr(strLstGet(this, listIdx));
|
||||
}
|
||||
|
||||
return list;
|
||||
FUNCTION_TEST_RESULT(CONST_CHARPP, list);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -316,7 +449,13 @@ Wrapper for lstSize()
|
||||
unsigned int
|
||||
strLstSize(const StringList *this)
|
||||
{
|
||||
return lstSize((List *)this);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(UINT, lstSize((List *)this));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -325,18 +464,41 @@ Sort strings in alphabetical order
|
||||
static int
|
||||
sortAscComparator(const void *item1, const void *item2)
|
||||
{
|
||||
return strCmp(*(String **)item1, *(String **)item2);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VOIDP, item1);
|
||||
FUNCTION_TEST_PARAM(VOIDP, item2);
|
||||
|
||||
FUNCTION_TEST_ASSERT(item1 != NULL);
|
||||
FUNCTION_TEST_ASSERT(item2 != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(INT, strCmp(*(String **)item1, *(String **)item2));
|
||||
}
|
||||
|
||||
static int
|
||||
sortDescComparator(const void *item1, const void *item2)
|
||||
{
|
||||
return strCmp(*(String **)item2, *(String **)item1);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VOIDP, item1);
|
||||
FUNCTION_TEST_PARAM(VOIDP, item2);
|
||||
|
||||
FUNCTION_TEST_ASSERT(item1 != NULL);
|
||||
FUNCTION_TEST_ASSERT(item2 != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(INT, strCmp(*(String **)item2, *(String **)item1));
|
||||
}
|
||||
|
||||
StringList *
|
||||
strLstSort(StringList *this, SortOrder sortOrder)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(ENUM, sortOrder);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
switch (sortOrder)
|
||||
{
|
||||
case sortOrderAsc:
|
||||
@ -351,7 +513,32 @@ strLstSort(StringList *this, SortOrder sortOrder)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert to a zero-terminated string for logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
strLstToLog(const StringList *this, char *buffer, size_t bufferSize)
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
String *string = NULL;
|
||||
|
||||
if (this == NULL)
|
||||
string = strNew("null");
|
||||
else
|
||||
string = strNewFmt("{[%s]}", strPtr(strLstJoinQuote(this, ", ", "\"")));
|
||||
|
||||
result = (size_t)snprintf(buffer, bufferSize, "%s", strPtr(string));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -360,5 +547,11 @@ Wrapper for lstFree()
|
||||
void
|
||||
strLstFree(StringList *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
lstFree((List *)this);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ bool strLstExists(const StringList *this, const String *string);
|
||||
bool strLstExistsZ(const StringList *this, const char *cstring);
|
||||
String *strLstGet(const StringList *this, unsigned int listIdx);
|
||||
String *strLstJoin(const StringList *this, const char *separator);
|
||||
String *strLstJoinQuote(const StringList *this, const char *separator, const char *quote);
|
||||
StringList * strLstMove(StringList *this, MemContext *parentNew);
|
||||
const char **strLstPtr(const StringList *this);
|
||||
unsigned int strLstSize(const StringList *this);
|
||||
@ -46,4 +47,14 @@ StringList *strLstSort(StringList *this, SortOrder sortOrder);
|
||||
|
||||
void strLstFree(StringList *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t strLstToLog(const StringList *this, char *buffer, size_t bufferSize);
|
||||
|
||||
#define FUNCTION_DEBUG_STRING_LIST_TYPE \
|
||||
StringList *
|
||||
#define FUNCTION_DEBUG_STRING_LIST_FORMAT(value, buffer, bufferSize) \
|
||||
strLstToLog(value, buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -8,7 +8,9 @@ Variant Data Type
|
||||
#include <strings.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/type/convert.h"
|
||||
#include "common/type/variant.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -40,9 +42,14 @@ New variant of any supported type
|
||||
static Variant *
|
||||
varNewInternal(VariantType type, void *data, size_t dataSize)
|
||||
{
|
||||
// Make sure there is some data to store
|
||||
ASSERT_DEBUG(dataSize > 0);
|
||||
ASSERT_DEBUG(data != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, type);
|
||||
FUNCTION_TEST_PARAM(VOIDP, data);
|
||||
FUNCTION_TEST_PARAM(SIZE, dataSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(data != NULL);
|
||||
FUNCTION_TEST_ASSERT(dataSize > 0);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Allocate memory for the variant and set the type
|
||||
Variant *this = memNew(sizeof(Variant) + dataSize);
|
||||
@ -52,7 +59,7 @@ varNewInternal(VariantType type, void *data, size_t dataSize)
|
||||
// Copy data
|
||||
memcpy((unsigned char *)this + sizeof(Variant), data, dataSize);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(VARIANT, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -61,7 +68,13 @@ Get a pointer to the data stored in the variant. This hides the complicated poi
|
||||
static void *
|
||||
varData(const Variant *this)
|
||||
{
|
||||
return (void *)((unsigned char *)this + sizeof(Variant));
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(VOIDP, (void *)((unsigned char *)this + sizeof(Variant)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -70,6 +83,10 @@ Duplicate a variant
|
||||
Variant *
|
||||
varDup(const Variant *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
Variant *result = NULL;
|
||||
|
||||
if (this != NULL)
|
||||
@ -121,7 +138,7 @@ varDup(const Variant *this)
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(VARIANT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -130,6 +147,11 @@ Test if variants are equal
|
||||
bool
|
||||
varEq(const Variant *this1, const Variant *this2)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this1);
|
||||
FUNCTION_TEST_PARAM(VARIANT, this2);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
// Test if both variants are non-null
|
||||
@ -180,7 +202,7 @@ varEq(const Variant *this1, const Variant *this2)
|
||||
else
|
||||
result = this1 == NULL && this2 == NULL;
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -189,7 +211,13 @@ Get variant type
|
||||
VariantType
|
||||
varType(const Variant *this)
|
||||
{
|
||||
return this->type;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(ENUM, this->type);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -198,7 +226,11 @@ New bool variant
|
||||
Variant *
|
||||
varNewBool(bool data)
|
||||
{
|
||||
return varNewInternal(varTypeBool, (void *)&data, sizeof(data));
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(BOOL, data);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT, varNewInternal(varTypeBool, (void *)&data, sizeof(data)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -207,12 +239,15 @@ Return bool
|
||||
bool
|
||||
varBool(const Variant *this)
|
||||
{
|
||||
// Only valid for int
|
||||
if (this->type != varTypeBool)
|
||||
THROW(AssertError, "variant type is not bool");
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
|
||||
// Get the int
|
||||
return *((bool *)varData(this));
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this->type == varTypeBool);
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, *((bool *)varData(this)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -221,6 +256,12 @@ Return bool regardless of variant type
|
||||
bool
|
||||
varBoolForce(const Variant *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
switch (this->type)
|
||||
@ -268,7 +309,7 @@ varBoolForce(const Variant *this)
|
||||
THROW_FMT(FormatError, "unable to force %s to %s", variantTypeName[this->type], variantTypeName[varTypeBool]);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -277,7 +318,11 @@ New double variant
|
||||
Variant *
|
||||
varNewDbl(double data)
|
||||
{
|
||||
return varNewInternal(varTypeDouble, (unsigned char *)&data, sizeof(data));
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(DOUBLE, data);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT, varNewInternal(varTypeDouble, (unsigned char *)&data, sizeof(data)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -286,12 +331,15 @@ Return double
|
||||
double
|
||||
varDbl(const Variant *this)
|
||||
{
|
||||
// Only valid for double
|
||||
if (this->type != varTypeDouble)
|
||||
THROW(AssertError, "variant type is not double");
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
|
||||
// Get the int
|
||||
return *((double *)varData(this));
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this->type == varTypeDouble);
|
||||
|
||||
FUNCTION_TEST_RESULT(DOUBLE, *((double *)varData(this)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -300,6 +348,12 @@ Return double regardless of variant type
|
||||
double
|
||||
varDblForce(const Variant *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
double result = 0;
|
||||
|
||||
switch (this->type)
|
||||
@ -330,15 +384,7 @@ varDblForce(const Variant *this)
|
||||
|
||||
case varTypeString:
|
||||
{
|
||||
sscanf(strPtr(varStr(this)), "%lf", &result);
|
||||
|
||||
if (result == 0 && strcmp(strPtr(varStr(this)), "0") != 0)
|
||||
{
|
||||
THROW_FMT(
|
||||
FormatError, "unable to force %s '%s' to %s", variantTypeName[this->type], strPtr(varStr(this)),
|
||||
variantTypeName[varTypeDouble]);
|
||||
}
|
||||
|
||||
result = cvtZToDouble(strPtr(varStr(this)));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -346,7 +392,7 @@ varDblForce(const Variant *this)
|
||||
THROW_FMT(FormatError, "unable to force %s to %s", variantTypeName[this->type], variantTypeName[varTypeDouble]);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(DOUBLE, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -355,7 +401,11 @@ New int variant
|
||||
Variant *
|
||||
varNewInt(int data)
|
||||
{
|
||||
return varNewInternal(varTypeInt, (void *)&data, sizeof(data));
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INT, data);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT, varNewInternal(varTypeInt, (void *)&data, sizeof(data)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -364,12 +414,15 @@ Return int
|
||||
int
|
||||
varInt(const Variant *this)
|
||||
{
|
||||
// Only valid for int
|
||||
if (this->type != varTypeInt)
|
||||
THROW(AssertError, "variant type is not int");
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
|
||||
// Get the int
|
||||
return *((int *)varData(this));
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this->type == varTypeInt);
|
||||
|
||||
FUNCTION_TEST_RESULT(INT, *((int *)varData(this)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -378,6 +431,12 @@ Return int regardless of variant type
|
||||
int
|
||||
varIntForce(const Variant *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
int result = 0;
|
||||
|
||||
switch (this->type)
|
||||
@ -409,11 +468,7 @@ varIntForce(const Variant *this)
|
||||
|
||||
case varTypeString:
|
||||
{
|
||||
result = atoi(strPtr(varStr(this)));
|
||||
|
||||
if (result == 0 && strcmp(strPtr(varStr(this)), "0") != 0)
|
||||
THROW_FMT(FormatError, "unable to convert str '%s' to int", strPtr(varStr(this)));
|
||||
|
||||
result = cvtZToInt(strPtr(varStr(this)));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -421,7 +476,7 @@ varIntForce(const Variant *this)
|
||||
THROW_FMT(FormatError, "unable to force %s to %s", variantTypeName[this->type], variantTypeName[varTypeInt]);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(INT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -430,7 +485,11 @@ New int64 variant
|
||||
Variant *
|
||||
varNewInt64(int64_t data)
|
||||
{
|
||||
return varNewInternal(varTypeInt64, (void *)&data, sizeof(data));
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INT64, data);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT, varNewInternal(varTypeInt64, (void *)&data, sizeof(data)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -439,12 +498,15 @@ Return int64
|
||||
int64_t
|
||||
varInt64(const Variant *this)
|
||||
{
|
||||
// Only valid for int
|
||||
if (this->type != varTypeInt64)
|
||||
THROW_FMT(AssertError, "variant type is not %s", variantTypeName[varTypeInt64]);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
|
||||
// Get the int
|
||||
return *((int64_t *)varData(this));
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this->type == varTypeInt64);
|
||||
|
||||
FUNCTION_TEST_RESULT(INT64, *((int64_t *)varData(this)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -453,6 +515,12 @@ Return int64 regardless of variant type
|
||||
int64_t
|
||||
varInt64Force(const Variant *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
int64_t result = 0;
|
||||
|
||||
switch (this->type)
|
||||
@ -477,16 +545,7 @@ varInt64Force(const Variant *this)
|
||||
|
||||
case varTypeString:
|
||||
{
|
||||
result = atoll(strPtr(varStr(this)));
|
||||
|
||||
char buffer[32];
|
||||
snprintf(buffer, sizeof(buffer), "%" PRId64, result);
|
||||
|
||||
if (strcmp(strPtr(varStr(this)), buffer) != 0)
|
||||
THROW_FMT(
|
||||
FormatError, "unable to convert %s '%s' to %s", variantTypeName[varTypeString], strPtr(varStr(this)),
|
||||
variantTypeName[varTypeInt64]);
|
||||
|
||||
result = cvtZToInt64(strPtr(varStr(this)));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -494,7 +553,7 @@ varInt64Force(const Variant *this)
|
||||
THROW_FMT(FormatError, "unable to force %s to %s", variantTypeName[this->type], variantTypeName[varTypeInt64]);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(INT64, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -503,9 +562,12 @@ New key/value variant
|
||||
Variant *
|
||||
varNewKv()
|
||||
{
|
||||
// Create the variant
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
// Create a new kv for the variant
|
||||
KeyValue *data = kvNew();
|
||||
return varNewInternal(varTypeKeyValue, (void *)&data, sizeof(data));
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT, varNewInternal(varTypeKeyValue, (void *)&data, sizeof(data)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -514,19 +576,19 @@ Return key/value
|
||||
KeyValue *
|
||||
varKv(const Variant *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
KeyValue *result = NULL;
|
||||
|
||||
if (this != NULL)
|
||||
{
|
||||
// Only valid for key/value
|
||||
if (this->type != varTypeKeyValue)
|
||||
THROW(AssertError, "variant type is not 'KeyValue'");
|
||||
|
||||
// Get the string
|
||||
ASSERT(this->type == varTypeKeyValue);
|
||||
result = *((KeyValue **)varData(this));
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(KEY_VALUE, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -535,13 +597,16 @@ New string variant
|
||||
Variant *
|
||||
varNewStr(const String *data)
|
||||
{
|
||||
// Make sure the string is not NULL
|
||||
if (data == NULL)
|
||||
THROW(AssertError, "string variant cannot be NULL");
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, data);
|
||||
|
||||
// Create the variant
|
||||
FUNCTION_TEST_ASSERT(data != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Create a copy of the string for the variant
|
||||
String *dataCopy = strDup(data);
|
||||
return varNewInternal(varTypeString, (void *)&dataCopy, sizeof(dataCopy));
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT, varNewInternal(varTypeString, (void *)&dataCopy, sizeof(dataCopy)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -550,13 +615,16 @@ New string variant from a zero-terminated string
|
||||
Variant *
|
||||
varNewStrZ(const char *data)
|
||||
{
|
||||
// Make sure the string is not NULL
|
||||
if (data == NULL)
|
||||
THROW(AssertError, "zero-terminated string cannot be NULL");
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRINGZ, data);
|
||||
|
||||
// Create the variant
|
||||
FUNCTION_TEST_ASSERT(data != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Create a string for the variant
|
||||
String *dataCopy = strNew(data);
|
||||
return varNewInternal(varTypeString, (void *)&dataCopy, sizeof(dataCopy));
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT, varNewInternal(varTypeString, (void *)&dataCopy, sizeof(dataCopy)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -565,19 +633,19 @@ Return string
|
||||
String *
|
||||
varStr(const Variant *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
String *result = NULL;
|
||||
|
||||
if (this != NULL)
|
||||
{
|
||||
// Only valid for strings
|
||||
if (this->type != varTypeString)
|
||||
THROW(AssertError, "variant type is not string");
|
||||
|
||||
// Get the string
|
||||
ASSERT(this->type == varTypeString);
|
||||
result = *((String **)varData(this));
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(STRING, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -586,60 +654,51 @@ Return string regardless of variant type
|
||||
String *
|
||||
varStrForce(const Variant *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
String *result = NULL;
|
||||
|
||||
switch (varType(this))
|
||||
{
|
||||
case varTypeBool:
|
||||
{
|
||||
if (varBool(this))
|
||||
result = strNew("true");
|
||||
else
|
||||
result = strNew("false");
|
||||
char working[6];
|
||||
|
||||
cvtBoolToZ(varBool(this), working, sizeof(working));
|
||||
result = strNew(working);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case varTypeDouble:
|
||||
{
|
||||
// Convert to a string
|
||||
String *working = strNewFmt("%f", varDbl(this));
|
||||
char working[64];
|
||||
|
||||
// Any formatted double should be at least 8 characters, i.e. 0.000000
|
||||
ASSERT_DEBUG(strSize(working) >= 8);
|
||||
// Any formatted double should have a decimal point
|
||||
ASSERT_DEBUG(strchr(strPtr(working), '.') != NULL);
|
||||
|
||||
// Strip off any final 0s and the decimal point if there are no non-zero digits after it
|
||||
const char *begin = strPtr(working);
|
||||
const char *end = begin + strSize(working) - 1;
|
||||
|
||||
while (*end == '0' || *end == '.')
|
||||
{
|
||||
// It should not be possible to go past the beginning because format "%f" will always write a decimal point
|
||||
ASSERT_DEBUG(end > begin);
|
||||
|
||||
end--;
|
||||
|
||||
if (*(end + 1) == '.')
|
||||
break;
|
||||
}
|
||||
|
||||
result = strNewN(begin, (size_t)(end - begin + 1));
|
||||
strFree(working);
|
||||
cvtDoubleToZ(varDbl(this), working, sizeof(working));
|
||||
result = strNew(working);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case varTypeInt:
|
||||
{
|
||||
result = strNewFmt("%d", varInt(this));
|
||||
char working[64];
|
||||
|
||||
cvtIntToZ(varInt(this), working, sizeof(working));
|
||||
result = strNew(working);
|
||||
break;
|
||||
}
|
||||
|
||||
case varTypeInt64:
|
||||
{
|
||||
result = strNewFmt("%" PRId64, varInt64(this));
|
||||
char working[64];
|
||||
|
||||
cvtInt64ToZ(varInt64(this), working, sizeof(working));
|
||||
result = strNew(working);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -654,7 +713,7 @@ varStrForce(const Variant *this)
|
||||
THROW_FMT(FormatError, "unable to force %s to %s", variantTypeName[this->type], variantTypeName[varTypeString]);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(STRING, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -663,20 +722,16 @@ New variant list variant
|
||||
Variant *
|
||||
varNewVarLst(const VariantList *data)
|
||||
{
|
||||
// Create the variant
|
||||
VariantList *dataCopy = varLstDup(data);
|
||||
return varNewInternal(varTypeVariantList, (void *)&dataCopy, sizeof(dataCopy));
|
||||
}
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT_LIST, data);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
New empty variant list variant
|
||||
***********************************************************************************************************************************/
|
||||
Variant *
|
||||
varNewVarLstEmpty()
|
||||
{
|
||||
// Create the variant
|
||||
VariantList *data = varLstNew();
|
||||
return varNewInternal(varTypeVariantList, (void *)&data, sizeof(data));
|
||||
FUNCTION_TEST_ASSERT(data != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Copy variant list for the variant
|
||||
VariantList *dataCopy = varLstDup(data);
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT, varNewInternal(varTypeVariantList, (void *)&dataCopy, sizeof(dataCopy)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -685,18 +740,77 @@ Return key/value
|
||||
VariantList *
|
||||
varVarLst(const Variant *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
VariantList *result = NULL;
|
||||
|
||||
if (this != NULL)
|
||||
{
|
||||
// Only valid for key/value
|
||||
if (this->type != varTypeVariantList)
|
||||
THROW_FMT(AssertError, "variant type is not '%s'", variantTypeName[varTypeVariantList]);
|
||||
|
||||
// Get the string
|
||||
ASSERT(this->type == varTypeVariantList);
|
||||
result = *((VariantList **)varData(this));
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT_LIST, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert variant to a zero-terminated string for logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
varToLog(const Variant *this, char *buffer, size_t bufferSize)
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
String *string = NULL;
|
||||
|
||||
if (this == NULL)
|
||||
{
|
||||
string = strNew("null");
|
||||
result = (size_t)snprintf(buffer, bufferSize, "%s", strPtr(string));
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (varType(this))
|
||||
{
|
||||
case varTypeString:
|
||||
{
|
||||
String *temp = varStrForce(this);
|
||||
string = strNewFmt("\"%s\"", strPtr(temp));
|
||||
strFree(temp);
|
||||
break;
|
||||
}
|
||||
|
||||
case varTypeKeyValue:
|
||||
{
|
||||
string = strNew("KeyValue");
|
||||
break;
|
||||
}
|
||||
|
||||
case varTypeVariantList:
|
||||
{
|
||||
string = strNew("VariantList");
|
||||
break;
|
||||
}
|
||||
|
||||
case varTypeBool:
|
||||
case varTypeDouble:
|
||||
case varTypeInt:
|
||||
case varTypeInt64:
|
||||
{
|
||||
string = varStrForce(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result = (size_t)snprintf(buffer, bufferSize, "{%s}", strPtr(string));
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -706,6 +820,10 @@ Free variant
|
||||
void
|
||||
varFree(Variant *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this != NULL)
|
||||
{
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
@ -742,4 +860,6 @@ varFree(Variant *this)
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -57,7 +57,6 @@ String *varStr(const Variant *this);
|
||||
String *varStrForce(const Variant *this);
|
||||
|
||||
Variant *varNewVarLst(const VariantList *data);
|
||||
Variant *varNewVarLstEmpty();
|
||||
VariantList *varVarLst(const Variant *this);
|
||||
|
||||
Variant *varDup(const Variant *this);
|
||||
@ -66,4 +65,19 @@ VariantType varType(const Variant *this);
|
||||
|
||||
void varFree(Variant *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t varToLog(const Variant *this, char *buffer, size_t bufferSize);
|
||||
|
||||
#define FUNCTION_DEBUG_CONST_VARIANT_TYPE \
|
||||
const FUNCTION_DEBUG_VARIANT_TYPE
|
||||
#define FUNCTION_DEBUG_CONST_VARIANT_FORMAT(value, buffer, bufferSize) \
|
||||
FUNCTION_DEBUG_VARIANT_FORMAT(value, buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_DEBUG_VARIANT_TYPE \
|
||||
Variant *
|
||||
#define FUNCTION_DEBUG_VARIANT_FORMAT(value, buffer, bufferSize) \
|
||||
varToLog(value, buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -5,6 +5,7 @@ Variant List Handler
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/type/list.h"
|
||||
#include "common/type/variantList.h"
|
||||
@ -15,7 +16,8 @@ Wrapper for lstNew()
|
||||
VariantList *
|
||||
varLstNew()
|
||||
{
|
||||
return (VariantList *)lstNew(sizeof(Variant *));
|
||||
FUNCTION_TEST_VOID();
|
||||
FUNCTION_TEST_RESULT(VARIANT_LIST, (VariantList *)lstNew(sizeof(Variant *)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -24,6 +26,10 @@ Create a variant list from a string list
|
||||
VariantList *
|
||||
varLstNewStrLst(const StringList *stringList)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, stringList);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
VariantList *result = NULL;
|
||||
|
||||
if (stringList != NULL)
|
||||
@ -34,7 +40,7 @@ varLstNewStrLst(const StringList *stringList)
|
||||
varLstAdd(result, varNewStr(strLstGet(stringList, listIdx)));
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(VARIANT_LIST, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -43,6 +49,10 @@ Duplicate a variant list
|
||||
VariantList *
|
||||
varLstDup(const VariantList *source)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT_LIST, source);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
VariantList *result = NULL;
|
||||
|
||||
if (source != NULL)
|
||||
@ -53,7 +63,7 @@ varLstDup(const VariantList *source)
|
||||
varLstAdd(result, varDup(varLstGet(source, listIdx)));
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(VARIANT_LIST, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -62,7 +72,14 @@ Wrapper for lstAdd()
|
||||
VariantList *
|
||||
varLstAdd(VariantList *this, Variant *data)
|
||||
{
|
||||
return (VariantList *)lstAdd((List *)this, &data);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT_LIST, this);
|
||||
FUNCTION_TEST_PARAM(VARIANT, data);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT_LIST, (VariantList *)lstAdd((List *)this, &data));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -71,7 +88,14 @@ Wrapper for lstGet()
|
||||
Variant *
|
||||
varLstGet(const VariantList *this, unsigned int listIdx)
|
||||
{
|
||||
return *(Variant **)lstGet((List *)this, listIdx);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT_LIST, this);
|
||||
FUNCTION_TEST_PARAM(UINT, listIdx);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT, *(Variant **)lstGet((List *)this, listIdx));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -80,7 +104,13 @@ Wrapper for lstSize()
|
||||
unsigned int
|
||||
varLstSize(const VariantList *this)
|
||||
{
|
||||
return lstSize((List *)this);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT_LIST, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(UINT, lstSize((List *)this));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -89,5 +119,11 @@ Wrapper for lstFree()
|
||||
void
|
||||
varLstFree(VariantList *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT_LIST, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
lstFree((List *)this);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -23,4 +23,12 @@ Variant *varLstGet(const VariantList *this, unsigned int listIdx);
|
||||
unsigned int varLstSize(const VariantList *this);
|
||||
void varLstFree(VariantList *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_VARIANT_LIST_TYPE \
|
||||
VariantList *
|
||||
#define FUNCTION_DEBUG_VARIANT_LIST_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "VariantList", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -1,6 +1,7 @@
|
||||
/***********************************************************************************************************************************
|
||||
Wait Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/time.h"
|
||||
#include "common/wait.h"
|
||||
@ -23,9 +24,11 @@ New wait handler
|
||||
Wait *
|
||||
waitNew(double waitTime)
|
||||
{
|
||||
// Make sure wait time is valid
|
||||
if (waitTime < 0.1 || waitTime > 999999.0)
|
||||
THROW(AssertError, "waitTime must be >= 0.1 and <= 999999.0");
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(DOUBLE, waitTime);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(waitTime >= 0.1 && waitTime <= 999999.0);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Allocate wait object
|
||||
Wait *this = NULL;
|
||||
@ -51,7 +54,7 @@ waitNew(double waitTime)
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_DEBUG_RESULT(WAIT, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -60,6 +63,12 @@ Wait and return whether the caller has more time left
|
||||
bool
|
||||
waitMore(Wait *this)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(WAIT, this);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
// If sleep is 0 then the wait time has already ended
|
||||
@ -93,7 +102,7 @@ waitMore(Wait *this)
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -102,6 +111,12 @@ Free the wait
|
||||
void
|
||||
waitFree(Wait *this)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(WAIT, this);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
if (this != NULL)
|
||||
memContextFree(this->memContext);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -16,4 +16,12 @@ Wait *waitNew(double waitTime);
|
||||
bool waitMore(Wait *this);
|
||||
void waitFree(Wait *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_WAIT_TYPE \
|
||||
Wait *
|
||||
#define FUNCTION_DEBUG_WAIT_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "Wait", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,7 @@ Command and Option Configuration
|
||||
#include <string.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
#include "common/memContext.h"
|
||||
#include "config/config.h"
|
||||
@ -71,39 +72,32 @@ Include the automatically generated configuration data
|
||||
***********************************************************************************************************************************/
|
||||
#include "config/config.auto.c"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Debug Asserts
|
||||
***********************************************************************************************************************************/
|
||||
// The command must be set
|
||||
#define ASSERT_DEBUG_COMMAND_SET() \
|
||||
ASSERT_DEBUG(cfgCommand() != cfgCmdNone)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Store the config memory context
|
||||
***********************************************************************************************************************************/
|
||||
MemContext *configMemContext = NULL;
|
||||
static MemContext *configMemContext = NULL;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Store the current command
|
||||
|
||||
This is generally set by the command parser but can also be set by during execute to change commands, i.e. backup -> expire.
|
||||
***********************************************************************************************************************************/
|
||||
ConfigCommand command = cfgCmdNone;
|
||||
static ConfigCommand command = cfgCmdNone;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Store the location of the executable
|
||||
***********************************************************************************************************************************/
|
||||
String *exe = NULL;
|
||||
static String *exe = NULL;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Was help requested for the command?
|
||||
***********************************************************************************************************************************/
|
||||
bool help = false;
|
||||
static bool help = false;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Store the list of parameters passed to the command
|
||||
***********************************************************************************************************************************/
|
||||
StringList *paramList = NULL;
|
||||
static StringList *paramList = NULL;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Map options names and indexes to option definitions.
|
||||
@ -127,6 +121,8 @@ Initialize or reinitialize the configuration data
|
||||
void
|
||||
cfgInit()
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
// Reset configuration
|
||||
command = cfgCmdNone;
|
||||
exe = NULL;
|
||||
@ -151,34 +147,32 @@ cfgInit()
|
||||
MEM_CONTEXT_NEW_END();
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get the current command
|
||||
Get/set the current command
|
||||
***********************************************************************************************************************************/
|
||||
ConfigCommand
|
||||
cfgCommand()
|
||||
{
|
||||
return command;
|
||||
FUNCTION_TEST_VOID();
|
||||
FUNCTION_TEST_RESULT(ENUM, command);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Set the current command
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
cfgCommandSet(ConfigCommand commandParam)
|
||||
{
|
||||
command = commandParam;
|
||||
}
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandParam);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Ensure that command id is valid
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
cfgCommandCheck(ConfigCommand commandId)
|
||||
{
|
||||
if (commandId >= CFG_COMMAND_TOTAL)
|
||||
THROW_FMT(AssertError, "command id %u invalid - must be >= 0 and < %d", commandId, CFG_COMMAND_TOTAL);
|
||||
FUNCTION_TEST_ASSERT(commandParam <= cfgCmdNone);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
command = commandParam;
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -187,13 +181,20 @@ Was help requested?
|
||||
bool
|
||||
cfgCommandHelp()
|
||||
{
|
||||
return help;
|
||||
FUNCTION_TEST_VOID();
|
||||
FUNCTION_TEST_RESULT(BOOL, help);
|
||||
}
|
||||
|
||||
void
|
||||
cfgCommandHelpSet(bool helpParam)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(BOOL, helpParam);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
help = helpParam;
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -205,16 +206,27 @@ be modified to do the mapping.
|
||||
ConfigDefineCommand
|
||||
cfgCommandDefIdFromId(ConfigCommand commandId)
|
||||
{
|
||||
cfgCommandCheck(commandId);
|
||||
return (ConfigDefineCommand)commandId;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandId < cfgCmdNone);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(ENUM, (ConfigDefineCommand)commandId);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get command id by name
|
||||
***********************************************************************************************************************************/
|
||||
int
|
||||
ConfigCommand
|
||||
cfgCommandId(const char *commandName)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRINGZ, commandName);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandName != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ConfigCommand commandId;
|
||||
|
||||
for (commandId = 0; commandId < cfgCmdNone; commandId++)
|
||||
@ -224,7 +236,7 @@ cfgCommandId(const char *commandName)
|
||||
if (commandId == cfgCmdNone)
|
||||
THROW_FMT(AssertError, "invalid command '%s'", commandName);
|
||||
|
||||
return commandId;
|
||||
FUNCTION_TEST_RESULT(ENUM, commandId);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -233,8 +245,13 @@ Get command name by id
|
||||
const char *
|
||||
cfgCommandName(ConfigCommand commandId)
|
||||
{
|
||||
cfgCommandCheck(commandId);
|
||||
return configCommandData[commandId].name;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandId < cfgCmdNone);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRINGZ, configCommandData[commandId].name);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -243,6 +260,8 @@ Command parameters, if any
|
||||
const StringList *
|
||||
cfgCommandParam()
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
if (paramList == NULL)
|
||||
{
|
||||
MEM_CONTEXT_BEGIN(configMemContext)
|
||||
@ -252,17 +271,25 @@ cfgCommandParam()
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
|
||||
return paramList;
|
||||
FUNCTION_TEST_RESULT(STRING_LIST, paramList);
|
||||
}
|
||||
|
||||
void
|
||||
cfgCommandParamSet(const StringList *param)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, param);
|
||||
|
||||
FUNCTION_TEST_ASSERT(param != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
MEM_CONTEXT_BEGIN(configMemContext)
|
||||
{
|
||||
paramList = strLstDup(param);
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -271,17 +298,26 @@ Command parameters, if any
|
||||
const String *
|
||||
cfgExe()
|
||||
{
|
||||
return exe;
|
||||
FUNCTION_TEST_VOID();
|
||||
FUNCTION_TEST_RESULT(STRING, exe);
|
||||
}
|
||||
|
||||
void
|
||||
cfgExeSet(const String *exeParam)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, exeParam);
|
||||
|
||||
FUNCTION_TEST_ASSERT(exeParam != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
MEM_CONTEXT_BEGIN(configMemContext)
|
||||
{
|
||||
exe = strDup(exeParam);
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -290,8 +326,11 @@ Does this command require an immediate lock?
|
||||
bool
|
||||
cfgLockRequired()
|
||||
{
|
||||
ASSERT_DEBUG_COMMAND_SET();
|
||||
return configCommandData[cfgCommand()].lockRequired;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_ASSERT(command != cfgCmdNone);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, configCommandData[cfgCommand()].lockRequired);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -300,8 +339,11 @@ Get the lock type required for this command
|
||||
LockType
|
||||
cfgLockType()
|
||||
{
|
||||
ASSERT_DEBUG_COMMAND_SET();
|
||||
return (LockType)configCommandData[cfgCommand()].lockType;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_ASSERT(command != cfgCmdNone);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(ENUM, (LockType)configCommandData[cfgCommand()].lockType);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -310,8 +352,11 @@ Does this command log to a file?
|
||||
bool
|
||||
cfgLogFile()
|
||||
{
|
||||
ASSERT_DEBUG_COMMAND_SET();
|
||||
return configCommandData[cfgCommand()].logFile;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_ASSERT(command != cfgCmdNone);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, configCommandData[cfgCommand()].logFile);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -320,8 +365,11 @@ Get default log level -- used for log messages that are common to all commands
|
||||
LogLevel
|
||||
cfgLogLevelDefault()
|
||||
{
|
||||
ASSERT_DEBUG_COMMAND_SET();
|
||||
return (LogLevel)configCommandData[cfgCommand()].logLevelDefault;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_ASSERT(command != cfgCmdNone);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(ENUM, (LogLevel)configCommandData[cfgCommand()].logLevelDefault);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -330,18 +378,11 @@ Get max stderr log level -- used to suppress error output for higher log levels,
|
||||
LogLevel
|
||||
cfgLogLevelStdErrMax()
|
||||
{
|
||||
ASSERT_DEBUG_COMMAND_SET();
|
||||
return (LogLevel)configCommandData[cfgCommand()].logLevelStdErrMax;
|
||||
}
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_ASSERT(command != cfgCmdNone);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Ensure that option id is valid
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
cfgOptionCheck(ConfigOption optionId)
|
||||
{
|
||||
if (optionId >= CFG_OPTION_TOTAL)
|
||||
THROW_FMT(AssertError, "option id %u invalid - must be >= 0 and < %d", optionId, CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_RESULT(ENUM, (LogLevel)configCommandData[cfgCommand()].logLevelStdErrMax);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -350,8 +391,13 @@ Get the option define for this option
|
||||
ConfigDefineOption
|
||||
cfgOptionDefIdFromId(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
return configOptionData[optionId].defineId;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(ENUM, configOptionData[optionId].defineId);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -360,7 +406,11 @@ Get/set option default
|
||||
const Variant *
|
||||
cfgOptionDefault(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (configOptionValue[optionId].defaultValue == NULL)
|
||||
{
|
||||
@ -410,12 +460,19 @@ cfgOptionDefault(ConfigOption optionId)
|
||||
}
|
||||
}
|
||||
|
||||
return configOptionValue[optionId].defaultValue;
|
||||
FUNCTION_TEST_RESULT(VARIANT, configOptionValue[optionId].defaultValue);
|
||||
}
|
||||
|
||||
void
|
||||
cfgOptionDefaultSet(ConfigOption optionId, const Variant *defaultValue)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
FUNCTION_TEST_PARAM(VARIANT, defaultValue);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
MEM_CONTEXT_BEGIN(configMemContext)
|
||||
{
|
||||
if (configOptionValue[optionId].defaultValue != NULL)
|
||||
@ -432,6 +489,8 @@ cfgOptionDefaultSet(ConfigOption optionId, const Variant *defaultValue)
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -440,8 +499,13 @@ Get index for option
|
||||
unsigned int
|
||||
cfgOptionIndex(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
return configOptionData[optionId].index;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(UINT, configOptionData[optionId].index);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -450,11 +514,19 @@ Get option id by name
|
||||
int
|
||||
cfgOptionId(const char *optionName)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRINGZ, optionName);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionName != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
int result = -1;
|
||||
|
||||
for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
|
||||
if (strcmp(optionName, configOptionData[optionId].name) == 0)
|
||||
return optionId;
|
||||
result = optionId;
|
||||
|
||||
return -1;
|
||||
FUNCTION_TEST_RESULT(INT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -463,8 +535,13 @@ Get total indexed values for option
|
||||
unsigned int
|
||||
cfgOptionIndexTotal(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
return cfgDefOptionIndexTotal(configOptionData[optionId].defineId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(UINT, cfgDefOptionIndexTotal(configOptionData[optionId].defineId));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -473,19 +550,26 @@ Get the id for this option define
|
||||
ConfigOption
|
||||
cfgOptionIdFromDefId(ConfigDefineOption optionDefId, unsigned int index)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
FUNCTION_TEST_PARAM(UINT, index);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_ASSERT(index < cfgDefOptionIndexTotal(optionDefId));
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Search for the option
|
||||
ConfigOption optionId;
|
||||
|
||||
for (optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
|
||||
for (optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++) // {uncoverable - only a bug in code gen lets this loop end}
|
||||
if (configOptionData[optionId].defineId == optionDefId)
|
||||
break;
|
||||
|
||||
// Error when not found
|
||||
if (optionId == CFG_OPTION_TOTAL)
|
||||
cfgDefOptionCheck(optionDefId);
|
||||
// If the mapping is not found then there is a bug in the code generator
|
||||
ASSERT_DEBUG(optionId != CFG_OPTION_TOTAL);
|
||||
|
||||
// Return with original index
|
||||
return optionId + index;
|
||||
FUNCTION_TEST_RESULT(ENUM, optionId + index);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -494,8 +578,13 @@ Get option name by id
|
||||
const char *
|
||||
cfgOptionName(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
return configOptionData[optionId].name;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRINGZ, configOptionData[optionId].name);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -504,15 +593,28 @@ Was the option negated?
|
||||
bool
|
||||
cfgOptionNegate(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
return configOptionValue[optionId].negate;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, configOptionValue[optionId].negate);
|
||||
}
|
||||
|
||||
void
|
||||
cfgOptionNegateSet(ConfigOption optionId, bool negate)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
FUNCTION_TEST_PARAM(BOOL, negate);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
configOptionValue[optionId].negate = negate;
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -521,15 +623,28 @@ Was the option reset?
|
||||
bool
|
||||
cfgOptionReset(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
return configOptionValue[optionId].reset;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, configOptionValue[optionId].reset);
|
||||
}
|
||||
|
||||
void
|
||||
cfgOptionResetSet(ConfigOption optionId, bool reset)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
FUNCTION_TEST_PARAM(BOOL, reset);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
configOptionValue[optionId].reset = reset;
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -538,69 +653,90 @@ Get and set config options
|
||||
const Variant *
|
||||
cfgOption(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
return configOptionValue[optionId].value;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(VARIANT, configOptionValue[optionId].value);
|
||||
}
|
||||
|
||||
bool
|
||||
cfgOptionBool(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, optionId);
|
||||
|
||||
if (varType(configOptionValue[optionId].value) != varTypeBool)
|
||||
THROW_FMT(AssertError, "option '%s' is not type 'bool'", cfgOptionName(optionId));
|
||||
FUNCTION_DEBUG_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_DEBUG_ASSERT(varType(configOptionValue[optionId].value) == varTypeBool);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
return varBool(configOptionValue[optionId].value);
|
||||
FUNCTION_DEBUG_RESULT(BOOL, varBool(configOptionValue[optionId].value));
|
||||
}
|
||||
|
||||
double
|
||||
cfgOptionDbl(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, optionId);
|
||||
|
||||
if (varType(configOptionValue[optionId].value) != varTypeDouble)
|
||||
THROW_FMT(AssertError, "option '%s' is not type 'double'", cfgOptionName(optionId));
|
||||
FUNCTION_DEBUG_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_DEBUG_ASSERT(varType(configOptionValue[optionId].value) == varTypeDouble);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
return varDbl(configOptionValue[optionId].value);
|
||||
FUNCTION_DEBUG_RESULT(DOUBLE, varDbl(configOptionValue[optionId].value));
|
||||
}
|
||||
|
||||
int
|
||||
cfgOptionInt(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, optionId);
|
||||
|
||||
if (varType(configOptionValue[optionId].value) != varTypeInt64)
|
||||
THROW_FMT(AssertError, "option '%s' is not type 'int64'", cfgOptionName(optionId));
|
||||
FUNCTION_DEBUG_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_DEBUG_ASSERT(varType(configOptionValue[optionId].value) == varTypeInt64);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
return varIntForce(configOptionValue[optionId].value);
|
||||
FUNCTION_DEBUG_RESULT(INT, varIntForce(configOptionValue[optionId].value));
|
||||
}
|
||||
|
||||
int64_t
|
||||
cfgOptionInt64(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, optionId);
|
||||
|
||||
if (varType(configOptionValue[optionId].value) != varTypeInt64)
|
||||
THROW_FMT(AssertError, "option '%s' is not type 'int64'", cfgOptionName(optionId));
|
||||
FUNCTION_DEBUG_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_DEBUG_ASSERT(varType(configOptionValue[optionId].value) == varTypeInt64);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
return varInt64(configOptionValue[optionId].value);
|
||||
FUNCTION_DEBUG_RESULT(INT64, varInt64(configOptionValue[optionId].value));
|
||||
}
|
||||
|
||||
const KeyValue *
|
||||
cfgOptionKv(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, optionId);
|
||||
|
||||
if (varType(configOptionValue[optionId].value) != varTypeKeyValue)
|
||||
THROW_FMT(AssertError, "option '%s' is not type 'KeyValue'", cfgOptionName(optionId));
|
||||
FUNCTION_DEBUG_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_DEBUG_ASSERT(varType(configOptionValue[optionId].value) == varTypeKeyValue);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
return varKv(configOptionValue[optionId].value);
|
||||
FUNCTION_DEBUG_RESULT(KEY_VALUE, varKv(configOptionValue[optionId].value));
|
||||
}
|
||||
|
||||
const VariantList *
|
||||
cfgOptionLst(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_DEBUG_ASSERT(
|
||||
configOptionValue[optionId].value == NULL || varType(configOptionValue[optionId].value) == varTypeVariantList);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
if (configOptionValue[optionId].value == NULL)
|
||||
{
|
||||
@ -610,34 +746,39 @@ cfgOptionLst(ConfigOption optionId)
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
else if (varType(configOptionValue[optionId].value) != varTypeVariantList)
|
||||
THROW_FMT(AssertError, "option '%s' is not type 'VariantList'", cfgOptionName(optionId));
|
||||
|
||||
return varVarLst(configOptionValue[optionId].value);
|
||||
FUNCTION_DEBUG_RESULT(VARIANT_LIST, varVarLst(configOptionValue[optionId].value));
|
||||
}
|
||||
|
||||
const String *
|
||||
cfgOptionStr(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_DEBUG_ASSERT(
|
||||
configOptionValue[optionId].value == NULL || varType(configOptionValue[optionId].value) == varTypeString);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
const String *result = NULL;
|
||||
|
||||
if (configOptionValue[optionId].value != NULL)
|
||||
{
|
||||
if (varType(configOptionValue[optionId].value) != varTypeString)
|
||||
THROW_FMT(AssertError, "option '%s' is not type 'String'", cfgOptionName(optionId));
|
||||
|
||||
result = varStr(configOptionValue[optionId].value);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(CONST_STRING, result);
|
||||
}
|
||||
|
||||
void
|
||||
cfgOptionSet(ConfigOption optionId, ConfigSource source, const Variant *value)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
FUNCTION_TEST_PARAM(ENUM, source);
|
||||
FUNCTION_TEST_PARAM(VARIANT, value);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
MEM_CONTEXT_BEGIN(configMemContext)
|
||||
{
|
||||
@ -720,6 +861,8 @@ cfgOptionSet(ConfigOption optionId, ConfigSource source, const Variant *value)
|
||||
varFree(valueOld);
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -728,8 +871,13 @@ How was the option set (default, param, config)?
|
||||
ConfigSource
|
||||
cfgOptionSource(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
return configOptionValue[optionId].source;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(ENUM, configOptionValue[optionId].source);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -738,8 +886,13 @@ Is the option valid for the command and set?
|
||||
bool
|
||||
cfgOptionTest(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
return cfgOptionValid(optionId) && configOptionValue[optionId].value != NULL;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, cfgOptionValid(optionId) && configOptionValue[optionId].value != NULL);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -748,13 +901,26 @@ Is the option valid for this command?
|
||||
bool
|
||||
cfgOptionValid(ConfigOption optionId)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
return configOptionValue[optionId].valid;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, configOptionValue[optionId].valid);
|
||||
}
|
||||
|
||||
void
|
||||
cfgOptionValidSet(ConfigOption optionId, bool valid)
|
||||
{
|
||||
cfgOptionCheck(optionId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionId);
|
||||
FUNCTION_TEST_PARAM(BOOL, valid);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionId < CFG_OPTION_TOTAL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
configOptionValue[optionId].valid = valid;
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ void cfgInit();
|
||||
ConfigDefineCommand cfgCommandDefIdFromId(ConfigCommand commandId);
|
||||
bool cfgCommandHelp();
|
||||
void cfgCommandHelpSet(bool helpParam);
|
||||
int cfgCommandId(const char *commandName);
|
||||
ConfigCommand cfgCommandId(const char *commandName);
|
||||
void cfgCommandParamSet(const StringList *param);
|
||||
void cfgCommandSet(ConfigCommand commandParam);
|
||||
|
||||
|
@ -6,6 +6,7 @@ Command and Option Configuration Definition
|
||||
#include <string.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
#include "config/define.h"
|
||||
|
||||
@ -180,6 +181,21 @@ cfgDefDataFind(
|
||||
ConfigDefineDataType typeFind, ConfigDefineCommand commandDefId, const void **dataList, bool *dataDefFound, int *dataDef,
|
||||
const void ***dataDefList, unsigned int *dataDefListSize)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, typeFind);
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(VOIDPP, dataList);
|
||||
FUNCTION_TEST_PARAM(BOOLP, dataDefFound);
|
||||
FUNCTION_TEST_PARAM(INTP, dataDef);
|
||||
FUNCTION_TEST_PARAM(VOIDPP, dataDefList);
|
||||
FUNCTION_TEST_PARAM(VOIDPP, dataDefListSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(dataDefFound != NULL);
|
||||
FUNCTION_TEST_ASSERT(dataDef != NULL);
|
||||
FUNCTION_TEST_ASSERT(dataDefList != NULL);
|
||||
FUNCTION_TEST_ASSERT(dataDefListSize != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
*dataDefFound = false;
|
||||
|
||||
// Only proceed if there is data
|
||||
@ -227,6 +243,8 @@ cfgDefDataFind(
|
||||
}
|
||||
while(type != configDefDataTypeEnd);
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
#define CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, type) \
|
||||
@ -244,37 +262,15 @@ Command and option define totals
|
||||
unsigned int
|
||||
cfgDefCommandTotal()
|
||||
{
|
||||
return sizeof(configDefineCommandData) / sizeof(ConfigDefineCommandData);
|
||||
FUNCTION_TEST_VOID();
|
||||
FUNCTION_TEST_RESULT(UINT, sizeof(configDefineCommandData) / sizeof(ConfigDefineCommandData));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
cfgDefOptionTotal()
|
||||
{
|
||||
return sizeof(configDefineOptionData) / sizeof(ConfigDefineOptionData);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Check that command and option ids are valid
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
cfgDefCommandCheck(ConfigDefineCommand commandDefId)
|
||||
{
|
||||
if (commandDefId >= cfgDefCommandTotal())
|
||||
THROW_FMT(AssertError, "command def id %u invalid - must be >= 0 and < %u", commandDefId, cfgDefCommandTotal());
|
||||
}
|
||||
|
||||
void
|
||||
cfgDefOptionCheck(ConfigDefineOption optionDefId)
|
||||
{
|
||||
if (optionDefId >= cfgDefOptionTotal())
|
||||
THROW_FMT(AssertError, "option def id %u invalid - must be >= 0 and < %u", optionDefId, cfgDefOptionTotal());
|
||||
}
|
||||
|
||||
static void
|
||||
cfgDefCommandOptionCheck(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandCheck(commandDefId);
|
||||
cfgDefOptionCheck(optionDefId);
|
||||
FUNCTION_TEST_VOID();
|
||||
FUNCTION_TEST_RESULT(UINT, sizeof(configDefineOptionData) / sizeof(ConfigDefineOptionData));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -283,8 +279,13 @@ Command help description
|
||||
const char *
|
||||
cfgDefCommandHelpDescription(ConfigDefineCommand commandDefId)
|
||||
{
|
||||
cfgDefCommandCheck(commandDefId);
|
||||
return configDefineCommandData[commandDefId].helpDescription;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRINGZ, configDefineCommandData[commandDefId].helpDescription);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -293,8 +294,13 @@ Command help summary
|
||||
const char *
|
||||
cfgDefCommandHelpSummary(ConfigDefineCommand commandDefId)
|
||||
{
|
||||
cfgDefCommandCheck(commandDefId);
|
||||
return configDefineCommandData[commandDefId].helpSummary;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRINGZ, configDefineCommandData[commandDefId].helpSummary);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -303,47 +309,76 @@ Option allow lists
|
||||
bool
|
||||
cfgDefOptionAllowList(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeAllowList);
|
||||
|
||||
return dataDefFound;
|
||||
FUNCTION_TEST_RESULT(BOOL, dataDefFound);
|
||||
}
|
||||
|
||||
const char *
|
||||
cfgDefOptionAllowListValue(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId, unsigned int valueId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
FUNCTION_TEST_PARAM(UINT, valueId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_ASSERT(valueId < cfgDefOptionAllowListValueTotal(commandDefId, optionDefId));
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeAllowList);
|
||||
|
||||
if (valueId >= dataDefListSize)
|
||||
THROW_FMT(AssertError, "value id %u invalid - must be >= 0 and < %u", valueId, dataDefListSize);
|
||||
|
||||
return (char *)dataDefList[valueId];
|
||||
FUNCTION_TEST_RESULT(STRINGZ, (char *)dataDefList[valueId]);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
cfgDefOptionAllowListValueTotal(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeAllowList);
|
||||
|
||||
return dataDefListSize;
|
||||
FUNCTION_TEST_RESULT(UINT, dataDefListSize);
|
||||
}
|
||||
|
||||
// Check if the value matches a value in the allow list
|
||||
bool
|
||||
cfgDefOptionAllowListValueValid(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId, const char *value)
|
||||
{
|
||||
ASSERT_DEBUG(value != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, value);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_ASSERT(value != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (unsigned int valueIdx = 0; valueIdx < cfgDefOptionAllowListValueTotal(commandDefId, optionDefId); valueIdx++)
|
||||
{
|
||||
if (strcmp(value, cfgDefOptionAllowListValue(commandDefId, optionDefId, valueIdx)) == 0)
|
||||
return true;
|
||||
result = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -352,31 +387,51 @@ Allow range
|
||||
bool
|
||||
cfgDefOptionAllowRange(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeAllowRange);
|
||||
|
||||
return dataDefFound;
|
||||
FUNCTION_TEST_RESULT(BOOL, dataDefFound);
|
||||
}
|
||||
|
||||
double
|
||||
cfgDefOptionAllowRangeMax(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeAllowRange);
|
||||
|
||||
return ((double)(((int64_t)(intptr_t)dataDefList[2]) + (((int64_t)(intptr_t)dataDefList[3]) * 1000000000L))) / 100;
|
||||
FUNCTION_TEST_RESULT(
|
||||
DOUBLE, ((double)(((int64_t)(intptr_t)dataDefList[2]) + (((int64_t)(intptr_t)dataDefList[3]) * 1000000000L))) / 100);
|
||||
}
|
||||
|
||||
double
|
||||
cfgDefOptionAllowRangeMin(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeAllowRange);
|
||||
|
||||
return ((double)(((int64_t)(intptr_t)dataDefList[0]) + (((int64_t)(intptr_t)dataDefList[1]) * 1000000000L))) / 100;
|
||||
FUNCTION_TEST_RESULT(
|
||||
DOUBLE, ((double)(((int64_t)(intptr_t)dataDefList[0]) + (((int64_t)(intptr_t)dataDefList[1]) * 1000000000L))) / 100);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -385,14 +440,22 @@ Default value for the option
|
||||
const char *
|
||||
cfgDefOptionDefault(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeDefault);
|
||||
|
||||
if (dataDefFound)
|
||||
return (char *)dataDefList[0];
|
||||
char *result = NULL;
|
||||
|
||||
return NULL;
|
||||
if (dataDefFound)
|
||||
result = (char *)dataDefList[0];
|
||||
|
||||
FUNCTION_TEST_RESULT(STRINGZ, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -401,57 +464,92 @@ Dependencies and depend lists
|
||||
bool
|
||||
cfgDefOptionDepend(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeDepend);
|
||||
|
||||
return dataDefFound;
|
||||
FUNCTION_TEST_RESULT(BOOL, dataDefFound);
|
||||
}
|
||||
|
||||
ConfigDefineOption
|
||||
cfgDefOptionDependOption(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeDepend);
|
||||
|
||||
return (ConfigDefineOption)dataDef;
|
||||
FUNCTION_TEST_RESULT(ENUM, (ConfigDefineOption)dataDef);
|
||||
}
|
||||
|
||||
const char *
|
||||
cfgDefOptionDependValue(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId, unsigned int valueId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
FUNCTION_TEST_PARAM(UINT, valueId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_ASSERT(valueId < cfgDefOptionDependValueTotal(commandDefId, optionDefId));
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeDepend);
|
||||
|
||||
if (valueId >= dataDefListSize)
|
||||
THROW_FMT(AssertError, "value id %u invalid - must be >= 0 and < %u", valueId, dataDefListSize);
|
||||
|
||||
return (char *)dataDefList[valueId];
|
||||
FUNCTION_TEST_RESULT(STRINGZ, (char *)dataDefList[valueId]);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
cfgDefOptionDependValueTotal(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeDepend);
|
||||
|
||||
return dataDefListSize;
|
||||
FUNCTION_TEST_RESULT(UINT, dataDefListSize);
|
||||
}
|
||||
|
||||
// Check if the value matches a value in the allow list
|
||||
bool
|
||||
cfgDefOptionDependValueValid(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId, const char *value)
|
||||
{
|
||||
ASSERT_DEBUG(value != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, value);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_ASSERT(value != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (unsigned int valueIdx = 0; valueIdx < cfgDefOptionDependValueTotal(commandDefId, optionDefId); valueIdx++)
|
||||
{
|
||||
if (strcmp(value, cfgDefOptionDependValue(commandDefId, optionDefId, valueIdx)) == 0)
|
||||
return true;
|
||||
result = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -460,14 +558,22 @@ Option help description
|
||||
const char *
|
||||
cfgDefOptionHelpDescription(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeHelpDescription);
|
||||
|
||||
if (dataDefFound)
|
||||
return (char *)dataDefList[0];
|
||||
const char *result = configDefineOptionData[optionDefId].helpDescription;
|
||||
|
||||
return configDefineOptionData[optionDefId].helpDescription;
|
||||
if (dataDefFound)
|
||||
result = (char *)dataDefList[0];
|
||||
|
||||
FUNCTION_TEST_RESULT(STRINGZ, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -476,34 +582,45 @@ Option help name alt
|
||||
bool
|
||||
cfgDefOptionHelpNameAlt(ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefOptionCheck(optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(-1, optionDefId, configDefDataTypeHelpNameAlt);
|
||||
|
||||
return dataDefFound;
|
||||
FUNCTION_TEST_RESULT(BOOL, dataDefFound);
|
||||
}
|
||||
|
||||
const char *
|
||||
cfgDefOptionHelpNameAltValue(ConfigDefineOption optionDefId, unsigned int valueId)
|
||||
{
|
||||
cfgDefOptionCheck(optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
FUNCTION_TEST_PARAM(UINT, valueId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_ASSERT(valueId < cfgDefOptionHelpNameAltValueTotal(optionDefId));
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(-1, optionDefId, configDefDataTypeHelpNameAlt);
|
||||
|
||||
if (valueId >= dataDefListSize)
|
||||
THROW_FMT(AssertError, "value id %u invalid - must be >= 0 and < %u", valueId, dataDefListSize);
|
||||
|
||||
return (char *)dataDefList[valueId];
|
||||
FUNCTION_TEST_RESULT(STRINGZ, (char *)dataDefList[valueId]);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
cfgDefOptionHelpNameAltValueTotal(ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefOptionCheck(optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(-1, optionDefId, configDefDataTypeHelpNameAlt);
|
||||
|
||||
return dataDefListSize;
|
||||
FUNCTION_TEST_RESULT(UINT, dataDefListSize);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -512,8 +629,13 @@ Option help section
|
||||
const char *
|
||||
cfgDefOptionHelpSection(ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefOptionCheck(optionDefId);
|
||||
return configDefineOptionData[optionDefId].helpSection;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRINGZ, configDefineOptionData[optionDefId].helpSection);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -522,14 +644,22 @@ Option help summary
|
||||
const char *
|
||||
cfgDefOptionHelpSummary(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeHelpSummary);
|
||||
|
||||
if (dataDefFound)
|
||||
return (char *)dataDefList[0];
|
||||
const char *result = configDefineOptionData[optionDefId].helpSummary;
|
||||
|
||||
return configDefineOptionData[optionDefId].helpSummary;
|
||||
if (dataDefFound)
|
||||
result = (char *)dataDefList[0];
|
||||
|
||||
FUNCTION_TEST_RESULT(STRINGZ, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -538,11 +668,19 @@ Get option id by name
|
||||
int
|
||||
cfgDefOptionId(const char *optionName)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRINGZ, optionName);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionName != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
int result = -1;
|
||||
|
||||
for (ConfigDefineOption optionDefId = 0; optionDefId < cfgDefOptionTotal(); optionDefId++)
|
||||
if (strcmp(optionName, configDefineOptionData[optionDefId].name) == 0)
|
||||
return optionDefId;
|
||||
result = optionDefId;
|
||||
|
||||
return -1;
|
||||
FUNCTION_TEST_RESULT(INT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -551,8 +689,13 @@ Get total indexed values for option
|
||||
unsigned int
|
||||
cfgDefOptionIndexTotal(ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefOptionCheck(optionDefId);
|
||||
return configDefineOptionData[optionDefId].indexTotal;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(UINT, configDefineOptionData[optionDefId].indexTotal);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -561,14 +704,22 @@ Is the option for internal use only?
|
||||
bool
|
||||
cfgDefOptionInternal(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeInternal);
|
||||
|
||||
if (dataDefFound)
|
||||
return (bool)dataDef;
|
||||
bool result = configDefineOptionData[optionDefId].internal;
|
||||
|
||||
return configDefineOptionData[optionDefId].internal;
|
||||
if (dataDefFound)
|
||||
result = (bool)dataDef;
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -577,8 +728,13 @@ Name of the option
|
||||
const char *
|
||||
cfgDefOptionName(ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefOptionCheck(optionDefId);
|
||||
return configDefineOptionData[optionDefId].name;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STRINGZ, configDefineOptionData[optionDefId].name);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -587,14 +743,20 @@ Option prefix for indexed options
|
||||
const char *
|
||||
cfgDefOptionPrefix(ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefOptionCheck(optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(-1, optionDefId, configDefDataTypePrefix);
|
||||
|
||||
if (dataDefFound)
|
||||
return (char *)dataDefList[0];
|
||||
char *result = NULL;
|
||||
|
||||
return NULL;
|
||||
if (dataDefFound)
|
||||
result = (char *)dataDefList[0];
|
||||
|
||||
FUNCTION_TEST_RESULT(STRINGZ, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -603,8 +765,13 @@ Does the option need to be protected from showing up in logs, command lines, etc
|
||||
bool
|
||||
cfgDefOptionSecure(ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefOptionCheck(optionDefId);
|
||||
return configDefineOptionData[optionDefId].secure;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, configDefineOptionData[optionDefId].secure);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -613,14 +780,22 @@ Is the option required
|
||||
bool
|
||||
cfgDefOptionRequired(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
CONFIG_DEFINE_DATA_FIND(commandDefId, optionDefId, configDefDataTypeRequired);
|
||||
|
||||
if (dataDefFound)
|
||||
return (bool)dataDef;
|
||||
bool result = configDefineOptionData[optionDefId].required;
|
||||
|
||||
return configDefineOptionData[optionDefId].required;
|
||||
if (dataDefFound)
|
||||
result = (bool)dataDef;
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -629,8 +804,13 @@ Get option section
|
||||
ConfigDefSection
|
||||
cfgDefOptionSection(ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefOptionCheck(optionDefId);
|
||||
return configDefineOptionData[optionDefId].section;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(ENUM, configDefineOptionData[optionDefId].section);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -639,8 +819,13 @@ Get option data type
|
||||
int
|
||||
cfgDefOptionType(ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefOptionCheck(optionDefId);
|
||||
return configDefineOptionData[optionDefId].type;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(INT, configDefineOptionData[optionDefId].type);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -649,6 +834,13 @@ Is the option valid for the command?
|
||||
bool
|
||||
cfgDefOptionValid(ConfigDefineCommand commandDefId, ConfigDefineOption optionDefId)
|
||||
{
|
||||
cfgDefCommandOptionCheck(commandDefId, optionDefId);
|
||||
return configDefineOptionData[optionDefId].commandValid & (1 << commandDefId);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, commandDefId);
|
||||
FUNCTION_TEST_PARAM(ENUM, optionDefId);
|
||||
|
||||
FUNCTION_TEST_ASSERT(commandDefId < cfgDefCommandTotal());
|
||||
FUNCTION_TEST_ASSERT(optionDefId < cfgDefOptionTotal());
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, configDefineOptionData[optionDefId].commandValid & (1 << commandDefId));
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ Configuration Load
|
||||
|
||||
#include "command/command.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/lock.h"
|
||||
#include "common/log.h"
|
||||
#include "config/config.h"
|
||||
@ -18,6 +19,8 @@ Load log settings
|
||||
void
|
||||
cfgLoadLogSetting()
|
||||
{
|
||||
FUNCTION_DEBUG_VOID(logLevelTrace);
|
||||
|
||||
// Initialize logging
|
||||
LogLevel logLevelConsole = logLevelOff;
|
||||
LogLevel logLevelStdErr = logLevelOff;
|
||||
@ -43,6 +46,8 @@ cfgLoadLogSetting()
|
||||
logTimestamp = cfgOptionBool(cfgOptLogTimestamp);
|
||||
|
||||
logInit(logLevelConsole, logLevelStdErr, logLevelFile, logTimestamp);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -51,6 +56,8 @@ Update options that have complex rules
|
||||
void
|
||||
cfgLoadUpdateOption()
|
||||
{
|
||||
FUNCTION_DEBUG_VOID(logLevelTrace);
|
||||
|
||||
// Set default for repo-host-cmd
|
||||
if (cfgOptionTest(cfgOptRepoHost) && cfgOptionSource(cfgOptRepoHostCmd) == cfgSourceDefault)
|
||||
cfgOptionDefaultSet(cfgOptRepoHostCmd, varNewStr(cfgExe()));
|
||||
@ -186,6 +193,8 @@ cfgLoadUpdateOption()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -194,6 +203,11 @@ Load the configuration
|
||||
void
|
||||
cfgLoad(unsigned int argListSize, const char *argList[])
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(UINT, argListSize);
|
||||
FUNCTION_DEBUG_PARAM(CHARPY, argList);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// Parse config from command line and config file
|
||||
@ -209,12 +223,8 @@ cfgLoad(unsigned int argListSize, const char *argList[])
|
||||
// If a command is set
|
||||
if (cfgCommand() != cfgCmdNone)
|
||||
{
|
||||
// Acquire a lock if required
|
||||
if (cfgLockRequired())
|
||||
lockAcquire(cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptStanza), cfgLockType(), 0, true);
|
||||
|
||||
// Open the log file if this command logs to a file
|
||||
if (cfgLogFile())
|
||||
if (cfgLogFile() && !cfgCommandHelp())
|
||||
{
|
||||
logFileSet(
|
||||
strPtr(strNewFmt("%s/%s-%s.log", strPtr(cfgOptionStr(cfgOptLogPath)), strPtr(cfgOptionStr(cfgOptStanza)),
|
||||
@ -224,9 +234,15 @@ cfgLoad(unsigned int argListSize, const char *argList[])
|
||||
// Begin the command
|
||||
cmdBegin(true);
|
||||
|
||||
// Open the log file if this command logs to a file
|
||||
if (cfgLockRequired() && !cfgCommandHelp())
|
||||
lockAcquire(cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptStanza), cfgLockType(), 0, true);
|
||||
|
||||
// Update options that have complex rules
|
||||
cfgLoadUpdateOption();
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ Command and Option Parse
|
||||
#include <strings.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
#include "common/ini.h"
|
||||
#include "common/log.h"
|
||||
@ -86,6 +87,13 @@ Convert the value passed into bytes and update valueDbl for range checking
|
||||
void
|
||||
convertToByte(String **value, double *valueDbl)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRINGP, value);
|
||||
FUNCTION_DEBUG_PARAM(DOUBLEP, valueDbl);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(valueDbl != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Make a copy of the value so it is not updated until we know the conversion will succeed
|
||||
String *result = strLower(strDup(*value));
|
||||
|
||||
@ -161,6 +169,8 @@ convertToByte(String **value, double *valueDbl)
|
||||
}
|
||||
else
|
||||
THROW_FMT(FormatError, "value '%s' is not valid", strPtr(*value));
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -198,6 +208,18 @@ cfgFileLoad( // NOTE: Pas
|
||||
const String *optConfigIncludePathDefault, // Current default for --config-include-path option
|
||||
const String *origConfigDefault) // Original --config option default (/etc/pgbackrest.conf)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM_PTR("ParseOption *", optionList);
|
||||
FUNCTION_DEBUG_PARAM(STRING, optConfigDefault);
|
||||
FUNCTION_DEBUG_PARAM(STRING, optConfigIncludePathDefault);
|
||||
FUNCTION_DEBUG_PARAM(STRING, origConfigDefault);
|
||||
|
||||
FUNCTION_TEST_ASSERT(optionList != NULL);
|
||||
FUNCTION_TEST_ASSERT(optConfigDefault != NULL);
|
||||
FUNCTION_TEST_ASSERT(optConfigIncludePathDefault != NULL);
|
||||
FUNCTION_TEST_ASSERT(origConfigDefault != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool loadConfig = true;
|
||||
bool loadConfigInclude = true;
|
||||
|
||||
@ -324,7 +346,7 @@ cfgFileLoad( // NOTE: Pas
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(STRING, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -336,6 +358,11 @@ logic to this critical path code.
|
||||
void
|
||||
configParse(unsigned int argListSize, const char *argList[])
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(UINT, argListSize);
|
||||
FUNCTION_DEBUG_PARAM(CHARPY, argList);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Initialize configuration
|
||||
cfgInit();
|
||||
|
||||
@ -406,17 +433,11 @@ configParse(unsigned int argListSize, const char *argList[])
|
||||
|
||||
// If the option is unknown then error
|
||||
case '?':
|
||||
{
|
||||
THROW_FMT(OptionInvalidError, "invalid option '%s'", argList[optind - 1]);
|
||||
break;
|
||||
}
|
||||
|
||||
// If the option is missing an argument then error
|
||||
case ':':
|
||||
{
|
||||
THROW_FMT(OptionInvalidError, "option '%s' requires argument", argList[optind - 1]);
|
||||
break;
|
||||
}
|
||||
|
||||
// Parse valid option
|
||||
default:
|
||||
@ -964,4 +985,6 @@ configParse(unsigned int argListSize, const char *argList[])
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
12
src/main.c
12
src/main.c
@ -8,6 +8,7 @@ Main
|
||||
#include "command/archive/push/push.h"
|
||||
#include "command/help/help.h"
|
||||
#include "command/command.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
#include "common/exit.h"
|
||||
#include "config/config.h"
|
||||
@ -18,6 +19,15 @@ Main
|
||||
int
|
||||
main(int argListSize, const char *argList[])
|
||||
{
|
||||
#ifdef WITH_BACKTRACE
|
||||
stackTraceInit(argList[0]);
|
||||
#endif
|
||||
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(INT, argListSize);
|
||||
FUNCTION_DEBUG_PARAM(CHARPY, argList);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
volatile bool result = 0;
|
||||
volatile bool error = false;
|
||||
|
||||
@ -88,5 +98,5 @@ main(int argListSize, const char *argList[])
|
||||
}
|
||||
TRY_END();
|
||||
|
||||
return exitSafe(result, error, 0);
|
||||
FUNCTION_DEBUG_RESULT(INT, exitSafe(result, error, 0));
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
/***********************************************************************************************************************************
|
||||
Perl Configuration
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "config/config.h"
|
||||
|
||||
@ -10,6 +11,8 @@ Build JSON output from options
|
||||
String *
|
||||
perlOptionJson()
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
String *result = strNew("{");
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -128,5 +131,5 @@ perlOptionJson()
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(STRING, result);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ Execute Perl for Legacy Functionality
|
||||
#include <unistd.h>
|
||||
|
||||
#include "version.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
#include "common/memContext.h"
|
||||
#include "config/config.h"
|
||||
@ -56,6 +57,8 @@ Build list of parameters to use for perl main
|
||||
String *
|
||||
perlMain()
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
// Add command arguments to pass to main
|
||||
String *commandParam = strNew("");
|
||||
|
||||
@ -66,22 +69,23 @@ perlMain()
|
||||
String *mainCall = strNewFmt(
|
||||
"($result, $message) = " PGBACKREST_MAIN "('%s'%s)", cfgCommandName(cfgCommand()), strPtr(commandParam));
|
||||
|
||||
return mainCall;
|
||||
FUNCTION_TEST_RESULT(STRING, mainCall);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Init the dynaloader so other C modules can be loaded
|
||||
|
||||
There are no FUNCTION_TEST* calls because this is a callback from Perl and it doesn't seem wise to mix our stack stuff up in it.
|
||||
***********************************************************************************************************************************/
|
||||
EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
|
||||
|
||||
static void xs_init(pTHX)
|
||||
{
|
||||
const char *file = __FILE__;
|
||||
dXSUB_SYS;
|
||||
PERL_UNUSED_CONTEXT;
|
||||
|
||||
/* DynaLoader is a special case */
|
||||
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
|
||||
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -90,7 +94,13 @@ Evaluate a perl statement
|
||||
static void
|
||||
perlEval(const String *statement)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, statement);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
eval_pv(strPtr(statement), TRUE);
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -99,6 +109,8 @@ Initialize Perl
|
||||
static void
|
||||
perlInit()
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
if (!my_perl)
|
||||
{
|
||||
// Initialize Perl with dummy args and environment
|
||||
@ -123,6 +135,8 @@ perlInit()
|
||||
// Set config data -- this is done separately to avoid it being included in stack traces
|
||||
perlEval(strNewFmt(PGBACKREST_MAIN "ConfigSet('%s', '%s')", strPtr(cfgExe()), strPtr(perlOptionJson())));
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -131,6 +145,8 @@ Execute main function in Perl
|
||||
int
|
||||
perlExec()
|
||||
{
|
||||
FUNCTION_DEBUG_VOID(logLevelDebug);
|
||||
|
||||
// Initialize Perl
|
||||
perlInit();
|
||||
|
||||
@ -144,7 +160,7 @@ perlExec()
|
||||
if (code >= errorTypeCode(&AssertError)) // {uncovered - success tested in integration}
|
||||
THROW_CODE(code, strlen(message) == 0 ? PERL_EMBED_ERROR : message); // {+uncovered}
|
||||
|
||||
return code; // {+uncovered}
|
||||
FUNCTION_DEBUG_RESULT(INT, code); // {+uncovered}
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -155,6 +171,12 @@ Don't bother freeing Perl itself since we are about to exit.
|
||||
void
|
||||
perlFree(int result)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INT, result);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (my_perl != NULL)
|
||||
perlEval(strNewFmt(PGBACKREST_MAIN "Cleanup(%d)", result));
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
/***********************************************************************************************************************************
|
||||
PostgreSQL Info
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "postgres/info.h"
|
||||
#include "postgres/type.h"
|
||||
@ -13,6 +14,11 @@ Map control/catalog version to PostgreSQL version
|
||||
static uint
|
||||
pgVersionMap(uint32_t controlVersion, uint32_t catalogVersion)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UINT32, controlVersion);
|
||||
FUNCTION_TEST_PARAM(UINT32, catalogVersion);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
uint result = 0;
|
||||
|
||||
if (controlVersion == 1002 && catalogVersion == 201707211)
|
||||
@ -44,7 +50,7 @@ pgVersionMap(uint32_t controlVersion, uint32_t catalogVersion)
|
||||
controlVersion, catalogVersion);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(UINT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -53,6 +59,12 @@ Get info from pg_control
|
||||
PgControlInfo
|
||||
pgControlInfo(const String *pgPath)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STRING, pgPath);
|
||||
|
||||
FUNCTION_TEST_ASSERT(pgPath != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
PgControlInfo result = {0};
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -73,5 +85,5 @@ pgControlInfo(const String *pgPath)
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(PG_CONTROL_INFO, result);
|
||||
}
|
||||
|
@ -25,4 +25,12 @@ Functions
|
||||
***********************************************************************************************************************************/
|
||||
PgControlInfo pgControlInfo(const String *pgPath);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_PG_CONTROL_INFO_TYPE \
|
||||
PgControlInfo
|
||||
#define FUNCTION_DEBUG_PG_CONTROL_INFO_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(&value, "PgControlInfo", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -65,6 +65,7 @@ minimize register spilling. For less sophisticated compilers it might be benefic
|
||||
#include <string.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
#include "postgres/pageChecksum.h"
|
||||
#include "postgres/type.h"
|
||||
@ -134,10 +135,15 @@ do { \
|
||||
} while (0)
|
||||
|
||||
static uint32_t
|
||||
pageChecksumBlock(const unsigned char *page, uint32_t pageSize)
|
||||
pageChecksumBlock(const unsigned char *page, unsigned int pageSize)
|
||||
{
|
||||
ASSERT_DEBUG(page != NULL);
|
||||
ASSERT_DEBUG(pageSize == PG_PAGE_SIZE);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UCHARP, page);
|
||||
FUNCTION_TEST_PARAM(UINT, pageSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(page != NULL);
|
||||
FUNCTION_TEST_ASSERT(pageSize == PG_PAGE_SIZE);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
uint32_t sums[N_SUMS];
|
||||
uint32_t (*dataArray)[N_SUMS] = (uint32_t (*)[N_SUMS])page;
|
||||
@ -161,7 +167,7 @@ pageChecksumBlock(const unsigned char *page, uint32_t pageSize)
|
||||
for (i = 0; i < N_SUMS; i++)
|
||||
result ^= sums[i];
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(UINT32, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -173,7 +179,14 @@ The checksum includes the block number (to detect the case where a page is someh
|
||||
uint16_t
|
||||
pageChecksum(const unsigned char *page, unsigned int blockNo, unsigned int pageSize)
|
||||
{
|
||||
ASSERT_DEBUG(page != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UCHARP, page);
|
||||
FUNCTION_TEST_PARAM(UINT, blockNo);
|
||||
FUNCTION_TEST_PARAM(UINT, pageSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(page != NULL);
|
||||
FUNCTION_TEST_ASSERT(pageSize == PG_PAGE_SIZE);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Save pd_checksum and temporarily set it to zero, so that the checksum calculation isn't affected by the old checksum stored
|
||||
// on the page. Restore it after, because actually updating the checksum is NOT part of the API of this function.
|
||||
@ -188,7 +201,7 @@ pageChecksum(const unsigned char *page, unsigned int blockNo, unsigned int pageS
|
||||
checksum ^= blockNo;
|
||||
|
||||
// Reduce to a uint16 with an offset of one. That avoids checksums of zero, which seems like a good idea.
|
||||
return (uint16_t)((checksum % 65535) + 1);
|
||||
FUNCTION_TEST_RESULT(UINT16, (uint16_t)(checksum % 65535 + 1));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -198,15 +211,25 @@ bool
|
||||
pageChecksumTest(
|
||||
const unsigned char *page, unsigned int blockNo, unsigned int pageSize, uint32_t ignoreWalId, uint32_t ignoreWalOffset)
|
||||
{
|
||||
ASSERT_DEBUG(page != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UCHARP, page);
|
||||
FUNCTION_TEST_PARAM(UINT, blockNo);
|
||||
FUNCTION_TEST_PARAM(UINT, pageSize);
|
||||
FUNCTION_TEST_PARAM(UINT32, ignoreWalId);
|
||||
FUNCTION_TEST_PARAM(UINT32, ignoreWalOffset);
|
||||
|
||||
return
|
||||
FUNCTION_TEST_ASSERT(page != NULL);
|
||||
FUNCTION_TEST_ASSERT(pageSize == PG_PAGE_SIZE);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(
|
||||
BOOL,
|
||||
// This is a new page so don't test checksum
|
||||
((PageHeader)page)->pd_upper == 0 ||
|
||||
// LSN is after the backup started so checksum is not tested because pages may be torn
|
||||
(((PageHeader)page)->pd_lsn.walid >= ignoreWalId && ((PageHeader)page)->pd_lsn.xrecoff >= ignoreWalOffset) ||
|
||||
// Checksum is valid
|
||||
((PageHeader)page)->pd_checksum == pageChecksum(page, blockNo, pageSize);
|
||||
((PageHeader)page)->pd_checksum == pageChecksum(page, blockNo, pageSize));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -217,13 +240,21 @@ pageChecksumBufferTest(
|
||||
const unsigned char *pageBuffer, unsigned int pageBufferSize, unsigned int blockNoBegin, unsigned int pageSize,
|
||||
uint32_t ignoreWalId, uint32_t ignoreWalOffset)
|
||||
{
|
||||
ASSERT_DEBUG(pageBuffer != NULL);
|
||||
ASSERT_DEBUG(pageBufferSize > 0);
|
||||
ASSERT_DEBUG(pageSize == PG_PAGE_SIZE);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(UCHARP, pageBuffer);
|
||||
FUNCTION_DEBUG_PARAM(UINT, pageBufferSize);
|
||||
FUNCTION_DEBUG_PARAM(UINT, blockNoBegin);
|
||||
FUNCTION_DEBUG_PARAM(UINT, pageSize);
|
||||
FUNCTION_DEBUG_PARAM(UINT32, ignoreWalId);
|
||||
FUNCTION_DEBUG_PARAM(UINT32, ignoreWalOffset);
|
||||
|
||||
// If the buffer does not represent an even number of pages then error
|
||||
if (pageBufferSize % pageSize != 0)
|
||||
THROW_FMT(AssertError, "buffer size %u, page size %u are not divisible", pageBufferSize, pageSize);
|
||||
FUNCTION_TEST_ASSERT(pageBuffer != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(pageBufferSize > 0);
|
||||
FUNCTION_DEBUG_ASSERT(pageSize == PG_PAGE_SIZE);
|
||||
FUNCTION_DEBUG_ASSERT(pageBufferSize % pageSize == 0);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool result = true;
|
||||
|
||||
// Loop through all pages in the buffer
|
||||
for (unsigned int pageIdx = 0; pageIdx < pageBufferSize / pageSize; pageIdx++)
|
||||
@ -232,9 +263,11 @@ pageChecksumBufferTest(
|
||||
|
||||
// Return false if the checksums do not match
|
||||
if (!pageChecksumTest(page, blockNoBegin + pageIdx, pageSize, ignoreWalId, ignoreWalOffset))
|
||||
return false;
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// All checksums match
|
||||
return true;
|
||||
FUNCTION_DEBUG_RESULT(BOOL, result);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ Storage Driver Posix
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/regExp.h"
|
||||
#include "storage/driver/posix/driver.h"
|
||||
@ -25,6 +26,12 @@ Does a file/path exist?
|
||||
bool
|
||||
storageDriverPosixExists(const String *path)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, path);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(path != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
// Attempt to stat the file to determine if it exists
|
||||
@ -40,7 +47,7 @@ storageDriverPosixExists(const String *path)
|
||||
else
|
||||
result = !S_ISDIR(statFile.st_mode);
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -49,6 +56,13 @@ File/path info
|
||||
StorageInfo
|
||||
storageDriverPosixInfo(const String *file, bool ignoreMissing)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, file);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, ignoreMissing);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(file != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
StorageInfo result = {0};
|
||||
|
||||
// Attempt to stat the file
|
||||
@ -79,7 +93,7 @@ storageDriverPosixInfo(const String *file, bool ignoreMissing)
|
||||
result.mode = statFile.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(STORAGE_INFO, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -88,6 +102,14 @@ Get a list of files from a directory
|
||||
StringList *
|
||||
storageDriverPosixList(const String *path, bool errorOnMissing, const String *expression)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, path);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, errorOnMissing);
|
||||
FUNCTION_DEBUG_PARAM(STRING, expression);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(path != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
StringList *result = NULL;
|
||||
DIR *dir = NULL;
|
||||
|
||||
@ -141,7 +163,7 @@ storageDriverPosixList(const String *path, bool errorOnMissing, const String *ex
|
||||
}
|
||||
TRY_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(STRING_LIST, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -150,6 +172,14 @@ Move a file
|
||||
bool
|
||||
storageDriverPosixMove(StorageFileReadPosix *source, StorageFileWritePosix *destination)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_READ_POSIX, source);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_WRITE_POSIX, destination);
|
||||
|
||||
FUNCTION_TEST_ASSERT(source != NULL);
|
||||
FUNCTION_TEST_ASSERT(destination != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool result = true;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -199,7 +229,7 @@ storageDriverPosixMove(StorageFileReadPosix *source, StorageFileWritePosix *dest
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -208,6 +238,15 @@ Create a path
|
||||
void
|
||||
storageDriverPosixPathCreate(const String *path, bool errorOnExists, bool noParentCreate, mode_t mode)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, path);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, errorOnExists);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, noParentCreate);
|
||||
FUNCTION_DEBUG_PARAM(MODE, mode);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(path != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Attempt to create the directory
|
||||
if (mkdir(strPtr(path), mode) == -1)
|
||||
{
|
||||
@ -221,6 +260,8 @@ storageDriverPosixPathCreate(const String *path, bool errorOnExists, bool noPare
|
||||
else if (errno != EEXIST || errorOnExists)
|
||||
THROW_SYS_ERROR_FMT(PathCreateError, "unable to create path '%s'", strPtr(path));
|
||||
}
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -229,6 +270,14 @@ Remove a path
|
||||
void
|
||||
storageDriverPosixPathRemove(const String *path, bool errorOnMissing, bool recurse)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, path);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, errorOnMissing);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, recurse);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(path != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// Recurse if requested
|
||||
@ -267,6 +316,8 @@ storageDriverPosixPathRemove(const String *path, bool errorOnMissing, bool recur
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -275,6 +326,13 @@ Sync a path
|
||||
void
|
||||
storageDriverPosixPathSync(const String *path, bool ignoreMissing)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, path);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, ignoreMissing);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(path != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Open directory and handle errors
|
||||
int handle = storageFilePosixOpen(path, O_RDONLY, 0, ignoreMissing, &PathOpenError, "sync");
|
||||
|
||||
@ -287,6 +345,8 @@ storageDriverPosixPathSync(const String *path, bool ignoreMissing)
|
||||
// Close the directory
|
||||
storageFilePosixClose(handle, path, &PathCloseError);
|
||||
}
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -295,10 +355,19 @@ Remove a file
|
||||
void
|
||||
storageDriverPosixRemove(const String *file, bool errorOnMissing)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, file);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, errorOnMissing);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(file != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Attempt to unlink the file
|
||||
if (unlink(strPtr(file)) == -1)
|
||||
{
|
||||
if (errorOnMissing || errno != ENOENT)
|
||||
THROW_SYS_ERROR_FMT(FileRemoveError, "unable to remove '%s'", strPtr(file));
|
||||
}
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ Storage File Routines For Posix
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "storage/driver/posix/driverFile.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -21,6 +22,19 @@ int
|
||||
storageFilePosixOpen(
|
||||
const String *name, int flags, mode_t mode, bool ignoreMissing, const ErrorType *errorType, const char *purpose)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, name);
|
||||
FUNCTION_TEST_PARAM(INT, flags);
|
||||
FUNCTION_TEST_PARAM(MODE, mode);
|
||||
FUNCTION_TEST_PARAM(BOOL, ignoreMissing);
|
||||
FUNCTION_TEST_PARAM(ERROR_TYPE, errorType);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, purpose);
|
||||
|
||||
FUNCTION_TEST_ASSERT(name != NULL);
|
||||
FUNCTION_TEST_ASSERT(errorType != NULL);
|
||||
FUNCTION_TEST_ASSERT(purpose != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
int result = -1;
|
||||
|
||||
result = open(strPtr(name), flags, mode);
|
||||
@ -31,7 +45,7 @@ storageFilePosixOpen(
|
||||
THROWP_SYS_ERROR_FMT(errorType, "unable to open '%s' for %s", strPtr(name), purpose);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(INT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -40,6 +54,17 @@ Sync a file/directory handle
|
||||
void
|
||||
storageFilePosixSync(int handle, const String *name, const ErrorType *errorType, bool closeOnError)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INT, handle);
|
||||
FUNCTION_TEST_PARAM(STRING, name);
|
||||
FUNCTION_TEST_PARAM(ERROR_TYPE, errorType);
|
||||
FUNCTION_TEST_PARAM(BOOL, closeOnError);
|
||||
|
||||
FUNCTION_TEST_ASSERT(handle != -1);
|
||||
FUNCTION_TEST_ASSERT(name != NULL);
|
||||
FUNCTION_TEST_ASSERT(errorType != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (fsync(handle) == -1)
|
||||
{
|
||||
int errNo = errno;
|
||||
@ -50,6 +75,8 @@ storageFilePosixSync(int handle, const String *name, const ErrorType *errorType,
|
||||
|
||||
THROWP_SYS_ERROR_CODE_FMT(errNo, errorType, "unable to sync '%s'", strPtr(name));
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -58,6 +85,18 @@ Close a file/directory handle
|
||||
void
|
||||
storageFilePosixClose(int handle, const String *name, const ErrorType *errorType)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INT, handle);
|
||||
FUNCTION_TEST_PARAM(STRING, name);
|
||||
FUNCTION_TEST_PARAM(ERROR_TYPE, errorType);
|
||||
|
||||
FUNCTION_TEST_ASSERT(handle != -1);
|
||||
FUNCTION_TEST_ASSERT(name != NULL);
|
||||
FUNCTION_TEST_ASSERT(errorType != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (close(handle) == -1)
|
||||
THROWP_SYS_ERROR_FMT(errorType, "unable to close '%s'", strPtr(name));
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ Storage File Read Driver For Posix
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "storage/driver/posix/driverFile.h"
|
||||
#include "storage/driver/posix/driverRead.h"
|
||||
@ -31,10 +32,16 @@ Create a new file
|
||||
StorageFileReadPosix *
|
||||
storageFileReadPosixNew(const String *name, bool ignoreMissing, size_t bufferSize)
|
||||
{
|
||||
StorageFileReadPosix *this = NULL;
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, name);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, ignoreMissing);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, bufferSize);
|
||||
|
||||
ASSERT_DEBUG(name != NULL);
|
||||
ASSERT_DEBUG(bufferSize > 0);
|
||||
FUNCTION_TEST_ASSERT(name != NULL);
|
||||
FUNCTION_TEST_ASSERT(bufferSize > 0);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
StorageFileReadPosix *this = NULL;
|
||||
|
||||
// Create the file object
|
||||
MEM_CONTEXT_NEW_BEGIN("StorageFileReadPosix")
|
||||
@ -49,7 +56,7 @@ storageFileReadPosixNew(const String *name, bool ignoreMissing, size_t bufferSiz
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_DEBUG_RESULT(STORAGE_FILE_READ_POSIX, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -58,10 +65,14 @@ Open the file
|
||||
bool
|
||||
storageFileReadPosixOpen(StorageFileReadPosix *this)
|
||||
{
|
||||
bool result = false;
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_READ_POSIX, this);
|
||||
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
ASSERT_DEBUG(this->handle == -1);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(this->handle == -1);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
// Open the file and handle errors
|
||||
this->handle = storageFilePosixOpen(this->name, O_RDONLY, 0, this->ignoreMissing, &FileOpenError, "read");
|
||||
@ -73,7 +84,7 @@ storageFileReadPosixOpen(StorageFileReadPosix *this)
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -82,6 +93,13 @@ Read from a file
|
||||
Buffer *
|
||||
storageFileReadPosix(StorageFileReadPosix *this)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_READ_POSIX, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(this->handle != -1);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
Buffer *result = NULL;
|
||||
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
@ -112,7 +130,7 @@ storageFileReadPosix(StorageFileReadPosix *this)
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(BUFFER, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -121,7 +139,11 @@ Close the file
|
||||
void
|
||||
storageFileReadPosixClose(StorageFileReadPosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_READ_POSIX, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Close if the file has not already been closed
|
||||
if (this->handle != -1)
|
||||
@ -131,6 +153,8 @@ storageFileReadPosixClose(StorageFileReadPosix *this)
|
||||
|
||||
this->handle = -1;
|
||||
}
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -139,9 +163,13 @@ Should a missing file be ignored?
|
||||
bool
|
||||
storageFileReadPosixIgnoreMissing(StorageFileReadPosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_READ_POSIX, this);
|
||||
|
||||
return this->ignoreMissing;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, this->ignoreMissing);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -150,9 +178,13 @@ File name
|
||||
const String *
|
||||
storageFileReadPosixName(StorageFileReadPosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_READ_POSIX, this);
|
||||
|
||||
return this->name;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(CONST_STRING, this->name);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -161,9 +193,13 @@ File size
|
||||
size_t
|
||||
storageFileReadPosixSize(StorageFileReadPosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_READ_POSIX, this);
|
||||
|
||||
return this->size;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(SIZE, this->size);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -172,9 +208,15 @@ Free the file
|
||||
void
|
||||
storageFileReadPosixFree(StorageFileReadPosix *this)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_READ_POSIX, this);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
if (this != NULL)
|
||||
{
|
||||
storageFileReadPosixClose(this);
|
||||
memContextFree(this->memContext);
|
||||
}
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -36,4 +36,12 @@ Destructor
|
||||
***********************************************************************************************************************************/
|
||||
void storageFileReadPosixFree(StorageFileReadPosix *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_STORAGE_FILE_READ_POSIX_TYPE \
|
||||
StorageFileReadPosix *
|
||||
#define FUNCTION_DEBUG_STORAGE_FILE_READ_POSIX_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "StorageFileReadPosix", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -6,6 +6,7 @@ Storage File Write Driver For Posix
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "storage/driver/posix/driverFile.h"
|
||||
#include "storage/driver/posix/driverWrite.h"
|
||||
@ -48,6 +49,18 @@ StorageFileWritePosix *
|
||||
storageFileWritePosixNew(
|
||||
const String *name, mode_t modeFile, mode_t modePath, bool noCreatePath, bool noSyncFile, bool noSyncPath, bool noAtomic)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, name);
|
||||
FUNCTION_DEBUG_PARAM(MODE, modeFile);
|
||||
FUNCTION_DEBUG_PARAM(MODE, modePath);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, noCreatePath);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, noSyncFile);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, noSyncPath);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, noAtomic);
|
||||
|
||||
FUNCTION_TEST_ASSERT(name != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
StorageFileWritePosix *this = NULL;
|
||||
|
||||
ASSERT_DEBUG(name != NULL);
|
||||
@ -71,7 +84,7 @@ storageFileWritePosixNew(
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_DEBUG_RESULT(STORAGE_FILE_WRITE_POSIX, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -80,8 +93,12 @@ Open the file
|
||||
void
|
||||
storageFileWritePosixOpen(StorageFileWritePosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
ASSERT_DEBUG(this->handle == -1);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_WRITE_POSIX, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(this->handle == -1);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Open the file and handle errors
|
||||
this->handle = storageFilePosixOpen(
|
||||
@ -100,6 +117,8 @@ storageFileWritePosixOpen(StorageFileWritePosix *this)
|
||||
// On success set free callback to ensure file handle is freed
|
||||
else
|
||||
memContextCallback(this->memContext, (MemContextCallback)storageFileWritePosixFree, this);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -108,13 +127,20 @@ Write to a file
|
||||
void
|
||||
storageFileWritePosix(StorageFileWritePosix *this, const Buffer *buffer)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
ASSERT_DEBUG(buffer != NULL);
|
||||
ASSERT_DEBUG(this->handle != -1);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_WRITE_POSIX, this);
|
||||
FUNCTION_DEBUG_PARAM(BUFFER, buffer);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_ASSERT(buffer != NULL);
|
||||
FUNCTION_TEST_ASSERT(this->handle != -1);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Write the data
|
||||
if (write(this->handle, bufPtr(buffer), bufSize(buffer)) != (ssize_t)bufSize(buffer))
|
||||
THROW_SYS_ERROR_FMT(FileWriteError, "unable to write '%s'", strPtr(this->name));
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -123,7 +149,11 @@ Close the file
|
||||
void
|
||||
storageFileWritePosixClose(StorageFileWritePosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_WRITE_POSIX, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Close if the file has not already been closed
|
||||
if (this->handle != -1)
|
||||
@ -149,6 +179,8 @@ storageFileWritePosixClose(StorageFileWritePosix *this)
|
||||
// This marks the file as closed
|
||||
this->handle = -1;
|
||||
}
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -159,9 +191,13 @@ For the posix driver this means writing to a temp file first and then renaming o
|
||||
bool
|
||||
storageFileWritePosixAtomic(StorageFileWritePosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE_POSIX, this);
|
||||
|
||||
return !this->noAtomic;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, !this->noAtomic);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -170,9 +206,13 @@ Will the path be created for the file if it does not exist?
|
||||
bool
|
||||
storageFileWritePosixCreatePath(StorageFileWritePosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE_POSIX, this);
|
||||
|
||||
return !this->noCreatePath;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, !this->noCreatePath);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -181,9 +221,13 @@ Mode for the file to be created
|
||||
mode_t
|
||||
storageFileWritePosixModeFile(StorageFileWritePosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE_POSIX, this);
|
||||
|
||||
return this->modeFile;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(MODE, this->modeFile);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -192,9 +236,13 @@ Mode for any paths that are created while writing the file
|
||||
mode_t
|
||||
storageFileWritePosixModePath(StorageFileWritePosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE_POSIX, this);
|
||||
|
||||
return this->modePath;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(MODE, this->modePath);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -203,9 +251,13 @@ File name
|
||||
const String *
|
||||
storageFileWritePosixName(StorageFileWritePosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE_POSIX, this);
|
||||
|
||||
return this->name;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(CONST_STRING, this->name);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -214,9 +266,13 @@ File path
|
||||
const String *
|
||||
storageFileWritePosixPath(StorageFileWritePosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE_POSIX, this);
|
||||
|
||||
return this->path;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(CONST_STRING, this->path);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -225,9 +281,13 @@ Will the file be synced after it is closed?
|
||||
bool
|
||||
storageFileWritePosixSyncFile(StorageFileWritePosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE_POSIX, this);
|
||||
|
||||
return !this->noSyncFile;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, !this->noSyncFile);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -236,9 +296,13 @@ Will the directory be synced to disk after the write is completed?
|
||||
bool
|
||||
storageFileWritePosixSyncPath(StorageFileWritePosix *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE_POSIX, this);
|
||||
|
||||
return !this->noSyncPath;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, !this->noSyncPath);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -247,9 +311,15 @@ Free the file
|
||||
void
|
||||
storageFileWritePosixFree(StorageFileWritePosix *this)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_WRITE_POSIX, this);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
if (this != NULL)
|
||||
{
|
||||
storageFileWritePosixClose(this);
|
||||
memContextFree(this->memContext);
|
||||
}
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -44,4 +44,12 @@ Destructor
|
||||
***********************************************************************************************************************************/
|
||||
void storageFileWritePosixFree(StorageFileWritePosix *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_STORAGE_FILE_WRITE_POSIX_TYPE \
|
||||
StorageFileWritePosix *
|
||||
#define FUNCTION_DEBUG_STORAGE_FILE_WRITE_POSIX_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "StorageFileWritePosix", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -2,6 +2,7 @@
|
||||
Storage File Read
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "storage/fileRead.h"
|
||||
|
||||
@ -20,9 +21,16 @@ Create a new storage file
|
||||
StorageFileRead *
|
||||
storageFileReadNew(const String *name, bool ignoreMissing, size_t bufferSize)
|
||||
{
|
||||
StorageFileRead *this = NULL;
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, name);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, ignoreMissing);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, bufferSize);
|
||||
|
||||
ASSERT_DEBUG(name != NULL);
|
||||
FUNCTION_TEST_ASSERT(name != NULL);
|
||||
FUNCTION_TEST_ASSERT(bufferSize > 0);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
StorageFileRead *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("StorageFileRead")
|
||||
{
|
||||
@ -34,7 +42,7 @@ storageFileReadNew(const String *name, bool ignoreMissing, size_t bufferSize)
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_DEBUG_RESULT(STORAGE_FILE_READ, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -43,9 +51,13 @@ Open the file
|
||||
bool
|
||||
storageFileReadOpen(StorageFileRead *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_READ, this);
|
||||
|
||||
return storageFileReadPosixOpen(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
FUNCTION_DEBUG_RESULT(BOOL, storageFileReadPosixOpen(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -54,9 +66,13 @@ Read data from the file
|
||||
Buffer *
|
||||
storageFileRead(StorageFileRead *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_READ, this);
|
||||
|
||||
return storageFileReadPosix(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
FUNCTION_DEBUG_RESULT(BUFFER, storageFileReadPosix(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -65,10 +81,17 @@ Move the file object to a new context
|
||||
StorageFileRead *
|
||||
storageFileReadMove(StorageFileRead *this, MemContext *parentNew)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_READ, this);
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, parentNew);
|
||||
|
||||
FUNCTION_TEST_ASSERT(parentNew != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this != NULL)
|
||||
memContextMove(this->memContext, parentNew);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STORAGE_FILE_READ, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -77,9 +100,15 @@ Close the file
|
||||
void
|
||||
storageFileReadClose(StorageFileRead *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_READ, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
storageFileReadPosixClose(this->fileDriver);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -88,9 +117,13 @@ Get file driver
|
||||
StorageFileReadPosix *
|
||||
storageFileReadFileDriver(const StorageFileRead *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_READ, this);
|
||||
|
||||
return this->fileDriver;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STORAGE_FILE_READ_POSIX, this->fileDriver);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -99,9 +132,13 @@ Should a missing file be ignored?
|
||||
bool
|
||||
storageFileReadIgnoreMissing(const StorageFileRead *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_READ, this);
|
||||
|
||||
return storageFileReadPosixIgnoreMissing(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, storageFileReadPosixIgnoreMissing(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -110,9 +147,13 @@ Get file name
|
||||
const String *
|
||||
storageFileReadName(const StorageFileRead *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_READ, this);
|
||||
|
||||
return storageFileReadPosixName(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(CONST_STRING, storageFileReadPosixName(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -121,9 +162,13 @@ Get file size
|
||||
size_t
|
||||
storageFileReadSize(const StorageFileRead *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_READ, this);
|
||||
|
||||
return storageFileReadPosixSize(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(SIZE, storageFileReadPosixSize(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -132,6 +177,12 @@ Free the file
|
||||
void
|
||||
storageFileReadFree(StorageFileRead *this)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_READ, this);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
if (this != NULL)
|
||||
memContextFree(this->memContext);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -40,4 +40,12 @@ Destructor
|
||||
***********************************************************************************************************************************/
|
||||
void storageFileReadFree(StorageFileRead *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_STORAGE_FILE_READ_TYPE \
|
||||
StorageFileRead *
|
||||
#define FUNCTION_DEBUG_STORAGE_FILE_READ_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "StorageFileRead", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -2,6 +2,7 @@
|
||||
Storage File Write
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "storage/fileWrite.h"
|
||||
|
||||
@ -24,6 +25,18 @@ StorageFileWrite *
|
||||
storageFileWriteNew(
|
||||
const String *name, mode_t modeFile, mode_t modePath, bool noCreatePath, bool noSyncFile, bool noSyncPath, bool noAtomic)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STRING, name);
|
||||
FUNCTION_DEBUG_PARAM(MODE, modeFile);
|
||||
FUNCTION_DEBUG_PARAM(MODE, modePath);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, noCreatePath);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, noSyncFile);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, noSyncPath);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, noAtomic);
|
||||
|
||||
FUNCTION_TEST_ASSERT(name != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
StorageFileWrite *this = NULL;
|
||||
|
||||
ASSERT_DEBUG(name != NULL);
|
||||
@ -39,7 +52,7 @@ storageFileWriteNew(
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_DEBUG_RESULT(STORAGE_FILE_WRITE, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -48,10 +61,16 @@ Open the file
|
||||
void
|
||||
storageFileWriteOpen(StorageFileWrite *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_WRITE, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Open the file
|
||||
storageFileWritePosixOpen(this->fileDriver);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -60,11 +79,18 @@ Write to a file
|
||||
void
|
||||
storageFileWrite(StorageFileWrite *this, const Buffer *buffer)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_WRITE, this);
|
||||
FUNCTION_DEBUG_PARAM(BUFFER, buffer);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
// Only write if there is data to write
|
||||
if (buffer != NULL && bufSize(buffer) > 0)
|
||||
storageFileWritePosix(this->fileDriver, buffer);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -73,10 +99,17 @@ Move the file object to a new context
|
||||
StorageFileWrite *
|
||||
storageFileWriteMove(StorageFileWrite *this, MemContext *parentNew)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE, this);
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, parentNew);
|
||||
|
||||
FUNCTION_TEST_ASSERT(parentNew != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (this != NULL)
|
||||
memContextMove(this->memContext, parentNew);
|
||||
|
||||
return this;
|
||||
FUNCTION_TEST_RESULT(STORAGE_FILE_WRITE, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -85,9 +118,15 @@ Close the file
|
||||
void
|
||||
storageFileWriteClose(StorageFileWrite *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_WRITE, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
storageFileWritePosixClose(this->fileDriver);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -98,9 +137,13 @@ Atomic writes means the file will be complete or be missing. Filesystems have d
|
||||
bool
|
||||
storageFileWriteAtomic(const StorageFileWrite *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE, this);
|
||||
|
||||
return storageFileWritePosixAtomic(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, storageFileWritePosixAtomic(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -109,9 +152,13 @@ Will the path be created if required?
|
||||
bool
|
||||
storageFileWriteCreatePath(const StorageFileWrite *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE, this);
|
||||
|
||||
return storageFileWritePosixCreatePath(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, storageFileWritePosixCreatePath(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -120,9 +167,13 @@ Get file driver
|
||||
StorageFileWritePosix *
|
||||
storageFileWriteFileDriver(const StorageFileWrite *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE, this);
|
||||
|
||||
return this->fileDriver;
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(STORAGE_FILE_WRITE_POSIX, this->fileDriver);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -131,9 +182,13 @@ Get file mode
|
||||
mode_t
|
||||
storageFileWriteModeFile(const StorageFileWrite *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE, this);
|
||||
|
||||
return storageFileWritePosixModeFile(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(MODE, storageFileWritePosixModeFile(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -142,9 +197,13 @@ Get path mode
|
||||
mode_t
|
||||
storageFileWriteModePath(const StorageFileWrite *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE, this);
|
||||
|
||||
return storageFileWritePosixModePath(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(MODE, storageFileWritePosixModePath(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -153,9 +212,13 @@ Get file name
|
||||
const String *
|
||||
storageFileWriteName(const StorageFileWrite *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE, this);
|
||||
|
||||
return storageFileWritePosixName(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(CONST_STRING, storageFileWritePosixName(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -164,9 +227,13 @@ Get file path
|
||||
const String *
|
||||
storageFileWritePath(const StorageFileWrite *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE, this);
|
||||
|
||||
return storageFileWritePosixPath(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(CONST_STRING, storageFileWritePosixPath(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -175,9 +242,13 @@ Will the file be synced after it is closed?
|
||||
bool
|
||||
storageFileWriteSyncFile(const StorageFileWrite *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE, this);
|
||||
|
||||
return storageFileWritePosixSyncFile(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, storageFileWritePosixSyncFile(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -186,9 +257,13 @@ Will the path be synced after the file is closed?
|
||||
bool
|
||||
storageFileWriteSyncPath(const StorageFileWrite *this)
|
||||
{
|
||||
ASSERT_DEBUG(this != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE_FILE_WRITE, this);
|
||||
|
||||
return storageFileWritePosixSyncPath(this->fileDriver);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(BOOL, storageFileWritePosixSyncPath(this->fileDriver));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -197,6 +272,12 @@ Free the file
|
||||
void
|
||||
storageFileWriteFree(const StorageFileWrite *this)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_WRITE, this);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
if (this != NULL)
|
||||
memContextFree(this->memContext);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -54,4 +54,12 @@ Destructor
|
||||
***********************************************************************************************************************************/
|
||||
void storageFileWriteFree(const StorageFileWrite *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_STORAGE_FILE_WRITE_TYPE \
|
||||
StorageFileWrite *
|
||||
#define FUNCTION_DEBUG_STORAGE_FILE_WRITE_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "StorageFileWrite", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -3,6 +3,7 @@ Storage Helper
|
||||
***********************************************************************************************************************************/
|
||||
#include <string.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "config/config.h"
|
||||
#include "storage/helper.h"
|
||||
@ -30,6 +31,8 @@ Create the storage helper memory context
|
||||
static void
|
||||
storageHelperInit()
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
if (memContextStorageHelper == NULL)
|
||||
{
|
||||
MEM_CONTEXT_BEGIN(memContextTop())
|
||||
@ -38,6 +41,8 @@ storageHelperInit()
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -46,10 +51,12 @@ Get a local storage object
|
||||
const Storage *
|
||||
storageLocal()
|
||||
{
|
||||
storageHelperInit();
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
if (storageLocalData == NULL)
|
||||
{
|
||||
storageHelperInit();
|
||||
|
||||
MEM_CONTEXT_BEGIN(memContextStorageHelper)
|
||||
{
|
||||
storageLocalData = storageNewNP(strNew("/"));
|
||||
@ -57,7 +64,7 @@ storageLocal()
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
|
||||
return storageLocalData;
|
||||
FUNCTION_TEST_RESULT(STORAGE, storageLocalData);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -68,10 +75,12 @@ This should be used very sparingly. If writes are not needed then always use st
|
||||
const Storage *
|
||||
storageLocalWrite()
|
||||
{
|
||||
storageHelperInit();
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
if (storageLocalWriteData == NULL)
|
||||
{
|
||||
storageHelperInit();
|
||||
|
||||
MEM_CONTEXT_BEGIN(memContextStorageHelper)
|
||||
{
|
||||
storageLocalWriteData = storageNewP(strNew("/"), .write = true);
|
||||
@ -79,7 +88,7 @@ storageLocalWrite()
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
|
||||
return storageLocalWriteData;
|
||||
FUNCTION_TEST_RESULT(STORAGE, storageLocalWriteData);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -88,6 +97,13 @@ Get a spool storage object
|
||||
String *
|
||||
storageSpoolPathExpression(const String *expression, const String *path)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, expression);
|
||||
FUNCTION_TEST_PARAM(STRING, path);
|
||||
|
||||
FUNCTION_TEST_ASSERT(expression != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
String *result = NULL;
|
||||
|
||||
if (strcmp(strPtr(expression), STORAGE_SPOOL_ARCHIVE_IN) == 0)
|
||||
@ -107,7 +123,7 @@ storageSpoolPathExpression(const String *expression, const String *path)
|
||||
else
|
||||
THROW_FMT(AssertError, "invalid expression '%s'", strPtr(expression));
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(STRING, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -116,10 +132,12 @@ Get a spool storage object
|
||||
const Storage *
|
||||
storageSpool()
|
||||
{
|
||||
storageHelperInit();
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
if (storageSpoolData == NULL)
|
||||
{
|
||||
storageHelperInit();
|
||||
|
||||
MEM_CONTEXT_BEGIN(memContextStorageHelper)
|
||||
{
|
||||
storageSpoolStanza = strDup(cfgOptionStr(cfgOptStanza));
|
||||
@ -130,5 +148,5 @@ storageSpool()
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
|
||||
return storageSpoolData;
|
||||
FUNCTION_TEST_RESULT(STORAGE, storageSpoolData);
|
||||
}
|
||||
|
@ -27,4 +27,12 @@ typedef struct StorageInfo
|
||||
mode_t mode; // Mode of path/file/link
|
||||
} StorageInfo;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_STORAGE_INFO_TYPE \
|
||||
StorageInfo
|
||||
#define FUNCTION_DEBUG_STORAGE_INFO_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(&value, "StorageInfo", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -1,9 +1,11 @@
|
||||
/***********************************************************************************************************************************
|
||||
Storage Manager
|
||||
***********************************************************************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/wait.h"
|
||||
#include "storage/driver/posix/driver.h"
|
||||
@ -23,24 +25,24 @@ struct Storage
|
||||
StoragePathExpressionCallback pathExpressionFunction;
|
||||
};
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Debug Asserts
|
||||
***********************************************************************************************************************************/
|
||||
// Check that commands that write are not allowed unless the storage is writable
|
||||
#define ASSERT_STORAGE_ALLOWS_WRITE() \
|
||||
ASSERT(this->write == true)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
New storage object
|
||||
***********************************************************************************************************************************/
|
||||
Storage *
|
||||
storageNew(const String *path, StorageNewParam param)
|
||||
{
|
||||
Storage *this = NULL;
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STRING, path);
|
||||
FUNCTION_DEBUG_PARAM(MODE, param.modeFile);
|
||||
FUNCTION_DEBUG_PARAM(MODE, param.modePath);
|
||||
FUNCTION_DEBUG_PARAM(SIZE, param.bufferSize);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.write);
|
||||
FUNCTION_DEBUG_PARAM(FUNCTIONP, param.pathExpressionFunction);
|
||||
|
||||
// Path is required
|
||||
if (path == NULL)
|
||||
THROW(AssertError, "storage base path cannot be null");
|
||||
FUNCTION_DEBUG_ASSERT(path != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
Storage *this = NULL;
|
||||
|
||||
// Create the storage
|
||||
MEM_CONTEXT_NEW_BEGIN("Storage")
|
||||
@ -56,7 +58,7 @@ storageNew(const String *path, StorageNewParam param)
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
return this;
|
||||
FUNCTION_DEBUG_RESULT(STORAGE, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -65,6 +67,14 @@ Copy a file
|
||||
bool
|
||||
storageCopy(StorageFileRead *source, StorageFileWrite *destination)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_READ, source);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_WRITE, destination);
|
||||
|
||||
FUNCTION_TEST_ASSERT(source != NULL);
|
||||
FUNCTION_TEST_ASSERT(destination != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -95,7 +105,7 @@ storageCopy(StorageFileRead *source, StorageFileWrite *destination)
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -104,10 +114,16 @@ Does a file/path exist?
|
||||
bool
|
||||
storageExists(const Storage *this, const String *pathExp, StorageExistsParam param)
|
||||
{
|
||||
bool result = false;
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, this);
|
||||
FUNCTION_DEBUG_PARAM(STRING, pathExp);
|
||||
FUNCTION_DEBUG_PARAM(DOUBLE, param.timeout);
|
||||
|
||||
// Timeout can't be negative
|
||||
ASSERT_DEBUG(param.timeout >= 0);
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(param.timeout >= 0);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool result = false;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
@ -127,7 +143,7 @@ storageExists(const Storage *this, const String *pathExp, StorageExistsParam par
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -136,9 +152,13 @@ Read from storage into a buffer
|
||||
Buffer *
|
||||
storageGet(StorageFileRead *file)
|
||||
{
|
||||
Buffer *result = NULL;
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_READ, file);
|
||||
|
||||
ASSERT_DEBUG(file != NULL);
|
||||
FUNCTION_TEST_ASSERT(file != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
Buffer *result = NULL;
|
||||
|
||||
// If the file exists
|
||||
if (storageFileReadOpen(file))
|
||||
@ -166,7 +186,7 @@ storageGet(StorageFileRead *file)
|
||||
storageFileReadClose(file);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(BUFFER, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -175,6 +195,14 @@ File/path info
|
||||
StorageInfo
|
||||
storageInfo(const Storage *this, const String *fileExp, StorageInfoParam param)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, this);
|
||||
FUNCTION_DEBUG_PARAM(STRING, fileExp);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.ignoreMissing);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
StorageInfo result = {0};
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -187,7 +215,7 @@ storageInfo(const Storage *this, const String *fileExp, StorageInfoParam param)
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(STORAGE_INFO, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -196,6 +224,15 @@ Get a list of files from a directory
|
||||
StringList *
|
||||
storageList(const Storage *this, const String *pathExp, StorageListParam param)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, this);
|
||||
FUNCTION_DEBUG_PARAM(STRING, pathExp);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.errorOnMissing);
|
||||
FUNCTION_DEBUG_PARAM(STRING, param.expression);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
StringList *result = NULL;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -208,7 +245,7 @@ storageList(const Storage *this, const String *pathExp, StorageListParam param)
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(STRING_LIST, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -217,7 +254,14 @@ Move a file
|
||||
void
|
||||
storageMove(StorageFileRead *source, StorageFileWrite *destination)
|
||||
{
|
||||
ASSERT_DEBUG(!storageFileReadIgnoreMissing(source));
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_READ, source);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_WRITE, destination);
|
||||
|
||||
FUNCTION_TEST_ASSERT(source != NULL);
|
||||
FUNCTION_TEST_ASSERT(destination != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(!storageFileReadIgnoreMissing(source));
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
@ -237,6 +281,8 @@ storageMove(StorageFileRead *source, StorageFileWrite *destination)
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -245,6 +291,14 @@ Open a file for reading
|
||||
StorageFileRead *
|
||||
storageNewRead(const Storage *this, const String *fileExp, StorageNewReadParam param)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, this);
|
||||
FUNCTION_DEBUG_PARAM(STRING, fileExp);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.ignoreMissing);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
StorageFileRead *result = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("StorageFileRead")
|
||||
@ -256,7 +310,7 @@ storageNewRead(const Storage *this, const String *fileExp, StorageNewReadParam p
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(STORAGE_FILE_READ, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -265,9 +319,21 @@ Open a file for writing
|
||||
StorageFileWrite *
|
||||
storageNewWrite(const Storage *this, const String *fileExp, StorageNewWriteParam param)
|
||||
{
|
||||
StorageFileWrite *result = NULL;
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, this);
|
||||
FUNCTION_DEBUG_PARAM(STRING, fileExp);
|
||||
FUNCTION_DEBUG_PARAM(MODE, param.modeFile);
|
||||
FUNCTION_DEBUG_PARAM(MODE, param.modePath);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.noCreatePath);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.noSyncFile);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.noSyncPath);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.noAtomic);
|
||||
|
||||
ASSERT_STORAGE_ALLOWS_WRITE();
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(this->write);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
StorageFileWrite *result = NULL;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
@ -283,7 +349,7 @@ storageNewWrite(const Storage *this, const String *fileExp, StorageNewWriteParam
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(STORAGE_FILE_WRITE, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -292,6 +358,13 @@ Get the absolute path in the storage
|
||||
String *
|
||||
storagePath(const Storage *this, const String *pathExp)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STORAGE, this);
|
||||
FUNCTION_TEST_PARAM(STRING, pathExp);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
String *result = NULL;
|
||||
|
||||
// If there there is no path expression then return the base storage path
|
||||
@ -378,7 +451,7 @@ storagePath(const Storage *this, const String *pathExp)
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(STRING, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -387,11 +460,21 @@ Create a path
|
||||
void
|
||||
storagePathCreate(const Storage *this, const String *pathExp, StoragePathCreateParam param)
|
||||
{
|
||||
ASSERT_STORAGE_ALLOWS_WRITE();
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, this);
|
||||
FUNCTION_DEBUG_PARAM(STRING, pathExp);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.errorOnExists);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.noParentCreate);
|
||||
FUNCTION_DEBUG_PARAM(MODE, param.mode);
|
||||
|
||||
// It doesn't make sense to combine these parameters because if we are creating missing parent paths why error when they exist?
|
||||
// If this somehow wasn't caught in testing, the worst case is that the path would not be created and an error would be thrown.
|
||||
ASSERT_DEBUG(!(param.noParentCreate && param.errorOnExists));
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(this->write);
|
||||
|
||||
// It doesn't make sense to combine these parameters because if we are creating missing parent paths why error when they
|
||||
// exist? If this somehow wasn't caught in testing, the worst case is that the path would not be created and an error would
|
||||
// be thrown.
|
||||
FUNCTION_TEST_ASSERT(!(param.noParentCreate && param.errorOnExists));
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
@ -403,6 +486,8 @@ storagePathCreate(const Storage *this, const String *pathExp, StoragePathCreateP
|
||||
path, param.errorOnExists, param.noParentCreate, param.mode != 0 ? param.mode : this->modePath);
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -411,7 +496,15 @@ Remove a path
|
||||
void
|
||||
storagePathRemove(const Storage *this, const String *pathExp, StoragePathRemoveParam param)
|
||||
{
|
||||
ASSERT_STORAGE_ALLOWS_WRITE();
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, this);
|
||||
FUNCTION_DEBUG_PARAM(STRING, pathExp);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.errorOnMissing);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.recurse);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(this->write);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
@ -422,6 +515,8 @@ storagePathRemove(const Storage *this, const String *pathExp, StoragePathRemoveP
|
||||
storageDriverPosixPathRemove(path, param.errorOnMissing, param.recurse);
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -429,7 +524,14 @@ Sync a path
|
||||
***********************************************************************************************************************************/
|
||||
void storagePathSync(const Storage *this, const String *pathExp, StoragePathSyncParam param)
|
||||
{
|
||||
ASSERT_STORAGE_ALLOWS_WRITE();
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, this);
|
||||
FUNCTION_DEBUG_PARAM(STRING, pathExp);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.ignoreMissing);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(this->write);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
@ -440,6 +542,8 @@ void storagePathSync(const Storage *this, const String *pathExp, StoragePathSync
|
||||
storageDriverPosixPathSync(path, param.ignoreMissing);
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -448,9 +552,18 @@ Write a buffer to storage
|
||||
void
|
||||
storagePut(StorageFileWrite *file, const Buffer *buffer)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE_FILE_WRITE, file);
|
||||
FUNCTION_DEBUG_PARAM(BUFFER, buffer);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(file != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
storageFileWriteOpen(file);
|
||||
storageFileWrite(file, buffer);
|
||||
storageFileWriteClose(file);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -459,7 +572,14 @@ Remove a file
|
||||
void
|
||||
storageRemove(const Storage *this, const String *fileExp, StorageRemoveParam param)
|
||||
{
|
||||
ASSERT_STORAGE_ALLOWS_WRITE();
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, this);
|
||||
FUNCTION_DEBUG_PARAM(STRING, fileExp);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, param.errorOnMissing);
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(this->write);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
@ -470,6 +590,32 @@ storageRemove(const Storage *this, const String *fileExp, StorageRemoveParam par
|
||||
storageDriverPosixRemove(file, param.errorOnMissing);
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert to a zero-terminated string for logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t
|
||||
storageToLog(const Storage *this, char *buffer, size_t bufferSize)
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
String *string = NULL;
|
||||
|
||||
if (this == NULL)
|
||||
string = strNew("null");
|
||||
else
|
||||
string = strNewFmt("{path: %s, write: %s}", strPtr(strQuoteZ(this->path, "\"")), this->write ? "true" : "false");
|
||||
|
||||
result = (size_t)snprintf(buffer, bufferSize, "%s", strPtr(string));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -478,6 +624,12 @@ Free storage
|
||||
void
|
||||
storageFree(const Storage *this)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, this);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
if (this != NULL)
|
||||
memContextFree(this->memContext);
|
||||
|
||||
FUNCTION_DEBUG_RESULT_VOID();
|
||||
}
|
||||
|
@ -247,4 +247,14 @@ storageFree
|
||||
|
||||
void storageFree(const Storage *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
size_t storageToLog(const Storage *this, char *buffer, size_t bufferSize);
|
||||
|
||||
#define FUNCTION_DEBUG_STORAGE_TYPE \
|
||||
Storage *
|
||||
#define FUNCTION_DEBUG_STORAGE_FORMAT(value, buffer, bufferSize) \
|
||||
(size_t)storageToLog(value, buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
5
test/Vagrantfile
vendored
5
test/Vagrantfile
vendored
@ -43,9 +43,8 @@ Vagrant.configure(2) do |config|
|
||||
# Set time sync settings so builds don't fail with clock drift errors
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
echo 'Time Sync Settings' && date
|
||||
/etc/init.d/virtualbox-guest-utils stop
|
||||
/usr/sbin/VBoxService --timesync-set-on-restore 1 --timesync-interval 5000 --timesync-set-threshold 1
|
||||
/etc/init.d/virtualbox-guest-utils start
|
||||
sudo /etc/init.d/virtualbox-guest-utils stop
|
||||
sudo /usr/sbin/VBoxService --timesync-set-on-restore 1 --timesync-interval 5000 --timesync-set-threshold 1
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
echo 'Install Perl Modules' && date
|
||||
|
@ -33,18 +33,10 @@ unit:
|
||||
- name: common
|
||||
|
||||
test:
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: time
|
||||
total: 2
|
||||
define: -DNO_ERROR -DNO_LOG
|
||||
|
||||
coverage:
|
||||
common/time: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: error
|
||||
total: 8
|
||||
define: -DNO_ERROR -DNO_LOG
|
||||
define: -DNO_ERROR -DNO_LOG -DNO_STACK_TRACE -DNO_MEM_CONTEXT
|
||||
|
||||
coverage:
|
||||
common/error: full
|
||||
@ -53,7 +45,7 @@ unit:
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: assert-on
|
||||
total: 2
|
||||
define: -DNO_LOG
|
||||
define: -DNO_LOG -DNO_STACK_TRACE -DNO_MEM_CONTEXT
|
||||
|
||||
coverage:
|
||||
common/assert: noCode
|
||||
@ -61,19 +53,19 @@ unit:
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: assert-off
|
||||
total: 2
|
||||
define: -DNDEBUG -DNO_LOG
|
||||
define: -DNDEBUG -DNO_LOG -DNO_STACK_TRACE -DNO_MEM_CONTEXT
|
||||
debugUnitSuppress: true
|
||||
|
||||
coverage:
|
||||
common/assert: noCode
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: fork
|
||||
total: 1
|
||||
define: -DNO_LOG
|
||||
- name: stack-trace
|
||||
total: 4
|
||||
define: -DNO_LOG -DNO_STACK_TRACE -DNO_MEM_CONTEXT
|
||||
|
||||
coverage:
|
||||
common/fork: full
|
||||
common/stackTrace: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: mem-context
|
||||
@ -83,20 +75,36 @@ unit:
|
||||
coverage:
|
||||
common/memContext: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: time
|
||||
total: 2
|
||||
define: -DNO_ERROR -DNO_LOG
|
||||
|
||||
coverage:
|
||||
common/time: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: fork
|
||||
total: 1
|
||||
define: -DNO_LOG
|
||||
|
||||
coverage:
|
||||
common/fork: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: log
|
||||
total: 5
|
||||
define: -DNO_LOG
|
||||
define: -DIN_LOG
|
||||
|
||||
coverage:
|
||||
common/log: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: debug-on
|
||||
total: 2
|
||||
total: 4
|
||||
|
||||
coverage:
|
||||
common/debug: noCode
|
||||
common/debug: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: debug-off
|
||||
@ -105,7 +113,7 @@ unit:
|
||||
debugUnitSuppress: true
|
||||
|
||||
coverage:
|
||||
common/debug: noCode
|
||||
common/debug: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: lock
|
||||
@ -135,6 +143,13 @@ unit:
|
||||
coverage:
|
||||
common/wait: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: type-convert
|
||||
total: 8
|
||||
|
||||
coverage:
|
||||
common/type/convert: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: type-list
|
||||
total: 3
|
||||
@ -144,14 +159,14 @@ unit:
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: type-string
|
||||
total: 11
|
||||
total: 13
|
||||
|
||||
coverage:
|
||||
common/type/string: full
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: type-string-list
|
||||
total: 8
|
||||
total: 9
|
||||
|
||||
coverage:
|
||||
common/type/stringList: full
|
||||
@ -165,7 +180,7 @@ unit:
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: type-variant
|
||||
total: 7
|
||||
total: 8
|
||||
|
||||
coverage:
|
||||
common/type/variant: full
|
||||
|
@ -83,8 +83,12 @@ full backup - create pg_stat link, pg_clog dir (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --manifest-save-threshold=3 --buffer-size=16384 --checksum-page --process-max=1 --repo1-type=cifs --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --buffer-size=16384 --checksum-page --no-compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --manifest-save-threshold=3 --no-online --pg1-path=[TEST_PATH]/db-master/db/base --process-max=1 --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --repo1-type=cifs --stanza=db --start-fast --type=full
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/db-master/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 16384, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/db-master/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -292,8 +296,10 @@ P00 DEBUG: Storage::Local->openWrite(): bAtomic = <false>, bPathCreate = <f
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/repo/backup/db
|
||||
P00 DEBUG: Storage::Local->openWrite(): bAtomic = <false>, bPathCreate = <false>, lTimestamp = [undef], rhyFilter = [undef], strCipherPass = [undef], strGroup = [undef], strMode = <0640>, strUser = [undef], xFileExp = [TEST_PATH]/db-master/repo/backup/db/backup.info.copy
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/repo/backup/db
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 INFO: backup command end: completed successfully
|
||||
P00 INFO: expire command begin
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
P00 DEBUG: Storage::Local->pathExists=>: bExists = true
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 0770, strPathExp = [TEST_PATH]/db-master/log
|
||||
@ -324,10 +330,16 @@ P00 DEBUG: Storage::Local->list=>: stryFileList = ([BACKUP-FULL-1])
|
||||
P00 DEBUG: Backup::Info->current(): strBackup = [BACKUP-FULL-1]
|
||||
P00 DEBUG: Backup::Info->current=>: bTest = true
|
||||
P00 INFO: option 'repo1-retention-archive' is not set - archive logs will not be expired
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: expire command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf
|
||||
----------------------------------------------------------
|
||||
@ -466,27 +478,39 @@ full backup - invalid cmd line (db-master host)
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
STDERR:
|
||||
ERROR: [037]: backup command requires option: pg1-path
|
||||
HINT: does this stanza exist?
|
||||
HINT: does this stanza exist?
|
||||
|
||||
stop all stanzas (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --force stop
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stop command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-path=[TEST_PATH]/db-master/repo
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBufferMax = [undef], oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = /, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 770, strPathExp = [TEST_PATH]/db-master/lock
|
||||
P00 INFO: sent term signal to process [PROCESS-ID]
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: stop command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
full backup - abort backup - local (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --type=full --stanza=db backup --test --test-delay=5 --test-point=backup-start=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --test --test-delay=5 --test-point=backup-start=y --type=full
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/db-master/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/db-master/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -563,8 +587,12 @@ full backup - global stop (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --type=full
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/db-master/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/db-master/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -574,42 +602,67 @@ P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBu
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 0770, strPathExp = [TEST_PATH]/db-master/log
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
P00 ERROR: [062]: stop file exists for all stanzas
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: true, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 62
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = false, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: backup command end: aborted with exception [062]
|
||||
P00 DEBUG: common/exit::exitSafe: => 62
|
||||
P00 DEBUG: main::main: => 62
|
||||
|
||||
stop db stanza (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db stop
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stop command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBufferMax = [undef], oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = /, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 770, strPathExp = [TEST_PATH]/db-master/lock
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: stop command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
stop db stanza (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db stop
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stop command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBufferMax = [undef], oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = /, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 770, strPathExp = [TEST_PATH]/db-master/lock
|
||||
P00 WARN: stop file already exists for stanza db
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: stop command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
full backup - stanza stop (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --type=full
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/db-master/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/db-master/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -619,45 +672,78 @@ P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBu
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 0770, strPathExp = [TEST_PATH]/db-master/log
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
P00 ERROR: [062]: stop file exists for stanza db
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: true, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 62
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = false, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: backup command end: aborted with exception [062]
|
||||
P00 DEBUG: common/exit::exitSafe: => 62
|
||||
P00 DEBUG: main::main: => 62
|
||||
|
||||
start db stanza (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db start
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: start command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: start command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
start all stanzas (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf start
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: start command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-path=[TEST_PATH]/db-master/repo
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: start command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
start all stanzas (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf start
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: start command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-path=[TEST_PATH]/db-master/repo
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 WARN: stop file does not exist
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: start command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
full backup - resume (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --force --checksum-page --type=full --stanza=db backup --test --test-delay=0.2 --test-point=backup-resume=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --checksum-page --no-compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --test --test-delay=0.2 --test-point=backup-resume=y --type=full
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/db-master/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/db-master/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -861,8 +947,10 @@ P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/r
|
||||
P00 DEBUG: Storage::Local->openWrite(): bAtomic = <false>, bPathCreate = <false>, lTimestamp = [undef], rhyFilter = [undef], strCipherPass = [undef], strGroup = [undef], strMode = <0640>, strUser = [undef], xFileExp = [TEST_PATH]/db-master/repo/backup/db/backup.info.copy
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/repo/backup/db
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = <REPO:BACKUP>
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 INFO: backup command end: completed successfully
|
||||
P00 INFO: expire command begin
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
P00 DEBUG: Storage::Local->pathExists=>: bExists = true
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 0770, strPathExp = [TEST_PATH]/db-master/log
|
||||
@ -893,10 +981,16 @@ P00 DEBUG: Storage::Local->list=>: stryFileList = ([BACKUP-FULL-2])
|
||||
P00 DEBUG: Backup::Info->current(): strBackup = [BACKUP-FULL-2]
|
||||
P00 DEBUG: Backup::Info->current=>: bTest = true
|
||||
P00 INFO: option 'repo1-retention-archive' is not set - archive logs will not be expired
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: expire command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf
|
||||
----------------------------------------------------------
|
||||
@ -1043,6 +1137,8 @@ restore delta, backup '[BACKUP-FULL-2]' - add and delete files (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --delta --set=[BACKUP-FULL-2] --link-all --stanza=db restore
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: restore command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --delta --link-all --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --set=[BACKUP-FULL-2] --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/db-master/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -1338,10 +1434,16 @@ P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/d
|
||||
P00 DEBUG: Storage::Local->remove(): bIgnoreMissing = <true>, bRecurse = <false>, xstryPathFileExp = [TEST_PATH]/db-master/db/base/backup.manifest
|
||||
P00 DEBUG: Storage::Local->remove=>: bRemoved = true
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/db/base
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: restore command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/db/base/recovery.conf
|
||||
----------------------------------------------------------------
|
||||
@ -1725,8 +1827,12 @@ incr backup - add tablespace 1 (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --test --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --test
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/db-master/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/db-master/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -1907,8 +2013,10 @@ P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/r
|
||||
P00 DEBUG: Storage::Local->openWrite(): bAtomic = <false>, bPathCreate = <false>, lTimestamp = [undef], rhyFilter = [undef], strCipherPass = [undef], strGroup = [undef], strMode = <0640>, strUser = [undef], xFileExp = [TEST_PATH]/db-master/repo/backup/db/backup.info.copy
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/repo/backup/db
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = <REPO:BACKUP>
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 INFO: backup command end: completed successfully
|
||||
P00 INFO: expire command begin
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
P00 DEBUG: Storage::Local->pathExists=>: bExists = true
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 0770, strPathExp = [TEST_PATH]/db-master/log
|
||||
@ -1947,10 +2055,16 @@ P00 DEBUG: Backup::Info->current=>: bTest = true
|
||||
P00 DEBUG: Backup::Info->current(): strBackup = [BACKUP-FULL-2]
|
||||
P00 DEBUG: Backup::Info->current=>: bTest = true
|
||||
P00 INFO: option 'repo1-retention-archive' is not set - archive logs will not be expired
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: expire command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf
|
||||
----------------------------------------------------------
|
||||
@ -2091,8 +2205,12 @@ incr backup - resume and add tablespace 2 (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --process-max=1 --stanza=db backup --test --test-delay=0.2 --test-point=backup-resume=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --process-max=1 --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --test --test-delay=0.2 --test-point=backup-resume=y
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/db-master/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/db-master/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -2317,8 +2435,10 @@ P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/r
|
||||
P00 DEBUG: Storage::Local->openWrite(): bAtomic = <false>, bPathCreate = <false>, lTimestamp = [undef], rhyFilter = [undef], strCipherPass = [undef], strGroup = [undef], strMode = <0640>, strUser = [undef], xFileExp = [TEST_PATH]/db-master/repo/backup/db/backup.info.copy
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/repo/backup/db
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = <REPO:BACKUP>
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 INFO: backup command end: completed successfully
|
||||
P00 INFO: expire command begin
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
P00 DEBUG: Storage::Local->pathExists=>: bExists = true
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 0770, strPathExp = [TEST_PATH]/db-master/log
|
||||
@ -2357,10 +2477,16 @@ P00 DEBUG: Backup::Info->current=>: bTest = true
|
||||
P00 DEBUG: Backup::Info->current(): strBackup = [BACKUP-FULL-2]
|
||||
P00 DEBUG: Backup::Info->current=>: bTest = true
|
||||
P00 INFO: option 'repo1-retention-archive' is not set - archive logs will not be expired
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: expire command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf
|
||||
----------------------------------------------------------
|
||||
@ -2848,6 +2974,8 @@ restore, backup '[BACKUP-DIFF-2]', remap - remap all paths (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --set=[BACKUP-DIFF-2] --stanza=db restore
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: restore command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base-2 --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --set=[BACKUP-DIFF-2] --stanza=db --tablespace-map=1=[TEST_PATH]/db-master/db/tablespace/ts1-2 --tablespace-map=2=[TEST_PATH]/db-master/db/tablespace/ts2-2
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/db-master/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -3143,10 +3271,16 @@ P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/d
|
||||
P00 DEBUG: Storage::Local->remove(): bIgnoreMissing = <true>, bRecurse = <false>, xstryPathFileExp = [TEST_PATH]/db-master/db/base-2/backup.manifest
|
||||
P00 DEBUG: Storage::Local->remove=>: bRemoved = true
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/db/base-2
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: restore command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/db/base-2/recovery.conf
|
||||
------------------------------------------------------------------
|
||||
|
@ -71,8 +71,12 @@ full backup - create pg_stat link, pg_clog dir (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --manifest-save-threshold=3 --protocol-timeout=2 --db-timeout=1 --cmd-ssh=/usr/bin/ssh --pg1-port=9999 --pg1-socket-path =/test_socket_path --buffer-size=16384 --checksum-page --process-max=1 --repo1-type=cifs --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --buffer-size=16384 --checksum-page --cmd-ssh=/usr/bin/ssh --no-compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=1 --lock-path=[TEST_PATH]/backup/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --no-log-timestamp --manifest-save-threshold=3 --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --pg1-port=9999 --pg1-socket-path==/test_socket_path --process-max=1 --protocol-timeout=2 --repo1-path=[TEST_PATH]/backup/repo --repo1-type=cifs --stanza=db --start-fast --type=full
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/backup/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 16384, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/backup/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -284,8 +288,10 @@ P00 DEBUG: Storage::Local->openWrite(): bAtomic = <false>, bPathCreate = <f
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/backup/repo/backup/db
|
||||
P00 DEBUG: Storage::Local->openWrite(): bAtomic = <false>, bPathCreate = <false>, lTimestamp = [undef], rhyFilter = [undef], strCipherPass = [undef], strGroup = [undef], strMode = <0640>, strUser = [undef], xFileExp = [TEST_PATH]/backup/repo/backup/db/backup.info.copy
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/backup/repo/backup/db
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 INFO: backup command end: completed successfully
|
||||
P00 INFO: expire command begin
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
P00 DEBUG: Storage::Local->pathExists=>: bExists = true
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 0770, strPathExp = [TEST_PATH]/backup/log
|
||||
@ -316,10 +322,16 @@ P00 DEBUG: Storage::Local->list=>: stryFileList = ([BACKUP-FULL-1])
|
||||
P00 DEBUG: Backup::Info->current(): strBackup = [BACKUP-FULL-1]
|
||||
P00 DEBUG: Backup::Info->current=>: bTest = true
|
||||
P00 INFO: option 'repo1-retention-archive' is not set - archive logs will not be expired
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: expire command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf
|
||||
----------------------------------------------------------
|
||||
@ -482,21 +494,33 @@ stop all stanzas (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --force stop
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stop command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2]
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBufferMax = [undef], oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = /, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 770, strPathExp = [TEST_PATH]/db-master/lock
|
||||
P00 INFO: sent term signal to process [PROCESS-ID]
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: stop command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
full backup - abort backup - local (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --type=full --stanza=db backup --test --test-delay=5 --test-point=backup-start=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/backup/repo --stanza=db --start-fast --test --test-delay=5 --test-point=backup-start=y --type=full
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/backup/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/backup/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -589,18 +613,27 @@ P00 TEST: PgBaCkReStTeSt-BACKUP-START-PgBaCkReStTeSt
|
||||
P00 DEBUG: Protocol::Helper::protocolGet(): bCache = <true>, iProcessIdx = [undef], iRemoteIdx = 1, strBackRestBin = [undef], strCommand = <backup>, strRemoteType = db
|
||||
P00 DEBUG: Protocol::Helper::protocolGet: found cached protocol
|
||||
P00 ERROR: [063]: remote process on 'db-master' terminated unexpectedly [063]
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: true, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 63
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = false, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy: found cached protocol: iRemoteIdx = 1, strRemoteType = db
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: backup command end: terminated on signal from child process
|
||||
P00 DEBUG: common/exit::exitSafe: => 63
|
||||
P00 DEBUG: main::main: => 63
|
||||
|
||||
full backup - global stop (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/backup/repo --stanza=db --start-fast --type=full
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/backup/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/backup/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -642,42 +675,67 @@ P00 DEBUG: Protocol::Remote::Master->new(): iBufferMax = 4194304, iCompress
|
||||
P00 DEBUG: Protocol::Command::Master->new(): iBufferMax = 4194304, iCompressLevel = 3, iCompressLevelNetwork = 1, iProtocolTimeout = 60, strCommand = ssh -o LogLevel=error -o Compression=no -o PasswordAuthentication=no [USER-1]@db-master '[BACKREST-BIN] --buffer-size=4194304 --command=backup --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/backup/repo --stanza=db --type=db remote', strId = remote process on 'db-master', strName = remote
|
||||
P00 ERROR: [062]: raised from remote process on 'db-master': stop file exists for all stanzas
|
||||
P00 DEBUG: Protocol::Command::Master->close=>: iExitStatus = 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: true, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 62
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = false, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: backup command end: aborted with exception [062]
|
||||
P00 DEBUG: common/exit::exitSafe: => 62
|
||||
P00 DEBUG: main::main: => 62
|
||||
|
||||
stop db stanza (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db stop
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stop command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2] --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBufferMax = [undef], oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = /, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 770, strPathExp = [TEST_PATH]/db-master/lock
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: stop command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
stop db stanza (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db stop
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stop command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2] --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBufferMax = [undef], oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = /, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 770, strPathExp = [TEST_PATH]/db-master/lock
|
||||
P00 WARN: stop file already exists for stanza db
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: stop command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
full backup - stanza stop (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/backup/repo --stanza=db --start-fast --type=full
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/backup/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/backup/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -719,58 +777,99 @@ P00 DEBUG: Protocol::Remote::Master->new(): iBufferMax = 4194304, iCompress
|
||||
P00 DEBUG: Protocol::Command::Master->new(): iBufferMax = 4194304, iCompressLevel = 3, iCompressLevelNetwork = 1, iProtocolTimeout = 60, strCommand = ssh -o LogLevel=error -o Compression=no -o PasswordAuthentication=no [USER-1]@db-master '[BACKREST-BIN] --buffer-size=4194304 --command=backup --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/backup/repo --stanza=db --type=db remote', strId = remote process on 'db-master', strName = remote
|
||||
P00 ERROR: [062]: raised from remote process on 'db-master': stop file exists for stanza db
|
||||
P00 DEBUG: Protocol::Command::Master->close=>: iExitStatus = 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: true, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 62
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = false, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: backup command end: aborted with exception [062]
|
||||
P00 DEBUG: common/exit::exitSafe: => 62
|
||||
P00 DEBUG: main::main: => 62
|
||||
|
||||
start db stanza (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db start
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: start command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2] --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: start command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
start all stanzas (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf start
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: start command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2]
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: start command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
start all stanzas (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf start
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: start command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2]
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 WARN: stop file does not exist
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: start command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
stop all stanzas (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --force stop
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stop command begin [BACKREST-VERSION]: --config=[TEST_PATH]/backup/pgbackrest.conf --force --lock-path=[TEST_PATH]/backup/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --no-log-timestamp --repo1-path=[TEST_PATH]/backup/repo
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBufferMax = [undef], oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = /, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 770, strPathExp = [TEST_PATH]/backup/lock
|
||||
P00 INFO: sent term signal to process [PROCESS-ID]
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: stop command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
full backup - abort backup - remote (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --type=full --stanza=db backup --test --test-delay=5 --test-point=backup-start=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/backup/repo --stanza=db --start-fast --test --test-delay=5 --test-point=backup-start=y --type=full
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/backup/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/backup/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -871,8 +970,12 @@ full backup - global stop (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/backup/repo --stanza=db --start-fast --type=full
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/backup/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/backup/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -882,26 +985,43 @@ P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBu
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 0770, strPathExp = [TEST_PATH]/backup/log
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
P00 ERROR: [062]: stop file exists for all stanzas
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: true, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 62
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = false, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: backup command end: aborted with exception [062]
|
||||
P00 DEBUG: common/exit::exitSafe: => 62
|
||||
P00 DEBUG: main::main: => 62
|
||||
|
||||
start all stanzas (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf start
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: start command begin [BACKREST-VERSION]: --config=[TEST_PATH]/backup/pgbackrest.conf --lock-path=[TEST_PATH]/backup/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --no-log-timestamp --repo1-path=[TEST_PATH]/backup/repo
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: start command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
full backup - resume (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --force --checksum-page --type=full --stanza=db backup --test --test-delay=0.2 --test-point=backup-resume=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --checksum-page --no-compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/backup/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/backup/repo --stanza=db --start-fast --test --test-delay=0.2 --test-point=backup-resume=y --type=full
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/backup/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/backup/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -1102,8 +1222,10 @@ P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/backup/repo
|
||||
P00 DEBUG: Storage::Local->openWrite(): bAtomic = <false>, bPathCreate = <false>, lTimestamp = [undef], rhyFilter = [undef], strCipherPass = [undef], strGroup = [undef], strMode = <0640>, strUser = [undef], xFileExp = [TEST_PATH]/backup/repo/backup/db/backup.info.copy
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/backup/repo/backup/db
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = <REPO:BACKUP>
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 INFO: backup command end: completed successfully
|
||||
P00 INFO: expire command begin
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
P00 DEBUG: Storage::Local->pathExists=>: bExists = true
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 0770, strPathExp = [TEST_PATH]/backup/log
|
||||
@ -1134,10 +1256,16 @@ P00 DEBUG: Storage::Local->list=>: stryFileList = ([BACKUP-FULL-2])
|
||||
P00 DEBUG: Backup::Info->current(): strBackup = [BACKUP-FULL-2]
|
||||
P00 DEBUG: Backup::Info->current=>: bTest = true
|
||||
P00 INFO: option 'repo1-retention-archive' is not set - archive logs will not be expired
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: expire command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf
|
||||
----------------------------------------------------------
|
||||
@ -1304,6 +1432,8 @@ restore delta, backup '[BACKUP-FULL-2]' - add and delete files (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --delta --set=[BACKUP-FULL-2] --link-all --cmd-ssh=/usr/bin/ssh --stanza=db restore
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: restore command begin [BACKREST-VERSION]: --cmd-ssh=/usr/bin/ssh --no-compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/db-master/pgbackrest.conf --delta --link-all --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2] --set=[BACKUP-FULL-2] --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = /, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 0770, strPathExp = [TEST_PATH]/db-master/log
|
||||
@ -1539,12 +1669,18 @@ P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/d
|
||||
P00 DEBUG: Storage::Local->remove(): bIgnoreMissing = <true>, bRecurse = <false>, xstryPathFileExp = [TEST_PATH]/db-master/db/base/backup.manifest
|
||||
P00 DEBUG: Storage::Local->remove=>: bRemoved = true
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/db-master/db/base
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy: found cached protocol: iRemoteIdx = 1, strRemoteType = backup
|
||||
P00 DEBUG: Protocol::Command::Master->close=>: iExitStatus = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: restore command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/db/base/recovery.conf
|
||||
----------------------------------------------------------------
|
||||
@ -1757,8 +1893,12 @@ incr backup - add tablespace 1 (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --test --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/backup/repo --stanza=db --start-fast --test
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/backup/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/backup/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -1936,8 +2076,10 @@ P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/backup/repo
|
||||
P00 DEBUG: Storage::Local->openWrite(): bAtomic = <false>, bPathCreate = <false>, lTimestamp = [undef], rhyFilter = [undef], strCipherPass = [undef], strGroup = [undef], strMode = <0640>, strUser = [undef], xFileExp = [TEST_PATH]/backup/repo/backup/db/backup.info.copy
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/backup/repo/backup/db
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = <REPO:BACKUP>
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 INFO: backup command end: completed successfully
|
||||
P00 INFO: expire command begin
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
P00 DEBUG: Storage::Local->pathExists=>: bExists = true
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 0770, strPathExp = [TEST_PATH]/backup/log
|
||||
@ -1976,10 +2118,16 @@ P00 DEBUG: Backup::Info->current=>: bTest = true
|
||||
P00 DEBUG: Backup::Info->current(): strBackup = [BACKUP-FULL-2]
|
||||
P00 DEBUG: Backup::Info->current=>: bTest = true
|
||||
P00 INFO: option 'repo1-retention-archive' is not set - archive logs will not be expired
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: expire command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf
|
||||
----------------------------------------------------------
|
||||
@ -2140,8 +2288,12 @@ incr backup - resume and add tablespace 2 (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --process-max=1 --stanza=db backup --test --test-delay=0.2 --test-point=backup-resume=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: backup command begin [BACKREST-VERSION]: --no-compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/backup/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --process-max=1 --protocol-timeout=60 --repo1-path=[TEST_PATH]/backup/repo --stanza=db --start-fast --test --test-delay=0.2 --test-point=backup-resume=y
|
||||
P00 DEBUG: common/lock::lockAcquire: (lockPath: {"[TEST_PATH]/backup/lock"}, stanza: {"db"}, lockType: 1, lockTimeout: 0, failOnNoLock: true)
|
||||
P00 DEBUG: common/lock::lockAcquire: => true
|
||||
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
|
||||
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [hash], lBufferMax = 4194304, oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = [TEST_PATH]/backup/repo, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
@ -2363,8 +2515,10 @@ P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/backup/repo
|
||||
P00 DEBUG: Storage::Local->openWrite(): bAtomic = <false>, bPathCreate = <false>, lTimestamp = [undef], rhyFilter = [undef], strCipherPass = [undef], strGroup = [undef], strMode = <0640>, strUser = [undef], xFileExp = [TEST_PATH]/backup/repo/backup/db/backup.info.copy
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = [TEST_PATH]/backup/repo/backup/db
|
||||
P00 DEBUG: Storage::Local->pathSync(): strPathExp = <REPO:BACKUP>
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 INFO: backup command end: completed successfully
|
||||
P00 INFO: expire command begin
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Local->pathExists(): strPathExp =
|
||||
P00 DEBUG: Storage::Local->pathExists=>: bExists = true
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 0770, strPathExp = [TEST_PATH]/backup/log
|
||||
@ -2403,10 +2557,16 @@ P00 DEBUG: Backup::Info->current=>: bTest = true
|
||||
P00 DEBUG: Backup::Info->current(): strBackup = [BACKUP-FULL-2]
|
||||
P00 DEBUG: Backup::Info->current=>: bTest = true
|
||||
P00 INFO: option 'repo1-retention-archive' is not set - archive logs will not be expired
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => true
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: expire command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf
|
||||
----------------------------------------------------------
|
||||
|
@ -68,6 +68,8 @@ db-version="9.4"
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push --log-level-console=debug [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --no-compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Push::Push->process(): strWalPathFile = [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
P00 DEBUG: Common::Lock::lockStopTest=>: bStopExists = false
|
||||
@ -105,14 +107,23 @@ P00 DEBUG: Storage::Local->openWrite(): bAtomic = true, bPathCreate = true,
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Push::File::archivePushFile=>: strWarning = [undef]
|
||||
P00 INFO: pushed WAL segment 000000010000000100000001
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-push command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-get --log-level-console=debug 000000010000000100000001 [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-get command begin [BACKREST-VERSION]: [000000010000000100000001, [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG] --no-compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: command/archive/get/get::cmdArchiveGet: (void)
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Get::Get->process(): rstryCommandArg = (000000010000000100000001, [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG)
|
||||
P00 DEBUG: Archive::Get::File::archiveGetFile(): bAtomic = false, strDestinationFile = [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG, strSourceArchive = 000000010000000100000001
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
@ -149,10 +160,17 @@ P00 DEBUG: Storage::Local->openWrite(): bAtomic = false, bPathCreate = <fal
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Get::File::archiveGetFile=>: iResult = 0
|
||||
P00 INFO: got WAL segment 000000010000000100000001
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: command/archive/get/get::cmdArchiveGet: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-get command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push --compress --archive-async --process-max=2 [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -60,6 +60,8 @@ db-version="9.4"
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push --cmd-ssh=/usr/bin/ssh --log-level-console=debug [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --cmd-ssh=/usr/bin/ssh --no-compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-1] --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Push::Push->process(): strWalPathFile = [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
P00 DEBUG: Common::Lock::lockStopTest=>: bStopExists = false
|
||||
@ -87,16 +89,25 @@ P00 DEBUG: Protocol::Storage::Remote->openWrite(): rhParam = [hash], strFil
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Push::File::archivePushFile=>: strWarning = [undef]
|
||||
P00 INFO: pushed WAL segment 000000010000000100000001
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy: found cached protocol: iRemoteIdx = 1, strRemoteType = backup
|
||||
P00 DEBUG: Protocol::Command::Master->close=>: iExitStatus = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-push command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-get --log-level-console=debug 000000010000000100000001 [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-get command begin [BACKREST-VERSION]: [000000010000000100000001, [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG] --no-compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-1] --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: command/archive/get/get::cmdArchiveGet: (void)
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Get::Get->process(): rstryCommandArg = (000000010000000100000001, [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG)
|
||||
P00 DEBUG: Archive::Get::File::archiveGetFile(): bAtomic = false, strDestinationFile = [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG, strSourceArchive = 000000010000000100000001
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
@ -124,12 +135,19 @@ P00 DEBUG: Storage::Local->openWrite(): bAtomic = false, bPathCreate = <fal
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Get::File::archiveGetFile=>: iResult = 0
|
||||
P00 INFO: got WAL segment 000000010000000100000001
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: command/archive/get/get::cmdArchiveGet: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy: found cached protocol: iRemoteIdx = 1, strRemoteType = backup
|
||||
P00 DEBUG: Protocol::Command::Master->close=>: iExitStatus = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-get command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push --compress --archive-async --process-max=2 [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -178,6 +178,8 @@ db-version="9.3"
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Push::Push->process(): strWalPathFile = [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
P00 DEBUG: Common::Lock::lockStopTest=>: bStopExists = false
|
||||
@ -215,10 +217,16 @@ P00 DEBUG: Storage::Local->openWrite(): bAtomic = true, bPathCreate = true,
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Push::File::archivePushFile=>: strWarning = [undef]
|
||||
P00 INFO: pushed WAL segment 000000010000000100000001
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-push command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
stanza-create db - fail on archive info file missing from non-empty dir (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --log-level-console=detail --no-online stanza-create
|
||||
@ -425,6 +433,8 @@ db-version="9.3"
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Push::Push->process(): strWalPathFile = [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
P00 DEBUG: Common::Lock::lockStopTest=>: bStopExists = false
|
||||
@ -462,10 +472,16 @@ P00 DEBUG: Storage::Local->openWrite(): bAtomic = true, bPathCreate = true,
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Push::File::archivePushFile=>: strWarning = [undef]
|
||||
P00 INFO: pushed WAL segment 000000010000000100000002
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-push command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -516,6 +532,9 @@ db-version="9.4"
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-get 000000010000000100000002 [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-get command begin [BACKREST-VERSION]: [000000010000000100000002, [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: command/archive/get/get::cmdArchiveGet: (void)
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Get::Get->process(): rstryCommandArg = (000000010000000100000002, [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG)
|
||||
P00 DEBUG: Archive::Get::File::archiveGetFile(): bAtomic = false, strDestinationFile = [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG, strSourceArchive = 000000010000000100000002
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
@ -552,10 +571,17 @@ P00 DEBUG: Storage::Local->openWrite(): bAtomic = false, bPathCreate = <fal
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Get::File::archiveGetFile=>: iResult = 0
|
||||
P00 INFO: got WAL segment 000000010000000100000002
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: command/archive/get/get::cmdArchiveGet: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-get command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -958,13 +984,21 @@ stop db stanza (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db stop
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stop command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBufferMax = [undef], oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = /, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 770, strPathExp = [TEST_PATH]/db-master/lock
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: stop command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
stanza-delete db - successfully delete the stanza (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --log-level-console=detail stanza-delete
|
||||
|
@ -202,6 +202,8 @@ db-version="9.3"
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2] --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Push::Push->process(): strWalPathFile = [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
P00 DEBUG: Common::Lock::lockStopTest=>: bStopExists = false
|
||||
@ -229,12 +231,18 @@ P00 DEBUG: Protocol::Storage::Remote->openWrite(): rhParam = [hash], strFil
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Push::File::archivePushFile=>: strWarning = [undef]
|
||||
P00 INFO: pushed WAL segment 000000010000000100000001
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy: found cached protocol: iRemoteIdx = 1, strRemoteType = backup
|
||||
P00 DEBUG: Protocol::Command::Master->close=>: iExitStatus = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-push command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
stanza-create db - gunzip fail on forced stanza-create (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --log-level-console=detail --no-online --force stanza-create
|
||||
@ -293,6 +301,8 @@ db-version="9.3"
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002] --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2] --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Push::Push->process(): strWalPathFile = [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
P00 DEBUG: Common::Lock::lockStopTest=>: bStopExists = false
|
||||
@ -320,12 +330,18 @@ P00 DEBUG: Protocol::Storage::Remote->openWrite(): rhParam = [hash], strFil
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Push::File::archivePushFile=>: strWarning = [undef]
|
||||
P00 INFO: pushed WAL segment 000000010000000100000002
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy: found cached protocol: iRemoteIdx = 1, strRemoteType = backup
|
||||
P00 DEBUG: Protocol::Command::Master->close=>: iExitStatus = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-push command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -382,6 +398,9 @@ db-version="9.4"
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-get 000000010000000100000002 [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-get command begin [BACKREST-VERSION]: [000000010000000100000002, [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG] --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2] --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: command/archive/get/get::cmdArchiveGet: (void)
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Get::Get->process(): rstryCommandArg = (000000010000000100000002, [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG)
|
||||
P00 DEBUG: Archive::Get::File::archiveGetFile(): bAtomic = false, strDestinationFile = [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG, strSourceArchive = 000000010000000100000002
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
@ -409,12 +428,19 @@ P00 DEBUG: Storage::Local->openWrite(): bAtomic = false, bPathCreate = <fal
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Get::File::archiveGetFile=>: iResult = 0
|
||||
P00 INFO: got WAL segment 000000010000000100000002
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: command/archive/get/get::cmdArchiveGet: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy: found cached protocol: iRemoteIdx = 1, strRemoteType = backup
|
||||
P00 DEBUG: Protocol::Command::Master->close=>: iExitStatus = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-get command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -792,13 +818,21 @@ stop db stanza (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db stop
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stop command begin [BACKREST-VERSION]: --config=[TEST_PATH]/backup/pgbackrest.conf --lock-path=[TEST_PATH]/backup/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --no-log-timestamp --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=[TEST_PATH]/backup/repo --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBufferMax = [undef], oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = /, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 770, strPathExp = [TEST_PATH]/backup/lock
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: stop command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
stanza-delete db - successfully delete the stanza (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --log-level-console=detail stanza-delete
|
||||
|
@ -178,6 +178,8 @@ db-version="9.3"
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-ssl --repo1-type=s3 --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Push::Push->process(): strWalPathFile = [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
P00 DEBUG: Common::Lock::lockStopTest=>: bStopExists = false
|
||||
@ -215,10 +217,16 @@ P00 DEBUG: Storage::Local->openWrite(): bAtomic = true, bPathCreate = true,
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Push::File::archivePushFile=>: strWarning = [undef]
|
||||
P00 INFO: pushed WAL segment 000000010000000100000001
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-push command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
stanza-create db - fail on archive info file missing from non-empty dir (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --log-level-console=detail --no-online stanza-create
|
||||
@ -400,6 +408,8 @@ db-version="9.3"
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-ssl --repo1-type=s3 --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Push::Push->process(): strWalPathFile = [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
P00 DEBUG: Common::Lock::lockStopTest=>: bStopExists = false
|
||||
@ -437,10 +447,16 @@ P00 DEBUG: Storage::Local->openWrite(): bAtomic = true, bPathCreate = true,
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Push::File::archivePushFile=>: strWarning = [undef]
|
||||
P00 INFO: pushed WAL segment 000000010000000100000002
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-push command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -491,6 +507,9 @@ db-version="9.4"
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-get 000000010000000100000002 [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-get command begin [BACKREST-VERSION]: [000000010000000100000002, [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-ssl --repo1-type=s3 --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: command/archive/get/get::cmdArchiveGet: (void)
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Archive::Get::Get->process(): rstryCommandArg = (000000010000000100000002, [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG)
|
||||
P00 DEBUG: Archive::Get::File::archiveGetFile(): bAtomic = false, strDestinationFile = [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG, strSourceArchive = 000000010000000100000002
|
||||
P00 DEBUG: Common::Lock::lockStopTest(): bStanzaStopRequired = <false>
|
||||
@ -527,10 +546,17 @@ P00 DEBUG: Storage::Local->openWrite(): bAtomic = false, bPathCreate = <fal
|
||||
P00 DEBUG: Storage::Base->copy(): xDestinationFile = [object], xSourceFile = [object]
|
||||
P00 DEBUG: Archive::Get::File::archiveGetFile=>: iResult = 0
|
||||
P00 INFO: got WAL segment 000000010000000100000002
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: command/archive/get/get::cmdArchiveGet: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: archive-get command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -945,13 +971,21 @@ stop db stanza (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db stop
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stop command begin [BACKREST-VERSION]: --config=[TEST_PATH]/db-master/pgbackrest.conf --lock-path=[TEST_PATH]/db-master/lock --log-level-console=debug --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-log-timestamp --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-ssl --repo1-type=s3 --stanza=db
|
||||
P00 DEBUG: config/load::cfgLoad: => void
|
||||
P00 DEBUG: perl/exec::perlExec: (void)
|
||||
P00 DEBUG: Storage::Posix::Driver->new(): bFileSync = <true>, bPathSync = <true>
|
||||
P00 DEBUG: Storage::Local->new(): bAllowTemp = <true>, hRule = [undef], lBufferMax = [undef], oDriver = [object], strCipherPassUser = [undef], strCipherType = [undef], strDefaultFileMode = <0640>, strDefaultPathMode = <0750>, strPathBase = /, strTempExtension = pgbackrest.tmp
|
||||
P00 DEBUG: Storage::Local->pathCreate(): bCreateParent = true, bIgnoreExists = true, strMode = 770, strPathExp = [TEST_PATH]/db-master/lock
|
||||
P00 DEBUG: perl/exec::perlExec: => 0
|
||||
P00 DEBUG: common/exit::exitSafe: (result: 0, error: false, signalType: 0)
|
||||
P00 DEBUG: common/lock::lockRelease: (failOnNoLock: false)
|
||||
P00 DEBUG: common/lock::lockRelease: => false
|
||||
P00 DEBUG: Main::mainCleanup(): iExitCode = 0
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy(): bComplete = true, iRemoteIdx = [undef], strRemoteType = [undef]
|
||||
P00 DEBUG: Protocol::Helper::protocolDestroy=>: iExitStatus = 0
|
||||
P00 INFO: stop command end: completed successfully
|
||||
P00 DEBUG: common/exit::exitSafe: => 0
|
||||
P00 DEBUG: main::main: => 0
|
||||
|
||||
stanza-delete db - successfully delete the stanza (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --log-level-console=detail stanza-delete
|
||||
|
@ -69,6 +69,7 @@ sub new
|
||||
$self->{bValgrindUnit},
|
||||
$self->{bCoverageUnit},
|
||||
$self->{bOptimize},
|
||||
$self->{bBackTrace},
|
||||
$self->{bProfile},
|
||||
$self->{bDebug},
|
||||
) =
|
||||
@ -94,6 +95,7 @@ sub new
|
||||
{name => 'bValgrindUnit'},
|
||||
{name => 'bCoverageUnit'},
|
||||
{name => 'bOptimize'},
|
||||
{name => 'bBackTrace'},
|
||||
{name => 'bProfile'},
|
||||
{name => 'bDebug'},
|
||||
);
|
||||
@ -360,8 +362,10 @@ sub run
|
||||
" -Wformat=2 -Wformat-nonliteral \\\n" .
|
||||
" `perl -MExtUtils::Embed -e ccopts`\n" .
|
||||
"LDFLAGS=-lcrypto" . (vmCoverage($self->{oTest}->{&TEST_VM}) && $self->{bCoverageUnit} ? " -lgcov" : '') .
|
||||
(vmWithBackTrace($self->{oTest}->{&TEST_VM}) && $self->{bBackTrace} ? ' -lbacktrace' : '') .
|
||||
" `perl -MExtUtils::Embed -e ldopts`\n" .
|
||||
'TESTFLAGS=' . ($self->{oTest}->{&TEST_DEBUG_UNIT_SUPPRESS} ? '' : "-DDEBUG_UNIT") .
|
||||
(vmWithBackTrace($self->{oTest}->{&TEST_VM}) && $self->{bBackTrace} ? ' -DWITH_BACKTRACE' : '') .
|
||||
($self->{oTest}->{&TEST_CDEF} ? " $self->{oTest}->{&TEST_CDEF}" : '') .
|
||||
($self->{bDebug} ? '' : " -DNDEBUG") .
|
||||
"\n" .
|
||||
|
@ -1,6 +1,7 @@
|
||||
/***********************************************************************************************************************************
|
||||
Harness for Loading Test Configurations
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/harnessDebug.h"
|
||||
#include "common/logTest.h"
|
||||
|
||||
#include "config/load.h"
|
||||
@ -15,7 +16,14 @@ log files, acquire locks, etc.
|
||||
void
|
||||
harnessCfgLoad(unsigned int argListSize, const char *argList[])
|
||||
{
|
||||
FUNCTION_HARNESS_BEGIN();
|
||||
FUNCTION_HARNESS_PARAM(UINT, argListSize);
|
||||
FUNCTION_HARNESS_PARAM(CHARPY, argList);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
configParse(argListSize, argList);
|
||||
logInit(logLevelInfo, logLevelOff, logLevelDebug, false);
|
||||
cfgLoadUpdateOption();
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
58
test/src/common/harnessDebug.h
Normal file
58
test/src/common/harnessDebug.h
Normal file
@ -0,0 +1,58 @@
|
||||
/***********************************************************************************************************************************
|
||||
C Debug Harness
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef TEST_COMMON_HARNESS_DEBUG_H
|
||||
#define TEST_COMMON_HARNESS_DEBUG_H
|
||||
|
||||
#ifdef NO_STACK_TRACE
|
||||
#define FUNCTION_HARNESS_INIT(exe)
|
||||
#define FUNCTION_HARNESS_BEGIN()
|
||||
#define FUNCTION_HARNESS_PARAM(typeMacroPrefix, param)
|
||||
#define FUNCTION_HARNESS_END()
|
||||
#define FUNCTION_HARNESS_VOID()
|
||||
#define FUNCTION_HARNESS_ASSERT(condition)
|
||||
|
||||
#define FUNCTION_HARNESS_RESULT(typeMacroPrefix, result) \
|
||||
return result
|
||||
|
||||
#define FUNCTION_HARNESS_RESULT_VOID();
|
||||
#else
|
||||
#include "common/debug.h"
|
||||
|
||||
#ifdef WITH_BACKTRACE
|
||||
#define FUNCTION_HARNESS_INIT(exe) \
|
||||
stackTraceInit(exe)
|
||||
#else
|
||||
#define FUNCTION_HARNESS_INIT(exe)
|
||||
#endif
|
||||
|
||||
#define FUNCTION_HARNESS_BEGIN() \
|
||||
STACK_TRACE_PUSH(logLevelDebug); \
|
||||
stackTraceParamLog()
|
||||
|
||||
#define FUNCTION_HARNESS_PARAM(typeMacroPrefix, param) \
|
||||
FUNCTION_DEBUG_PARAM(typeMacroPrefix, param)
|
||||
|
||||
#define FUNCTION_HARNESS_END()
|
||||
|
||||
#define FUNCTION_HARNESS_VOID() \
|
||||
FUNCTION_HARNESS_BEGIN(); \
|
||||
FUNCTION_HARNESS_END()
|
||||
|
||||
#define FUNCTION_HARNESS_ASSERT(condition) \
|
||||
do \
|
||||
{ \
|
||||
if (!(condition)) \
|
||||
THROW_FMT(AssertError, "function harness assertion '%s' failed", #condition); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define FUNCTION_HARNESS_RESULT(typeMacroPrefix, result) \
|
||||
STACK_TRACE_POP(); \
|
||||
return result \
|
||||
|
||||
#define FUNCTION_HARNESS_RESULT_VOID() \
|
||||
STACK_TRACE_POP();
|
||||
#endif
|
||||
|
||||
#endif
|
@ -5,6 +5,7 @@ C Test Harness
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/harnessDebug.h"
|
||||
#include "common/harnessTest.h"
|
||||
#include "common/logTest.h"
|
||||
|
||||
@ -21,21 +22,55 @@ static int testRun = 0;
|
||||
static int testTotal = 0;
|
||||
static bool testFirst = true;
|
||||
|
||||
static const char *testExeData = NULL;
|
||||
static const char *testPathData = NULL;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get and set the test exe
|
||||
***********************************************************************************************************************************/
|
||||
const char *
|
||||
testExe()
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
FUNCTION_HARNESS_RESULT(STRINGZ, testExeData);
|
||||
}
|
||||
|
||||
void
|
||||
testExeSet(const char *testExe)
|
||||
{
|
||||
FUNCTION_HARNESS_BEGIN();
|
||||
FUNCTION_HARNESS_PARAM(STRINGZ, testExe);
|
||||
|
||||
FUNCTION_HARNESS_ASSERT(testExe != NULL);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
testExeData = testExe;
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get and set the test path, i.e., the path where this test should write its files
|
||||
***********************************************************************************************************************************/
|
||||
const char *
|
||||
testPath()
|
||||
{
|
||||
return testPathData;
|
||||
FUNCTION_HARNESS_VOID();
|
||||
FUNCTION_HARNESS_RESULT(STRINGZ, testPathData);
|
||||
}
|
||||
|
||||
void
|
||||
testPathSet(const char *testPathParam)
|
||||
testPathSet(const char *testPath)
|
||||
{
|
||||
testPathData = testPathParam;
|
||||
FUNCTION_HARNESS_BEGIN();
|
||||
FUNCTION_HARNESS_PARAM(STRINGZ, testPath);
|
||||
|
||||
FUNCTION_HARNESS_ASSERT(testPath != NULL);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
testPathData = testPath;
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -44,6 +79,11 @@ testAdd - add a new test
|
||||
void
|
||||
testAdd(int run, bool selected)
|
||||
{
|
||||
FUNCTION_HARNESS_BEGIN();
|
||||
FUNCTION_HARNESS_PARAM(INT, run);
|
||||
FUNCTION_HARNESS_PARAM(BOOL, selected);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
if (run != testTotal + 1)
|
||||
{
|
||||
fprintf(stderr, "ERROR: test run %d is not in order\n", run);
|
||||
@ -53,6 +93,8 @@ testAdd(int run, bool selected)
|
||||
|
||||
testList[testTotal].selected = selected;
|
||||
testTotal++;
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -61,14 +103,23 @@ testBegin - should this test run?
|
||||
bool
|
||||
testBegin(const char *name)
|
||||
{
|
||||
FUNCTION_HARNESS_BEGIN();
|
||||
FUNCTION_HARNESS_PARAM(STRINGZ, name);
|
||||
|
||||
FUNCTION_HARNESS_ASSERT(name != NULL);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
bool result = false;
|
||||
testRun++;
|
||||
|
||||
if (testList[testRun - 1].selected)
|
||||
{
|
||||
#ifndef NO_LOG
|
||||
#ifndef IN_LOG
|
||||
// Make sure there is nothing untested left in the log
|
||||
if (!testFirst)
|
||||
testLogFinal();
|
||||
#endif
|
||||
#endif
|
||||
// No longer the first test
|
||||
testFirst = false;
|
||||
@ -80,14 +131,16 @@ testBegin(const char *name)
|
||||
fflush(stdout);
|
||||
|
||||
#ifndef NO_LOG
|
||||
#ifndef IN_LOG
|
||||
// Initialize logging
|
||||
testLogInit();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return true;
|
||||
result = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
FUNCTION_HARNESS_RESULT(BOOL, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -96,9 +149,13 @@ testComplete - make sure all expected tests ran
|
||||
void
|
||||
testComplete()
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
#ifndef NO_LOG
|
||||
#ifndef IN_LOG
|
||||
// Make sure there is nothing untested left in the log
|
||||
testLogFinal();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Check that all tests ran
|
||||
@ -108,4 +165,6 @@ testComplete()
|
||||
fflush(stderr);
|
||||
exit(255);
|
||||
}
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
@ -16,8 +16,11 @@ void testAdd(int run, bool selected);
|
||||
bool testBegin(const char *name);
|
||||
void testComplete();
|
||||
|
||||
const char *testExe();
|
||||
void testExeSet(const char *testExe);
|
||||
|
||||
const char *testPath();
|
||||
void testPathSet(const char *testPathParam);
|
||||
void testPathSet(const char *testPath);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert a macro to a string -- handy for testing debug macros
|
||||
@ -53,8 +56,8 @@ Test that an expected error is actually thrown and error when it isn't
|
||||
\
|
||||
if (strcmp(errorMessage(), errorMessageExpected) != 0 || errorType() != &errorTypeExpected) \
|
||||
THROW_FMT( \
|
||||
AssertError, "expected error %s, '%s' but got %s, '%s'", errorTypeName(&errorTypeExpected), errorMessageExpected, \
|
||||
errorName(), errorMessage()); \
|
||||
AssertError, "EXECTED %s: %s\n\nBUT GOT %s: %s\n\nTHROWN AT:\n%s", errorTypeName(&errorTypeExpected), \
|
||||
errorMessageExpected, errorName(), errorMessage(), errorStackTrace()); \
|
||||
} \
|
||||
TRY_END(); \
|
||||
\
|
||||
@ -153,8 +156,8 @@ parameters.
|
||||
{ \
|
||||
/* No errors were expected so error */ \
|
||||
THROW_FMT( \
|
||||
AssertError, "statement '%s' threw error %s, '%s' but result <%s> expected", \
|
||||
#statement, errorName(), errorMessage(), TEST_RESULT_resultExpectedStr); \
|
||||
AssertError, "STATEMENT: %s\n\nTHREW %s: %s\n\nTHROWN AT:\n%s\n\nBUT EXPECTED RESULT:\n%s", \
|
||||
#statement, errorName(), errorMessage(), errorStackTrace(), TEST_RESULT_resultExpectedStr); \
|
||||
} \
|
||||
TRY_END(); \
|
||||
\
|
||||
|
@ -3,11 +3,14 @@ Log Test Harness
|
||||
***********************************************************************************************************************************/
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/harnessTest.h"
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/log.h"
|
||||
#include "storage/helper.h"
|
||||
|
||||
#include "common/harnessDebug.h"
|
||||
#include "common/harnessTest.h"
|
||||
|
||||
#ifndef NO_LOG
|
||||
|
||||
@ -19,8 +22,35 @@ static bool harnessLogInit = false;
|
||||
/***********************************************************************************************************************************
|
||||
Name of file where logs are stored for testing
|
||||
***********************************************************************************************************************************/
|
||||
String *stdoutFile = NULL;
|
||||
String *stderrFile = NULL;
|
||||
static char stdoutFile[1024];
|
||||
static char stderrFile[1024];
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Buffer where log results are loaded for comparison purposes
|
||||
***********************************************************************************************************************************/
|
||||
char harnessLogBuffer[256 * 1024];
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Open a log file -- centralized here for error handling
|
||||
***********************************************************************************************************************************/
|
||||
static int
|
||||
harnessLogOpen(const char *logFile, int flags, int mode)
|
||||
{
|
||||
FUNCTION_HARNESS_BEGIN();
|
||||
FUNCTION_HARNESS_PARAM(STRINGZ, logFile);
|
||||
FUNCTION_HARNESS_PARAM(INT, flags);
|
||||
FUNCTION_HARNESS_PARAM(INT, mode);
|
||||
|
||||
FUNCTION_HARNESS_ASSERT(logFile != NULL);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
int result = open(logFile, flags, mode);
|
||||
|
||||
if (result == -1)
|
||||
THROW_SYS_ERROR_FMT(FileOpenError, "unable to open log file '%s'", logFile);
|
||||
|
||||
FUNCTION_HARNESS_RESULT(INT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Initialize log for testing
|
||||
@ -28,18 +58,61 @@ Initialize log for testing
|
||||
void
|
||||
testLogInit()
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
if (!harnessLogInit)
|
||||
{
|
||||
logInit(logLevelInfo, logLevelOff, logLevelOff, false);
|
||||
|
||||
stdoutFile = strNewFmt("%s/stdout.log", testPath());
|
||||
logHandleStdOut = open(strPtr(stdoutFile), O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
||||
snprintf(stdoutFile, sizeof(stdoutFile), "%s/stdout.log", testPath());
|
||||
logHandleStdOut = harnessLogOpen(stdoutFile, O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
||||
|
||||
stderrFile = strNewFmt("%s/stderr.log", testPath());
|
||||
logHandleStdErr = open(strPtr(stderrFile), O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
||||
snprintf(stderrFile, sizeof(stderrFile), "%s/stderr.log", testPath());
|
||||
logHandleStdErr = harnessLogOpen(stderrFile, O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
||||
|
||||
harnessLogInit = true;
|
||||
}
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Load log result from file into the log buffer
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
harnessLogLoad(const char *logFile)
|
||||
{
|
||||
FUNCTION_HARNESS_BEGIN();
|
||||
FUNCTION_HARNESS_PARAM(STRINGZ, logFile);
|
||||
|
||||
FUNCTION_HARNESS_ASSERT(logFile != NULL);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
harnessLogBuffer[0] = 0;
|
||||
|
||||
int handle = harnessLogOpen(logFile, O_RDONLY, 0);
|
||||
|
||||
size_t totalBytes = 0;
|
||||
ssize_t actualBytes = 0;
|
||||
|
||||
do
|
||||
{
|
||||
actualBytes = read(handle, harnessLogBuffer, sizeof(harnessLogBuffer) - totalBytes);
|
||||
|
||||
if (actualBytes == -1)
|
||||
THROW_SYS_ERROR_FMT(FileOpenError, "unable to read log file '%s'", logFile);
|
||||
|
||||
totalBytes += (size_t)actualBytes;
|
||||
}
|
||||
while (actualBytes != 0);
|
||||
|
||||
if (close(handle) == -1)
|
||||
THROW_SYS_ERROR_FMT(FileOpenError, "unable to close log file '%s'", logFile);
|
||||
|
||||
// Remove final linefeed
|
||||
harnessLogBuffer[totalBytes - 1] = 0;
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -50,13 +123,67 @@ After the comparison the log is cleared so the next result can be compared.
|
||||
void
|
||||
testLogResult(const char *expected)
|
||||
{
|
||||
String *actual = strTrim(strNewBuf(storageGetNP(storageNewReadNP(storageLocal(), stdoutFile))));
|
||||
FUNCTION_HARNESS_BEGIN();
|
||||
FUNCTION_HARNESS_PARAM(STRINGZ, expected);
|
||||
|
||||
if (!strEqZ(actual, expected))
|
||||
THROW_FMT(AssertError, "\n\nexpected log:\n\n%s\n\nbut actual log was:\n\n%s\n\n", expected, strPtr(actual));
|
||||
FUNCTION_HARNESS_ASSERT(expected != NULL);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
harnessLogLoad(stdoutFile);
|
||||
|
||||
if (strcmp(harnessLogBuffer, expected) != 0)
|
||||
THROW_FMT(AssertError, "\n\nexpected log:\n\n%s\n\nbut actual log was:\n\n%s\n\n", expected, harnessLogBuffer);
|
||||
|
||||
close(logHandleStdOut);
|
||||
logHandleStdOut = open(strPtr(stdoutFile), O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
||||
logHandleStdOut = harnessLogOpen(stdoutFile, O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Compare log to a regexp
|
||||
|
||||
After the comparison the log is cleared so the next result can be compared.
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
testLogResultRegExp(const char *expression)
|
||||
{
|
||||
FUNCTION_HARNESS_BEGIN();
|
||||
FUNCTION_HARNESS_PARAM(STRINGZ, expression);
|
||||
|
||||
FUNCTION_HARNESS_ASSERT(expression != NULL);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
regex_t regExp;
|
||||
|
||||
TRY_BEGIN()
|
||||
{
|
||||
harnessLogLoad(stdoutFile);
|
||||
|
||||
// Compile the regexp and process errors
|
||||
int result = 0;
|
||||
|
||||
if ((result = regcomp(®Exp, expression, REG_NOSUB | REG_EXTENDED)) != 0)
|
||||
{
|
||||
char buffer[4096];
|
||||
regerror(result, NULL, buffer, sizeof(buffer));
|
||||
THROW(FormatError, buffer);
|
||||
}
|
||||
|
||||
// Do the match
|
||||
if (regexec(®Exp, harnessLogBuffer, 0, NULL, 0) != 0)
|
||||
THROW_FMT(AssertError, "\n\nexpected log regexp:\n\n%s\n\nbut actual log was:\n\n%s\n\n", expression, harnessLogBuffer);
|
||||
|
||||
close(logHandleStdOut);
|
||||
logHandleStdOut = harnessLogOpen(stdoutFile, O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
||||
}
|
||||
FINALLY()
|
||||
{
|
||||
regfree(®Exp);
|
||||
}
|
||||
TRY_END();
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -67,13 +194,21 @@ After the comparison the log is cleared so the next result can be compared.
|
||||
void
|
||||
testLogErrResult(const char *expected)
|
||||
{
|
||||
String *actual = strTrim(strNewBuf(storageGetNP(storageNewReadNP(storageLocal(), stderrFile))));
|
||||
FUNCTION_HARNESS_BEGIN();
|
||||
FUNCTION_HARNESS_PARAM(STRINGZ, expected);
|
||||
|
||||
if (!strEqZ(actual, expected))
|
||||
THROW_FMT(AssertError, "\n\nexpected error log:\n\n%s\n\nbut actual error log was:\n\n%s\n\n", expected, strPtr(actual));
|
||||
FUNCTION_HARNESS_ASSERT(expected != NULL);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
harnessLogLoad(stderrFile);
|
||||
|
||||
if (strcmp(harnessLogBuffer, expected) != 0)
|
||||
THROW_FMT(AssertError, "\n\nexpected error log:\n\n%s\n\nbut actual error log was:\n\n%s\n\n", expected, harnessLogBuffer);
|
||||
|
||||
close(logHandleStdErr);
|
||||
logHandleStdErr = open(strPtr(stderrFile), O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
||||
logHandleStdErr = harnessLogOpen(stderrFile, O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -82,15 +217,19 @@ Make sure nothing is left in the log after all tests have completed
|
||||
void
|
||||
testLogFinal()
|
||||
{
|
||||
String *actual = strTrim(strNewBuf(storageGetNP(storageNewReadNP(storageLocal(), stdoutFile))));
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
if (!strEqZ(actual, ""))
|
||||
THROW_FMT(AssertError, "\n\nexpected log to be empty but actual log was:\n\n%s\n\n", strPtr(actual));
|
||||
harnessLogLoad(stdoutFile);
|
||||
|
||||
actual = strTrim(strNewBuf(storageGetNP(storageNewReadNP(storageLocal(), stderrFile))));
|
||||
if (strcmp(harnessLogBuffer, "") != 0)
|
||||
THROW_FMT(AssertError, "\n\nexpected log to be empty but actual log was:\n\n%s\n\n", harnessLogBuffer);
|
||||
|
||||
if (!strEqZ(actual, ""))
|
||||
THROW_FMT(AssertError, "\n\nexpected error log to be empty but actual error log was:\n\n%s\n\n", strPtr(actual));
|
||||
harnessLogLoad(stderrFile);
|
||||
|
||||
if (strcmp(harnessLogBuffer, "") != 0)
|
||||
THROW_FMT(AssertError, "\n\nexpected error log to be empty but actual error log was:\n\n%s\n\n", harnessLogBuffer);
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -7,11 +7,10 @@ Log Test Harness
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef NO_LOG
|
||||
void testLogInit();
|
||||
void testLogResult(const char *expected);
|
||||
void testLogResultRegExp(const char *expression);
|
||||
void testLogErrResult(const char *expected);
|
||||
void testLogFinal();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -11,6 +11,8 @@ Test Run
|
||||
void
|
||||
testRun()
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("archiveAsyncStatus()"))
|
||||
{
|
||||
@ -53,7 +55,7 @@ testRun()
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
|
||||
bufNewStr(strNew(BOGUS_STR "\nmessage")));
|
||||
TEST_ERROR(archiveAsyncStatus(archiveModePush, segment, false), FormatError, "unable to convert str 'BOGUS' to int");
|
||||
TEST_ERROR(archiveAsyncStatus(archiveModePush, segment, false), FormatError, "unable to convert string 'BOGUS' to int");
|
||||
|
||||
storagePutNP(storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))), NULL);
|
||||
TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false), true, "ok file");
|
||||
@ -143,4 +145,6 @@ testRun()
|
||||
"000000070000000700000FFE|000000070000000700000FFF|000000070000000800000000|000000070000000800000001",
|
||||
"get range >= 11/1MB");
|
||||
}
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ Test Run
|
||||
void
|
||||
testRun()
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
Storage *storageTest = storageNewP(strNew(testPath()), .write = true);
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
@ -48,12 +50,15 @@ testRun()
|
||||
"000000010000000100000001|000000010000000100000002|000000010000000100000003", "empty queue");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
Buffer *walSegmentBuffer = bufNew(walSegmentSize);
|
||||
memset(bufPtr(walSegmentBuffer), 0, walSegmentSize);
|
||||
|
||||
storagePutNP(
|
||||
storageNewWriteNP(
|
||||
storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FE")), bufNew(walSegmentSize));
|
||||
storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FE")), walSegmentBuffer);
|
||||
storagePutNP(
|
||||
storageNewWriteNP(
|
||||
storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FF")), bufNew(walSegmentSize));
|
||||
storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FF")), walSegmentBuffer);
|
||||
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strLstJoin(queueNeed(strNew("0000000100000001000000FE"), false, queueSize, walSegmentSize, PG_VERSION_92), "|")),
|
||||
@ -67,13 +72,13 @@ testRun()
|
||||
walSegmentSize = 1024 * 1024;
|
||||
queueSize = walSegmentSize * 5;
|
||||
|
||||
storagePutNP(storageNewWriteNP(storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/junk")), bufNew(16));
|
||||
storagePutNP(storageNewWriteNP(storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/junk")), bufNewStr(strNew("JUNK")));
|
||||
storagePutNP(
|
||||
storageNewWriteNP(
|
||||
storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/000000010000000A00000FFE")), bufNew(walSegmentSize));
|
||||
storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/000000010000000A00000FFE")), walSegmentBuffer);
|
||||
storagePutNP(
|
||||
storageNewWriteNP(
|
||||
storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/000000010000000A00000FFF")), bufNew(walSegmentSize));
|
||||
storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/000000010000000A00000FFF")), walSegmentBuffer);
|
||||
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strLstJoin(queueNeed(strNew("000000010000000A00000FFD"), true, queueSize, walSegmentSize, PG_VERSION_11), "|")),
|
||||
@ -106,7 +111,7 @@ testRun()
|
||||
strLstAdd(argListTemp, walSegment);
|
||||
harnessCfgLoad(strLstSize(argListTemp), strLstPtr(argListTemp));
|
||||
|
||||
TEST_ERROR(cmdArchiveGet(), ParamRequiredError, "Path to copy WAL segment required");
|
||||
TEST_ERROR(cmdArchiveGet(), ParamRequiredError, "path to copy WAL segment required");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
String *controlFile = strNew("db/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL);
|
||||
@ -240,6 +245,8 @@ testRun()
|
||||
strLstAddZ(argList, BOGUS_STR);
|
||||
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
|
||||
|
||||
TEST_ERROR(cmdArchiveGet(), ParamRequiredError, "extra parameters found");
|
||||
TEST_ERROR(cmdArchiveGet(), ParamInvalidError, "extra parameters found");
|
||||
}
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ Test Run
|
||||
void
|
||||
testRun()
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
// Create default storage object for testing
|
||||
Storage *storageTest = storageNewP(strNew(testPath()), .write = true);
|
||||
|
||||
@ -83,4 +85,6 @@ testRun()
|
||||
cmdArchivePush(), ArchiveTimeoutError,
|
||||
"unable to push WAL segment '000000010000000100000001' asynchronously after 1 second(s)");
|
||||
}
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ Test Run
|
||||
void
|
||||
testRun()
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
if (testBegin("blockCipherNew() and blockCipherFree()"))
|
||||
{
|
||||
@ -30,9 +32,6 @@ testRun()
|
||||
cipherBlockNew(
|
||||
cipherModeEncrypt, BOGUS_STR, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL), AssertError,
|
||||
"unable to load cipher 'BOGUS'");
|
||||
TEST_ERROR(
|
||||
cipherBlockNew(cipherModeEncrypt, NULL, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL), AssertError,
|
||||
"unable to load cipher '(null)'");
|
||||
TEST_ERROR(
|
||||
cipherBlockNew(
|
||||
cipherModeEncrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, BOGUS_STR), AssertError,
|
||||
@ -159,7 +158,7 @@ testRun()
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
blockEncrypt = cipherBlockNew(cipherModeEncrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL);
|
||||
|
||||
TEST_RESULT_INT(cipherBlockProcess(blockEncrypt, NULL, 0, encryptBuffer), 16, "process header");
|
||||
TEST_RESULT_INT(cipherBlockProcess(blockEncrypt, decryptBuffer, 0, encryptBuffer), 16, "process header");
|
||||
TEST_RESULT_INT(cipherBlockFlush(blockEncrypt, encryptBuffer + 16), 16, "flush remaining bytes");
|
||||
|
||||
cipherBlockFree(blockEncrypt);
|
||||
@ -200,7 +199,7 @@ testRun()
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
blockDecrypt = cipherBlockNew(cipherModeDecrypt, TEST_CIPHER, (unsigned char *)TEST_PASS, TEST_PASS_SIZE, NULL);
|
||||
|
||||
TEST_RESULT_INT(cipherBlockProcess(blockDecrypt, NULL, 0, decryptBuffer), 0, "no header processed");
|
||||
TEST_RESULT_INT(cipherBlockProcess(blockDecrypt, encryptBuffer, 0, decryptBuffer), 0, "no header processed");
|
||||
TEST_ERROR(cipherBlockFlush(blockDecrypt, decryptBuffer), CipherError, "cipher header missing");
|
||||
|
||||
cipherBlockFree(blockDecrypt);
|
||||
@ -217,5 +216,5 @@ testRun()
|
||||
cipherBlockFree(blockDecrypt);
|
||||
}
|
||||
|
||||
cipherFree();
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ Test Run
|
||||
void
|
||||
testRun()
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
if (testBegin("randomBytes()"))
|
||||
{
|
||||
@ -24,9 +26,11 @@ testRun()
|
||||
int nonZeroTotal = 0;
|
||||
|
||||
for (unsigned int charIdx = 0; charIdx < bufferSize; charIdx++)
|
||||
if (buffer[charIdx] != 0)
|
||||
if (buffer[charIdx] != 0) // {uncovered - ok if there are no zeros}
|
||||
nonZeroTotal++;
|
||||
|
||||
TEST_RESULT_INT_NE(nonZeroTotal, 0, "check that there are non-zero values in the buffer");
|
||||
}
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user