@@ -156,6 +156,8 @@ ptrackMapInit(void)
156156sprintf (ptrack_path ,"%s/%s" ,DataDir ,PTRACK_PATH );
157157sprintf (ptrack_mmap_path ,"%s/%s" ,DataDir ,PTRACK_MMAP_PATH );
158158
159+ ptrack_map_reinit :
160+
159161/* Remove old PTRACK_MMAP_PATH file, if exists */
160162if (ptrack_file_exists (ptrack_mmap_path ))
161163durable_unlink (ptrack_mmap_path ,LOG );
@@ -175,18 +177,15 @@ ptrackMapInit(void)
175177if (stat (ptrack_path ,& stat_buf )== 0 )
176178{
177179copy_file (ptrack_path ,ptrack_mmap_path );
178- is_new_map = false;/* flag to check checksum */
180+ is_new_map = false;/* flag to checkmap file format and checksum */
179181ptrack_fd = BasicOpenFile (ptrack_mmap_path ,O_RDWR |PG_BINARY );
180- if (ptrack_fd < 0 )
181- elog (ERROR ,"ptrack init: failed to open map file \"%s\": %m" ,ptrack_mmap_path );
182182}
183183else
184- {
185184/* Create new file for PTRACK_MMAP_PATH */
186185ptrack_fd = BasicOpenFile (ptrack_mmap_path ,O_RDWR |O_CREAT |PG_BINARY );
187- if ( ptrack_fd < 0 )
188- elog ( ERROR , "ptrack init: failed to open map file \"%s\": %m" , ptrack_mmap_path );
189- }
186+
187+ if ( ptrack_fd < 0 )
188+ elog ( ERROR , "ptrack init: failed to open map file \"%s\": %m" , ptrack_mmap_path );
190189
191190#ifdef WIN32
192191{
@@ -227,7 +226,19 @@ ptrackMapInit(void)
227226elog (ERROR ,"ptrack init: wrong map format of file \"%s\"" ,ptrack_path );
228227
229228/* Check ptrack version inside old ptrack map */
230- /* No-op for now, but may be used for future compatibility checks */
229+ if (ptrack_map -> version_num != PTRACK_VERSION_NUM )
230+ {
231+ ereport (WARNING ,
232+ (errcode (ERRCODE_DATA_CORRUPTED ),
233+ errmsg ("ptrack init: map format version %d in the file \"%s\" is incompatible with loaded version %d" ,
234+ ptrack_map -> version_num ,ptrack_path ,PTRACK_VERSION_NUM ),
235+ errdetail ("Deleting file \"%s\" and reinitializing ptrack map." ,ptrack_path )));
236+
237+ /* Delete and try again */
238+ durable_unlink (ptrack_path ,LOG );
239+ is_new_map = true;
240+ gotoptrack_map_reinit ;
241+ }
231242
232243/* Check CRC */
233244INIT_CRC32C (crc );
@@ -641,48 +652,56 @@ void
641652ptrack_mark_block (RelFileNodeBackend smgr_rnode ,
642653ForkNumber forknum ,BlockNumber blocknum )
643654{
655+ PtBlockId bid ;
644656size_t hash ;
657+ size_t slot1 ;
658+ size_t slot2 ;
645659XLogRecPtr new_lsn ;
646- PtBlockId bid ;
647660/*
648661 * We use pg_atomic_uint64 here only for alignment purposes, because
649- * pg_atomic_uint64 isforcely aligned on 8 bytes during the MSVC build.
662+ * pg_atomic_uint64 isforcedly aligned on 8 bytes during the MSVC build.
650663 */
651664pg_atomic_uint64 old_lsn ;
652665pg_atomic_uint64 old_init_lsn ;
653666
654- if (ptrack_map_size != 0 && (ptrack_map != NULL )&&
655- smgr_rnode .backend == InvalidBackendId )/* do not track temporary
656- * relations */
657- {
658- bid .relnode = smgr_rnode .node ;
659- bid .forknum = forknum ;
660- bid .blocknum = blocknum ;
661- hash = BID_HASH_FUNC (bid );
662-
663- if (RecoveryInProgress ())
664- new_lsn = GetXLogReplayRecPtr (NULL );
665- else
666- new_lsn = GetXLogInsertRecPtr ();
667+ if (ptrack_map_size == 0
668+ || ptrack_map == NULL
669+ || smgr_rnode .backend != InvalidBackendId )/* do not track temporary
670+ * relations */
671+ return ;
667672
668- old_lsn .value = pg_atomic_read_u64 (& ptrack_map -> entries [hash ]);
673+ bid .relnode = smgr_rnode .node ;
674+ bid .forknum = forknum ;
675+ bid .blocknum = blocknum ;
669676
670- /* Atomically assign new init LSN value */
671- old_init_lsn .value = pg_atomic_read_u64 (& ptrack_map -> init_lsn );
677+ hash = BID_HASH_FUNC (bid );
678+ slot1 = hash %PtrackContentNblocks ;
679+ slot2 = ((hash <<32 ) | (hash >>32 )) %PtrackContentNblocks ;
672680
673- if (old_init_lsn .value == InvalidXLogRecPtr )
674- {
675- elog (DEBUG1 ,"ptrack_mark_block: init_lsn " UINT64_FORMAT " <- " UINT64_FORMAT ,old_init_lsn .value ,new_lsn );
676-
677- while (old_init_lsn .value < new_lsn &&
678- !pg_atomic_compare_exchange_u64 (& ptrack_map -> init_lsn , (uint64 * )& old_init_lsn .value ,new_lsn ));
679- }
681+ if (RecoveryInProgress ())
682+ new_lsn = GetXLogReplayRecPtr (NULL );
683+ else
684+ new_lsn = GetXLogInsertRecPtr ();
680685
681- elog (DEBUG3 ,"ptrack_mark_block: map[%zu]=" UINT64_FORMAT " <- " UINT64_FORMAT ,hash ,old_lsn .value ,new_lsn );
686+ /* Atomically assign new init LSN value */
687+ old_init_lsn .value = pg_atomic_read_u64 (& ptrack_map -> init_lsn );
688+ if (old_init_lsn .value == InvalidXLogRecPtr )
689+ {
690+ elog (DEBUG1 ,"ptrack_mark_block: init_lsn " UINT64_FORMAT " <- " UINT64_FORMAT ,old_init_lsn .value ,new_lsn );
682691
683- /* Atomically assign new LSN value */
684- while (old_lsn .value < new_lsn &&
685- !pg_atomic_compare_exchange_u64 (& ptrack_map -> entries [hash ], (uint64 * )& old_lsn .value ,new_lsn ));
686- elog (DEBUG3 ,"ptrack_mark_block: map[%zu]=" UINT64_FORMAT ,hash ,pg_atomic_read_u64 (& ptrack_map -> entries [hash ]));
692+ while (old_init_lsn .value < new_lsn &&
693+ !pg_atomic_compare_exchange_u64 (& ptrack_map -> init_lsn , (uint64 * )& old_init_lsn .value ,new_lsn ));
687694}
695+
696+ /* Atomically assign new LSN value to the first slot */
697+ old_lsn .value = pg_atomic_read_u64 (& ptrack_map -> entries [slot1 ]);
698+ elog (DEBUG3 ,"ptrack_mark_block: map[%zu]=" UINT64_FORMAT " <- " UINT64_FORMAT ,slot1 ,old_lsn .value ,new_lsn );
699+ while (old_lsn .value < new_lsn &&
700+ !pg_atomic_compare_exchange_u64 (& ptrack_map -> entries [slot1 ], (uint64 * )& old_lsn .value ,new_lsn ));
701+ elog (DEBUG3 ,"ptrack_mark_block: map[%zu]=" UINT64_FORMAT ,hash ,pg_atomic_read_u64 (& ptrack_map -> entries [slot1 ]));
702+
703+ /* And to the second */
704+ old_lsn .value = pg_atomic_read_u64 (& ptrack_map -> entries [slot2 ]);
705+ while (old_lsn .value < new_lsn &&
706+ !pg_atomic_compare_exchange_u64 (& ptrack_map -> entries [slot2 ], (uint64 * )& old_lsn .value ,new_lsn ));
688707}