1/*-------------------------------------------------------------------------
2 *
3 * standbydesc.c
4 * rmgr descriptor routines for storage/ipc/standby.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/standbydesc.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include "storage/standbydefs.h"
18
19static void
20standby_desc_running_xacts(StringInfo buf, xl_running_xacts *xlrec)
21{
22 int i;
23
24 appendStringInfo(buf, "nextXid %u latestCompletedXid %u oldestRunningXid %u",
25 xlrec->nextXid,
26 xlrec->latestCompletedXid,
27 xlrec->oldestRunningXid);
28 if (xlrec->xcnt > 0)
29 {
30 appendStringInfo(buf, "; %d xacts:", xlrec->xcnt);
31 for (i = 0; i < xlrec->xcnt; i++)
32 appendStringInfo(buf, " %u", xlrec->xids[i]);
33 }
34
35 if (xlrec->subxid_overflow)
36 appendStringInfoString(buf, "; subxid ovf");
37}
38
39void
40standby_desc(StringInfo buf, XLogReaderState *record)
41{
42 char *rec = XLogRecGetData(record);
43 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
44
45 if (info == XLOG_STANDBY_LOCK)
46 {
47 xl_standby_locks *xlrec = (xl_standby_locks *) rec;
48 int i;
49
50 for (i = 0; i < xlrec->nlocks; i++)
51 appendStringInfo(buf, "xid %u db %u rel %u ",
52 xlrec->locks[i].xid, xlrec->locks[i].dbOid,
53 xlrec->locks[i].relOid);
54 }
55 else if (info == XLOG_RUNNING_XACTS)
56 {
57 xl_running_xacts *xlrec = (xl_running_xacts *) rec;
58
59 standby_desc_running_xacts(buf, xlrec);
60 }
61 else if (info == XLOG_INVALIDATIONS)
62 {
63 xl_invalidations *xlrec = (xl_invalidations *) rec;
64
65 standby_desc_invalidations(buf, xlrec->nmsgs, xlrec->msgs,
66 xlrec->dbId, xlrec->tsId,
67 xlrec->relcacheInitFileInval);
68 }
69}
70
71const char *
72standby_identify(uint8 info)
73{
74 const char *id = NULL;
75
76 switch (info & ~XLR_INFO_MASK)
77 {
78 case XLOG_STANDBY_LOCK:
79 id = "LOCK";
80 break;
81 case XLOG_RUNNING_XACTS:
82 id = "RUNNING_XACTS";
83 break;
84 case XLOG_INVALIDATIONS:
85 id = "INVALIDATIONS";
86 break;
87 }
88
89 return id;
90}
91
92/*
93 * This routine is used by both standby_desc and xact_desc, because
94 * transaction commits and XLOG_INVALIDATIONS messages contain invalidations;
95 * it seems pointless to duplicate the code.
96 */
97void
98standby_desc_invalidations(StringInfo buf,
99 int nmsgs, SharedInvalidationMessage *msgs,
100 Oid dbId, Oid tsId,
101 bool relcacheInitFileInval)
102{
103 int i;
104
105 if (relcacheInitFileInval)
106 appendStringInfo(buf, "; relcache init file inval dbid %u tsid %u",
107 dbId, tsId);
108
109 appendStringInfoString(buf, "; inval msgs:");
110 for (i = 0; i < nmsgs; i++)
111 {
112 SharedInvalidationMessage *msg = &msgs[i];
113
114 if (msg->id >= 0)
115 appendStringInfo(buf, " catcache %d", msg->id);
116 else if (msg->id == SHAREDINVALCATALOG_ID)
117 appendStringInfo(buf, " catalog %u", msg->cat.catId);
118 else if (msg->id == SHAREDINVALRELCACHE_ID)
119 appendStringInfo(buf, " relcache %u", msg->rc.relId);
120 /* not expected, but print something anyway */
121 else if (msg->id == SHAREDINVALSMGR_ID)
122 appendStringInfoString(buf, " smgr");
123 /* not expected, but print something anyway */
124 else if (msg->id == SHAREDINVALRELMAP_ID)
125 appendStringInfo(buf, " relmap db %u", msg->rm.dbId);
126 else if (msg->id == SHAREDINVALSNAPSHOT_ID)
127 appendStringInfo(buf, " snapshot %u", msg->sn.relId);
128 else
129 appendStringInfo(buf, " unrecognized id %d", msg->id);
130 }
131}
132