94
94
#include <unistd.h>
95
95
96
96
#include "access/xact.h"
97
+ #include "access/xlog.h"
97
98
#include "lib/dshash.h"
98
99
#include "pgstat.h"
99
100
#include "port/atomics.h"
@@ -171,8 +172,8 @@ typedef struct PgStat_SnapshotEntry
171
172
* ----------
172
173
*/
173
174
174
- static void pgstat_write_statsfile (void );
175
- static void pgstat_read_statsfile (void );
175
+ static void pgstat_write_statsfile (XLogRecPtr redo );
176
+ static void pgstat_read_statsfile (XLogRecPtr redo );
176
177
177
178
static void pgstat_reset_after_failure (void );
178
179
@@ -448,9 +449,9 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = {
448
449
* Should only be called by the startup process or in single user mode.
449
450
*/
450
451
void
451
- pgstat_restore_stats (void )
452
+ pgstat_restore_stats (XLogRecPtr redo )
452
453
{
453
- pgstat_read_statsfile ();
454
+ pgstat_read_statsfile (redo );
454
455
}
455
456
456
457
/*
@@ -526,7 +527,7 @@ pgstat_before_server_shutdown(int code, Datum arg)
526
527
if (code == 0 )
527
528
{
528
529
pgStatLocal .shmem -> is_shutdown = true;
529
- pgstat_write_statsfile ();
530
+ pgstat_write_statsfile (GetRedoRecPtr () );
530
531
}
531
532
}
532
533
@@ -1349,7 +1350,7 @@ write_chunk(FILE *fpout, void *ptr, size_t len)
1349
1350
* stats so locking is not required.
1350
1351
*/
1351
1352
static void
1352
- pgstat_write_statsfile (void )
1353
+ pgstat_write_statsfile (XLogRecPtr redo )
1353
1354
{
1354
1355
FILE * fpout ;
1355
1356
int32 format_id ;
@@ -1366,7 +1367,8 @@ pgstat_write_statsfile(void)
1366
1367
/* we're shutting down, so it's ok to just override this */
1367
1368
pgstat_fetch_consistency = PGSTAT_FETCH_CONSISTENCY_NONE ;
1368
1369
1369
- elog (DEBUG2 , "writing stats file \"%s\"" , statfile );
1370
+ elog (DEBUG2 , "writing stats file \"%s\" with redo %X/%X" , statfile ,
1371
+ LSN_FORMAT_ARGS (redo ));
1370
1372
1371
1373
/*
1372
1374
* Open the statistics temp file to write out the current values.
@@ -1387,6 +1389,9 @@ pgstat_write_statsfile(void)
1387
1389
format_id = PGSTAT_FILE_FORMAT_ID ;
1388
1390
write_chunk_s (fpout , & format_id );
1389
1391
1392
+ /* Write the redo LSN, used to cross check the file read */
1393
+ write_chunk_s (fpout , & redo );
1394
+
1390
1395
/* Write various stats structs for fixed number of objects */
1391
1396
for (int kind = PGSTAT_KIND_FIRST_VALID ; kind <= PGSTAT_KIND_LAST ; kind ++ )
1392
1397
{
@@ -1501,18 +1506,20 @@ read_chunk(FILE *fpin, void *ptr, size_t len)
1501
1506
* stats so locking is not required.
1502
1507
*/
1503
1508
static void
1504
- pgstat_read_statsfile (void )
1509
+ pgstat_read_statsfile (XLogRecPtr redo )
1505
1510
{
1506
1511
FILE * fpin ;
1507
1512
int32 format_id ;
1508
1513
bool found ;
1509
1514
const char * statfile = PGSTAT_STAT_PERMANENT_FILENAME ;
1510
1515
PgStat_ShmemControl * shmem = pgStatLocal .shmem ;
1516
+ XLogRecPtr file_redo ;
1511
1517
1512
1518
/* shouldn't be called from postmaster */
1513
1519
Assert (IsUnderPostmaster || !IsPostmasterEnvironment );
1514
1520
1515
- elog (DEBUG2 , "reading stats file \"%s\"" , statfile );
1521
+ elog (DEBUG2 , "reading stats file \"%s\" with redo %X/%X" , statfile ,
1522
+ LSN_FORMAT_ARGS (redo ));
1516
1523
1517
1524
/*
1518
1525
* Try to open the stats file. If it doesn't exist, the backends simply
@@ -1550,6 +1557,22 @@ pgstat_read_statsfile(void)
1550
1557
goto error ;
1551
1558
}
1552
1559
1560
+ /*
1561
+ * Read the redo LSN stored in the file.
1562
+ */
1563
+ if (!read_chunk_s (fpin , & file_redo ))
1564
+ {
1565
+ elog (WARNING , "could not read redo LSN" );
1566
+ goto error ;
1567
+ }
1568
+
1569
+ if (file_redo != redo )
1570
+ {
1571
+ elog (WARNING , "found incorrect redo LSN %X/%X (expected %X/%X)" ,
1572
+ LSN_FORMAT_ARGS (file_redo ), LSN_FORMAT_ARGS (redo ));
1573
+ goto error ;
1574
+ }
1575
+
1553
1576
/*
1554
1577
* We found an existing statistics file. Read it and put all the stats
1555
1578
* data into place.
0 commit comments