Skip to content

Commit

Permalink
Sort and find improvements to List and StringList objects.
Browse files Browse the repository at this point in the history
Push the responsibility for sort and find down to the List object by introducing a general comparator function that can be used for both sorting and finding.

Update insert and add functions to return the item added rather than the list.  This is more useful in the core code, though numerous updates to the tests were required.
  • Loading branch information
dwsteele committed Sep 12, 2019
1 parent e4a071c commit 506c10f
Show file tree
Hide file tree
Showing 20 changed files with 557 additions and 247 deletions.
140 changes: 70 additions & 70 deletions src/Makefile.in

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/command/archive/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,8 @@ walSegmentRange(const String *walSegmentBegin, size_t walSegmentSize, unsigned i

MEM_CONTEXT_TEMP_BEGIN()
{
result = strLstAdd(strLstNew(), walSegmentBegin);
result = strLstNew();
strLstAdd(result, walSegmentBegin);

if (range > 1)
{
Expand Down
48 changes: 6 additions & 42 deletions src/command/expire/expire.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ typedef struct ArchiveExpired
} ArchiveExpired;

static int
archiveIdAscComparator(const void *item1, const void *item2)
archiveIdComparator(const void *item1, const void *item2)
{
StringList *archiveSort1 = strLstNewSplitZ(*(String **)item1, "-");
StringList *archiveSort2 = strLstNewSplitZ(*(String **)item2, "-");
Expand All @@ -37,45 +37,6 @@ archiveIdAscComparator(const void *item1, const void *item2)
return (int1 - int2);
}

static int
archiveIdDescComparator(const void *item1, const void *item2)
{
StringList *archiveSort1 = strLstNewSplitZ(*(String **)item1, "-");
StringList *archiveSort2 = strLstNewSplitZ(*(String **)item2, "-");
int int1 = atoi(strPtr(strLstGet(archiveSort1, 1)));
int int2 = atoi(strPtr(strLstGet(archiveSort2, 1)));

return (int2 - int1);
}

static StringList *
sortArchiveId(StringList *sortString, SortOrder sortOrder)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STRING_LIST, sortString);
FUNCTION_LOG_PARAM(ENUM, sortOrder);
FUNCTION_LOG_END();

ASSERT(sortString != NULL);

switch (sortOrder)
{
case sortOrderAsc:
{
lstSort((List *)sortString, archiveIdAscComparator);
break;
}

case sortOrderDesc:
{
lstSort((List *)sortString, archiveIdDescComparator);
break;
}
}

FUNCTION_LOG_RETURN(STRING_LIST, sortString);
}

typedef struct ArchiveRange
{
const String *start;
Expand Down Expand Up @@ -311,8 +272,11 @@ removeExpiredArchive(InfoBackup *infoBackup)
InfoPg *infoArchivePgData = infoArchivePg(infoArchive);

// Get a list of archive directories (e.g. 9.4-1, 10-2, etc) sorted by the db-id (number after the dash).
StringList *listArchiveDisk = sortArchiveId(
storageListP(storageRepo(), STRDEF(STORAGE_REPO_ARCHIVE), .expression = STRDEF(REGEX_ARCHIVE_DIR_DB_VERSION)),
StringList *listArchiveDisk = strLstSort(
strLstComparatorSet(
storageListP(
storageRepo(), STRDEF(STORAGE_REPO_ARCHIVE), .expression = STRDEF(REGEX_ARCHIVE_DIR_DB_VERSION)),
archiveIdComparator),
sortOrderAsc);

StringList *globalBackupArchiveRetentionList = strLstNew();
Expand Down
185 changes: 169 additions & 16 deletions src/common/type/list.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct List
unsigned int listSize;
unsigned int listSizeMax;
unsigned char *list;
ListComparator *comparator;
};

OBJECT_DEFINE_MOVE(LIST);
Expand All @@ -33,7 +34,20 @@ Create a new list
List *
lstNew(size_t itemSize)
{
FUNCTION_TEST_VOID();
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(SIZE, itemSize);
FUNCTION_TEST_END();

FUNCTION_TEST_RETURN(lstNewP(itemSize, .comparator = lstComparatorStr));
}

List *
lstNewParam(size_t itemSize, ListParam param)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(SIZE, itemSize);
FUNCTION_TEST_PARAM(FUNCTIONP, param.comparator);
FUNCTION_TEST_END();

List *this = NULL;

Expand All @@ -43,6 +57,7 @@ lstNew(size_t itemSize)
this = memNew(sizeof(List));
this->memContext = MEM_CONTEXT_NEW();
this->itemSize = itemSize;
this->comparator = param.comparator;
}
MEM_CONTEXT_NEW_END();

Expand All @@ -52,7 +67,7 @@ lstNew(size_t itemSize)
/***********************************************************************************************************************************
Add an item to the end of the list
***********************************************************************************************************************************/
List *
void *
lstAdd(List *this, const void *item)
{
FUNCTION_TEST_BEGIN();
Expand All @@ -63,9 +78,7 @@ lstAdd(List *this, const void *item)
ASSERT(this != NULL);
ASSERT(item != NULL);

lstInsert(this, lstSize(this), item);

FUNCTION_TEST_RETURN(this);
FUNCTION_TEST_RETURN(lstInsert(this, lstSize(this), item));
}

/***********************************************************************************************************************************
Expand Down Expand Up @@ -95,6 +108,23 @@ lstClear(List *this)
FUNCTION_TEST_RETURN(this);
}

/***********************************************************************************************************************************
Compare Strings or structs with a String as the first member
***********************************************************************************************************************************/
int
lstComparatorStr(const void *item1, const void *item2)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM_P(VOID, item1);
FUNCTION_TEST_PARAM_P(VOID, item2);
FUNCTION_TEST_END();

ASSERT(item1 != NULL);
ASSERT(item2 != NULL);

FUNCTION_TEST_RETURN(strCmp(*(String **)item1, *(String **)item2));
}

/***********************************************************************************************************************************
Get an item from the list
***********************************************************************************************************************************/
Expand All @@ -116,10 +146,69 @@ lstGet(const List *this, unsigned int listIdx)
FUNCTION_TEST_RETURN(this->list + (listIdx * this->itemSize));
}

/***********************************************************************************************************************************
Find an item in the list
***********************************************************************************************************************************/
unsigned int
lstFindIdx(const List *this, const void *item)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(LIST, this);
FUNCTION_TEST_PARAM_P(VOID, item);
FUNCTION_TEST_END();

ASSERT(this != NULL);
ASSERT(item != NULL);

unsigned int result = LIST_NOT_FOUND;

for (unsigned int listIdx = 0; listIdx < lstSize(this); listIdx++)
{
if (this->comparator(item, lstGet(this, listIdx)) == 0)
{
result = listIdx;
break;
}
}

FUNCTION_TEST_RETURN(result);
}

void *
lstFindDefault(const List *this, const void *item, void *itemDefault)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(LIST, this);
FUNCTION_TEST_PARAM_P(VOID, item);
FUNCTION_TEST_PARAM_P(VOID, itemDefault);
FUNCTION_TEST_END();

ASSERT(this != NULL);
ASSERT(item != NULL);

unsigned int listIdx = lstFindIdx(this, item);

FUNCTION_TEST_RETURN(listIdx == LIST_NOT_FOUND ? itemDefault : lstGet(this, listIdx));
}

void *
lstFind(const List *this, const void *item)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(LIST, this);
FUNCTION_TEST_PARAM_P(VOID, item);
FUNCTION_TEST_END();

ASSERT(this != NULL);
ASSERT(item != NULL);

FUNCTION_TEST_RETURN(lstFindDefault(this, item, NULL));
}

/***********************************************************************************************************************************
Insert an item into the list
***********************************************************************************************************************************/
List *
void *
lstInsert(List *this, unsigned int listIdx, const void *item)
{
FUNCTION_TEST_BEGIN();
Expand Down Expand Up @@ -153,18 +242,16 @@ lstInsert(List *this, unsigned int listIdx, const void *item)
}

// If not inserting at the end then move items down to make space
void *itemPtr = this->list + (listIdx * this->itemSize);

if (listIdx != lstSize(this))
{
memmove(
this->list + ((listIdx + 1) * this->itemSize), this->list + (listIdx * this->itemSize),
(lstSize(this) - listIdx) * this->itemSize);
}
memmove(this->list + ((listIdx + 1) * this->itemSize), itemPtr, (lstSize(this) - listIdx) * this->itemSize);

// Copy item into the list
memcpy(this->list + (listIdx * this->itemSize), item, this->itemSize);
memcpy(itemPtr, item, this->itemSize);
this->listSize++;

FUNCTION_TEST_RETURN(this);
FUNCTION_TEST_RETURN(itemPtr);
}

/***********************************************************************************************************************************
Expand All @@ -190,6 +277,28 @@ lstRemoveIdx(List *this, unsigned int listIdx)
FUNCTION_TEST_RETURN(this);
}

bool
lstRemove(List *this, const void *item)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(LIST, this);
FUNCTION_TEST_PARAM_P(VOID, item);
FUNCTION_TEST_END();

ASSERT(this != NULL);
ASSERT(item != NULL);

unsigned int listIdx = lstFindIdx(this, item);

if (listIdx != LIST_NOT_FOUND)
{
lstRemoveIdx(this, listIdx);
FUNCTION_TEST_RETURN(true);
}

FUNCTION_TEST_RETURN(false);
}

/***********************************************************************************************************************************
Return the memory context for this list
***********************************************************************************************************************************/
Expand Down Expand Up @@ -223,18 +332,62 @@ lstSize(const List *this)
/***********************************************************************************************************************************
List sort
***********************************************************************************************************************************/
static List *lstSortList = NULL;

static int
lstSortDescComparator(const void *item1, const void *item2)
{
return lstSortList->comparator(item2, item1);
}

List *
lstSort(List *this, SortOrder sortOrder)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(LIST, this);
FUNCTION_TEST_PARAM(ENUM, sortOrder);
FUNCTION_TEST_END();

ASSERT(this != NULL);

switch (sortOrder)
{
case sortOrderAsc:
{
qsort(this->list, this->listSize, this->itemSize, this->comparator);
break;
}

case sortOrderDesc:
{
// Assign the list that will be sorted for the comparator function to use
lstSortList = this;

qsort(this->list, this->listSize, this->itemSize, lstSortDescComparator);
break;
}

case sortOrderNone:
break;
}

FUNCTION_TEST_RETURN(this);
}

/***********************************************************************************************************************************
Set a new comparator
***********************************************************************************************************************************/
List *
lstSort(List *this, int (*comparator)(const void *, const void*))
lstComparatorSet(List *this, ListComparator *comparator)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(LIST, this);
FUNCTION_TEST_PARAM(FUNCTIONP, comparator);
FUNCTION_TEST_END();

ASSERT(this != NULL);
ASSERT(comparator != NULL);

qsort(this->list, this->listSize, this->itemSize, comparator);
this->comparator = comparator;

FUNCTION_TEST_RETURN(this);
}
Expand Down
Loading

0 comments on commit 506c10f

Please sign in to comment.