/*********************************************************************************************************************************** Read all IO into a buffer ***********************************************************************************************************************************/ Buffer * ioReadBuf(IoRead *read) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(IO_READ, read); FUNCTION_TEST_END(); ASSERT(read != NULL); Buffer *result = NULL; MEM_CONTEXT_TEMP_BEGIN() { // Read IO into the buffer result = bufNew(0); do { bufResize(result, bufSize(result) + ioBufferSize()); ioRead(read, result); } while (!ioReadEof(read)); // Resize the buffer and move to calling context bufResize(result, bufUsed(result)); bufMove(result, MEM_CONTEXT_OLD()); } MEM_CONTEXT_TEMP_END(); FUNCTION_TEST_RETURN(result); }
/*********************************************************************************************************************************** Dynamic module loader ***********************************************************************************************************************************/ static const char * embeddedModuleGetInternal(const char *moduleName) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(STRINGZ, moduleName); FUNCTION_TEST_END(); // Find module const char *result = NULL; for (unsigned int moduleIdx = 0; moduleIdx < sizeof(embeddedModule) / sizeof(EmbeddedModule); moduleIdx++) { if (strcmp(embeddedModule[moduleIdx].name, moduleName) == 0) { result = embeddedModule[moduleIdx].data; break; } } // Error if the module was not found if (result == NULL) THROW_FMT(AssertError, "unable to load embedded module '%s'", moduleName); FUNCTION_TEST_RETURN(result); }
/*********************************************************************************************************************************** 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) { case signalTypeHup: { name = "HUP"; break; } case signalTypeInt: { name = "INT"; break; } case signalTypeTerm: { name = "TERM"; break; } case signalTypeNone: THROW(AssertError, "no name for signal none"); } FUNCTION_TEST_RETURN(name); }
/*********************************************************************************************************************************** Create the stop filename ***********************************************************************************************************************************/ String * lockStopFileName(const String *stanza) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(STRING, stanza); FUNCTION_TEST_END(); String *result = strNewFmt("%s/%s.stop", strPtr(cfgOptionStr(cfgOptLockPath)), stanza != NULL ? strPtr(stanza) : "all"); FUNCTION_TEST_RETURN(result); }
/*********************************************************************************************************************************** Format the warning when a file is dropped ***********************************************************************************************************************************/ static String * archivePushDropWarning(const String *walFile, uint64_t queueMax) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(STRING, walFile); FUNCTION_TEST_PARAM(UINT64, queueMax); FUNCTION_TEST_END(); FUNCTION_TEST_RETURN( strNewFmt("dropped WAL file '%s' because archive queue exceeded %s", strPtr(walFile), strPtr(strSizeFormat(queueMax)))); }
/*********************************************************************************************************************************** Build list of parameters to use for perl main ***********************************************************************************************************************************/ String * perlMain(void) { FUNCTION_TEST_VOID(); // Add command arguments to pass to main String *commandParam = strNew(""); for (unsigned int paramIdx = 0; paramIdx < strLstSize(cfgCommandParam()); paramIdx++) strCatFmt(commandParam, ",'%s'", strPtr(strLstGet(cfgCommandParam(), paramIdx))); // Construct Perl main call String *mainCall = strNewFmt( "($iResult, $bErrorC, $strMessage) = " PGBACKREST_MAIN "('%s'%s)", cfgCommandName(cfgCommand()), strPtr(commandParam)); FUNCTION_TEST_RETURN(mainCall); }
/*********************************************************************************************************************************** Execute main function in Perl ***********************************************************************************************************************************/ static int perlExecResult(int code, bool errorC, const char *message) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(INT, code); FUNCTION_TEST_PARAM(BOOL, errorC); FUNCTION_TEST_PARAM(STRINGZ, message); FUNCTION_TEST_END(); int result = code; if (code >= errorTypeCode(&AssertError)) { if (errorC) RETHROW(); else THROW_CODE(code, strlen(message) == 0 ? PERL_EMBED_ERROR : message); } FUNCTION_TEST_RETURN(result); }
/*********************************************************************************************************************************** Wrapper for lstNew() ***********************************************************************************************************************************/ StringList * strLstNew(void) { FUNCTION_TEST_VOID(); FUNCTION_TEST_RETURN((StringList *)lstNew(sizeof(String *))); }
/*********************************************************************************************************************************** Build JSON output from options ***********************************************************************************************************************************/ String * perlOptionJson(void) { FUNCTION_TEST_VOID(); String *result = NULL; MEM_CONTEXT_TEMP_BEGIN() { KeyValue *configKv = kvNew(); for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++) { // Skip if not valid if (!cfgOptionValid(optionId)) continue; Variant *optionVar = varNewKv(kvNew()); // Add valid kvPut(varKv(optionVar), VARSTRDEF("valid"), BOOL_TRUE_VAR); // Add source const Variant *source = NULL; switch (cfgOptionSource(optionId)) { case cfgSourceParam: { source = VARSTRDEF("param"); break; } case cfgSourceConfig: { source = VARSTRDEF("config"); break; } case cfgSourceDefault: { source = VARSTRDEF("default"); break; } } kvPut(varKv(optionVar), VARSTRDEF("source"), source); // Add negate and reset kvPut(varKv(optionVar), VARSTRDEF("negate"), VARBOOL(cfgOptionNegate(optionId))); kvPut(varKv(optionVar), VARSTRDEF("reset"), VARBOOL(cfgOptionReset(optionId))); // Add value if it is set if (cfgOptionTest(optionId)) { const Variant *valueVar = NULL; switch (cfgDefOptionType(cfgOptionDefIdFromId(optionId))) { case cfgDefOptTypeBoolean: case cfgDefOptTypeFloat: case cfgDefOptTypeInteger: case cfgDefOptTypePath: case cfgDefOptTypeSize: case cfgDefOptTypeString: { valueVar = cfgOption(optionId); break; } case cfgDefOptTypeHash: { valueVar = varNewKv(kvNew()); const KeyValue *valueKv = cfgOptionKv(optionId); const VariantList *keyList = kvKeyList(valueKv); for (unsigned int listIdx = 0; listIdx < varLstSize(keyList); listIdx++) kvPut(varKv(valueVar), varLstGet(keyList, listIdx), kvGet(valueKv, varLstGet(keyList, listIdx))); break; } case cfgDefOptTypeList: { valueVar = varNewKv(kvNew()); const VariantList *valueList = cfgOptionLst(optionId); for (unsigned int listIdx = 0; listIdx < varLstSize(valueList); listIdx++) kvPut(varKv(valueVar), varLstGet(valueList, listIdx), BOOL_TRUE_VAR); break; } } kvPut(varKv(optionVar), VARSTRDEF("value"), valueVar); } kvPut(configKv, VARSTRZ(cfgOptionName(optionId)), optionVar); } memContextSwitch(MEM_CONTEXT_OLD()); result = jsonFromKv(configKv, 0); memContextSwitch(MEM_CONTEXT_TEMP()); } MEM_CONTEXT_TEMP_END(); FUNCTION_TEST_RETURN(result); }
/*********************************************************************************************************************************** Get/set buffer size ***********************************************************************************************************************************/ size_t ioBufferSize(void) { FUNCTION_TEST_VOID(); FUNCTION_TEST_RETURN(bufferSize); }