Skip to content

Commit c8d9d87

Browse files
author
Daniel Shelepanov
committed
intermediate wraparound
1 parent 9aca915 commit c8d9d87

File tree

4 files changed

+39
-9
lines changed

4 files changed

+39
-9
lines changed

engine.c

+23-7
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,10 @@ ptrackCheckpoint(void)
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,21 +412,25 @@ ptrackCheckpoint(void)
408412
ptrack_write_chunk(ptrack_tmp_fd, &crc, (char *) ptrack_map,
409413
offsetof(PtrackMapHdr, init_lsn));
410414

415+
latest_lsn = pg_atomic_read_u32(&ptrack_map->latest_lsn);
411416
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-
uint32 new_init_lsn32;
418-
419421
if (RecoveryInProgress())
420422
new_init_lsn = GetXLogReplayRecPtr(NULL);
421423
else
422424
new_init_lsn = GetXLogInsertRecPtr();
423425

424426
new_init_lsn32 = (uint32)(new_init_lsn >> 16);
425-
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;
426434
pg_atomic_write_u32(&ptrack_map->init_lsn, new_init_lsn32);
427435
init_lsn = new_init_lsn32;
428436
}
@@ -449,7 +457,11 @@ ptrackCheckpoint(void)
449457
* TODO: is it safe and can we do any better?
450458
*/
451459
lsn = pg_atomic_read_u32(&ptrack_map->entries[i]);
452-
buf[j].value = lsn;
460+
461+
if (lsn_was_advanced && lsn_diff(lsn, init_lsn) < 0)
462+
buf[j].value = InvalidXLogRecPtr;
463+
else
464+
buf[j].value = lsn;
453465

454466
i++;
455467
j++;
@@ -467,7 +479,6 @@ ptrackCheckpoint(void)
467479
ptrack_write_chunk(ptrack_tmp_fd, &crc, (char *) buf, writesz);
468480
elog(DEBUG5, "ptrack checkpoint: i " UINT64_FORMAT ", j " UINT64_FORMAT ", writesz %zu PtrackContentNblocks " UINT64_FORMAT,
469481
i, j, writesz, (uint64) PtrackContentNblocks);
470-
471482
j = 0;
472483
}
473484
}
@@ -726,7 +737,12 @@ ptrack_mark_block(RelFileNodeBackend smgr_rnode,
726737
!pg_atomic_compare_exchange_u32(&ptrack_map->init_lsn, (uint32 *) &old_init_lsn.value, new_lsn32));
727738
}
728739

729-
/* Atomically assign new LSN value to the first slot */
740+
/* Assign latest_lsn first */
741+
old_lsn.value = pg_atomic_read_u32(&ptrack_map->latest_lsn);
742+
while (old_lsn.value < new_lsn32 &&
743+
!pg_atomic_compare_exchange_u32(&ptrack_map->latest_lsn, (uint32 *) &old_lsn.value, new_lsn32));
744+
745+
/* Then, atomically assign new LSN value to the first slot */
730746
old_lsn.value = pg_atomic_read_u32(&ptrack_map->entries[slot1]);
731747
elog(DEBUG3, "ptrack_mark_block: map[%zu]=%u <- %u", slot1, old_lsn.value, new_lsn32);
732748
while (old_lsn.value < new_lsn32 &&

engine.h

+3
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ typedef struct PtrackMapHdr
6565
*/
6666
uint32 version_num;
6767

68+
/* LSN of current writing position */
69+
pg_atomic_uint32 latest_lsn;
6870
/* LSN of the moment, when map was last enabled. */
6971
pg_atomic_uint32 init_lsn;
7072

@@ -94,6 +96,7 @@ typedef PtrackMapHdr * PtrackMap;
9496
#define BID_HASH_FUNC(bid) \
9597
(DatumGetUInt64(hash_any_extended((unsigned char *)&bid, sizeof(bid), 0)))
9698

99+
#define PtrackLSNGap 10e8
97100
/*
98101
* Per process pointer to shared ptrack_map
99102
*/

ptrack.c

+11-2
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,8 @@ ptrack_get_pagemapset(PG_FUNCTION_ARGS)
533533
datapagemap_t pagemap;
534534
int64 pagecount = 0;
535535
char gather_path[MAXPGPATH];
536+
uint32 init_lsn = InvalidXLogRecPtr;
537+
bool within_ptrack_map = true;
536538

537539
/* Exit immediately if there is no map */
538540
if (ptrack_map == NULL)
@@ -639,6 +641,7 @@ ptrack_get_pagemapset(PG_FUNCTION_ARGS)
639641
SRF_RETURN_DONE(funcctx);
640642
}
641643

644+
init_lsn = pg_atomic_read_u32(&ptrack_map->init_lsn);
642645
hash = BID_HASH_FUNC(ctx->bid);
643646
slot1 = (size_t)(hash % PtrackContentNblocks);
644647

@@ -649,8 +652,11 @@ ptrack_get_pagemapset(PG_FUNCTION_ARGS)
649652
(uint16) (update_lsn1 >> 16), (uint16) update_lsn1,
650653
ctx->bid.blocknum, ctx->relpath);
651654

655+
if (init_lsn != InvalidXLogRecPtr)
656+
within_ptrack_map = lsn_diff(init_lsn, update_lsn1) <= 0;
657+
652658
/* Only probe the second slot if the first one is marked */
653-
if (update_lsn1 >= ctx->lsn)
659+
if (within_ptrack_map && lsn_diff(ctx->lsn, update_lsn1) <= 0)
654660
{
655661
slot2 = (size_t)(((hash << 32) | (hash >> 32)) % PtrackContentNblocks);
656662
update_lsn2 = pg_atomic_read_u32(&ptrack_map->entries[slot2]);
@@ -660,8 +666,11 @@ ptrack_get_pagemapset(PG_FUNCTION_ARGS)
660666
(uint16) (update_lsn1 >> 16), (uint16) update_lsn2,
661667
ctx->bid.blocknum, ctx->relpath);
662668

669+
if (init_lsn != InvalidXLogRecPtr)
670+
within_ptrack_map = lsn_diff(init_lsn, update_lsn2) <= 0;
671+
663672
/* Block has been changed since specified LSN. Mark it in the bitmap */
664-
if (update_lsn2 >= ctx->lsn)
673+
if (within_ptrack_map && lsn_diff(ctx->lsn, update_lsn2) <= 0)
665674
{
666675
pagecount += 1;
667676
datapagemap_add(&pagemap, ctx->bid.blocknum % ((BlockNumber) RELSEG_SIZE));

ptrack.h

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
#define nodeOf(ndbck) (ndbck).node
4848
#endif
4949

50+
#define lsn_diff(lsn1, lsn2) ((int32)(lsn1-lsn2))
51+
#define lsn_advance(lsn, incr) ((uint32)(lsn+incr))
5052
/*
5153
* Structure identifying block on the disk.
5254
*/

0 commit comments

Comments
 (0)