PostgreSQL Source Code git master
pg_walsummary.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_walsummary.c
4 * Prints the contents of WAL summary files.
5 *
6 * Copyright (c) 2017-2025, PostgreSQL Global Development Group
7 *
8 * IDENTIFICATION
9 * src/bin/pg_walsummary/pg_walsummary.c
10 *
11 *-------------------------------------------------------------------------
12 */
13#include "postgres_fe.h"
14
15#include <fcntl.h>
16#include <limits.h>
17
18#include "common/blkreftable.h"
19#include "common/int.h"
20#include "common/logging.h"
22#include "getopt_long.h"
23
24typedef struct ws_options
25{
27 bool quiet;
29
30typedef struct ws_file_info
31{
32 int fd;
33 char *filename;
35
37static unsigned block_buffer_size = 512; /* Initial size. */
38
39static void dump_one_relation(ws_options *opt, RelFileLocator *rlocator,
40 ForkNumber forknum, BlockNumber limit_block,
41 BlockRefTableReader *reader);
42static void help(const char *progname);
43static int compare_block_numbers(const void *a, const void *b);
44static int walsummary_read_callback(void *callback_arg, void *data,
45 int length);
46static void walsummary_error_callback(void *callback_arg, char *fmt,...) pg_attribute_printf(2, 3);
47
48/*
49 * Main program.
50 */
51int
52main(int argc, char *argv[])
53{
54 static struct option long_options[] = {
55 {"individual", no_argument, NULL, 'i'},
56 {"quiet", no_argument, NULL, 'q'},
57 {NULL, 0, NULL, 0}
58 };
59
60 const char *progname;
61 int optindex;
62 int c;
63 ws_options opt;
64
65 memset(&opt, 0, sizeof(ws_options));
66
67 pg_logging_init(argv[0]);
68 progname = get_progname(argv[0]);
69 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_walsummary"));
71
72 /* process command-line options */
73 while ((c = getopt_long(argc, argv, "iq",
74 long_options, &optindex)) != -1)
75 {
76 switch (c)
77 {
78 case 'i':
79 opt.individual = true;
80 break;
81 case 'q':
82 opt.quiet = true;
83 break;
84 default:
85 /* getopt_long already emitted a complaint */
86 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
87 exit(1);
88 }
89 }
90
91 if (optind >= argc)
92 {
93 pg_log_error("no input files specified");
94 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
95 exit(1);
96 }
97
98 while (optind < argc)
99 {
100 ws_file_info ws;
101 BlockRefTableReader *reader;
102 RelFileLocator rlocator;
103 ForkNumber forknum;
104 BlockNumber limit_block;
105
106 ws.filename = argv[optind++];
107 if ((ws.fd = open(ws.filename, O_RDONLY | PG_BINARY, 0)) < 0)
108 pg_fatal("could not open file \"%s\": %m", ws.filename);
109
111 ws.filename,
113 while (BlockRefTableReaderNextRelation(reader, &rlocator, &forknum,
114 &limit_block))
115 dump_one_relation(&opt, &rlocator, forknum, limit_block, reader);
116
118 close(ws.fd);
119 }
120
121 exit(0);
122}
123
124/*
125 * Dump details for one relation.
126 */
127static void
129 ForkNumber forknum, BlockNumber limit_block,
130 BlockRefTableReader *reader)
131{
132 unsigned i = 0;
133 unsigned nblocks;
134 BlockNumber startblock = InvalidBlockNumber;
136
137 /* Dump limit block, if any. */
138 if (limit_block != InvalidBlockNumber)
139 printf("TS %u, DB %u, REL %u, FORK %s: limit %u\n",
140 rlocator->spcOid, rlocator->dbOid, rlocator->relNumber,
141 forkNames[forknum], limit_block);
142
143 /* If we haven't allocated a block buffer yet, do that now. */
144 if (block_buffer == NULL)
146
147 /* Try to fill the block buffer. */
148 nblocks = BlockRefTableReaderGetBlocks(reader,
151
152 /* If we filled the block buffer completely, we must enlarge it. */
153 while (nblocks >= block_buffer_size)
154 {
155 unsigned new_size;
156
157 /* Double the size, being careful about overflow. */
158 new_size = block_buffer_size * 2;
159 if (new_size < block_buffer_size)
160 new_size = PG_UINT32_MAX;
162
163 /* Try to fill the newly-allocated space. */
164 nblocks +=
167 new_size - block_buffer_size);
168
169 /* Save the new size for later calls. */
170 block_buffer_size = new_size;
171 }
172
173 /* If we don't need to produce any output, skip the rest of this. */
174 if (opt->quiet)
175 return;
176
177 /*
178 * Sort the returned block numbers. If the block reference table was using
179 * the bitmap representation for a given chunk, the block numbers in that
180 * chunk will already be sorted, but when the array-of-offsets
181 * representation is used, we can receive block numbers here out of order.
182 */
184
185 /* Dump block references. */
186 while (i < nblocks)
187 {
188 /*
189 * Find the next range of blocks to print, but if --individual was
190 * specified, then consider each block a separate range.
191 */
192 startblock = endblock = block_buffer[i++];
193 if (!opt->individual)
194 {
195 while (i < nblocks && block_buffer[i] == endblock + 1)
196 {
197 endblock++;
198 i++;
199 }
200 }
201
202 /* Format this range of block numbers as a string. */
203 if (startblock == endblock)
204 printf("TS %u, DB %u, REL %u, FORK %s: block %u\n",
205 rlocator->spcOid, rlocator->dbOid, rlocator->relNumber,
206 forkNames[forknum], startblock);
207 else
208 printf("TS %u, DB %u, REL %u, FORK %s: blocks %u..%u\n",
209 rlocator->spcOid, rlocator->dbOid, rlocator->relNumber,
210 forkNames[forknum], startblock, endblock);
211 }
212}
213
214/*
215 * Quicksort comparator for block numbers.
216 */
217static int
218compare_block_numbers(const void *a, const void *b)
219{
220 BlockNumber aa = *(BlockNumber *) a;
221 BlockNumber bb = *(BlockNumber *) b;
222
223 return pg_cmp_u32(aa, bb);
224}
225
226/*
227 * Error callback.
228 */
229void
230walsummary_error_callback(void *callback_arg, char *fmt,...)
231{
232 va_list ap;
233
234 va_start(ap, fmt);
236 va_end(ap);
237
238 exit(1);
239}
240
241/*
242 * Read callback.
243 */
244int
245walsummary_read_callback(void *callback_arg, void *data, int length)
246{
247 ws_file_info *ws = callback_arg;
248 int rc;
249
250 if ((rc = read(ws->fd, data, length)) < 0)
251 pg_fatal("could not read file \"%s\": %m", ws->filename);
252
253 return rc;
254}
255
256/*
257 * help
258 *
259 * Prints help page for the program
260 *
261 * progname: the name of the executed program, such as "pg_walsummary"
262 */
263static void
264help(const char *progname)
265{
266 printf(_("%s prints the contents of a WAL summary file.\n\n"), progname);
267 printf(_("Usage:\n"));
268 printf(_(" %s [OPTION]... FILE...\n"), progname);
269 printf(_("\nOptions:\n"));
270 printf(_(" -i, --individual list block numbers individually, not as ranges\n"));
271 printf(_(" -q, --quiet don't print anything, just parse the files\n"));
272 printf(_(" -V, --version output version information, then exit\n"));
273 printf(_(" -?, --help show this help, then exit\n"));
274
275 printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
276 printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
277}
bool BlockRefTableReaderNextRelation(BlockRefTableReader *reader, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *limit_block)
Definition: blkreftable.c:613
BlockRefTableReader * CreateBlockRefTableReader(io_callback_fn read_callback, void *read_callback_arg, char *error_filename, report_error_fn error_callback, void *error_callback_arg)
Definition: blkreftable.c:577
unsigned BlockRefTableReaderGetBlocks(BlockRefTableReader *reader, BlockNumber *blocks, int nblocks)
Definition: blkreftable.c:689
void DestroyBlockRefTableReader(BlockRefTableReader *reader)
Definition: blkreftable.c:773
uint32 BlockNumber
Definition: block.h:31
#define InvalidBlockNumber
Definition: block.h:33
#define PG_UINT32_MAX
Definition: c.h:547
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1171
#define PG_BINARY
Definition: c.h:1230
#define pg_attribute_printf(f, a)
Definition: c.h:213
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:429
#define _(x)
Definition: elog.c:90
#define repalloc_array(pointer, type, count)
Definition: fe_memutils.h:78
#define palloc_array(type, count)
Definition: fe_memutils.h:76
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:60
#define no_argument
Definition: getopt_long.h:25
static int pg_cmp_u32(uint32 a, uint32 b)
Definition: int.h:652
#define close(a)
Definition: win32.h:12
#define read(a, b, c)
Definition: win32.h:13
int b
Definition: isn.c:69
int a
Definition: isn.c:68
int i
Definition: isn.c:72
static void const char * fmt
va_end(args)
exit(1)
va_start(args, fmt)
void pg_logging_init(const char *argv0)
Definition: logging.c:83
void pg_log_generic_v(enum pg_log_level level, enum pg_log_part part, const char *pg_restrict fmt, va_list ap)
Definition: logging.c:219
#define pg_log_error(...)
Definition: logging.h:106
#define pg_log_error_hint(...)
Definition: logging.h:112
@ PG_LOG_PRIMARY
Definition: logging.h:67
@ PG_LOG_ERROR
Definition: logging.h:43
const char * progname
Definition: main.c:44
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
Definition: option_utils.c:24
#define pg_fatal(...)
const void * data
PGDLLIMPORT int optind
Definition: getopt.c:51
static void walsummary_error_callback(void *callback_arg, char *fmt,...) pg_attribute_printf(2
struct ws_file_info ws_file_info
static void help(const char *progname)
static void dump_one_relation(ws_options *opt, RelFileLocator *rlocator, ForkNumber forknum, BlockNumber limit_block, BlockRefTableReader *reader)
static int compare_block_numbers(const void *a, const void *b)
static void int main(int argc, char *argv[])
Definition: pg_walsummary.c:52
static int walsummary_read_callback(void *callback_arg, void *data, int length)
static BlockNumber * block_buffer
Definition: pg_walsummary.c:36
static unsigned block_buffer_size
Definition: pg_walsummary.c:37
struct ws_options ws_options
const char * get_progname(const char *argv0)
Definition: path.c:575
#define qsort(a, b, c, d)
Definition: port.h:474
#define printf(...)
Definition: port.h:244
char * c
const char *const forkNames[]
Definition: relpath.c:33
ForkNumber
Definition: relpath.h:56
RelFileNumber relNumber
char * filename
Definition: pg_walsummary.c:33
bool individual
Definition: pg_walsummary.c:26