Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * gindesc.c
4 : * rmgr descriptor routines for access/transam/gin/ginxlog.c
5 : *
6 : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/access/rmgrdesc/gindesc.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "access/ginxlog.h"
18 : #include "lib/stringinfo.h"
19 :
20 : static void
21 0 : desc_recompress_leaf(StringInfo buf, ginxlogRecompressDataLeaf *insertData)
22 : {
23 : int i;
24 0 : char *walbuf = ((char *) insertData) + sizeof(ginxlogRecompressDataLeaf);
25 :
26 0 : appendStringInfo(buf, " %d segments:", (int) insertData->nactions);
27 :
28 0 : for (i = 0; i < insertData->nactions; i++)
29 : {
30 0 : uint8 a_segno = *((uint8 *) (walbuf++));
31 0 : uint8 a_action = *((uint8 *) (walbuf++));
32 0 : uint16 nitems = 0;
33 0 : int newsegsize = 0;
34 :
35 0 : if (a_action == GIN_SEGMENT_INSERT ||
36 : a_action == GIN_SEGMENT_REPLACE)
37 : {
38 0 : newsegsize = SizeOfGinPostingList((GinPostingList *) walbuf);
39 0 : walbuf += SHORTALIGN(newsegsize);
40 : }
41 :
42 0 : if (a_action == GIN_SEGMENT_ADDITEMS)
43 : {
44 0 : memcpy(&nitems, walbuf, sizeof(uint16));
45 0 : walbuf += sizeof(uint16);
46 0 : walbuf += nitems * sizeof(ItemPointerData);
47 : }
48 :
49 0 : switch (a_action)
50 : {
51 0 : case GIN_SEGMENT_ADDITEMS:
52 0 : appendStringInfo(buf, " %d (add %d items)", a_segno, nitems);
53 0 : break;
54 0 : case GIN_SEGMENT_DELETE:
55 0 : appendStringInfo(buf, " %d (delete)", a_segno);
56 0 : break;
57 0 : case GIN_SEGMENT_INSERT:
58 0 : appendStringInfo(buf, " %d (insert)", a_segno);
59 0 : break;
60 0 : case GIN_SEGMENT_REPLACE:
61 0 : appendStringInfo(buf, " %d (replace)", a_segno);
62 0 : break;
63 0 : default:
64 0 : appendStringInfo(buf, " %d unknown action %d ???", a_segno, a_action);
65 : /* cannot decode unrecognized actions further */
66 0 : return;
67 : }
68 : }
69 : }
70 :
71 : void
72 0 : gin_desc(StringInfo buf, XLogReaderState *record)
73 : {
74 0 : char *rec = XLogRecGetData(record);
75 0 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
76 :
77 0 : switch (info)
78 : {
79 0 : case XLOG_GIN_CREATE_PTREE:
80 : /* no further information */
81 0 : break;
82 0 : case XLOG_GIN_INSERT:
83 : {
84 0 : ginxlogInsert *xlrec = (ginxlogInsert *) rec;
85 :
86 0 : appendStringInfo(buf, "isdata: %c isleaf: %c",
87 0 : (xlrec->flags & GIN_INSERT_ISDATA) ? 'T' : 'F',
88 0 : (xlrec->flags & GIN_INSERT_ISLEAF) ? 'T' : 'F');
89 0 : if (!(xlrec->flags & GIN_INSERT_ISLEAF))
90 : {
91 0 : char *payload = rec + sizeof(ginxlogInsert);
92 : BlockNumber leftChildBlkno;
93 : BlockNumber rightChildBlkno;
94 :
95 0 : leftChildBlkno = BlockIdGetBlockNumber((BlockId) payload);
96 0 : payload += sizeof(BlockIdData);
97 0 : rightChildBlkno = BlockIdGetBlockNumber((BlockId) payload);
98 0 : payload += sizeof(BlockNumber);
99 0 : appendStringInfo(buf, " children: %u/%u",
100 : leftChildBlkno, rightChildBlkno);
101 : }
102 0 : if (XLogRecHasBlockImage(record, 0))
103 : {
104 0 : if (XLogRecBlockImageApply(record, 0))
105 0 : appendStringInfoString(buf, " (full page image)");
106 : else
107 0 : appendStringInfoString(buf, " (full page image, for WAL verification)");
108 : }
109 : else
110 : {
111 0 : char *payload = XLogRecGetBlockData(record, 0, NULL);
112 :
113 0 : if (!(xlrec->flags & GIN_INSERT_ISDATA))
114 0 : appendStringInfo(buf, " isdelete: %c",
115 0 : (((ginxlogInsertEntry *) payload)->isDelete) ? 'T' : 'F');
116 0 : else if (xlrec->flags & GIN_INSERT_ISLEAF)
117 0 : desc_recompress_leaf(buf, (ginxlogRecompressDataLeaf *) payload);
118 : else
119 : {
120 0 : ginxlogInsertDataInternal *insertData =
121 : (ginxlogInsertDataInternal *) payload;
122 :
123 0 : appendStringInfo(buf, " pitem: %u-%u/%u",
124 0 : PostingItemGetBlockNumber(&insertData->newitem),
125 0 : ItemPointerGetBlockNumber(&insertData->newitem.key),
126 0 : ItemPointerGetOffsetNumber(&insertData->newitem.key));
127 : }
128 : }
129 : }
130 0 : break;
131 0 : case XLOG_GIN_SPLIT:
132 : {
133 0 : ginxlogSplit *xlrec = (ginxlogSplit *) rec;
134 :
135 0 : appendStringInfo(buf, "isrootsplit: %c",
136 0 : (((ginxlogSplit *) rec)->flags & GIN_SPLIT_ROOT) ? 'T' : 'F');
137 0 : appendStringInfo(buf, " isdata: %c isleaf: %c",
138 0 : (xlrec->flags & GIN_INSERT_ISDATA) ? 'T' : 'F',
139 0 : (xlrec->flags & GIN_INSERT_ISLEAF) ? 'T' : 'F');
140 : }
141 0 : break;
142 0 : case XLOG_GIN_VACUUM_PAGE:
143 : /* no further information */
144 0 : break;
145 0 : case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
146 : {
147 0 : if (XLogRecHasBlockImage(record, 0))
148 : {
149 0 : if (XLogRecBlockImageApply(record, 0))
150 0 : appendStringInfoString(buf, " (full page image)");
151 : else
152 0 : appendStringInfoString(buf, " (full page image, for WAL verification)");
153 : }
154 : else
155 : {
156 : ginxlogVacuumDataLeafPage *xlrec =
157 0 : (ginxlogVacuumDataLeafPage *) XLogRecGetBlockData(record, 0, NULL);
158 :
159 0 : desc_recompress_leaf(buf, &xlrec->data);
160 : }
161 : }
162 0 : break;
163 0 : case XLOG_GIN_DELETE_PAGE:
164 : /* no further information */
165 0 : break;
166 0 : case XLOG_GIN_UPDATE_META_PAGE:
167 : /* no further information */
168 0 : break;
169 0 : case XLOG_GIN_INSERT_LISTPAGE:
170 : /* no further information */
171 0 : break;
172 0 : case XLOG_GIN_DELETE_LISTPAGE:
173 0 : appendStringInfo(buf, "ndeleted: %d",
174 : ((ginxlogDeleteListPages *) rec)->ndeleted);
175 0 : break;
176 : }
177 0 : }
178 :
179 : const char *
180 0 : gin_identify(uint8 info)
181 : {
182 0 : const char *id = NULL;
183 :
184 0 : switch (info & ~XLR_INFO_MASK)
185 : {
186 0 : case XLOG_GIN_CREATE_PTREE:
187 0 : id = "CREATE_PTREE";
188 0 : break;
189 0 : case XLOG_GIN_INSERT:
190 0 : id = "INSERT";
191 0 : break;
192 0 : case XLOG_GIN_SPLIT:
193 0 : id = "SPLIT";
194 0 : break;
195 0 : case XLOG_GIN_VACUUM_PAGE:
196 0 : id = "VACUUM_PAGE";
197 0 : break;
198 0 : case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
199 0 : id = "VACUUM_DATA_LEAF_PAGE";
200 0 : break;
201 0 : case XLOG_GIN_DELETE_PAGE:
202 0 : id = "DELETE_PAGE";
203 0 : break;
204 0 : case XLOG_GIN_UPDATE_META_PAGE:
205 0 : id = "UPDATE_META_PAGE";
206 0 : break;
207 0 : case XLOG_GIN_INSERT_LISTPAGE:
208 0 : id = "INSERT_LISTPAGE";
209 0 : break;
210 0 : case XLOG_GIN_DELETE_LISTPAGE:
211 0 : id = "DELETE_LISTPAGE";
212 0 : break;
213 : }
214 :
215 0 : return id;
216 : }
|