PostgreSQL Source Code  git master
xactdesc.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * xactdesc.c
4  * rmgr descriptor routines for access/transam/xact.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/xactdesc.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/transam.h"
18 #include "access/xact.h"
19 #include "storage/sinval.h"
20 #include "storage/standbydefs.h"
21 #include "utils/timestamp.h"
22 
23 /*
24  * Parse the WAL format of an xact commit and abort records into an easier to
25  * understand format.
26  *
27  * This routines are in xactdesc.c because they're accessed in backend (when
28  * replaying WAL) and frontend (pg_waldump) code. This file is the only xact
29  * specific one shared between both. They're complicated enough that
30  * duplication would be bothersome.
31  */
32 
33 void
35 {
36  char *data = ((char *) xlrec) + MinSizeOfXactCommit;
37 
38  memset(parsed, 0, sizeof(*parsed));
39 
40  parsed->xinfo = 0; /* default, if no XLOG_XACT_HAS_INFO is
41  * present */
42 
43  parsed->xact_time = xlrec->xact_time;
44 
45  if (info & XLOG_XACT_HAS_INFO)
46  {
47  xl_xact_xinfo *xl_xinfo = (xl_xact_xinfo *) data;
48 
49  parsed->xinfo = xl_xinfo->xinfo;
50 
51  data += sizeof(xl_xact_xinfo);
52  }
53 
54  if (parsed->xinfo & XACT_XINFO_HAS_DBINFO)
55  {
56  xl_xact_dbinfo *xl_dbinfo = (xl_xact_dbinfo *) data;
57 
58  parsed->dbId = xl_dbinfo->dbId;
59  parsed->tsId = xl_dbinfo->tsId;
60 
61  data += sizeof(xl_xact_dbinfo);
62  }
63 
64  if (parsed->xinfo & XACT_XINFO_HAS_SUBXACTS)
65  {
66  xl_xact_subxacts *xl_subxacts = (xl_xact_subxacts *) data;
67 
68  parsed->nsubxacts = xl_subxacts->nsubxacts;
69  parsed->subxacts = xl_subxacts->subxacts;
70 
71  data += MinSizeOfXactSubxacts;
72  data += parsed->nsubxacts * sizeof(TransactionId);
73  }
74 
75  if (parsed->xinfo & XACT_XINFO_HAS_RELFILENODES)
76  {
77  xl_xact_relfilenodes *xl_relfilenodes = (xl_xact_relfilenodes *) data;
78 
79  parsed->nrels = xl_relfilenodes->nrels;
80  parsed->xnodes = xl_relfilenodes->xnodes;
81 
83  data += xl_relfilenodes->nrels * sizeof(RelFileNode);
84  }
85 
86  if (parsed->xinfo & XACT_XINFO_HAS_INVALS)
87  {
88  xl_xact_invals *xl_invals = (xl_xact_invals *) data;
89 
90  parsed->nmsgs = xl_invals->nmsgs;
91  parsed->msgs = xl_invals->msgs;
92 
93  data += MinSizeOfXactInvals;
94  data += xl_invals->nmsgs * sizeof(SharedInvalidationMessage);
95  }
96 
97  if (parsed->xinfo & XACT_XINFO_HAS_TWOPHASE)
98  {
99  xl_xact_twophase *xl_twophase = (xl_xact_twophase *) data;
100 
101  parsed->twophase_xid = xl_twophase->xid;
102 
103  data += sizeof(xl_xact_twophase);
104 
105  if (parsed->xinfo & XACT_XINFO_HAS_GID)
106  {
107  strlcpy(parsed->twophase_gid, data, sizeof(parsed->twophase_gid));
108  data += strlen(data) + 1;
109  }
110  }
111 
112  /* Note: no alignment is guaranteed after this point */
113 
114  if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
115  {
116  xl_xact_origin xl_origin;
117 
118  /* no alignment is guaranteed, so copy onto stack */
119  memcpy(&xl_origin, data, sizeof(xl_origin));
120 
121  parsed->origin_lsn = xl_origin.origin_lsn;
122  parsed->origin_timestamp = xl_origin.origin_timestamp;
123 
124  data += sizeof(xl_xact_origin);
125  }
126 }
127 
128 void
130 {
131  char *data = ((char *) xlrec) + MinSizeOfXactAbort;
132 
133  memset(parsed, 0, sizeof(*parsed));
134 
135  parsed->xinfo = 0; /* default, if no XLOG_XACT_HAS_INFO is
136  * present */
137 
138  parsed->xact_time = xlrec->xact_time;
139 
140  if (info & XLOG_XACT_HAS_INFO)
141  {
142  xl_xact_xinfo *xl_xinfo = (xl_xact_xinfo *) data;
143 
144  parsed->xinfo = xl_xinfo->xinfo;
145 
146  data += sizeof(xl_xact_xinfo);
147  }
148 
149  if (parsed->xinfo & XACT_XINFO_HAS_DBINFO)
150  {
151  xl_xact_dbinfo *xl_dbinfo = (xl_xact_dbinfo *) data;
152 
153  parsed->dbId = xl_dbinfo->dbId;
154  parsed->tsId = xl_dbinfo->tsId;
155 
156  data += sizeof(xl_xact_dbinfo);
157  }
158 
159  if (parsed->xinfo & XACT_XINFO_HAS_SUBXACTS)
160  {
161  xl_xact_subxacts *xl_subxacts = (xl_xact_subxacts *) data;
162 
163  parsed->nsubxacts = xl_subxacts->nsubxacts;
164  parsed->subxacts = xl_subxacts->subxacts;
165 
166  data += MinSizeOfXactSubxacts;
167  data += parsed->nsubxacts * sizeof(TransactionId);
168  }
169 
170  if (parsed->xinfo & XACT_XINFO_HAS_RELFILENODES)
171  {
172  xl_xact_relfilenodes *xl_relfilenodes = (xl_xact_relfilenodes *) data;
173 
174  parsed->nrels = xl_relfilenodes->nrels;
175  parsed->xnodes = xl_relfilenodes->xnodes;
176 
178  data += xl_relfilenodes->nrels * sizeof(RelFileNode);
179  }
180 
181  if (parsed->xinfo & XACT_XINFO_HAS_TWOPHASE)
182  {
183  xl_xact_twophase *xl_twophase = (xl_xact_twophase *) data;
184 
185  parsed->twophase_xid = xl_twophase->xid;
186 
187  data += sizeof(xl_xact_twophase);
188 
189  if (parsed->xinfo & XACT_XINFO_HAS_GID)
190  {
191  strlcpy(parsed->twophase_gid, data, sizeof(parsed->twophase_gid));
192  data += strlen(data) + 1;
193  }
194  }
195 
196  /* Note: no alignment is guaranteed after this point */
197 
198  if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
199  {
200  xl_xact_origin xl_origin;
201 
202  /* no alignment is guaranteed, so copy onto stack */
203  memcpy(&xl_origin, data, sizeof(xl_origin));
204 
205  parsed->origin_lsn = xl_origin.origin_lsn;
206  parsed->origin_timestamp = xl_origin.origin_timestamp;
207 
208  data += sizeof(xl_xact_origin);
209  }
210 }
211 
212 /*
213  * ParsePrepareRecord
214  */
215 void
217 {
218  char *bufptr;
219 
220  bufptr = ((char *) xlrec) + MAXALIGN(sizeof(xl_xact_prepare));
221 
222  memset(parsed, 0, sizeof(*parsed));
223 
224  parsed->xact_time = xlrec->prepared_at;
225  parsed->origin_lsn = xlrec->origin_lsn;
226  parsed->origin_timestamp = xlrec->origin_timestamp;
227  parsed->twophase_xid = xlrec->xid;
228  parsed->dbId = xlrec->database;
229  parsed->nsubxacts = xlrec->nsubxacts;
230  parsed->nrels = xlrec->ncommitrels;
231  parsed->nabortrels = xlrec->nabortrels;
232  parsed->nmsgs = xlrec->ninvalmsgs;
233 
234  strncpy(parsed->twophase_gid, bufptr, xlrec->gidlen);
235  bufptr += MAXALIGN(xlrec->gidlen);
236 
237  parsed->subxacts = (TransactionId *) bufptr;
238  bufptr += MAXALIGN(xlrec->nsubxacts * sizeof(TransactionId));
239 
240  parsed->xnodes = (RelFileNode *) bufptr;
241  bufptr += MAXALIGN(xlrec->ncommitrels * sizeof(RelFileNode));
242 
243  parsed->abortnodes = (RelFileNode *) bufptr;
244  bufptr += MAXALIGN(xlrec->nabortrels * sizeof(RelFileNode));
245 
246  parsed->msgs = (SharedInvalidationMessage *) bufptr;
247  bufptr += MAXALIGN(xlrec->ninvalmsgs * sizeof(SharedInvalidationMessage));
248 }
249 
250 static void
252  RelFileNode *xnodes)
253 {
254  int i;
255 
256  if (nrels > 0)
257  {
258  appendStringInfo(buf, "; %s:", label);
259  for (i = 0; i < nrels; i++)
260  {
261  char *path = relpathperm(xnodes[i], MAIN_FORKNUM);
262 
263  appendStringInfo(buf, " %s", path);
264  pfree(path);
265  }
266  }
267 }
268 
269 static void
270 xact_desc_subxacts(StringInfo buf, int nsubxacts, TransactionId *subxacts)
271 {
272  int i;
273 
274  if (nsubxacts > 0)
275  {
276  appendStringInfoString(buf, "; subxacts:");
277  for (i = 0; i < nsubxacts; i++)
278  appendStringInfo(buf, " %u", subxacts[i]);
279  }
280 }
281 
282 static void
284 {
285  xl_xact_parsed_commit parsed;
286 
287  ParseCommitRecord(info, xlrec, &parsed);
288 
289  /* If this is a prepared xact, show the xid of the original xact */
291  appendStringInfo(buf, "%u: ", parsed.twophase_xid);
292 
294 
295  xact_desc_relations(buf, "rels", parsed.nrels, parsed.xnodes);
296  xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);
297 
299  buf, parsed.nmsgs, parsed.msgs, parsed.dbId, parsed.tsId,
301 
303  appendStringInfoString(buf, "; sync");
304 
305  if (parsed.xinfo & XACT_XINFO_HAS_ORIGIN)
306  {
307  appendStringInfo(buf, "; origin: node %u, lsn %X/%X, at %s",
308  origin_id,
309  (uint32) (parsed.origin_lsn >> 32),
310  (uint32) parsed.origin_lsn,
312  }
313 }
314 
315 static void
317 {
318  xl_xact_parsed_abort parsed;
319 
320  ParseAbortRecord(info, xlrec, &parsed);
321 
322  /* If this is a prepared xact, show the xid of the original xact */
324  appendStringInfo(buf, "%u: ", parsed.twophase_xid);
325 
327 
328  xact_desc_relations(buf, "rels", parsed.nrels, parsed.xnodes);
329  xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);
330 }
331 
332 static void
334 {
335  xl_xact_parsed_prepare parsed;
336 
337  ParsePrepareRecord(info, xlrec, &parsed);
338 
339  appendStringInfo(buf, "gid %s: ", parsed.twophase_gid);
341 
342  xact_desc_relations(buf, "rels(commit)", parsed.nrels, parsed.xnodes);
343  xact_desc_relations(buf, "rels(abort)", parsed.nabortrels,
344  parsed.abortnodes);
345  xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);
346 
348  buf, parsed.nmsgs, parsed.msgs, parsed.dbId, parsed.tsId,
349  xlrec->initfileinval);
350 }
351 
352 static void
354 {
355  int i;
356 
357  appendStringInfoString(buf, "subxacts:");
358 
359  for (i = 0; i < xlrec->nsubxacts; i++)
360  appendStringInfo(buf, " %u", xlrec->xsub[i]);
361 }
362 
363 void
365 {
366  char *rec = XLogRecGetData(record);
367  uint8 info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
368 
369  if (info == XLOG_XACT_COMMIT || info == XLOG_XACT_COMMIT_PREPARED)
370  {
371  xl_xact_commit *xlrec = (xl_xact_commit *) rec;
372 
373  xact_desc_commit(buf, XLogRecGetInfo(record), xlrec,
374  XLogRecGetOrigin(record));
375  }
376  else if (info == XLOG_XACT_ABORT || info == XLOG_XACT_ABORT_PREPARED)
377  {
378  xl_xact_abort *xlrec = (xl_xact_abort *) rec;
379 
380  xact_desc_abort(buf, XLogRecGetInfo(record), xlrec);
381  }
382  else if (info == XLOG_XACT_PREPARE)
383  {
384  xl_xact_prepare *xlrec = (xl_xact_prepare *) rec;
385 
386  xact_desc_prepare(buf, XLogRecGetInfo(record), xlrec);
387  }
388  else if (info == XLOG_XACT_ASSIGNMENT)
389  {
390  xl_xact_assignment *xlrec = (xl_xact_assignment *) rec;
391 
392  /*
393  * Note that we ignore the WAL record's xid, since we're more
394  * interested in the top-level xid that issued the record and which
395  * xids are being reported here.
396  */
397  appendStringInfo(buf, "xtop %u: ", xlrec->xtop);
398  xact_desc_assignment(buf, xlrec);
399  }
400 }
401 
402 const char *
404 {
405  const char *id = NULL;
406 
407  switch (info & XLOG_XACT_OPMASK)
408  {
409  case XLOG_XACT_COMMIT:
410  id = "COMMIT";
411  break;
412  case XLOG_XACT_PREPARE:
413  id = "PREPARE";
414  break;
415  case XLOG_XACT_ABORT:
416  id = "ABORT";
417  break;
419  id = "COMMIT_PREPARED";
420  break;
422  id = "ABORT_PREPARED";
423  break;
425  id = "ASSIGNMENT";
426  break;
427  }
428 
429  return id;
430 }
RelFileNode * xnodes
Definition: xact.h:330
int32 ninvalmsgs
Definition: xact.h:306
#define relpathperm(rnode, forknum)
Definition: relpath.h:83
#define XLOG_XACT_COMMIT
Definition: xact.h:143
int32 nsubxacts
Definition: xact.h:303
#define XACT_XINFO_HAS_ORIGIN
Definition: xact.h:167
#define XactCompletionRelcacheInitFileInval(xinfo)
Definition: xact.h:186
struct xl_xact_xinfo xl_xact_xinfo
#define XLOG_XACT_PREPARE
Definition: xact.h:144
const char * xact_identify(uint8 info)
Definition: xactdesc.c:403
uint32 TransactionId
Definition: c.h:514
int32 ncommitrels
Definition: xact.h:304
void standby_desc_invalidations(StringInfo buf, int nmsgs, SharedInvalidationMessage *msgs, Oid dbId, Oid tsId, bool relcacheInitFileInval)
Definition: standbydesc.c:98
TimestampTz origin_timestamp
Definition: xact.h:341
TransactionId xid
Definition: xact.h:256
TransactionId twophase_xid
Definition: xact.h:335
unsigned char uint8
Definition: c.h:357
TransactionId * subxacts
Definition: xact.h:327
uint16 RepOriginId
Definition: xlogdefs.h:58
#define MinSizeOfXactAbort
Definition: xact.h:293
#define XLOG_XACT_HAS_INFO
Definition: xact.h:156
SharedInvalidationMessage * msgs
Definition: xact.h:333
TransactionId xtop
Definition: xact.h:193
XLogRecPtr origin_lsn
Definition: xact.h:340
uint16 gidlen
Definition: xact.h:308
TransactionId xsub[FLEXIBLE_ARRAY_MEMBER]
Definition: xact.h:195
#define XACT_XINFO_HAS_SUBXACTS
Definition: xact.h:163
struct xl_xact_dbinfo xl_xact_dbinfo
#define MinSizeOfXactRelfilenodes
Definition: xact.h:245
TimestampTz xact_time
Definition: xact.h:282
Oid tsId
Definition: xact.h:230
#define XLogRecGetOrigin(decoder)
Definition: xlogreader.h:282
Oid database
Definition: xact.h:300
struct xl_xact_origin xl_xact_origin
static void xact_desc_relations(StringInfo buf, char *label, int nrels, RelFileNode *xnodes)
Definition: xactdesc.c:251
RelFileNode xnodes[FLEXIBLE_ARRAY_MEMBER]
Definition: xact.h:243
int32 nabortrels
Definition: xact.h:305
#define MinSizeOfXactSubxacts
Definition: xact.h:238
void pfree(void *pointer)
Definition: mcxt.c:1056
#define XLogRecGetData(decoder)
Definition: xlogreader.h:283
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define MinSizeOfXactCommit
Definition: xact.h:278
SharedInvalidationMessage msgs[FLEXIBLE_ARRAY_MEMBER]
Definition: xact.h:250
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
struct RelFileNode RelFileNode
void ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed)
Definition: xactdesc.c:34
static char * buf
Definition: pg_test_fsync.c:67
TimestampTz xact_time
Definition: xact.h:267
#define XLOG_XACT_ABORT_PREPARED
Definition: xact.h:147
XLogRecPtr origin_lsn
Definition: xact.h:309
static void xact_desc_abort(StringInfo buf, uint8 info, xl_xact_abort *xlrec)
Definition: xactdesc.c:316
struct xl_xact_twophase xl_xact_twophase
unsigned int uint32
Definition: c.h:359
#define MinSizeOfXactInvals
Definition: xact.h:252
#define XACT_XINFO_HAS_DBINFO
Definition: xact.h:162
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:279
XLogRecPtr origin_lsn
Definition: xact.h:261
TransactionId * subxacts
Definition: xact.h:355
#define XLOG_XACT_ASSIGNMENT
Definition: xact.h:148
uint32 xinfo
Definition: xact.h:224
XLogRecPtr origin_lsn
Definition: xact.h:363
static char * label
RelFileNode * xnodes
Definition: xact.h:358
int nsubxacts
Definition: xact.h:235
#define XACT_XINFO_HAS_TWOPHASE
Definition: xact.h:166
void ParsePrepareRecord(uint8 info, xl_xact_prepare *xlrec, xl_xact_parsed_prepare *parsed)
Definition: xactdesc.c:216
Oid dbId
Definition: xact.h:229
TransactionId twophase_xid
Definition: xact.h:360
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define XactCompletionForceSyncCommit(xinfo)
Definition: xact.h:188
bool initfileinval
Definition: xact.h:307
RelFileNode * abortnodes
Definition: xact.h:338
#define XLOG_XACT_ABORT
Definition: xact.h:145
static void xact_desc_prepare(StringInfo buf, uint8 info, xl_xact_prepare *xlrec)
Definition: xactdesc.c:333
TimestampTz origin_timestamp
Definition: xact.h:310
#define XLOG_XACT_OPMASK
Definition: xact.h:153
TimestampTz xact_time
Definition: xact.h:348
#define MAXALIGN(LEN)
Definition: c.h:692
void ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed)
Definition: xactdesc.c:129
TransactionId xid
Definition: xact.h:299
TimestampTz origin_timestamp
Definition: xact.h:262
static void xact_desc_assignment(StringInfo buf, xl_xact_assignment *xlrec)
Definition: xactdesc.c:353
int i
#define XACT_XINFO_HAS_INVALS
Definition: xact.h:165
#define XACT_XINFO_HAS_RELFILENODES
Definition: xact.h:164
TimestampTz prepared_at
Definition: xact.h:301
void xact_desc(StringInfo buf, XLogReaderState *record)
Definition: xactdesc.c:364
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define XLOG_XACT_COMMIT_PREPARED
Definition: xact.h:146
TimestampTz origin_timestamp
Definition: xact.h:364
int nmsgs
Definition: xact.h:249
#define XACT_XINFO_HAS_GID
Definition: xact.h:169
char twophase_gid[GIDSIZE]
Definition: xact.h:336
char twophase_gid[GIDSIZE]
Definition: xact.h:361
TransactionId subxacts[FLEXIBLE_ARRAY_MEMBER]
Definition: xact.h:236
static void xact_desc_commit(StringInfo buf, uint8 info, xl_xact_commit *xlrec, RepOriginId origin_id)
Definition: xactdesc.c:283
TimestampTz xact_time
Definition: xact.h:320
static void xact_desc_subxacts(StringInfo buf, int nsubxacts, TransactionId *subxacts)
Definition: xactdesc.c:270
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1743