1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-07 00:35:37 +02:00
Files
pgbackrest/src/command/command.c
David Steele 1aca2cc902 Move extern function comments to headers.
This has been the policy for some time but due to migration pressure only new functions and refactors have been following this rule. Now it seems sensible to make a clean sweep and move all the comments that have not been moved already (i.e. most of them).

Only obvious typos and gross inaccuracies in the comments have been fixed. For this most part this was a copy and paste operation.

Useless comments, e.g. "New object", were not copied. Even so, there are surely many deficient comments left.

Some rearranging was done where needed and functions were placed in the proper sections, e.g. "Constructors", "Functions", etc.

A few function prototypes were found that not longer had an implementation. These were removed, but there may be more.

The coding document has been updated to reflect this policy, which is not new but has never been documented.
2020-04-03 18:01:28 -04:00

224 lines
8.9 KiB
C

/***********************************************************************************************************************************
Common Command Routines
***********************************************************************************************************************************/
#include "build.auto.h"
#include <inttypes.h>
#include <string.h>
#include "common/debug.h"
#include "common/io/http/client.h"
#include "common/io/tls/client.h"
#include "common/log.h"
#include "common/memContext.h"
#include "common/time.h"
#include "config/config.h"
#include "version.h"
/***********************************************************************************************************************************
Track time command started
***********************************************************************************************************************************/
static TimeMSec timeBegin;
/**********************************************************************************************************************************/
void
cmdInit(void)
{
FUNCTION_LOG_VOID(logLevelTrace);
timeBegin = timeMSec();
FUNCTION_LOG_RETURN_VOID();
}
/**********************************************************************************************************************************/
void
cmdBegin(bool logOption)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(BOOL, logOption);
FUNCTION_LOG_END();
ASSERT(cfgCommand() != cfgCmdNone);
// This is fairly expensive log message to generate so skip it if it won't be output
if (logAny(cfgLogLevelDefault()))
{
MEM_CONTEXT_TEMP_BEGIN()
{
// Basic info on command start
String *info = strNewFmt("%s command begin", strPtr(cfgCommandRoleName()));
if (logOption)
{
strCatFmt(info, " %s:", PROJECT_VERSION);
// Get command define id used to determine which options are valid for this command
ConfigDefineCommand commandDefId = cfgCommandDefIdFromId(cfgCommand());
// Add command parameters if they exist
const StringList *commandParamList = cfgCommandParam();
if (strLstSize(commandParamList) != 0)
{
strCatFmt(info, " [");
for (unsigned int commandParamIdx = 0; commandParamIdx < strLstSize(commandParamList); commandParamIdx++)
{
const String *commandParam = strLstGet(commandParamList, commandParamIdx);
if (commandParamIdx != 0)
strCatFmt(info, ", ");
if (strchr(strPtr(commandParam), ' ') != NULL)
commandParam = strNewFmt("\"%s\"", strPtr(commandParam));
strCat(info, strPtr(commandParam));
}
strCatFmt(info, "]");
}
// Loop though options and add the ones that are interesting
for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
{
// Skip the option if not valid for this command. Generally only one command runs at a time, but sometimes
// commands are chained together (e.g. backup and expire) and the second command may not use all the options of
// the first command. Displaying them is harmless but might cause confusion.
if (!cfgDefOptionValid(commandDefId, cfgOptionDefIdFromId(optionId)))
continue;
// If option was negated
if (cfgOptionNegate(optionId))
strCatFmt(info, " --no-%s", cfgOptionName(optionId));
// If option was reset
else if (cfgOptionReset(optionId))
strCatFmt(info, " --reset-%s", cfgOptionName(optionId));
// Else set and not default
else if (cfgOptionSource(optionId) != cfgSourceDefault && cfgOptionTest(optionId))
{
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(optionId);
// Don't show redacted options
if (cfgDefOptionSecure(optionDefId))
strCatFmt(info, " --%s=<redacted>", cfgOptionName(optionId));
// Output boolean option
else if (cfgDefOptionType(optionDefId) == cfgDefOptTypeBoolean)
strCatFmt(info, " --%s", cfgOptionName(optionId));
// Output other options
else
{
StringList *valueList = NULL;
// Generate the values of hash options
if (cfgDefOptionType(optionDefId) == cfgDefOptTypeHash)
{
valueList = strLstNew();
const KeyValue *optionKv = cfgOptionKv(optionId);
const VariantList *keyList = kvKeyList(optionKv);
for (unsigned int keyIdx = 0; keyIdx < varLstSize(keyList); keyIdx++)
{
strLstAdd(
valueList,
strNewFmt(
"%s=%s", strPtr(varStr(varLstGet(keyList, keyIdx))),
strPtr(varStrForce(kvGet(optionKv, varLstGet(keyList, keyIdx))))));
}
}
// Generate values for list options
else if (cfgDefOptionType(optionDefId) == cfgDefOptTypeList)
{
valueList = strLstNewVarLst(cfgOptionLst(optionId));
}
// Else only one value
else
{
valueList = strLstNew();
strLstAdd(valueList, varStrForce(cfgOption(optionId)));
}
// Output options and values
for (unsigned int valueListIdx = 0; valueListIdx < strLstSize(valueList); valueListIdx++)
{
const String *value = strLstGet(valueList, valueListIdx);
strCatFmt(info, " --%s", cfgOptionName(optionId));
if (strchr(strPtr(value), ' ') != NULL)
value = strNewFmt("\"%s\"", strPtr(value));
strCatFmt(info, "=%s", strPtr(value));
}
}
}
}
}
LOG(cfgLogLevelDefault(), 0, strPtr(info));
}
MEM_CONTEXT_TEMP_END();
}
FUNCTION_LOG_RETURN_VOID();
}
/**********************************************************************************************************************************/
void
cmdEnd(int code, const String *errorMessage)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(INT, code);
FUNCTION_LOG_PARAM(STRING, errorMessage);
FUNCTION_LOG_END();
ASSERT(cfgCommand() != cfgCmdNone);
// Skip this log message if it won't be output. It's not too expensive but since we skipped cmdBegin(), may as well.
if (logAny(cfgLogLevelDefault()))
{
MEM_CONTEXT_TEMP_BEGIN()
{
// Log socket statistics
String *sckClientStat = sckClientStatStr();
if (sckClientStat != NULL)
LOG_DETAIL(strPtr(sckClientStat));
// Log tls statistics
String *tlsClientStat = tlsClientStatStr();
if (tlsClientStat != NULL)
LOG_DETAIL(strPtr(tlsClientStat));
// Log http statistics
String *httpClientStat = httpClientStatStr();
if (httpClientStat != NULL)
LOG_INFO(strPtr(httpClientStat));
// Basic info on command end
String *info = strNewFmt("%s command end: ", strPtr(cfgCommandRoleName()));
if (errorMessage == NULL)
{
strCat(info, "completed successfully");
if (cfgOptionValid(cfgOptLogTimestamp) && cfgOptionBool(cfgOptLogTimestamp))
strCatFmt(info, " (%" PRIu64 "ms)", timeMSec() - timeBegin);
}
else
strCat(info, strPtr(errorMessage));
LOG(cfgLogLevelDefault(), 0, strPtr(info));
}
MEM_CONTEXT_TEMP_END();
}
// Reset timeBegin in case there is another command following this one
timeBegin = timeMSec();
FUNCTION_LOG_RETURN_VOID();
}