1 /*-------------------------------------------------------------------------
2  *
3  * itemid.h
4  *	  Standard POSTGRES buffer page item identifier/line pointer definitions.
5  *
6  *
7  * Portions Copyright (c) 1996-2020, 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  */
25 typedef 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 
32 typedef 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  */
47 typedef uint16 ItemOffset;
48 typedef 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