Skip to content

Commit

Permalink
Add macros to create constant Buffer objects.
Browse files Browse the repository at this point in the history
These are more efficient than creating buffers in place when needed.

After replacement discovered that bufNewStr() and BufNewZ() were not being used in the core code so removed them.  This required using the macros in tests which is not the usual pattern.
  • Loading branch information
dwsteele committed Apr 20, 2019
1 parent c916802 commit e513c52
Show file tree
Hide file tree
Showing 27 changed files with 236 additions and 224 deletions.
4 changes: 4 additions & 0 deletions doc/xml/release.xml
Expand Up @@ -21,6 +21,10 @@
</release-improvement-list> </release-improvement-list>


<release-development-list> <release-development-list>
<release-item>
<p>Add macros to create constant <code>Buffer</code> objects.</p>
</release-item>

<release-item> <release-item>
<p>Add <code>unsigned int</code> <code>Variant</code> type and update code to use it.</p> <p>Add <code>unsigned int</code> <code>Variant</code> type and update code to use it.</p>
</release-item> </release-item>
Expand Down
4 changes: 2 additions & 2 deletions src/command/archive/common.c
Expand Up @@ -172,7 +172,7 @@ archiveAsyncStatusErrorWrite(ArchiveMode archiveMode, const String *walSegment,
storageNewWriteNP( storageNewWriteNP(
storageSpoolWrite(), storageSpoolWrite(),
strNewFmt("%s/%s" STATUS_EXT_ERROR, strPtr(archiveAsyncSpoolQueue(archiveMode)), strPtr(errorFile))), strNewFmt("%s/%s" STATUS_EXT_ERROR, strPtr(archiveAsyncSpoolQueue(archiveMode)), strPtr(errorFile))),
bufNewStr(strNewFmt("%d\n%s", code, strPtr(message)))); BUFSTR(strNewFmt("%d\n%s", code, strPtr(message))));
} }
MEM_CONTEXT_TEMP_END(); MEM_CONTEXT_TEMP_END();


Expand Down Expand Up @@ -200,7 +200,7 @@ archiveAsyncStatusOkWrite(ArchiveMode archiveMode, const String *walSegment, con
storageNewWriteNP( storageNewWriteNP(
storageSpoolWrite(), storageSpoolWrite(),
strNewFmt("%s/%s" STATUS_EXT_OK, strPtr(archiveAsyncSpoolQueue(archiveMode)), strPtr(walSegment))), strNewFmt("%s/%s" STATUS_EXT_OK, strPtr(archiveAsyncSpoolQueue(archiveMode)), strPtr(walSegment))),
warning == NULL ? NULL : bufNewStr(strNewFmt("0\n%s", strPtr(warning)))); warning == NULL ? NULL : BUFSTR(strNewFmt("0\n%s", strPtr(warning))));
} }
MEM_CONTEXT_TEMP_END(); MEM_CONTEXT_TEMP_END();


Expand Down
2 changes: 1 addition & 1 deletion src/command/archive/get/file.c
Expand Up @@ -153,7 +153,7 @@ archiveGetFile(
ioFilterGroupAdd( ioFilterGroupAdd(
filterGroup, filterGroup,
cipherBlockFilter( cipherBlockFilter(
cipherBlockNew(cipherModeDecrypt, cipherType, bufNewStr(archiveGetCheckResult.cipherPass), NULL))); cipherBlockNew(cipherModeDecrypt, cipherType, BUFSTR(archiveGetCheckResult.cipherPass), NULL)));
} }


// If file is compressed then add the decompression filter // If file is compressed then add the decompression filter
Expand Down
4 changes: 1 addition & 3 deletions src/command/archive/push/file.c
Expand Up @@ -131,9 +131,7 @@ archivePushFile(
if (cipherType != cipherTypeNone) if (cipherType != cipherTypeNone)
{ {
ioFilterGroupAdd( ioFilterGroupAdd(
filterGroup, filterGroup, cipherBlockFilter(cipherBlockNew(cipherModeEncrypt, cipherType, BUFSTR(cipherPass), NULL)));
cipherBlockFilter(
cipherBlockNew(cipherModeEncrypt, cipherType, bufNewStr(cipherPass), NULL)));
} }


ioReadFilterGroupSet(storageFileReadIo(source), filterGroup); ioReadFilterGroupSet(storageFileReadIo(source), filterGroup);
Expand Down
14 changes: 2 additions & 12 deletions src/common/io/write.c
Expand Up @@ -133,18 +133,8 @@ ioWriteLine(IoWrite *this, const String *string)
ASSERT(string != NULL); ASSERT(string != NULL);
ASSERT(this->opened && !this->closed); ASSERT(this->opened && !this->closed);


MEM_CONTEXT_TEMP_BEGIN() ioWrite(this, BUFSTR(string));
{ ioWrite(this, LF_BUF);
// Load a buffer with the linefeed-terminated string
Buffer *buffer = bufNew(strSize(string) + 1);
memcpy(bufPtr(buffer), strPtr(string), strSize(string));
bufPtr(buffer)[strSize(string)] = '\n';
bufUsedSet(buffer, bufSize(buffer));

// Write the string
ioWrite(this, buffer);
}
MEM_CONTEXT_TEMP_END()


FUNCTION_LOG_RETURN_VOID(); FUNCTION_LOG_RETURN_VOID();
} }
Expand Down
56 changes: 10 additions & 46 deletions src/common/type/buffer.c
Expand Up @@ -7,17 +7,21 @@ Buffer Handler
#include "common/debug.h" #include "common/debug.h"
#include "common/type/buffer.h" #include "common/type/buffer.h"


/***********************************************************************************************************************************
Constant buffers that are generally useful
***********************************************************************************************************************************/
BUFFER_STRDEF_EXTERN(BRACKETL_BUF, "[");
BUFFER_STRDEF_EXTERN(BRACKETR_BUF, "]");
BUFFER_STRDEF_EXTERN(EQ_BUF, "=");
BUFFER_STRDEF_EXTERN(LF_BUF, "\n");

/*********************************************************************************************************************************** /***********************************************************************************************************************************
Contains information about the buffer Contains information about the buffer
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
struct Buffer struct Buffer
{ {
MemContext *memContext; BUFFER_COMMON // Variables that are common to static and dynamic buffers
size_t size; // Actual size of buffer MemContext *memContext; // Mem context for dynamic buffers
bool limitSet; // Has a limit been set?
size_t limit; // Limited reported size of the buffer to make it appear smaller
size_t used; // Amount of buffer used
unsigned char *buffer; // Buffer allocation
}; };


/*********************************************************************************************************************************** /***********************************************************************************************************************************
Expand Down Expand Up @@ -70,46 +74,6 @@ bufNewC(size_t size, const void *buffer)
FUNCTION_TEST_RETURN(this); FUNCTION_TEST_RETURN(this);
} }


/***********************************************************************************************************************************
Create a new buffer from a string
***********************************************************************************************************************************/
Buffer *
bufNewStr(const String *string)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING, string);
FUNCTION_TEST_END();

ASSERT(string != NULL);

// Create object and copy string
Buffer *this = bufNew(strSize(string));
memcpy(this->buffer, strPtr(string), bufSize(this));
this->used = bufSize(this);

FUNCTION_TEST_RETURN(this);
}

/***********************************************************************************************************************************
Create a new buffer from a zero-terminated string
***********************************************************************************************************************************/
Buffer *
bufNewZ(const char *string)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRINGZ, string);
FUNCTION_TEST_END();

ASSERT(string != NULL);

// Create a new buffer and then copy the string into it.
Buffer *this = bufNew(strlen(string));
memcpy(this->buffer, string, bufSize(this));
this->used = bufSize(this);

FUNCTION_TEST_RETURN(this);
}

/*********************************************************************************************************************************** /***********************************************************************************************************************************
Append the contents of another buffer Append the contents of another buffer
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
Expand Down
66 changes: 64 additions & 2 deletions src/common/type/buffer.h
Expand Up @@ -17,8 +17,6 @@ Functions
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
Buffer *bufNew(size_t size); Buffer *bufNew(size_t size);
Buffer *bufNewC(size_t size, const void *buffer); Buffer *bufNewC(size_t size, const void *buffer);
Buffer *bufNewStr(const String *string);
Buffer *bufNewZ(const char *string);


Buffer *bufCat(Buffer *this, const Buffer *cat); Buffer *bufCat(Buffer *this, const Buffer *cat);
Buffer *bufCatC(Buffer *this, const unsigned char *cat, size_t catOffset, size_t catSize); Buffer *bufCatC(Buffer *this, const unsigned char *cat, size_t catOffset, size_t catSize);
Expand All @@ -42,6 +40,70 @@ void bufUsedZero(Buffer *this);


void bufFree(Buffer *this); void bufFree(Buffer *this);


/***********************************************************************************************************************************
Fields that are common between dynamically allocated and constant buffers
There is nothing user-accessible here but this construct allows constant buffers to be created and then handled by the same
functions that process dynamically allocated buffers.
***********************************************************************************************************************************/
#define BUFFER_COMMON \
size_t size; /* Actual size of buffer */ \
bool limitSet; /* Has a limit been set? */ \
size_t limit; /* Make the buffer appear smaller */ \
size_t used; /* Amount of buffer used */ \
unsigned char *buffer; /* Buffer allocation */

typedef struct BufferConst
{
BUFFER_COMMON
} BufferConst;

/***********************************************************************************************************************************
Macros for constant buffers
Frequently used constant buffers can be declared with these macros at compile time rather than dynamically at run time.
Note that buffers created in this way are declared as const so can't be modified or freed by the buf*() methods. Casting to
Buffer * will result in a segfault.
By convention all buffer constant identifiers are appended with _BUF.
***********************************************************************************************************************************/
// Create a buffer constant inline from an unsigned char[]
#define BUF(bufferParam, sizeParam) \
((const Buffer *)&(const BufferConst){.size = sizeParam, .used = sizeParam, .buffer = bufferParam})

// Create a buffer constant inline from a non-constant zero-terminated string
#define BUFSTRZ(stringz) \
BUF((unsigned char *)stringz, strlen(stringz))

// Create a buffer constant inline from a String
#define BUFSTR(string) \
BUF((unsigned char *)strPtr(string), strSize(string))

// Create a buffer constant inline from a constant zero-terminated string
#define BUFSTRDEF(stringdef) \
BUF((unsigned char *)stringdef, (sizeof(stringdef) - 1))

// Used to declare buffer constants that will be externed using BUFFER_DECLARE(). Must be used in a .c file.
#define BUFFER_STRDEF_EXTERN(name, string) \
const Buffer *name = BUFSTRDEF(string)

// Used to declare buffer constants that will be local to the .c file. Must be used in a .c file.
#define BUFFER_STRDEF_STATIC(name, string) \
static BUFFER_STRDEF_EXTERN(name, string)

// Used to extern buffer constants declared with BUFFER_STRDEF_EXTERN(. Must be used in a .h file.
#define BUFFER_DECLARE(name) \
extern const Buffer *name

/***********************************************************************************************************************************
Constant buffers that are generally useful
***********************************************************************************************************************************/
BUFFER_DECLARE(BRACKETL_BUF);
BUFFER_DECLARE(BRACKETR_BUF);
BUFFER_DECLARE(EQ_BUF);
BUFFER_DECLARE(LF_BUF);

/*********************************************************************************************************************************** /***********************************************************************************************************************************
Macros for function logging Macros for function logging
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
Expand Down
2 changes: 1 addition & 1 deletion src/info/info.c
Expand Up @@ -137,7 +137,7 @@ infoLoad(Info *this, const Storage *storage, bool copyFile, CipherType cipherTyp
ioReadFilterGroupSet( ioReadFilterGroupSet(
storageFileReadIo(infoRead), storageFileReadIo(infoRead),
ioFilterGroupAdd( ioFilterGroupAdd(
ioFilterGroupNew(), cipherBlockFilter(cipherBlockNew(cipherModeDecrypt, cipherType, bufNewStr(cipherPass), ioFilterGroupNew(), cipherBlockFilter(cipherBlockNew(cipherModeDecrypt, cipherType, BUFSTR(cipherPass),
NULL)))); NULL))));
} }


Expand Down
12 changes: 7 additions & 5 deletions src/storage/driver/s3/storage.c
Expand Up @@ -53,8 +53,10 @@ STRING_STATIC(S3_XML_TAG_PREFIX_STR, "Prefix");
AWS authentication v4 constants AWS authentication v4 constants
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
#define S3 "s3" #define S3 "s3"
BUFFER_STRDEF_STATIC(S3_BUF, S3);
#define AWS4 "AWS4" #define AWS4 "AWS4"
#define AWS4_REQUEST "aws4_request" #define AWS4_REQUEST "aws4_request"
BUFFER_STRDEF_STATIC(AWS4_REQUEST_BUF, AWS4_REQUEST);
#define AWS4_HMAC_SHA256 "AWS4-HMAC-SHA256" #define AWS4_HMAC_SHA256 "AWS4-HMAC-SHA256"


/*********************************************************************************************************************************** /***********************************************************************************************************************************
Expand Down Expand Up @@ -186,14 +188,14 @@ storageDriverS3Auth(
if (!strEq(date, this->signingKeyDate)) if (!strEq(date, this->signingKeyDate))
{ {
const Buffer *dateKey = cryptoHmacOne( const Buffer *dateKey = cryptoHmacOne(
HASH_TYPE_SHA256_STR, bufNewStr(strNewFmt(AWS4 "%s", strPtr(this->secretAccessKey))), bufNewStr(date)); HASH_TYPE_SHA256_STR, BUFSTR(strNewFmt(AWS4 "%s", strPtr(this->secretAccessKey))), BUFSTR(date));
const Buffer *regionKey = cryptoHmacOne(HASH_TYPE_SHA256_STR, dateKey, bufNewStr(this->region)); const Buffer *regionKey = cryptoHmacOne(HASH_TYPE_SHA256_STR, dateKey, BUFSTR(this->region));
const Buffer *serviceKey = cryptoHmacOne(HASH_TYPE_SHA256_STR, regionKey, bufNewZ(S3)); const Buffer *serviceKey = cryptoHmacOne(HASH_TYPE_SHA256_STR, regionKey, S3_BUF);


// Switch to the object context so signing key and date are not lost // Switch to the object context so signing key and date are not lost
MEM_CONTEXT_BEGIN(this->memContext) MEM_CONTEXT_BEGIN(this->memContext)
{ {
this->signingKey = cryptoHmacOne(HASH_TYPE_SHA256_STR, serviceKey, bufNewZ(AWS4_REQUEST)); this->signingKey = cryptoHmacOne(HASH_TYPE_SHA256_STR, serviceKey, AWS4_REQUEST_BUF);
this->signingKeyDate = strDup(date); this->signingKeyDate = strDup(date);
} }
MEM_CONTEXT_END(); MEM_CONTEXT_END();
Expand All @@ -203,7 +205,7 @@ storageDriverS3Auth(
const String *authorization = strNewFmt( const String *authorization = strNewFmt(
AWS4_HMAC_SHA256 " Credential=%s/%s/%s/" S3 "/" AWS4_REQUEST ",SignedHeaders=%s,Signature=%s", AWS4_HMAC_SHA256 " Credential=%s/%s/%s/" S3 "/" AWS4_REQUEST ",SignedHeaders=%s,Signature=%s",
strPtr(this->accessKey), strPtr(date), strPtr(this->region), strPtr(signedHeaders), strPtr(this->accessKey), strPtr(date), strPtr(this->region), strPtr(signedHeaders),
strPtr(bufHex(cryptoHmacOne(HASH_TYPE_SHA256_STR, this->signingKey, bufNewStr(stringToSign))))); strPtr(bufHex(cryptoHmacOne(HASH_TYPE_SHA256_STR, this->signingKey, BUFSTR(stringToSign)))));


httpHeaderPut(httpHeader, S3_HEADER_AUTHORIZATION_STR, authorization); httpHeaderPut(httpHeader, S3_HEADER_AUTHORIZATION_STR, authorization);
} }
Expand Down
14 changes: 7 additions & 7 deletions test/src/module/command/archiveCommonTest.c
Expand Up @@ -48,20 +48,20 @@ testRun(void)
// ------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------
storagePutNP( storagePutNP(
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))), storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
bufNewZ(BOGUS_STR)); BUFSTRDEF(BOGUS_STR));
TEST_ERROR( TEST_ERROR(
archiveAsyncStatus(archiveModePush, segment, false), FormatError, archiveAsyncStatus(archiveModePush, segment, false), FormatError,
"000000010000000100000001.ok content must have at least two lines"); "000000010000000100000001.ok content must have at least two lines");


storagePutNP( storagePutNP(
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))), storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
bufNewZ(BOGUS_STR "\n")); BUFSTRDEF(BOGUS_STR "\n"));
TEST_ERROR( TEST_ERROR(
archiveAsyncStatus(archiveModePush, segment, false), FormatError, "000000010000000100000001.ok message must be > 0"); archiveAsyncStatus(archiveModePush, segment, false), FormatError, "000000010000000100000001.ok message must be > 0");


storagePutNP( storagePutNP(
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))), storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
bufNewZ(BOGUS_STR "\nmessage")); BUFSTRDEF(BOGUS_STR "\nmessage"));
TEST_ERROR( TEST_ERROR(
archiveAsyncStatus(archiveModePush, segment, false), FormatError, "unable to convert base 10 string 'BOGUS' to int"); archiveAsyncStatus(archiveModePush, segment, false), FormatError, "unable to convert base 10 string 'BOGUS' to int");


Expand All @@ -70,13 +70,13 @@ testRun(void)


storagePutNP( storagePutNP(
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))), storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
bufNewZ("0\nwarning")); BUFSTRDEF("0\nwarning"));
TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false), true, "ok file with warning"); TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false), true, "ok file with warning");
harnessLogResult("P00 WARN: warning"); harnessLogResult("P00 WARN: warning");


storagePutNP( storagePutNP(
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))), storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
bufNewZ("25\nerror")); BUFSTRDEF("25\nerror"));
TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false), true, "error status renamed to ok"); TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false), true, "error status renamed to ok");
harnessLogResult( harnessLogResult(
"P00 WARN: WAL segment '000000010000000100000001' was not pushed due to error [25] and was manually skipped: error"); "P00 WARN: WAL segment '000000010000000100000001' was not pushed due to error [25] and was manually skipped: error");
Expand All @@ -94,15 +94,15 @@ testRun(void)


storagePutNP( storagePutNP(
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.error", strPtr(segment))), storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.error", strPtr(segment))),
bufNewZ("25\nmessage")); BUFSTRDEF("25\nmessage"));
TEST_ERROR(archiveAsyncStatus(archiveModePush, segment, true), AssertError, "message"); TEST_ERROR(archiveAsyncStatus(archiveModePush, segment, true), AssertError, "message");


TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false), false, "suppress error"); TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false), false, "suppress error");


// ------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------
storagePutNP( storagePutNP(
storageNewWriteNP(storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_OUT "/global.error")), storageNewWriteNP(storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_OUT "/global.error")),
bufNewZ("102\nexecute error")); BUFSTRDEF("102\nexecute error"));


TEST_ERROR(archiveAsyncStatus(archiveModePush, strNew("anyfile"), true), ExecuteError, "execute error"); TEST_ERROR(archiveAsyncStatus(archiveModePush, strNew("anyfile"), true), ExecuteError, "execute error");
} }
Expand Down

0 comments on commit e513c52

Please sign in to comment.