00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "access/heapam_xlog.h"
00018
00019 static void
00020 out_target(StringInfo buf, xl_heaptid *target)
00021 {
00022 appendStringInfo(buf, "rel %u/%u/%u; tid %u/%u",
00023 target->node.spcNode, target->node.dbNode, target->node.relNode,
00024 ItemPointerGetBlockNumber(&(target->tid)),
00025 ItemPointerGetOffsetNumber(&(target->tid)));
00026 }
00027
00028 static void
00029 out_infobits(StringInfo buf, uint8 infobits)
00030 {
00031 if (infobits & XLHL_XMAX_IS_MULTI)
00032 appendStringInfo(buf, "IS_MULTI ");
00033 if (infobits & XLHL_XMAX_LOCK_ONLY)
00034 appendStringInfo(buf, "LOCK_ONLY ");
00035 if (infobits & XLHL_XMAX_EXCL_LOCK)
00036 appendStringInfo(buf, "EXCL_LOCK ");
00037 if (infobits & XLHL_XMAX_KEYSHR_LOCK)
00038 appendStringInfo(buf, "KEYSHR_LOCK ");
00039 if (infobits & XLHL_KEYS_UPDATED)
00040 appendStringInfo(buf, "KEYS_UPDATED ");
00041 }
00042
00043 void
00044 heap_desc(StringInfo buf, uint8 xl_info, char *rec)
00045 {
00046 uint8 info = xl_info & ~XLR_INFO_MASK;
00047
00048 info &= XLOG_HEAP_OPMASK;
00049 if (info == XLOG_HEAP_INSERT)
00050 {
00051 xl_heap_insert *xlrec = (xl_heap_insert *) rec;
00052
00053 if (xl_info & XLOG_HEAP_INIT_PAGE)
00054 appendStringInfo(buf, "insert(init): ");
00055 else
00056 appendStringInfo(buf, "insert: ");
00057 out_target(buf, &(xlrec->target));
00058 }
00059 else if (info == XLOG_HEAP_DELETE)
00060 {
00061 xl_heap_delete *xlrec = (xl_heap_delete *) rec;
00062
00063 appendStringInfo(buf, "delete: ");
00064 out_target(buf, &(xlrec->target));
00065 appendStringInfoChar(buf, ' ');
00066 out_infobits(buf, xlrec->infobits_set);
00067 }
00068 else if (info == XLOG_HEAP_UPDATE)
00069 {
00070 xl_heap_update *xlrec = (xl_heap_update *) rec;
00071
00072 if (xl_info & XLOG_HEAP_INIT_PAGE)
00073 appendStringInfo(buf, "update(init): ");
00074 else
00075 appendStringInfo(buf, "update: ");
00076 out_target(buf, &(xlrec->target));
00077 appendStringInfo(buf, " xmax %u ", xlrec->old_xmax);
00078 out_infobits(buf, xlrec->old_infobits_set);
00079 appendStringInfo(buf, "; new tid %u/%u xmax %u",
00080 ItemPointerGetBlockNumber(&(xlrec->newtid)),
00081 ItemPointerGetOffsetNumber(&(xlrec->newtid)),
00082 xlrec->new_xmax);
00083 }
00084 else if (info == XLOG_HEAP_HOT_UPDATE)
00085 {
00086 xl_heap_update *xlrec = (xl_heap_update *) rec;
00087
00088 if (xl_info & XLOG_HEAP_INIT_PAGE)
00089 appendStringInfo(buf, "hot_update(init): ");
00090 else
00091 appendStringInfo(buf, "hot_update: ");
00092 out_target(buf, &(xlrec->target));
00093 appendStringInfo(buf, " xmax %u ", xlrec->old_xmax);
00094 out_infobits(buf, xlrec->old_infobits_set);
00095 appendStringInfo(buf, "; new tid %u/%u xmax %u",
00096 ItemPointerGetBlockNumber(&(xlrec->newtid)),
00097 ItemPointerGetOffsetNumber(&(xlrec->newtid)),
00098 xlrec->new_xmax);
00099 }
00100 else if (info == XLOG_HEAP_NEWPAGE)
00101 {
00102 xl_heap_newpage *xlrec = (xl_heap_newpage *) rec;
00103
00104 appendStringInfo(buf, "newpage: rel %u/%u/%u; fork %u, blk %u",
00105 xlrec->node.spcNode, xlrec->node.dbNode,
00106 xlrec->node.relNode, xlrec->forknum,
00107 xlrec->blkno);
00108 }
00109 else if (info == XLOG_HEAP_LOCK)
00110 {
00111 xl_heap_lock *xlrec = (xl_heap_lock *) rec;
00112
00113 appendStringInfo(buf, "lock %u: ", xlrec->locking_xid);
00114 out_target(buf, &(xlrec->target));
00115 appendStringInfoChar(buf, ' ');
00116 out_infobits(buf, xlrec->infobits_set);
00117 }
00118 else if (info == XLOG_HEAP_INPLACE)
00119 {
00120 xl_heap_inplace *xlrec = (xl_heap_inplace *) rec;
00121
00122 appendStringInfo(buf, "inplace: ");
00123 out_target(buf, &(xlrec->target));
00124 }
00125 else
00126 appendStringInfo(buf, "UNKNOWN");
00127 }
00128 void
00129 heap2_desc(StringInfo buf, uint8 xl_info, char *rec)
00130 {
00131 uint8 info = xl_info & ~XLR_INFO_MASK;
00132
00133 info &= XLOG_HEAP_OPMASK;
00134 if (info == XLOG_HEAP2_FREEZE)
00135 {
00136 xl_heap_freeze *xlrec = (xl_heap_freeze *) rec;
00137
00138 appendStringInfo(buf, "freeze: rel %u/%u/%u; blk %u; cutoff xid %u multi %u",
00139 xlrec->node.spcNode, xlrec->node.dbNode,
00140 xlrec->node.relNode, xlrec->block,
00141 xlrec->cutoff_xid, xlrec->cutoff_multi);
00142 }
00143 else if (info == XLOG_HEAP2_CLEAN)
00144 {
00145 xl_heap_clean *xlrec = (xl_heap_clean *) rec;
00146
00147 appendStringInfo(buf, "clean: rel %u/%u/%u; blk %u remxid %u",
00148 xlrec->node.spcNode, xlrec->node.dbNode,
00149 xlrec->node.relNode, xlrec->block,
00150 xlrec->latestRemovedXid);
00151 }
00152 else if (info == XLOG_HEAP2_CLEANUP_INFO)
00153 {
00154 xl_heap_cleanup_info *xlrec = (xl_heap_cleanup_info *) rec;
00155
00156 appendStringInfo(buf, "cleanup info: remxid %u",
00157 xlrec->latestRemovedXid);
00158 }
00159 else if (info == XLOG_HEAP2_VISIBLE)
00160 {
00161 xl_heap_visible *xlrec = (xl_heap_visible *) rec;
00162
00163 appendStringInfo(buf, "visible: rel %u/%u/%u; blk %u",
00164 xlrec->node.spcNode, xlrec->node.dbNode,
00165 xlrec->node.relNode, xlrec->block);
00166 }
00167 else if (info == XLOG_HEAP2_MULTI_INSERT)
00168 {
00169 xl_heap_multi_insert *xlrec = (xl_heap_multi_insert *) rec;
00170
00171 if (xl_info & XLOG_HEAP_INIT_PAGE)
00172 appendStringInfo(buf, "multi-insert (init): ");
00173 else
00174 appendStringInfo(buf, "multi-insert: ");
00175 appendStringInfo(buf, "rel %u/%u/%u; blk %u; %d tuples",
00176 xlrec->node.spcNode, xlrec->node.dbNode, xlrec->node.relNode,
00177 xlrec->blkno, xlrec->ntuples);
00178 }
00179 else if (info == XLOG_HEAP2_LOCK_UPDATED)
00180 {
00181 xl_heap_lock_updated *xlrec = (xl_heap_lock_updated *) rec;
00182
00183 appendStringInfo(buf, "lock updated: xmax %u msk %04x; ", xlrec->xmax,
00184 xlrec->infobits_set);
00185 out_target(buf, &(xlrec->target));
00186 }
00187 else
00188 appendStringInfo(buf, "UNKNOWN");
00189 }