From 2a1399e97bebae7fc001dadba54b243cabca8282 Mon Sep 17 00:00:00 2001 From: l00280231 Date: Mon, 6 Dec 2021 18:03:17 +0800 Subject: [PATCH] fix gs_probackup sort core dump --- src/bin/pg_probackup/dir.cpp | 8 ++--- src/bin/pg_probackup/parray.cpp | 54 ++++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/bin/pg_probackup/dir.cpp b/src/bin/pg_probackup/dir.cpp index 828b27eeb..a14f016d7 100644 --- a/src/bin/pg_probackup/dir.cpp +++ b/src/bin/pg_probackup/dir.cpp @@ -479,8 +479,8 @@ pgFileCompareLinked(const void *f1, const void *f2) int pgFileCompareSize(const void *f1, const void *f2) { - pgFile *f1p = (pgFile *)const_cast(f1); - pgFile *f2p = (pgFile *)const_cast(f2); + pgFile *f1p = *(pgFile **)f1; + pgFile *f2p = *(pgFile **)f2; if (f1p->size > f2p->size) return 1; @@ -493,7 +493,7 @@ pgFileCompareSize(const void *f1, const void *f2) static int pgCompareString(const void *str1, const void *str2) { - return strcmp((char *)const_cast( str1), (char *)const_cast(str2)); + return strcmp(*(char **) str1, *(char **) str2); } /* Compare two Oids */ @@ -1037,7 +1037,7 @@ opt_externaldir_map(ConfigOption *opt, const char *arg) * Enforce permissions from backup_content.control. The only * problem now is with PGDATA itself. * TODO: we must preserve PGDATA permissions somewhere. Is it actually a problem? - * Shouldn`t starting postgres force correct permissions on PGDATA? + * Shouldn`t starting openGauss force correct permissions on PGDATA? * * TODO: symlink handling. If user located symlink in PG_TBLSPC_DIR, it will * be restored as directory. diff --git a/src/bin/pg_probackup/parray.cpp b/src/bin/pg_probackup/parray.cpp index 1459e5038..0b679f380 100644 --- a/src/bin/pg_probackup/parray.cpp +++ b/src/bin/pg_probackup/parray.cpp @@ -13,6 +13,8 @@ #include "parray.h" #include "pgut.h" +static size_t qsort_size = 100000; /* 100000 = default size */ + /* members of struct parray are hidden from client. */ struct parray { @@ -191,10 +193,60 @@ parray_num(const parray *array) return array->used; } +static void HeapAdjust(void **array, size_t size, size_t index, + int(*compare)(const void *, const void *)) +{ + size_t parent = index; + size_t child = 2 * parent + 1; /* 2 * n + 1 :left child */ + while (child < size) { + if (child + 1 < size && compare(&array[child + 1], &array[child]) > 0) { + child = child + 1; + } + + if (compare(&array[child], &array[parent]) > 0) { + void *tmp = array[child]; + array[child] = array[parent]; + array[parent] = tmp; + } else { + break; + } + + parent = child; + child = 2 * parent + 1; /* 2 * n + 1 :left child */ + } +} + +static void HeapPop(void **array, size_t size, + int(*compare)(const void *, const void *)) +{ + void *tmp = array[0]; + array[0] = array[size - 1]; + array[size - 1] = tmp; + + HeapAdjust(array, size - 1, 0, compare); +} + +static void HeapSort(void **array, size_t size, + int(*compare)(const void *, const void *)) +{ + for (int64 i = (size - 2) / 2; i >= 0; i--) { /* parent node:(size -2) / 2 */ + HeapAdjust(array, size, i, compare); + } + + for (size_t i = 0; i < size; i++) { + HeapPop(array, size - i, compare); + } +} + void parray_qsort(parray *array, int(*compare)(const void *, const void *)) { - qsort(array->data, array->used, sizeof(void *), compare); + Assert(array->used < (PG_UINT64_MAX / 1024)); + if (array->used <= qsort_size) { + qsort(array->data, array->used, sizeof(void *), compare); + } else { + HeapSort(array->data, array->used, compare); + } } void