blob: 224552183ac0b651d8215cae94b2886acc7682e8 [file] [log] [blame]
/*-------------------------------------------------------------------------
*
* appendonlytid.h
*
* Portions Copyright (c) 2007-2009, Greenplum inc
* Portions Copyright (c) 2012-Present VMware, Inc. or its affiliates.
*
*
* IDENTIFICATION
* src/include/access/appendonlytid.h
*
*-------------------------------------------------------------------------
*/
#ifndef APPENDONLYTID_H
#define APPENDONLYTID_H
#include "c.h"
#include "storage/itemptr.h"
/*
* AOTupleId is a unique tuple id, specific to AO relation tuples, of the
* form (segfile#, row#)
*
* *** WARNING *** Outside the appendonly AM code, AOTIDs are treated as
* HEAPTIDs! Therefore, AOTupleId struct must have the same size and
* alignment as ItemPointer, and we mustn't construct AOTupleIds that would
* look like invalid ItemPointers.
*
* The 48 bits available in the struct are divided as follow:
*
* - the 7 most significant bits stand for which segment file the tuple is in
* (Limit: 128 (2^7)). This also makes up part of the "block number" when
* interpreted as a heap TID.
*
* - The next 25 bits come from the 25 most significant bits of the row
* number. This makes up the "lower" part of the block number when
* interpreted as a heap TID.
*
* - Next up, slightly more interesting: we take the least significant 15 bits
* from the row numbers, add one to it. The results take up 16 bits (range:
* 1 - 2^15). This forms the "offset" when interpreted as a heap TID. We
* plus one on the LSB to accommodate the assumption in various places that
* heap TID's never have a zero offset.
*
* NOTE: Before GPDB6, we *always* set the reserved bit, not only when
* 'bytes_4_5' would otherwise be zero. That was simpler, but caused problems
* of its own, because very high offset numbers, which cannot occur in heap
* tables, have a special meaning in some places. See TUPLE_IS_INVALID in
* gist_private.h, for example. In other words, the 'ip_posid' field now uses
* values in the range 1..32768, whereas before GPDB 6, it used the range
* (32768..65535).
*/
typedef struct AOTupleId
{
uint16 bytes_0_1;
uint16 bytes_2_3;
uint16 bytes_4_5;
} AOTupleId;
/*
* This represents the maximum number of row numbers (or tuples) per logical
* heap block that an AO table can hold. The lower bytes: bytes_4_5 of AOTupleId
* gives us this value.
*/
#define AO_MAX_TUPLES_PER_HEAP_BLOCK (1 << 15)
/*
* This represents the maximum number of logical heap blocks that an AO segment
* file can contain. The 25 bits in the middle, describe in AOTupleId gives us
* this value.
*/
#define AO_MAX_HEAP_BLOCKS_PER_SEGMENT (1 << 25)
#define AOSegmentGet_segno(heapBlk) ((heapBlk) / AO_MAX_HEAP_BLOCKS_PER_SEGMENT)
#define AOTupleIdGet_segmentFileNum(h) ((((h)->bytes_0_1&0xFE00)>>9)) // 7 bits
/*
* Get the start block number of the specified aoseg.
*
* The higher order 32 bits of an AOTupleId (bytes_0_1 and bytes_2_3), form the
* heap block number when it is interpreted as an ItemPointer. Within that the
* top 7 bits form the segno. The starting heap block number is thus those
* combos of those 7 bits with the remaining 25 bits all being 0.
*/
#define AOSegmentGet_startHeapBlock(segno) ((segno) << 25)
/*
* Get the start block number of the current aoseg/block sequence from a given
* logical heap block number.
*
* The highest 7 bits of the BlockNumber represents the segment file number. So,
* the starting block number in a specific segment (or block sequence) is just
* those bits with the lower order bits masked out.
*/
#define AOHeapBlockGet_startHeapBlock(heapBlk) ((heapBlk) & 0xFE000000)
#define AOSegmentGet_blockSequenceNum(heapBlk) (AOSegmentGet_segno((heapBlk)))
#define InvalidBlockSequenceNum (-1)
static inline uint64
AOTupleIdGet_rowNum(AOTupleId *h)
{
uint64 rowNumber;
Assert(h->bytes_4_5 > 0);
Assert(h->bytes_4_5 <= 0x8000);
/* top 25 bits */
rowNumber = ((uint64)(h->bytes_0_1&0x01FF))<<31;
rowNumber |= ((uint64)(h->bytes_2_3))<<15;
/* lower 15 bits */
/* subtract one since we always add one when initialing the bytes_4_5 */
rowNumber |= h->bytes_4_5 - 1;
return rowNumber;
}
static inline void
AOTupleIdInit(AOTupleId *h, uint16 segfilenum, uint64 rownum)
{
h->bytes_0_1 = ((uint16) (0x007F & segfilenum)) << 9;
h->bytes_0_1 |= (uint16) ((INT64CONST(0x000000FFFFFFFFFF) & rownum) >> 31);
h->bytes_2_3 = (uint16) ((INT64CONST(0x000000007FFFFFFF) & rownum) >> 15);
/*
* Add one to make sure bytes_4_5 is never zero. Since bytes_4_5 form
* offset part when interpreted as TID, rest of system expects offset to
* be greater than zero.
*/
h->bytes_4_5 = (0x7FFF & rownum) + 1;
}
/* like ItemPointerSetInvalid */
static inline void
AOTupleIdSetInvalid(AOTupleId *h)
{
ItemPointerSetInvalid((ItemPointer) h);
}
#define AOTupleId_MaxRowNum INT64CONST(1099511627775) // 40 bits, or 1099511627775 (1 trillion).
#define AOTupleId_MaxSegmentFileNum 127
#define AOTupleId_MultiplierSegmentFileNum 128 // Next up power of 2 as multiplier.
extern char *AOTupleIdToString(AOTupleId *aoTupleId);
#endif /* APPENDONLYTID_H */