Add more debugging information when failing to read pgstats files
authorMichael Paquier <michael@paquier.xyz>
Tue, 30 Jul 2024 06:08:21 +0000 (15:08 +0900)
committerMichael Paquier <michael@paquier.xyz>
Tue, 30 Jul 2024 06:08:21 +0000 (15:08 +0900)
This is useful to know which part of a stats file is corrupted when
reading it, adding to the server logs a WARNING with details about what
could not be read before giving up with the remaining data in the file.

Author: Michael Paquier
Reviewed-by: Bertrand Drouvot
Discussion: https://postgr.es/m/Zp8o6_cl0KSgsnvS@paquier.xyz

src/backend/utils/activity/pgstat.c

index 2e22bf270781ae5b1cee0f83da7de673e67a726d..228cdf73f775ba15baccf5cdea4af264fe8d491c 100644 (file)
@@ -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 with size %u",
+                            kind, t, info->shared_data_len);
                        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,11 +1714,15 @@ pgstat_read_statsfile(void)
                 * file
                 */
                if (fgetc(fpin) != EOF)
+               {
+                   elog(WARNING, "could not read end-of-file");
                    goto error;
+               }
 
                goto done;
 
            default:
+               elog(WARNING, "could not read entry of type %c", t);
                goto error;
        }
    }