@@ -258,7 +258,7 @@ ptrackMapReadFromFile(const char *ptrack_path)
258258 * postmaster is the only user right now.
259259 */
260260 elog (DEBUG1 , "ptrack read map: crc %u, file_crc %u, init_lsn %X/%X" ,
261- crc , * file_crc , (uint32 ) (ptrack_map -> init_lsn .value >> 32 ), (uint32 ) ptrack_map -> init_lsn .value );
261+ crc , * file_crc , (uint16 ) (ptrack_map -> init_lsn .value >> 16 ), (uint16 ) ptrack_map -> init_lsn .value );
262262
263263 if (!EQ_CRC32C (* file_crc , crc ))
264264 {
@@ -330,7 +330,7 @@ ptrackMapInit(void)
330330 * Fill entries with InvalidXLogRecPtr
331331 * (InvalidXLogRecPtr is actually 0)
332332 */
333- memset (ptrack_map -> entries , 0 , PtrackContentNblocks * sizeof (pg_atomic_uint64 ));
333+ memset (ptrack_map -> entries , 0 , PtrackContentNblocks * sizeof (pg_atomic_uint32 ));
334334 /*
335335 * Last part of memory representation of ptrack_map (crc) is actually unused
336336 * so leave it as it is
@@ -348,11 +348,15 @@ ptrackCheckpoint(void)
348348 pg_crc32c crc ;
349349 char ptrack_path [MAXPGPATH ];
350350 char ptrack_path_tmp [MAXPGPATH ];
351- XLogRecPtr init_lsn ;
352- pg_atomic_uint64 buf [PTRACK_BUF_SIZE ];
351+ uint32 init_lsn ;
352+ pg_atomic_uint32 buf [PTRACK_BUF_SIZE ];
353353 struct stat stat_buf ;
354354 uint64 i = 0 ;
355355 uint64 j = 0 ;
356+ XLogRecPtr new_init_lsn ;
357+ uint32 new_init_lsn32 ;
358+ uint32 latest_lsn ;
359+ bool lsn_was_advanced = false;
356360
357361 elog (DEBUG1 , "ptrack checkpoint" );
358362
@@ -408,20 +412,27 @@ ptrackCheckpoint(void)
408412 ptrack_write_chunk (ptrack_tmp_fd , & crc , (char * ) ptrack_map ,
409413 offsetof(PtrackMapHdr , init_lsn ));
410414
411- init_lsn = pg_atomic_read_u64 (& ptrack_map -> init_lsn );
415+ latest_lsn = pg_atomic_read_u32 (& ptrack_map -> latest_lsn );
416+ init_lsn = pg_atomic_read_u32 (& ptrack_map -> init_lsn );
412417
413418 /* Set init_lsn during checkpoint if it is not set yet */
414419 if (init_lsn == InvalidXLogRecPtr )
415420 {
416- XLogRecPtr new_init_lsn ;
417-
418421 if (RecoveryInProgress ())
419422 new_init_lsn = GetXLogReplayRecPtr (NULL );
420423 else
421424 new_init_lsn = GetXLogInsertRecPtr ();
422425
423- pg_atomic_write_u64 (& ptrack_map -> init_lsn , new_init_lsn );
424- init_lsn = new_init_lsn ;
426+ new_init_lsn32 = (uint32 )(new_init_lsn >> 16 );
427+ pg_atomic_write_u32 (& ptrack_map -> init_lsn , new_init_lsn32 );
428+ init_lsn = new_init_lsn32 ;
429+ }
430+ else if (lsn_diff (lsn_advance (init_lsn , PtrackLSNGap ), latest_lsn ) < 0 )
431+ {
432+ new_init_lsn32 = lsn_advance (init_lsn , PtrackLSNGap );
433+ lsn_was_advanced = true;
434+ pg_atomic_write_u32 (& ptrack_map -> init_lsn , new_init_lsn32 );
435+ init_lsn = new_init_lsn32 ;
425436 }
426437
427438 /* Put init_lsn in the same buffer */
@@ -435,7 +446,7 @@ ptrackCheckpoint(void)
435446 */
436447 while (i < PtrackContentNblocks )
437448 {
438- XLogRecPtr lsn ;
449+ uint32 lsn ;
439450
440451 /*
441452 * We store LSN values as pg_atomic_uint64 in the ptrack map, but
@@ -445,8 +456,12 @@ ptrackCheckpoint(void)
445456 *
446457 * TODO: is it safe and can we do any better?
447458 */
448- lsn = pg_atomic_read_u64 (& ptrack_map -> entries [i ]);
449- buf [j ].value = lsn ;
459+ lsn = pg_atomic_read_u32 (& ptrack_map -> entries [i ]);
460+
461+ if (lsn_was_advanced && lsn_diff (lsn , init_lsn ) < 0 )
462+ buf [j ].value = InvalidXLogRecPtr ;
463+ else
464+ buf [j ].value = lsn ;
450465
451466 i ++ ;
452467 j ++ ;
@@ -464,15 +479,14 @@ ptrackCheckpoint(void)
464479 ptrack_write_chunk (ptrack_tmp_fd , & crc , (char * ) buf , writesz );
465480 elog (DEBUG5 , "ptrack checkpoint: i " UINT64_FORMAT ", j " UINT64_FORMAT ", writesz %zu PtrackContentNblocks " UINT64_FORMAT ,
466481 i , j , writesz , (uint64 ) PtrackContentNblocks );
467-
468482 j = 0 ;
469483 }
470484 }
471485
472486 /* Write if anything left */
473487 if ((i + 1 ) % PTRACK_BUF_SIZE != 0 )
474488 {
475- size_t writesz = sizeof (pg_atomic_uint64 ) * j ;
489+ size_t writesz = sizeof (pg_atomic_uint32 ) * j ;
476490
477491 ptrack_write_chunk (ptrack_tmp_fd , & crc , (char * ) buf , writesz );
478492 elog (DEBUG5 , "ptrack checkpoint: final i " UINT64_FORMAT ", j " UINT64_FORMAT ", writesz %zu PtrackContentNblocks " UINT64_FORMAT ,
@@ -682,25 +696,30 @@ static void swap_slots(size_t *slot1, size_t *slot2) {
682696}
683697
684698static void
685- ptrack_mark_map_pair (size_t slot1 , size_t slot2 , XLogRecPtr new_lsn )
699+ ptrack_mark_map_pair (size_t slot1 , size_t slot2 , uint32 new_lsn32 )
686700{
687701 /*
688702 * We use pg_atomic_uint64 here only for alignment purposes, because
689703 * pg_atomic_uint64 is forcedly aligned on 8 bytes during the MSVC build.
690704 */
691- pg_atomic_uint64 old_lsn ;
705+ pg_atomic_uint32 old_lsn ;
692706
693- /* Atomically assign new LSN value to the first slot */
694- old_lsn .value = pg_atomic_read_u64 (& ptrack_map -> entries [slot1 ]);
695- elog (DEBUG3 , "ptrack_mark_block: map[%zu]=" UINT64_FORMAT " <- " UINT64_FORMAT , slot1 , old_lsn .value , new_lsn );
696- while (old_lsn .value < new_lsn &&
697- !pg_atomic_compare_exchange_u64 (& ptrack_map -> entries [slot1 ], (uint64 * ) & old_lsn .value , new_lsn ));
707+ /* Assign latest_lsn first */
708+ old_lsn .value = pg_atomic_read_u32 (& ptrack_map -> latest_lsn );
709+ while (old_lsn .value < new_lsn32 &&
710+ !pg_atomic_compare_exchange_u32 (& ptrack_map -> latest_lsn , (uint32 * ) & old_lsn .value , new_lsn32 ));
711+
712+ /* Then, atomically assign new LSN value to the first slot */
713+ old_lsn .value = pg_atomic_read_u32 (& ptrack_map -> entries [slot1 ]);
714+ elog (DEBUG3 , "ptrack_mark_block: map[%zu]=%u <- %u" , slot1 , old_lsn .value , new_lsn32 );
715+ while (old_lsn .value < new_lsn32 &&
716+ !pg_atomic_compare_exchange_u32 (& ptrack_map -> entries [slot1 ], (uint32 * ) & old_lsn .value , new_lsn32 ));
698717
699718 /* And to the second */
700- old_lsn .value = pg_atomic_read_u64 (& ptrack_map -> entries [slot2 ]);
701- elog (DEBUG3 , "ptrack_mark_block: map[%zu]=" UINT64_FORMAT " <- " UINT64_FORMAT , slot2 , old_lsn .value , new_lsn );
702- while (old_lsn .value < new_lsn &&
703- !pg_atomic_compare_exchange_u64 (& ptrack_map -> entries [slot2 ], (uint64 * ) & old_lsn .value , new_lsn ));
719+ old_lsn .value = pg_atomic_read_u32 (& ptrack_map -> entries [slot2 ]);
720+ elog (DEBUG3 , "ptrack_mark_block: map[%zu]=%u <- %u" , slot2 , old_lsn .value , new_lsn32 );
721+ while (old_lsn .value < new_lsn32 &&
722+ !pg_atomic_compare_exchange_u32 (& ptrack_map -> entries [slot2 ], (uint32 * ) & old_lsn .value , new_lsn32 ));
704723}
705724
706725void
@@ -714,11 +733,13 @@ ptrack_mark_block(RelFileNodeBackend smgr_rnode,
714733 size_t max_lsn_slot1 ;
715734 size_t max_lsn_slot2 ;
716735 XLogRecPtr new_lsn ;
736+ uint32 new_lsn32 ;
717737 /*
718738 * We use pg_atomic_uint64 here only for alignment purposes, because
719739 * pg_atomic_uint64 is forcedly aligned on 8 bytes during the MSVC build.
720740 */
721- pg_atomic_uint64 old_init_lsn ;
741+ pg_atomic_uint32 old_lsn ;
742+ pg_atomic_uint32 old_init_lsn ;
722743
723744 if (ptrack_map_size == 0
724745 || ptrack_map == NULL
@@ -747,20 +768,22 @@ ptrack_mark_block(RelFileNodeBackend smgr_rnode,
747768 else
748769 new_lsn = GetXLogInsertRecPtr ();
749770
771+ new_lsn32 = (uint32 )(new_lsn >> 16 );
772+
750773 /* Atomically assign new init LSN value */
751- old_init_lsn .value = pg_atomic_read_u64 (& ptrack_map -> init_lsn );
774+ old_init_lsn .value = pg_atomic_read_u32 (& ptrack_map -> init_lsn );
752775 if (old_init_lsn .value == InvalidXLogRecPtr )
753776 {
754- elog (DEBUG1 , "ptrack_mark_block: init_lsn " UINT64_FORMAT " <- " UINT64_FORMAT , old_init_lsn .value , new_lsn );
777+ elog (DEBUG1 , "ptrack_mark_block: init_lsn %u <- %u" , old_init_lsn .value , new_lsn32 );
755778
756- while (old_init_lsn .value < new_lsn &&
757- !pg_atomic_compare_exchange_u64 (& ptrack_map -> init_lsn , (uint64 * ) & old_init_lsn .value , new_lsn ));
779+ while (old_init_lsn .value < new_lsn32 &&
780+ !pg_atomic_compare_exchange_u32 (& ptrack_map -> init_lsn , (uint32 * ) & old_init_lsn .value , new_lsn32 ));
758781 }
759782
760783 // mark the page
761- ptrack_mark_map_pair (slot1 , slot2 , new_lsn );
784+ ptrack_mark_map_pair (slot1 , slot2 , new_lsn32 );
762785 // mark the file (new LSN is always valid maximum LSN)
763- ptrack_mark_map_pair (max_lsn_slot1 , max_lsn_slot2 , new_lsn );
786+ ptrack_mark_map_pair (max_lsn_slot1 , max_lsn_slot2 , new_lsn32 );
764787}
765788
766789XLogRecPtr ptrack_read_file_maxlsn (RelFileNode rnode , ForkNumber forknum )
0 commit comments