From cb1f44150c0f047facd0ad7fa9a782fa5101d769 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Tue, 23 Jul 2024 12:31:08 +0900
Subject: [PATCH v4 2/4] Add more debugging information when reading stats
 files

This is useful to know which part of a stats file is corrupted when
loading it.
---
 src/backend/utils/activity/pgstat.c | 65 +++++++++++++++++++++++++++--
 1 file changed, 61 insertions(+), 4 deletions(-)

diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index 2e22bf2707..4a1724d342 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -1537,9 +1537,18 @@ pgstat_read_statsfile(void)
 	/*
 	 * Verify it's of the expected format.
 	 */
-	if (!read_chunk_s(fpin, &format_id) ||
-		format_id != PGSTAT_FILE_FORMAT_ID)
+	if (!read_chunk_s(fpin, &format_id))
+	{
+		elog(WARNING, "could not read format ID");
 		goto error;
+	}
+
+	if (format_id != PGSTAT_FILE_FORMAT_ID)
+	{
+		elog(WARNING, "found incorrect format ID %d (expected %d)",
+			 format_id, PGSTAT_FILE_FORMAT_ID);
+		goto error;
+	}
 
 	/*
 	 * We found an existing statistics file. Read it and put all the stats
@@ -1559,22 +1568,37 @@ pgstat_read_statsfile(void)
 
 					/* entry for fixed-numbered stats */
 					if (!read_chunk_s(fpin, &kind))
+					{
+						elog(WARNING, "could not read stats kind for entry of type %c", t);
 						goto error;
+					}
 
 					if (!pgstat_is_kind_valid(kind))
+					{
+						elog(WARNING, "invalid stats kind %d for entry of type %c",
+							 kind, t);
 						goto error;
+					}
 
 					info = pgstat_get_kind_info(kind);
 
 					if (!info->fixed_amount)
+					{
+						elog(WARNING, "invalid fixed_amount in stats kind %d for entry of type %c",
+							 kind, t);
 						goto error;
+					}
 
 					/* Load back stats into shared memory */
 					ptr = ((char *) shmem) + info->shared_ctl_off +
 						info->shared_data_off;
 
 					if (!read_chunk(fpin, ptr, info->shared_data_len))
+					{
+						elog(WARNING, "could not read data of stats kind %d for entry of type %c",
+							 kind, t);
 						goto error;
+					}
 
 					break;
 				}
@@ -1591,10 +1615,17 @@ pgstat_read_statsfile(void)
 					{
 						/* normal stats entry, identified by PgStat_HashKey */
 						if (!read_chunk_s(fpin, &key))
+						{
+							elog(WARNING, "could not read key for entry of type %c", t);
 							goto error;
+						}
 
 						if (!pgstat_is_kind_valid(key.kind))
+						{
+							elog(WARNING, "invalid stats kind for entry %d/%u/%u of type %c",
+								 key.kind, key.dboid, key.objoid, t);
 							goto error;
+						}
 					}
 					else
 					{
@@ -1604,22 +1635,41 @@ pgstat_read_statsfile(void)
 						NameData	name;
 
 						if (!read_chunk_s(fpin, &kind))
+						{
+							elog(WARNING, "could not read stats kind for entry of type %c", t);
 							goto error;
+						}
 						if (!read_chunk_s(fpin, &name))
+						{
+							elog(WARNING, "could not read name of stats kind %d for entry of type %c",
+								 kind, t);
 							goto error;
+						}
 						if (!pgstat_is_kind_valid(kind))
+						{
+							elog(WARNING, "invalid stats kind %d for entry of type %c",
+								 kind, t);
 							goto error;
+						}
 
 						kind_info = pgstat_get_kind_info(kind);
 
 						if (!kind_info->from_serialized_name)
+						{
+							elog(WARNING, "invalid from_serialized_name in stats kind %d for entry of type %c",
+								 kind, t);
 							goto error;
+						}
 
 						if (!kind_info->from_serialized_name(&name, &key))
 						{
 							/* skip over data for entry we don't care about */
 							if (fseek(fpin, pgstat_get_entry_len(kind), SEEK_CUR) != 0)
+							{
+								elog(WARNING, "could not seek \"%s\" of stats kind %d for entry of type %c",
+									 NameStr(name), kind, t);
 								goto error;
+							}
 
 							continue;
 						}
@@ -1638,8 +1688,8 @@ pgstat_read_statsfile(void)
 					if (found)
 					{
 						dshash_release_lock(pgStatLocal.shared_hash, p);
-						elog(WARNING, "found duplicate stats entry %d/%u/%u",
-							 key.kind, key.dboid, key.objoid);
+						elog(WARNING, "found duplicate stats entry %d/%u/%u of type %c",
+							 key.kind, key.dboid, key.objoid, t);
 						goto error;
 					}
 
@@ -1649,7 +1699,11 @@ pgstat_read_statsfile(void)
 					if (!read_chunk(fpin,
 									pgstat_get_entry_data(key.kind, header),
 									pgstat_get_entry_len(key.kind)))
+					{
+						elog(WARNING, "could not read data for entry %d/%u/%u of type %c",
+							 key.kind, key.dboid, key.objoid, t);
 						goto error;
+					}
 
 					break;
 				}
@@ -1660,7 +1714,10 @@ pgstat_read_statsfile(void)
 				 * file
 				 */
 				if (fgetc(fpin) != EOF)
+				{
+					elog(WARNING, "could not read end-of-file");
 					goto error;
+				}
 
 				goto done;
 
-- 
2.45.2

