| 1 | /*------------------------------------------------------------------------- |
| 2 | * |
| 3 | * heapdesc.c |
| 4 | * rmgr descriptor routines for access/heap/heapam.c |
| 5 | * |
| 6 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
| 7 | * Portions Copyright (c) 1994, Regents of the University of California |
| 8 | * |
| 9 | * |
| 10 | * IDENTIFICATION |
| 11 | * src/backend/access/rmgrdesc/heapdesc.c |
| 12 | * |
| 13 | *------------------------------------------------------------------------- |
| 14 | */ |
| 15 | #include "postgres.h" |
| 16 | |
| 17 | #include "access/heapam_xlog.h" |
| 18 | |
| 19 | static void |
| 20 | out_infobits(StringInfo buf, uint8 infobits) |
| 21 | { |
| 22 | if (infobits & XLHL_XMAX_IS_MULTI) |
| 23 | appendStringInfoString(buf, "IS_MULTI " ); |
| 24 | if (infobits & XLHL_XMAX_LOCK_ONLY) |
| 25 | appendStringInfoString(buf, "LOCK_ONLY " ); |
| 26 | if (infobits & XLHL_XMAX_EXCL_LOCK) |
| 27 | appendStringInfoString(buf, "EXCL_LOCK " ); |
| 28 | if (infobits & XLHL_XMAX_KEYSHR_LOCK) |
| 29 | appendStringInfoString(buf, "KEYSHR_LOCK " ); |
| 30 | if (infobits & XLHL_KEYS_UPDATED) |
| 31 | appendStringInfoString(buf, "KEYS_UPDATED " ); |
| 32 | } |
| 33 | |
| 34 | void |
| 35 | heap_desc(StringInfo buf, XLogReaderState *record) |
| 36 | { |
| 37 | char *rec = XLogRecGetData(record); |
| 38 | uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; |
| 39 | |
| 40 | info &= XLOG_HEAP_OPMASK; |
| 41 | if (info == XLOG_HEAP_INSERT) |
| 42 | { |
| 43 | xl_heap_insert *xlrec = (xl_heap_insert *) rec; |
| 44 | |
| 45 | appendStringInfo(buf, "off %u flags 0x%02X" , xlrec->offnum, |
| 46 | xlrec->flags); |
| 47 | } |
| 48 | else if (info == XLOG_HEAP_DELETE) |
| 49 | { |
| 50 | xl_heap_delete *xlrec = (xl_heap_delete *) rec; |
| 51 | |
| 52 | appendStringInfo(buf, "off %u flags 0x%02X " , |
| 53 | xlrec->offnum, |
| 54 | xlrec->flags); |
| 55 | out_infobits(buf, xlrec->infobits_set); |
| 56 | } |
| 57 | else if (info == XLOG_HEAP_UPDATE) |
| 58 | { |
| 59 | xl_heap_update *xlrec = (xl_heap_update *) rec; |
| 60 | |
| 61 | appendStringInfo(buf, "off %u xmax %u flags 0x%02X " , |
| 62 | xlrec->old_offnum, |
| 63 | xlrec->old_xmax, |
| 64 | xlrec->flags); |
| 65 | out_infobits(buf, xlrec->old_infobits_set); |
| 66 | appendStringInfo(buf, "; new off %u xmax %u" , |
| 67 | xlrec->new_offnum, |
| 68 | xlrec->new_xmax); |
| 69 | } |
| 70 | else if (info == XLOG_HEAP_HOT_UPDATE) |
| 71 | { |
| 72 | xl_heap_update *xlrec = (xl_heap_update *) rec; |
| 73 | |
| 74 | appendStringInfo(buf, "off %u xmax %u flags 0x%02X " , |
| 75 | xlrec->old_offnum, |
| 76 | xlrec->old_xmax, |
| 77 | xlrec->flags); |
| 78 | out_infobits(buf, xlrec->old_infobits_set); |
| 79 | appendStringInfo(buf, "; new off %u xmax %u" , |
| 80 | xlrec->new_offnum, |
| 81 | xlrec->new_xmax); |
| 82 | } |
| 83 | else if (info == XLOG_HEAP_TRUNCATE) |
| 84 | { |
| 85 | xl_heap_truncate *xlrec = (xl_heap_truncate *) rec; |
| 86 | int i; |
| 87 | |
| 88 | if (xlrec->flags & XLH_TRUNCATE_CASCADE) |
| 89 | appendStringInfo(buf, "cascade " ); |
| 90 | if (xlrec->flags & XLH_TRUNCATE_RESTART_SEQS) |
| 91 | appendStringInfo(buf, "restart_seqs " ); |
| 92 | appendStringInfo(buf, "nrelids %u relids" , xlrec->nrelids); |
| 93 | for (i = 0; i < xlrec->nrelids; i++) |
| 94 | appendStringInfo(buf, " %u" , xlrec->relids[i]); |
| 95 | } |
| 96 | else if (info == XLOG_HEAP_CONFIRM) |
| 97 | { |
| 98 | xl_heap_confirm *xlrec = (xl_heap_confirm *) rec; |
| 99 | |
| 100 | appendStringInfo(buf, "off %u" , xlrec->offnum); |
| 101 | } |
| 102 | else if (info == XLOG_HEAP_LOCK) |
| 103 | { |
| 104 | xl_heap_lock *xlrec = (xl_heap_lock *) rec; |
| 105 | |
| 106 | appendStringInfo(buf, "off %u: xid %u: flags 0x%02X " , |
| 107 | xlrec->offnum, xlrec->locking_xid, xlrec->flags); |
| 108 | out_infobits(buf, xlrec->infobits_set); |
| 109 | } |
| 110 | else if (info == XLOG_HEAP_INPLACE) |
| 111 | { |
| 112 | xl_heap_inplace *xlrec = (xl_heap_inplace *) rec; |
| 113 | |
| 114 | appendStringInfo(buf, "off %u" , xlrec->offnum); |
| 115 | } |
| 116 | } |
| 117 | void |
| 118 | heap2_desc(StringInfo buf, XLogReaderState *record) |
| 119 | { |
| 120 | char *rec = XLogRecGetData(record); |
| 121 | uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; |
| 122 | |
| 123 | info &= XLOG_HEAP_OPMASK; |
| 124 | if (info == XLOG_HEAP2_CLEAN) |
| 125 | { |
| 126 | xl_heap_clean *xlrec = (xl_heap_clean *) rec; |
| 127 | |
| 128 | appendStringInfo(buf, "remxid %u" , xlrec->latestRemovedXid); |
| 129 | } |
| 130 | else if (info == XLOG_HEAP2_FREEZE_PAGE) |
| 131 | { |
| 132 | xl_heap_freeze_page *xlrec = (xl_heap_freeze_page *) rec; |
| 133 | |
| 134 | appendStringInfo(buf, "cutoff xid %u ntuples %u" , |
| 135 | xlrec->cutoff_xid, xlrec->ntuples); |
| 136 | } |
| 137 | else if (info == XLOG_HEAP2_CLEANUP_INFO) |
| 138 | { |
| 139 | xl_heap_cleanup_info *xlrec = (xl_heap_cleanup_info *) rec; |
| 140 | |
| 141 | appendStringInfo(buf, "remxid %u" , xlrec->latestRemovedXid); |
| 142 | } |
| 143 | else if (info == XLOG_HEAP2_VISIBLE) |
| 144 | { |
| 145 | xl_heap_visible *xlrec = (xl_heap_visible *) rec; |
| 146 | |
| 147 | appendStringInfo(buf, "cutoff xid %u flags 0x%02X" , |
| 148 | xlrec->cutoff_xid, xlrec->flags); |
| 149 | } |
| 150 | else if (info == XLOG_HEAP2_MULTI_INSERT) |
| 151 | { |
| 152 | xl_heap_multi_insert *xlrec = (xl_heap_multi_insert *) rec; |
| 153 | |
| 154 | appendStringInfo(buf, "%d tuples flags 0x%02X" , xlrec->ntuples, |
| 155 | xlrec->flags); |
| 156 | } |
| 157 | else if (info == XLOG_HEAP2_LOCK_UPDATED) |
| 158 | { |
| 159 | xl_heap_lock_updated *xlrec = (xl_heap_lock_updated *) rec; |
| 160 | |
| 161 | appendStringInfo(buf, "off %u: xmax %u: flags 0x%02X " , |
| 162 | xlrec->offnum, xlrec->xmax, xlrec->flags); |
| 163 | out_infobits(buf, xlrec->infobits_set); |
| 164 | } |
| 165 | else if (info == XLOG_HEAP2_NEW_CID) |
| 166 | { |
| 167 | xl_heap_new_cid *xlrec = (xl_heap_new_cid *) rec; |
| 168 | |
| 169 | appendStringInfo(buf, "rel %u/%u/%u; tid %u/%u" , |
| 170 | xlrec->target_node.spcNode, |
| 171 | xlrec->target_node.dbNode, |
| 172 | xlrec->target_node.relNode, |
| 173 | ItemPointerGetBlockNumber(&(xlrec->target_tid)), |
| 174 | ItemPointerGetOffsetNumber(&(xlrec->target_tid))); |
| 175 | appendStringInfo(buf, "; cmin: %u, cmax: %u, combo: %u" , |
| 176 | xlrec->cmin, xlrec->cmax, xlrec->combocid); |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | const char * |
| 181 | heap_identify(uint8 info) |
| 182 | { |
| 183 | const char *id = NULL; |
| 184 | |
| 185 | switch (info & ~XLR_INFO_MASK) |
| 186 | { |
| 187 | case XLOG_HEAP_INSERT: |
| 188 | id = "INSERT" ; |
| 189 | break; |
| 190 | case XLOG_HEAP_INSERT | XLOG_HEAP_INIT_PAGE: |
| 191 | id = "INSERT+INIT" ; |
| 192 | break; |
| 193 | case XLOG_HEAP_DELETE: |
| 194 | id = "DELETE" ; |
| 195 | break; |
| 196 | case XLOG_HEAP_UPDATE: |
| 197 | id = "UPDATE" ; |
| 198 | break; |
| 199 | case XLOG_HEAP_UPDATE | XLOG_HEAP_INIT_PAGE: |
| 200 | id = "UPDATE+INIT" ; |
| 201 | break; |
| 202 | case XLOG_HEAP_HOT_UPDATE: |
| 203 | id = "HOT_UPDATE" ; |
| 204 | break; |
| 205 | case XLOG_HEAP_HOT_UPDATE | XLOG_HEAP_INIT_PAGE: |
| 206 | id = "HOT_UPDATE+INIT" ; |
| 207 | break; |
| 208 | case XLOG_HEAP_TRUNCATE: |
| 209 | id = "TRUNCATE" ; |
| 210 | break; |
| 211 | case XLOG_HEAP_CONFIRM: |
| 212 | id = "HEAP_CONFIRM" ; |
| 213 | break; |
| 214 | case XLOG_HEAP_LOCK: |
| 215 | id = "LOCK" ; |
| 216 | break; |
| 217 | case XLOG_HEAP_INPLACE: |
| 218 | id = "INPLACE" ; |
| 219 | break; |
| 220 | } |
| 221 | |
| 222 | return id; |
| 223 | } |
| 224 | |
| 225 | const char * |
| 226 | heap2_identify(uint8 info) |
| 227 | { |
| 228 | const char *id = NULL; |
| 229 | |
| 230 | switch (info & ~XLR_INFO_MASK) |
| 231 | { |
| 232 | case XLOG_HEAP2_CLEAN: |
| 233 | id = "CLEAN" ; |
| 234 | break; |
| 235 | case XLOG_HEAP2_FREEZE_PAGE: |
| 236 | id = "FREEZE_PAGE" ; |
| 237 | break; |
| 238 | case XLOG_HEAP2_CLEANUP_INFO: |
| 239 | id = "CLEANUP_INFO" ; |
| 240 | break; |
| 241 | case XLOG_HEAP2_VISIBLE: |
| 242 | id = "VISIBLE" ; |
| 243 | break; |
| 244 | case XLOG_HEAP2_MULTI_INSERT: |
| 245 | id = "MULTI_INSERT" ; |
| 246 | break; |
| 247 | case XLOG_HEAP2_MULTI_INSERT | XLOG_HEAP_INIT_PAGE: |
| 248 | id = "MULTI_INSERT+INIT" ; |
| 249 | break; |
| 250 | case XLOG_HEAP2_LOCK_UPDATED: |
| 251 | id = "LOCK_UPDATED" ; |
| 252 | break; |
| 253 | case XLOG_HEAP2_NEW_CID: |
| 254 | id = "NEW_CID" ; |
| 255 | break; |
| 256 | case XLOG_HEAP2_REWRITE: |
| 257 | id = "REWRITE" ; |
| 258 | break; |
| 259 | } |
| 260 | |
| 261 | return id; |
| 262 | } |
| 263 | |