/src/postgres/src/backend/access/rmgrdesc/standbydesc.c
Line | Count | Source |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * standbydesc.c |
4 | | * rmgr descriptor routines for storage/ipc/standby.c |
5 | | * |
6 | | * Portions Copyright (c) 1996-2025, 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 | | |
19 | | static void |
20 | | standby_desc_running_xacts(StringInfo buf, xl_running_xacts *xlrec) |
21 | 0 | { |
22 | 0 | int i; |
23 | |
|
24 | 0 | appendStringInfo(buf, "nextXid %u latestCompletedXid %u oldestRunningXid %u", |
25 | 0 | xlrec->nextXid, |
26 | 0 | xlrec->latestCompletedXid, |
27 | 0 | xlrec->oldestRunningXid); |
28 | 0 | if (xlrec->xcnt > 0) |
29 | 0 | { |
30 | 0 | appendStringInfo(buf, "; %d xacts:", xlrec->xcnt); |
31 | 0 | for (i = 0; i < xlrec->xcnt; i++) |
32 | 0 | appendStringInfo(buf, " %u", xlrec->xids[i]); |
33 | 0 | } |
34 | |
|
35 | 0 | if (xlrec->subxid_overflow) |
36 | 0 | appendStringInfoString(buf, "; subxid overflowed"); |
37 | |
|
38 | 0 | if (xlrec->subxcnt > 0) |
39 | 0 | { |
40 | 0 | appendStringInfo(buf, "; %d subxacts:", xlrec->subxcnt); |
41 | 0 | for (i = 0; i < xlrec->subxcnt; i++) |
42 | 0 | appendStringInfo(buf, " %u", xlrec->xids[xlrec->xcnt + i]); |
43 | 0 | } |
44 | 0 | } |
45 | | |
46 | | void |
47 | | standby_desc(StringInfo buf, XLogReaderState *record) |
48 | 0 | { |
49 | 0 | char *rec = XLogRecGetData(record); |
50 | 0 | uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; |
51 | |
|
52 | 0 | if (info == XLOG_STANDBY_LOCK) |
53 | 0 | { |
54 | 0 | xl_standby_locks *xlrec = (xl_standby_locks *) rec; |
55 | 0 | int i; |
56 | |
|
57 | 0 | for (i = 0; i < xlrec->nlocks; i++) |
58 | 0 | appendStringInfo(buf, "xid %u db %u rel %u ", |
59 | 0 | xlrec->locks[i].xid, xlrec->locks[i].dbOid, |
60 | 0 | xlrec->locks[i].relOid); |
61 | 0 | } |
62 | 0 | else if (info == XLOG_RUNNING_XACTS) |
63 | 0 | { |
64 | 0 | xl_running_xacts *xlrec = (xl_running_xacts *) rec; |
65 | |
|
66 | 0 | standby_desc_running_xacts(buf, xlrec); |
67 | 0 | } |
68 | 0 | else if (info == XLOG_INVALIDATIONS) |
69 | 0 | { |
70 | 0 | xl_invalidations *xlrec = (xl_invalidations *) rec; |
71 | |
|
72 | 0 | standby_desc_invalidations(buf, xlrec->nmsgs, xlrec->msgs, |
73 | 0 | xlrec->dbId, xlrec->tsId, |
74 | 0 | xlrec->relcacheInitFileInval); |
75 | 0 | } |
76 | 0 | } |
77 | | |
78 | | const char * |
79 | | standby_identify(uint8 info) |
80 | 0 | { |
81 | 0 | const char *id = NULL; |
82 | |
|
83 | 0 | switch (info & ~XLR_INFO_MASK) |
84 | 0 | { |
85 | 0 | case XLOG_STANDBY_LOCK: |
86 | 0 | id = "LOCK"; |
87 | 0 | break; |
88 | 0 | case XLOG_RUNNING_XACTS: |
89 | 0 | id = "RUNNING_XACTS"; |
90 | 0 | break; |
91 | 0 | case XLOG_INVALIDATIONS: |
92 | 0 | id = "INVALIDATIONS"; |
93 | 0 | break; |
94 | 0 | } |
95 | | |
96 | 0 | return id; |
97 | 0 | } |
98 | | |
99 | | /* also used by non-standby records having analogous invalidation fields */ |
100 | | void |
101 | | standby_desc_invalidations(StringInfo buf, |
102 | | int nmsgs, SharedInvalidationMessage *msgs, |
103 | | Oid dbId, Oid tsId, |
104 | | bool relcacheInitFileInval) |
105 | 0 | { |
106 | 0 | int i; |
107 | | |
108 | | /* Do nothing if there are no invalidation messages */ |
109 | 0 | if (nmsgs <= 0) |
110 | 0 | return; |
111 | | |
112 | 0 | if (relcacheInitFileInval) |
113 | 0 | appendStringInfo(buf, "; relcache init file inval dbid %u tsid %u", |
114 | 0 | dbId, tsId); |
115 | |
|
116 | 0 | appendStringInfoString(buf, "; inval msgs:"); |
117 | 0 | for (i = 0; i < nmsgs; i++) |
118 | 0 | { |
119 | 0 | SharedInvalidationMessage *msg = &msgs[i]; |
120 | |
|
121 | 0 | if (msg->id >= 0) |
122 | 0 | appendStringInfo(buf, " catcache %d", msg->id); |
123 | 0 | else if (msg->id == SHAREDINVALCATALOG_ID) |
124 | 0 | appendStringInfo(buf, " catalog %u", msg->cat.catId); |
125 | 0 | else if (msg->id == SHAREDINVALRELCACHE_ID) |
126 | 0 | appendStringInfo(buf, " relcache %u", msg->rc.relId); |
127 | | /* not expected, but print something anyway */ |
128 | 0 | else if (msg->id == SHAREDINVALSMGR_ID) |
129 | 0 | appendStringInfoString(buf, " smgr"); |
130 | | /* not expected, but print something anyway */ |
131 | 0 | else if (msg->id == SHAREDINVALRELMAP_ID) |
132 | 0 | appendStringInfo(buf, " relmap db %u", msg->rm.dbId); |
133 | 0 | else if (msg->id == SHAREDINVALSNAPSHOT_ID) |
134 | 0 | appendStringInfo(buf, " snapshot %u", msg->sn.relId); |
135 | 0 | else if (msg->id == SHAREDINVALRELSYNC_ID) |
136 | 0 | appendStringInfo(buf, " relsync %u", msg->rs.relid); |
137 | 0 | else |
138 | 0 | appendStringInfo(buf, " unrecognized id %d", msg->id); |
139 | 0 | } |
140 | 0 | } |