005_slru.pl.txt

text/plain

Filename: 005_slru.pl.txt
Type: text/plain
Part: 0
Message: Re: [PATCH] Refactor SLRU to always use long file names
# Copyright (c) 2024, PostgreSQL Global Development Group

use strict;
use warnings FATAL => 'all';

use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;

# This test ensures that pg_upgrade renames SLRU segments.
# After the upgrade all segments should have long file names.

# equals SLRU_SEG_FILENAMES_CHANGE_CAT_VER in pg_upgrade.h
my $slru_seg_filenames_change_cat_ver = 202411121;

my @slru_dirs = (
	"pg_xact",
	"pg_commit_ts",
	"pg_multixact/offsets",
	"pg_multixact/members",
	"pg_subtrans",
	"pg_serial",
);

my $short_segment_name = "1234";
my $long_segment_name = "000000000001234";

my $oldnode = PostgreSQL::Test::Cluster->new('old_node');
$oldnode->init();
my $oldbindir = $oldnode->config_data('--bindir');

my $newnode = PostgreSQL::Test::Cluster->new('new_node');
$newnode->init();
my $newbindir = $newnode->config_data('--bindir');

# Fill data_dir of the old node with SLRU segments that use short file names.
# pg_upgrade renames the files without looking at the content, so the content
# is not important.
foreach my $dir (@slru_dirs)
{
	my $fname = $oldnode->data_dir."/".$dir."/".$short_segment_name;
	open my $fh, ">", $fname or die $!;
	close $fh;
}

# Modify pg_control of the old node to make it look like a version that needs
# migration (decrease ControlData->cat_ver). Otherwise pg_upgrade will skip it.
my $pg_control_fname = $oldnode->data_dir."/global/pg_control";

open my $fh, "+<", $pg_control_fname or die $!;
binmode($fh);
sysseek($fh, 12, 0);
my $binval = pack("L!", $slru_seg_filenames_change_cat_ver - 1);
syswrite($fh, $binval, 4);
close($fh);

# Calculate CRC of the updated file using pg_read_binary_file() and crc32c()
my $fsize = -s $pg_control_fname; # WRONG! should be sizeof(ControlFile)
$newnode->start;
my $newcrc;
$newnode->psql(
	"postgres",
	"SELECT crc32(pg_read_binary_file('".$pg_control_fname."',0,".($fsize-4)."));",
	stdout => \$newcrc,
	on_error_die => 1,
	);
$newnode->stop;

# Update CRC
open $fh, "+<", $pg_control_fname or die $!;
binmode($fh);
sysseek($fh, $fsize-4, 0);
my $bincrc = pack("L!", $newcrc);
syswrite($fh, $bincrc, 4);
close($fh);

$newnode->command_ok(
	[
		'pg_upgrade',
		'--old-datadir', $oldnode->data_dir,
		'--new-datadir', $newnode->data_dir,
		'--old-bindir', $oldbindir,
		'--new-bindir', $newbindir,
	],
	'run of pg_upgrade');

# Check that pg_upgrade renamed the SLRU segments we created
foreach my $dir (@slru_dirs)
{
	ok(-e $newnode->data_dir."/".$dir."/".$long_segment_name);
}

done_testing();