1/*-------------------------------------------------------------------------
2 *
3 * itemid.h
4 * Standard POSTGRES buffer page item identifier/line pointer definitions.
5 *
6 *
7 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 * src/include/storage/itemid.h
11 *
12 *-------------------------------------------------------------------------
13 */
14#ifndef ITEMID_H
15#define ITEMID_H
16
17/*
18 * A line pointer on a buffer page. See buffer page definitions and comments
19 * for an explanation of how line pointers are used.
20 *
21 * In some cases a line pointer is "in use" but does not have any associated
22 * storage on the page. By convention, lp_len == 0 in every line pointer
23 * that does not have storage, independently of its lp_flags state.
24 */
25typedef struct ItemIdData
26{
27 unsigned lp_off:15, /* offset to tuple (from start of page) */
28 lp_flags:2, /* state of line pointer, see below */
29 lp_len:15; /* byte length of tuple */
30} ItemIdData;
31
32typedef ItemIdData *ItemId;
33
34/*
35 * lp_flags has these possible states. An UNUSED line pointer is available
36 * for immediate re-use, the other states are not.
37 */
38#define LP_UNUSED 0 /* unused (should always have lp_len=0) */
39#define LP_NORMAL 1 /* used (should always have lp_len>0) */
40#define LP_REDIRECT 2 /* HOT redirect (should have lp_len=0) */
41#define LP_DEAD 3 /* dead, may or may not have storage */
42
43/*
44 * Item offsets and lengths are represented by these types when
45 * they're not actually stored in an ItemIdData.
46 */
47typedef uint16 ItemOffset;
48typedef uint16 ItemLength;
49
50
51/* ----------------
52 * support macros
53 * ----------------
54 */
55
56/*
57 * ItemIdGetLength
58 */
59#define ItemIdGetLength(itemId) \
60 ((itemId)->lp_len)
61
62/*
63 * ItemIdGetOffset
64 */
65#define ItemIdGetOffset(itemId) \
66 ((itemId)->lp_off)
67
68/*
69 * ItemIdGetFlags
70 */
71#define ItemIdGetFlags(itemId) \
72 ((itemId)->lp_flags)
73
74/*
75 * ItemIdGetRedirect
76 * In a REDIRECT pointer, lp_off holds offset number for next line pointer
77 */
78#define ItemIdGetRedirect(itemId) \
79 ((itemId)->lp_off)
80
81/*
82 * ItemIdIsValid
83 * True iff item identifier is valid.
84 * This is a pretty weak test, probably useful only in Asserts.
85 */
86#define ItemIdIsValid(itemId) PointerIsValid(itemId)
87
88/*
89 * ItemIdIsUsed
90 * True iff item identifier is in use.
91 */
92#define ItemIdIsUsed(itemId) \
93 ((itemId)->lp_flags != LP_UNUSED)
94
95/*
96 * ItemIdIsNormal
97 * True iff item identifier is in state NORMAL.
98 */
99#define ItemIdIsNormal(itemId) \
100 ((itemId)->lp_flags == LP_NORMAL)
101
102/*
103 * ItemIdIsRedirected
104 * True iff item identifier is in state REDIRECT.
105 */
106#define ItemIdIsRedirected(itemId) \
107 ((itemId)->lp_flags == LP_REDIRECT)
108
109/*
110 * ItemIdIsDead
111 * True iff item identifier is in state DEAD.
112 */
113#define ItemIdIsDead(itemId) \
114 ((itemId)->lp_flags == LP_DEAD)
115
116/*
117 * ItemIdHasStorage
118 * True iff item identifier has associated storage.
119 */
120#define ItemIdHasStorage(itemId) \
121 ((itemId)->lp_len != 0)
122
123/*
124 * ItemIdSetUnused
125 * Set the item identifier to be UNUSED, with no storage.
126 * Beware of multiple evaluations of itemId!
127 */
128#define ItemIdSetUnused(itemId) \
129( \
130 (itemId)->lp_flags = LP_UNUSED, \
131 (itemId)->lp_off = 0, \
132 (itemId)->lp_len = 0 \
133)
134
135/*
136 * ItemIdSetNormal
137 * Set the item identifier to be NORMAL, with the specified storage.
138 * Beware of multiple evaluations of itemId!
139 */
140#define ItemIdSetNormal(itemId, off, len) \
141( \
142 (itemId)->lp_flags = LP_NORMAL, \
143 (itemId)->lp_off = (off), \
144 (itemId)->lp_len = (len) \
145)
146
147/*
148 * ItemIdSetRedirect
149 * Set the item identifier to be REDIRECT, with the specified link.
150 * Beware of multiple evaluations of itemId!
151 */
152#define ItemIdSetRedirect(itemId, link) \
153( \
154 (itemId)->lp_flags = LP_REDIRECT, \
155 (itemId)->lp_off = (link), \
156 (itemId)->lp_len = 0 \
157)
158
159/*
160 * ItemIdSetDead
161 * Set the item identifier to be DEAD, with no storage.
162 * Beware of multiple evaluations of itemId!
163 */
164#define ItemIdSetDead(itemId) \
165( \
166 (itemId)->lp_flags = LP_DEAD, \
167 (itemId)->lp_off = 0, \
168 (itemId)->lp_len = 0 \
169)
170
171/*
172 * ItemIdMarkDead
173 * Set the item identifier to be DEAD, keeping its existing storage.
174 *
175 * Note: in indexes, this is used as if it were a hint-bit mechanism;
176 * we trust that multiple processors can do this in parallel and get
177 * the same result.
178 */
179#define ItemIdMarkDead(itemId) \
180( \
181 (itemId)->lp_flags = LP_DEAD \
182)
183
184#endif /* ITEMID_H */
185