备机全量build对undometa文件做校验

This commit is contained in:
liuchangfeng
2024-09-20 11:48:02 +08:00
parent 03e6cefbed
commit b3a66b9a2f
4 changed files with 206 additions and 0 deletions

View File

@ -832,3 +832,109 @@ void ResetUndoZoneLock()
}
} // namespace undo
bool CheckUndoZone(char *undoMeta)
{
Assert(undoMeta != NULL);
uint32 zoneId = 0;
char *persistblock = undoMeta;
char *uspMetaBuffer = NULL;
pg_crc32 pageCrcVal = 0; /* CRC store in undo meta page */
pg_crc32 comCrcVal = 0; /* calculating CRC current */
for (zoneId = 0; zoneId < PERSIST_ZONE_COUNT; zoneId++) {
if (zoneId % (UNDOZONE_COUNT_PER_PAGE * PAGES_READ_NUM) == 0) {
if (zoneId / (UNDOZONE_COUNT_PER_PAGE * PAGES_READ_NUM) > 0) {
persistblock = persistblock + UNDO_META_PAGE_SIZE * PAGES_READ_NUM;
}
}
if (zoneId % UNDOZONE_COUNT_PER_PAGE == 0) {
uspMetaBuffer =
persistblock +
((zoneId % (UNDOZONE_COUNT_PER_PAGE * PAGES_READ_NUM)) / UNDOZONE_COUNT_PER_PAGE) * UNDO_META_PAGE_SIZE;
uint32 count = UNDOZONE_COUNT_PER_PAGE;
if ((uint32)(PERSIST_ZONE_COUNT - zoneId) < UNDOZONE_COUNT_PER_PAGE) {
count = PERSIST_ZONE_COUNT - zoneId;
}
/* Get page CRC from uspMetaBuffer. */
pageCrcVal = *(pg_crc32 *)(uspMetaBuffer + sizeof(undo::UndoZoneMetaInfo) * count);
/*
* Calculate the CRC value based on all undospace meta information stored on the page.
* Then compare with pageCrcVal.
*/
INIT_CRC32C(comCrcVal);
COMP_CRC32C(comCrcVal, (void *)uspMetaBuffer, sizeof(undo::UndoZoneMetaInfo) * count);
FIN_CRC32C(comCrcVal);
if (!EQ_CRC32C(pageCrcVal, comCrcVal)) {
ereport(
ERROR,
(errmsg(UNDOFORMAT(
"Undo meta zoneid(%d) CRC calculated(%u) is different from CRC recorded(%u) in page."),
zoneId, comCrcVal, pageCrcVal)));
return false;
}
}
}
return true;
}
bool CheckUndoSpace(char *undoMeta, UndoSpaceType type)
{
Assert(undoMeta != NULL);
uint32 zoneId = 0;
uint32 totalPageCnt = 0;
char *persistblock = NULL;
uint32 seek = 0;
char *uspMetaBuffer = NULL;
pg_crc32 pageCrcVal = 0; /* CRC store in undo meta page */
pg_crc32 comCrcVal = 0; /* calculating CRC current */
if (type == UNDO_LOG_SPACE) {
UNDOSPACE_META_PAGE_COUNT(PERSIST_ZONE_COUNT, UNDOZONE_COUNT_PER_PAGE, totalPageCnt);
seek = totalPageCnt * UNDO_META_PAGE_SIZE;
} else {
UNDOSPACE_META_PAGE_COUNT(PERSIST_ZONE_COUNT, UNDOZONE_COUNT_PER_PAGE, totalPageCnt);
seek = totalPageCnt * UNDO_META_PAGE_SIZE;
UNDOSPACE_META_PAGE_COUNT(PERSIST_ZONE_COUNT, UNDOSPACE_COUNT_PER_PAGE, totalPageCnt);
seek += totalPageCnt * UNDO_META_PAGE_SIZE;
}
persistblock = undoMeta + seek;
for (zoneId = 0; zoneId < PERSIST_ZONE_COUNT; zoneId++) {
if (zoneId % (UNDOSPACE_COUNT_PER_PAGE * PAGES_READ_NUM) == 0) {
if (zoneId / (UNDOZONE_COUNT_PER_PAGE * PAGES_READ_NUM) > 0) {
persistblock = persistblock + UNDO_META_PAGE_SIZE * PAGES_READ_NUM;
}
}
if (zoneId % UNDOSPACE_COUNT_PER_PAGE == 0) {
uspMetaBuffer =
persistblock + ((zoneId % (UNDOSPACE_COUNT_PER_PAGE * PAGES_READ_NUM)) / UNDOSPACE_COUNT_PER_PAGE) *
UNDO_META_PAGE_SIZE;
uint32 count = UNDOSPACE_COUNT_PER_PAGE;
if ((uint32)(PERSIST_ZONE_COUNT - zoneId) < UNDOSPACE_COUNT_PER_PAGE) {
count = PERSIST_ZONE_COUNT - zoneId;
}
/* Get page CRC from uspMetaBuffer. */
pageCrcVal = *(pg_crc32 *)(uspMetaBuffer + sizeof(undo::UndoSpaceMetaInfo) * count);
/*
* Calculate the CRC value based on all undospace meta information stored on the page.
* Then compare with pageCrcVal.
*/
INIT_CRC32C(comCrcVal);
COMP_CRC32C(comCrcVal, (void *)uspMetaBuffer, sizeof(undo::UndoSpaceMetaInfo) * count);
FIN_CRC32C(comCrcVal);
if (!EQ_CRC32C(pageCrcVal, comCrcVal)) {
ereport(ERROR,
(errmsg(UNDOFORMAT("Undo meta space type(%d) zonid(%d) CRC calculated(%u) is different from CRC recorded(%u) in page."),
type, zoneId, comCrcVal, pageCrcVal)));
return false;
}
}
}
return true;
}
bool CheckUndoMetaBuf(char *undoMeta)
{
Assert(undoMeta != NULL);
return CheckUndoZone(undoMeta) && CheckUndoSpace(undoMeta, UNDO_LOG_SPACE) &&
CheckUndoSpace(undoMeta, UNDO_SLOT_SPACE);
}

View File

@ -127,6 +127,9 @@ static XLogRecPtr UpdateStartPtr(XLogRecPtr minLsn, XLogRecPtr curStartPtr);
/* compressed Function */
static void SendCompressedFile(char* readFileName, int basePathLen, struct stat& statbuf, bool missingOk, int64* size);
static bool SendUndoMeta(FILE *fp, struct stat *statbuf);
const int undometaSize = UNDOSPACE_META_PAGE_SIZE + 2 * UNDOSPACE_SPACE_PAGE_SIZE;
const int undometaRetryMax = 3;
/*
* save xlog location
@ -2240,6 +2243,10 @@ static bool sendFile(char *readfilename, char *tarfilename, struct stat *statbuf
/* send the pkg header containing msg like file size */
_tarWriteHeader(tarfilename, NULL, statbuf);
char *fname = NULL;
if ((fname = strstr(readfilename, UNDO_META_FILE)) != NULL) {
return SendUndoMeta(fp, statbuf);
}
/* Because pg_control file is shared in all instance when dss is enabled. Here pg_control of primary id
* need to send to main standby in standby cluster, so we must seek a postion accoring to primary id.
@ -2462,3 +2469,88 @@ void ut_save_xlogloc(const char *xloglocation)
{
save_xlogloc(xloglocation);
}
static bool SendUndoMeta(FILE *fp, struct stat *statbuf)
{
Assert(fp != NULL);
Assert(statbuf != NULL);
if (statbuf->st_size != undometaSize) {
(void)FreeFile(fp);
ereport(ERROR, (errmsg("Undometa size[%d] error", statbuf->st_size)));
}
pgoff_t len = 0;
MemoryContext oldcxt = MemoryContextSwitchTo(THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE));
char *undoMeta = (char *)palloc0(statbuf->st_size);
MemoryContextSwitchTo(oldcxt);
int retry = 0;
size_t cnt = 0;
errno_t rc = 0;
size_t pad;
fseek(fp, 0, SEEK_SET);
while ((cnt = fread(undoMeta, 1, statbuf->st_size, fp)) > 0) {
if (t_thrd.walsender_cxt.walsender_ready_to_stop) {
pfree(undoMeta);
ereport(ERROR, (errcode_for_file_access(), errmsg("base backup receive stop message, aborting backup")));
}
if (cnt != (size_t)statbuf->st_size) {
if (ferror(fp)) {
pfree(undoMeta);
ereport(ERROR, (errcode_for_file_access(), errmsg("could not read file undometa file")));
}
}
if (CheckUndoMetaBuf(undoMeta)) {
ereport(LOG, (errmsg("checkUndoMeta Success")));
break;
}
retry++;
fseek(fp, 0, SEEK_SET);
if (retry > undometaRetryMax) {
pfree(undoMeta);
(void)FreeFile(fp);
ereport(ERROR, (errmsg("Read undo meta error")));
}
}
while (len < statbuf->st_size) {
if (t_thrd.walsender_cxt.walsender_ready_to_stop) {
ereport(ERROR, (errcode_for_file_access(), errmsg("base backup receive stop message, aborting backup")));
}
cnt = Min(TAR_SEND_SIZE, statbuf->st_size - len);
/* Send the chunk as a CopyData Message */
if (pq_putmessage_noblock('d', undoMeta + len, cnt)) {
ereport(ERROR, (errcode_for_file_access(), errmsg("base backup could not send data, aborting backup")));
}
len += cnt;
if (len >= statbuf->st_size) {
/*
* Reached end of file. The file could be longer, if it was
* extended while we were sending it, but for a base backup we can
* ignore such extended data. It will be restored from WAL.
*/
break;
}
}
/* If the file was truncated while we were sending it, pad it with zeros */
if (len < statbuf->st_size) {
rc = memset_s(t_thrd.basebackup_cxt.buf_block, TAR_SEND_SIZE, 0, TAR_SEND_SIZE);
securec_check(rc, "", "");
while (len < statbuf->st_size) {
cnt = Min(TAR_SEND_SIZE, statbuf->st_size - len);
(void)pq_putmessage_noblock('d', t_thrd.basebackup_cxt.buf_block, cnt);
len += cnt;
}
}
/* Pad to 512 byte boundary, per tar format requirements */
pad = ((len + 511) & ~511) - len;
if (pad > 0) {
rc = memset_s(t_thrd.basebackup_cxt.buf_block, pad, 0, pad);
securec_check(rc, "", "");
(void)pq_putmessage_noblock('d', t_thrd.basebackup_cxt.buf_block, pad);
}
pfree(undoMeta);
(void)FreeFile(fp);
return true;
}

View File

@ -70,4 +70,5 @@ void ResetUndoZoneLock();
} // namespace undo
extern void GetUndoFileDirectory(char *path, int len, UndoPersistence upersistence);
bool CheckUndoMetaBuf(char *undoMeta);
#endif // __KNL_UUNDOAPI_H__

View File

@ -41,6 +41,13 @@ typedef struct UndoSpaceMetaInfo {
count = (total % unit == 0) ? (total / unit) : (total / unit) + 1; \
} while (0)
#define UNDOSPACE_META_PAGE_SIZE UNDO_META_PAGE_SIZE * \
((PERSIST_ZONE_COUNT % UNDOZONE_COUNT_PER_PAGE == 0) ? (PERSIST_ZONE_COUNT / UNDOZONE_COUNT_PER_PAGE) : (PERSIST_ZONE_COUNT / UNDOZONE_COUNT_PER_PAGE) + 1)
#define UNDOSPACE_SPACE_PAGE_SIZE UNDO_META_PAGE_SIZE * \
((PERSIST_ZONE_COUNT % UNDOSPACE_COUNT_PER_PAGE == 0) ? (PERSIST_ZONE_COUNT / UNDOSPACE_COUNT_PER_PAGE) : (PERSIST_ZONE_COUNT / UNDOSPACE_COUNT_PER_PAGE) + 1)
/*
* UndoSpace class is used as a proxy to manipulate undo zone(segment) file.
*/