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