>>>>> "Michael" == Michael Paquier <michael@paquier.xyz> writes:
> On Thu, Nov 08, 2018 at 04:00:26PM +0900, Michael Paquier wrote:
>> Yes, I don't disagree with you and I thought about it. Fetching the
>> value from the control file is easy, doing the comparison between
>> two LSNs is also simple by doing it directly with pg_lsn in the
>> database (and I don't want to add math logics about LSNs as a TAP
>> API). Now I am less sure about how portable it is possible to make
>> the read of 8 bytes on the page header for the last page of a
>> relation portable across many architectures in perl.
Michael> Has a perl monk a specific idea here? It seems to me that the
Michael> amount of specific facility which would be needed overweights
Michael> the current simplicity of the test.
Seems simple enough - the LSN on the page is actually two 4-byte values
with the most significant one first, regardless of platform byte order
(though each individual word is in native order), so
my ($hi,$lo) = unpack("LL", $buf);
should suffice. ("L" is always 32 bits regardless of platform, and it
has the platform's endianness.)
Looking only at the last page seems questionable. Something like this
should work to return the largest LSN of any page in the specified list
of files:
# find_largest_lsn(blocksize,filenames...)
sub find_largest_lsn
{
my $blocksize = shift;
my @filenames = ref($_[0]) eq 'ARRAY' ? @{$_[0]} : @_;
my ($max_hi,$max_lo) = (0,0);
for my $filename (@filenames)
{
open(my $fh, "<:raw", $filename)
or die "failed to open $filename: $!";
my ($buf,$len);
while ($len = read($fh, $buf, $blocksize))
{
$len == $blocksize
or die "read only $len of $blocksize bytes from $filename";
my ($hi,$lo) = unpack("LL", $buf);
($max_hi,$max_lo) = ($hi,$lo)
if ($hi > $max_hi or ($hi == $max_hi and $lo > $max_lo));
}
defined($len) or die "read error on $filename: $!";
close($fh);
}
return sprintf("%X/%X", $max_hi, $max_lo);
}
--
Andrew (irc:RhodiumToad)