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