Thread: BRIN page type identifier

BRIN page type identifier

From
Heikki Linnakangas
Date:
The "special" area in a BRIN page looks like this:

> /* special space on all BRIN pages stores a "type" identifier */
> #define        BRIN_PAGETYPE_META            0xF091
> #define        BRIN_PAGETYPE_REVMAP        0xF092
> #define        BRIN_PAGETYPE_REGULAR        0xF093
>...
> typedef struct BrinSpecialSpace
> {
>     uint16        flags;
>     uint16        type;
> } BrinSpecialSpace;

I believe this is supposed to follow the usual convention that the last 
two bytes of a page can be used to identify the page type. SP-GiST uses 
0xFF82, while GIN uses values 0x00XX.

However, because the special size is MAXALIGNed, the 'type' field are 
not the last 2 bytes on the page, as intended. I'd suggest just adding 
"char padding[6]"  in BrinSpecialSpace, before 'flags'. That'll waste 4 
bytes on 32-bit systems, but that seems acceptable.

Also, the comment in GinPageOpaqueData needs updating:

> /*
>  * Page opaque data in an inverted index page.
>  *
>  * Note: GIN does not include a page ID word as do the other index types.
>  * This is OK because the opaque data is only 8 bytes and so can be reliably
>  * distinguished by size.  Revisit this if the size ever increases.
>  * Further note: as of 9.2, SP-GiST also uses 8-byte special space.  This is
>  * still OK, as long as GIN isn't using all of the high-order bits in its
>  * flags word, because that way the flags word cannot match the page ID used
>  * by SP-GiST.
>  */

BRIN now also uses 8-byte special space. While you're at it, might want 
to move that comment somewhere else, as it's really about a convention 
among all page types, not just GIN.

- Heikki



Re: BRIN page type identifier

From
Alvaro Herrera
Date:
Heikki Linnakangas wrote:
> The "special" area in a BRIN page looks like this:
> 
> >/* special space on all BRIN pages stores a "type" identifier */
> >#define        BRIN_PAGETYPE_META            0xF091
> >#define        BRIN_PAGETYPE_REVMAP        0xF092
> >#define        BRIN_PAGETYPE_REGULAR        0xF093
> >...
> >typedef struct BrinSpecialSpace
> >{
> >    uint16        flags;
> >    uint16        type;
> >} BrinSpecialSpace;
> 
> I believe this is supposed to follow the usual convention that the last two
> bytes of a page can be used to identify the page type. SP-GiST uses 0xFF82,
> while GIN uses values 0x00XX.
> 
> However, because the special size is MAXALIGNed, the 'type' field are not
> the last 2 bytes on the page, as intended. I'd suggest just adding "char
> padding[6]"  in BrinSpecialSpace, before 'flags'. That'll waste 4 bytes on
> 32-bit systems, but that seems acceptable.

Ouch.  You're right.  I don't understand why you suggest to use 6 bytes,
though -- that would make the struct size be 10 bytes, which maxaligns
to 16, and so we're back where we started.  Using 4 bytes does the
trick.

I wonder if this is permissible and whether it will do the right thing
on 32-bit systems:

/** Special area of BRIN pages.** We add some padding bytes to ensure that 'type' ends up in the last two* bytes of the
page,for consumption by pg_filedump and similar utilities.* (Special space is MAXALIGN'ed).*/
 
typedef struct BrinSpecialSpace
{char        padding[MAXALIGN(1) - 2 * sizeof(uint16)];uint16        flags;uint16        type;
} BrinSpecialSpace;


It's a bit ugly, but it seems to work for me on x86-64 ...

-- 
Álvaro Herrera                http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services



Re: BRIN page type identifier

From
Tom Lane
Date:
Alvaro Herrera <alvherre@2ndquadrant.com> writes:
> I wonder if this is permissible and whether it will do the right thing
> on 32-bit systems:

> /*
>  * Special area of BRIN pages.
>  *
>  * We add some padding bytes to ensure that 'type' ends up in the last two
>  * bytes of the page, for consumption by pg_filedump and similar utilities.
>  * (Special space is MAXALIGN'ed).
>  */
> typedef struct BrinSpecialSpace
> {
>     char        padding[MAXALIGN(1) - 2 * sizeof(uint16)];
>     uint16        flags;
>     uint16        type;
> } BrinSpecialSpace;

I should expect that to fail altogether on 32-bit machines, because
the declared array size will be zero.

You could try something like

typedef struct BrinSpecialSpace
{uint16        vector[MAXALIGN(1) / sizeof(uint16)];
} BrinSpecialSpace;

and then some access macros to use the last and next-to-last
elements of that array.
        regards, tom lane



Re: BRIN page type identifier

From
Alvaro Herrera
Date:
Tom Lane wrote:
> Alvaro Herrera <alvherre@2ndquadrant.com> writes:

> > typedef struct BrinSpecialSpace
> > {
> >     char        padding[MAXALIGN(1) - 2 * sizeof(uint16)];
> >     uint16        flags;
> >     uint16        type;
> > } BrinSpecialSpace;
>
> I should expect that to fail altogether on 32-bit machines, because
> the declared array size will be zero.

Hah, of course.

> You could try something like
>
> typedef struct BrinSpecialSpace
> {
>     uint16        vector[MAXALIGN(1) / sizeof(uint16)];
> } BrinSpecialSpace;
>
> and then some access macros to use the last and next-to-last
> elements of that array.

Ah, thanks, that works fine on x86-64.  Here's a patch I intend to push
tomorrow.

Heikki suggested that the comment above GinPageOpaqueData be moved to
some better place, but I couldn't find any such.  If there are other
ideas, I'm all ears.

--
Álvaro Herrera                http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

Attachment

Re: BRIN page type identifier

From
Tom Lane
Date:
I wrote:
> You could try something like
> typedef struct BrinSpecialSpace
> {
>     uint16        vector[MAXALIGN(1) / sizeof(uint16)];
> } BrinSpecialSpace;
> and then some access macros to use the last and next-to-last
> elements of that array.

On second thought, consider

typedef struct BrinSpecialSpace
{uint16        flags;uint16        vector[MAXALIGN(1) / sizeof(uint16) - 1];
} BrinSpecialSpace;

This way, accesses to "flags" require no source code changes.
You still need a macro to map "type" onto the last element of
the vector, but there's probably about one reference to "type"
in the source code so it shouldn't be too painful.
        regards, tom lane



Re: BRIN page type identifier

From
Tom Lane
Date:
[ paths crossed in mail ]

I wrote:
> This way, accesses to "flags" require no source code changes.
> You still need a macro to map "type" onto the last element of
> the vector, but there's probably about one reference to "type"
> in the source code so it shouldn't be too painful.

Ah, nevermind, I see you already did the work to do it the other
way.
        regards, tom lane