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-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/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 6192 : gin_desc(StringInfo buf, XLogReaderState *record)
73 : {
74 6192 : char *rec = XLogRecGetData(record);
75 6192 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
76 :
77 6192 : switch (info)
78 : {
79 0 : case XLOG_GIN_CREATE_PTREE:
80 : /* no further information */
81 0 : break;
82 72 : case XLOG_GIN_INSERT:
83 : {
84 72 : ginxlogInsert *xlrec = (ginxlogInsert *) rec;
85 :
86 144 : appendStringInfo(buf, "isdata: %c isleaf: %c",
87 72 : (xlrec->flags & GIN_INSERT_ISDATA) ? 'T' : 'F',
88 72 : (xlrec->flags & GIN_INSERT_ISLEAF) ? 'T' : 'F');
89 72 : 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 72 : if (!XLogRecHasBlockImage(record, 0))
103 : {
104 72 : char *payload = XLogRecGetBlockData(record, 0, NULL);
105 :
106 72 : if (!(xlrec->flags & GIN_INSERT_ISDATA))
107 72 : appendStringInfo(buf, " isdelete: %c",
108 72 : (((ginxlogInsertEntry *) payload)->isDelete) ? 'T' : 'F');
109 0 : else if (xlrec->flags & GIN_INSERT_ISLEAF)
110 0 : desc_recompress_leaf(buf, (ginxlogRecompressDataLeaf *) payload);
111 : else
112 : {
113 0 : ginxlogInsertDataInternal *insertData =
114 : (ginxlogInsertDataInternal *) payload;
115 :
116 0 : appendStringInfo(buf, " pitem: %u-%u/%u",
117 0 : PostingItemGetBlockNumber(&insertData->newitem),
118 0 : ItemPointerGetBlockNumber(&insertData->newitem.key),
119 0 : ItemPointerGetOffsetNumber(&insertData->newitem.key));
120 : }
121 : }
122 : }
123 72 : break;
124 0 : case XLOG_GIN_SPLIT:
125 : {
126 0 : ginxlogSplit *xlrec = (ginxlogSplit *) rec;
127 :
128 0 : appendStringInfo(buf, "isrootsplit: %c",
129 0 : (((ginxlogSplit *) rec)->flags & GIN_SPLIT_ROOT) ? 'T' : 'F');
130 0 : appendStringInfo(buf, " isdata: %c isleaf: %c",
131 0 : (xlrec->flags & GIN_INSERT_ISDATA) ? 'T' : 'F',
132 0 : (xlrec->flags & GIN_INSERT_ISLEAF) ? 'T' : 'F');
133 0 : if (xlrec->leftChildBlkno != InvalidBlockNumber)
134 0 : appendStringInfo(buf, " children: %u/%u",
135 : xlrec->leftChildBlkno, xlrec->rightChildBlkno);
136 : }
137 0 : break;
138 0 : case XLOG_GIN_VACUUM_PAGE:
139 : /* no further information */
140 0 : break;
141 0 : case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
142 : {
143 0 : if (!XLogRecHasBlockImage(record, 0))
144 : {
145 : ginxlogVacuumDataLeafPage *xlrec =
146 0 : (ginxlogVacuumDataLeafPage *) XLogRecGetBlockData(record, 0, NULL);
147 :
148 0 : desc_recompress_leaf(buf, &xlrec->data);
149 : }
150 : }
151 0 : break;
152 0 : case XLOG_GIN_DELETE_PAGE:
153 : /* no further information */
154 0 : break;
155 6012 : case XLOG_GIN_UPDATE_META_PAGE:
156 : {
157 6012 : ginxlogUpdateMeta *xlrec = (ginxlogUpdateMeta *) rec;
158 :
159 6012 : appendStringInfo(buf, "ntuples: %d", xlrec->ntuples);
160 6012 : if (xlrec->prevTail != InvalidBlockNumber)
161 84 : appendStringInfo(buf, " prevTail: %u",
162 : xlrec->prevTail);
163 6012 : if (xlrec->newRightlink != InvalidBlockNumber)
164 84 : appendStringInfo(buf, " newRightLink: %u",
165 : xlrec->newRightlink);
166 : }
167 6012 : break;
168 96 : case XLOG_GIN_INSERT_LISTPAGE:
169 : {
170 96 : ginxlogInsertListPage *xlrec = (ginxlogInsertListPage *) rec;
171 :
172 96 : appendStringInfo(buf, "ntuples: %d", xlrec->ntuples);
173 96 : if (xlrec->rightlink != InvalidBlockNumber)
174 0 : appendStringInfo(buf, " rightlink: %u",
175 : xlrec->rightlink);
176 : }
177 96 : break;
178 12 : case XLOG_GIN_DELETE_LISTPAGE:
179 12 : appendStringInfo(buf, "ndeleted: %d",
180 : ((ginxlogDeleteListPages *) rec)->ndeleted);
181 12 : break;
182 : }
183 6192 : }
184 :
185 : const char *
186 6200 : gin_identify(uint8 info)
187 : {
188 6200 : const char *id = NULL;
189 :
190 6200 : switch (info & ~XLR_INFO_MASK)
191 : {
192 0 : case XLOG_GIN_CREATE_PTREE:
193 0 : id = "CREATE_PTREE";
194 0 : break;
195 74 : case XLOG_GIN_INSERT:
196 74 : id = "INSERT";
197 74 : break;
198 0 : case XLOG_GIN_SPLIT:
199 0 : id = "SPLIT";
200 0 : break;
201 0 : case XLOG_GIN_VACUUM_PAGE:
202 0 : id = "VACUUM_PAGE";
203 0 : break;
204 0 : case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
205 0 : id = "VACUUM_DATA_LEAF_PAGE";
206 0 : break;
207 0 : case XLOG_GIN_DELETE_PAGE:
208 0 : id = "DELETE_PAGE";
209 0 : break;
210 6014 : case XLOG_GIN_UPDATE_META_PAGE:
211 6014 : id = "UPDATE_META_PAGE";
212 6014 : break;
213 98 : case XLOG_GIN_INSERT_LISTPAGE:
214 98 : id = "INSERT_LISTPAGE";
215 98 : break;
216 14 : case XLOG_GIN_DELETE_LISTPAGE:
217 14 : id = "DELETE_LISTPAGE";
218 14 : break;
219 : }
220 :
221 6200 : return id;
222 : }
|