/
postgres_page_header.go
55 lines (49 loc) · 1.74 KB
/
postgres_page_header.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package internal
import (
"github.com/wal-g/wal-g/internal/walparser/parsingutil"
"io"
)
type PostgresPageHeader struct {
pdLsnH uint32
pdLsnL uint32
pdChecksum uint16
pdFlags uint16
pdLower uint16
pdUpper uint16
pdSpecial uint16
pdPageSizeVersion uint16
}
func (header *PostgresPageHeader) Lsn() uint64 {
return ((uint64(header.pdLsnH)) << 32) + uint64(header.pdLsnL)
}
func (header *PostgresPageHeader) IsValid() bool {
return !((header.pdFlags&validFlags) != header.pdFlags ||
header.pdLower < headerSize ||
header.pdLower > header.pdUpper ||
header.pdUpper > header.pdSpecial ||
header.pdSpecial > DatabasePageSize ||
(header.Lsn() == invalidLsn) ||
header.pdPageSizeVersion != DatabasePageSize+layoutVersion)
}
func (header *PostgresPageHeader) IsNew() bool {
return header.pdUpper == 0 // #define PageIsNew(page) (((PageHeader) (page))->pd_upper == 0) in bufpage.h
}
// ParsePostgresPageHeader reads information from PostgreSQL page header. Exported for test reasons.
func ParsePostgresPageHeader(reader io.Reader) (*PostgresPageHeader, error) {
pageHeader := PostgresPageHeader{}
fields := []parsingutil.FieldToParse{
{Field: &pageHeader.pdLsnH, Name: "pdLsnH"},
{Field: &pageHeader.pdLsnL, Name: "pdLsnL"},
{Field: &pageHeader.pdChecksum, Name: "pdChecksum"},
{Field: &pageHeader.pdFlags, Name: "pdFlags"},
{Field: &pageHeader.pdLower, Name: "pdLower"},
{Field: &pageHeader.pdUpper, Name: "pdUpper"},
{Field: &pageHeader.pdSpecial, Name: "pdSpecial"},
{Field: &pageHeader.pdPageSizeVersion, Name: "pdPageSizeVersion"},
}
err := parsingutil.ParseMultipleFieldsFromReader(fields, reader)
if err != nil {
return nil, err
}
return &pageHeader, nil
}