1 /*------------------------------------------------------------------------- 2 * 3 * itemid.h 4 * Standard POSTGRES buffer page item identifier definitions. 5 * 6 * 7 * Portions Copyright (c) 1996-2018, 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