PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_waldump.h File Reference
Include dependency graph for pg_waldump.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  XLogDumpPrivate
 

Typedefs

typedef struct XLogDumpPrivate XLogDumpPrivate
 

Functions

int open_file_in_directory (const char *directory, const char *fname)
 
void init_archive_reader (XLogDumpPrivate *privateInfo, pg_compress_algorithm compression)
 
void free_archive_reader (XLogDumpPrivate *privateInfo)
 
int read_archive_wal_page (XLogDumpPrivate *privateInfo, XLogRecPtr targetPagePtr, size_t count, char *readBuff)
 
void free_archive_wal_entry (const char *fname, XLogDumpPrivate *privateInfo)
 

Variables

charTmpWalSegDir
 

Typedef Documentation

◆ XLogDumpPrivate

Function Documentation

◆ free_archive_reader()

void free_archive_reader ( XLogDumpPrivate privateInfo)
extern

Definition at line 253 of file archive_waldump.c.

254{
255 /*
256 * NB: Normally, astreamer_finalize() is called before astreamer_free() to
257 * flush any remaining buffered data or to ensure the end of the tar
258 * archive is reached. read_archive_file() may have done so. However,
259 * when decoding WAL we can stop once we hit the end LSN, so we may never
260 * have read all of the input file. In that case any remaining buffered
261 * data or unread portion of the archive can be safely ignored.
262 */
263 astreamer_free(privateInfo->archive_streamer);
264
265 /* Free any remaining hash table entries and their buffers. */
266 if (privateInfo->archive_wal_htab != NULL)
267 {
269 ArchivedWALFile *entry;
270
271 ArchivedWAL_start_iterate(privateInfo->archive_wal_htab, &iter);
272 while ((entry = ArchivedWAL_iterate(privateInfo->archive_wal_htab,
273 &iter)) != NULL)
274 {
275 if (entry->buf != NULL)
276 destroyStringInfo(entry->buf);
277 }
279 privateInfo->archive_wal_htab = NULL;
280 }
281
282 /* Free the reusable read buffer. */
283 if (privateInfo->archive_read_buf != NULL)
284 {
285 pg_free(privateInfo->archive_read_buf);
286 privateInfo->archive_read_buf = NULL;
287 }
288
289 /* Close the file. */
290 if (close(privateInfo->archive_fd) != 0)
291 pg_log_error("could not close file \"%s\": %m",
292 privateInfo->archive_name);
293}
static void astreamer_free(astreamer *streamer)
Definition astreamer.h:155
void pg_free(void *ptr)
#define close(a)
Definition win32.h:12
#define pg_log_error(...)
Definition logging.h:106
static int fb(int x)
void destroyStringInfo(StringInfo str)
Definition stringinfo.c:409
struct ArchivedWAL_hash * archive_wal_htab
Definition pg_waldump.h:59
astreamer * archive_streamer
Definition pg_waldump.h:40
char * archive_read_buf
Definition pg_waldump.h:41
char * archive_name
Definition pg_waldump.h:36

References XLogDumpPrivate::archive_fd, XLogDumpPrivate::archive_name, XLogDumpPrivate::archive_read_buf, XLogDumpPrivate::archive_streamer, XLogDumpPrivate::archive_wal_htab, astreamer_free(), ArchivedWALFile::buf, close, destroyStringInfo(), fb(), pg_free(), and pg_log_error.

Referenced by main().

◆ free_archive_wal_entry()

void free_archive_wal_entry ( const char fname,
XLogDumpPrivate privateInfo 
)
extern

Definition at line 405 of file archive_waldump.c.

406{
407 ArchivedWALFile *entry;
408 const char *oldfname;
409
410 entry = ArchivedWAL_lookup(privateInfo->archive_wal_htab, fname);
411
412 if (entry == NULL)
413 return;
414
415 /* Destroy the buffer */
416 destroyStringInfo(entry->buf);
417 entry->buf = NULL;
418
419 /* Remove temporary file if any */
420 if (entry->spilled)
421 {
422 char fpath[MAXPGPATH];
423
424 snprintf(fpath, MAXPGPATH, "%s/%s", TmpWalSegDir, fname);
425
426 if (unlink(fpath) == 0)
427 pg_log_debug("removed file \"%s\"", fpath);
428 }
429
430 /* Clear cur_file if it points to the entry being freed */
431 if (privateInfo->cur_file == entry)
432 privateInfo->cur_file = NULL;
433
434 /*
435 * ArchivedWAL_delete_item may cause other hash table entries to move.
436 * Therefore, if cur_file isn't NULL now, we have to be prepared to look
437 * that entry up again after the deletion. Fortunately, the entry's fname
438 * string won't move.
439 */
440 oldfname = privateInfo->cur_file ? privateInfo->cur_file->fname : NULL;
441
442 ArchivedWAL_delete_item(privateInfo->archive_wal_htab, entry);
443
444 if (oldfname)
445 {
446 privateInfo->cur_file = ArchivedWAL_lookup(privateInfo->archive_wal_htab,
447 oldfname);
448 /* ... it had better still be there */
449 Assert(privateInfo->cur_file != NULL);
450 }
451}
char * TmpWalSegDir
#define Assert(condition)
Definition c.h:943
#define pg_log_debug(...)
Definition logging.h:133
#define MAXPGPATH
#define snprintf
Definition port.h:260
const char * fname
struct ArchivedWALFile * cur_file
Definition pg_waldump.h:52

References XLogDumpPrivate::archive_wal_htab, Assert, ArchivedWALFile::buf, XLogDumpPrivate::cur_file, destroyStringInfo(), fb(), ArchivedWALFile::fname, MAXPGPATH, pg_log_debug, snprintf, ArchivedWALFile::spilled, and TmpWalSegDir.

Referenced by init_archive_reader(), and TarWALDumpReadPage().

◆ init_archive_reader()

void init_archive_reader ( XLogDumpPrivate privateInfo,
pg_compress_algorithm  compression 
)
extern

Definition at line 129 of file archive_waldump.c.

131{
132 int fd;
133 astreamer *streamer;
134 ArchivedWALFile *entry = NULL;
137
138 /* Open tar archive and store its file descriptor */
140 privateInfo->archive_name);
141
142 if (fd < 0)
143 pg_fatal("could not open file \"%s\"", privateInfo->archive_name);
144
145 privateInfo->archive_fd = fd;
146 privateInfo->archive_fd_eof = false;
147
148 streamer = astreamer_waldump_new(privateInfo);
149
150 /* We must first parse the tar archive. */
151 streamer = astreamer_tar_parser_new(streamer);
152
153 /* If the archive is compressed, decompress before parsing. */
154 if (compression == PG_COMPRESSION_GZIP)
155 streamer = astreamer_gzip_decompressor_new(streamer);
156 else if (compression == PG_COMPRESSION_LZ4)
157 streamer = astreamer_lz4_decompressor_new(streamer);
158 else if (compression == PG_COMPRESSION_ZSTD)
159 streamer = astreamer_zstd_decompressor_new(streamer);
160
161 privateInfo->archive_streamer = streamer;
162
163 /*
164 * Allocate a buffer for reading the archive file to begin content
165 * decoding.
166 */
169
170 /*
171 * Hash table storing WAL entries read from the archive with an arbitrary
172 * initial size.
173 */
174 privateInfo->archive_wal_htab = ArchivedWAL_create(8, NULL);
175
176 /*
177 * Read until we have at least one WAL segment with enough data to extract
178 * the WAL segment size from the long page header.
179 *
180 * We must not rely on cur_file here, because it can become NULL if a
181 * member trailer is processed during a read_archive_file() call. Instead,
182 * scan the hash table after each read to find any entry with sufficient
183 * data.
184 */
185 while (entry == NULL)
186 {
187 if (!read_archive_file(privateInfo))
188 pg_fatal("could not find WAL in archive \"%s\"",
189 privateInfo->archive_name);
190
191 ArchivedWAL_start_iterate(privateInfo->archive_wal_htab, &iter);
192 while ((entry = ArchivedWAL_iterate(privateInfo->archive_wal_htab,
193 &iter)) != NULL)
194 {
195 if (entry->read_len >= sizeof(XLogLongPageHeaderData))
196 break;
197 }
198 }
199
200 /* Extract the WAL segment size from the long page header */
202
203 if (!IsValidWalSegSize(longhdr->xlp_seg_size))
204 {
205 pg_log_error(ngettext("invalid WAL segment size in WAL file from archive \"%s\" (%d byte)",
206 "invalid WAL segment size in WAL file from archive \"%s\" (%d bytes)",
207 longhdr->xlp_seg_size),
208 privateInfo->archive_name, longhdr->xlp_seg_size);
209 pg_log_error_detail("The WAL segment size must be a power of two between 1 MB and 1 GB.");
210 exit(1);
211 }
212
213 privateInfo->segsize = longhdr->xlp_seg_size;
214
215 /*
216 * With the WAL segment size available, we can now initialize the
217 * dependent start and end segment numbers.
218 */
219 Assert(!XLogRecPtrIsInvalid(privateInfo->startptr));
220 XLByteToSeg(privateInfo->startptr, privateInfo->start_segno,
221 privateInfo->segsize);
222
223 if (!XLogRecPtrIsInvalid(privateInfo->endptr))
224 XLByteToSeg(privateInfo->endptr, privateInfo->end_segno,
225 privateInfo->segsize);
226
227 /*
228 * Now that we have initialized the filtering parameters (start_segno and
229 * end_segno), we can discard any already-loaded WAL hash table entries
230 * for segments we don't actually need. Subsequent WAL will be filtered
231 * automatically by the archive streamer using the updated start_segno and
232 * end_segno values.
233 */
234 ArchivedWAL_start_iterate(privateInfo->archive_wal_htab, &iter);
235 while ((entry = ArchivedWAL_iterate(privateInfo->archive_wal_htab,
236 &iter)) != NULL)
237 {
238 XLogSegNo segno;
239 TimeLineID timeline;
240
241 XLogFromFileName(entry->fname, &timeline, &segno, privateInfo->segsize);
242 if (privateInfo->timeline != timeline ||
243 privateInfo->start_segno > segno ||
244 privateInfo->end_segno < segno)
245 free_archive_wal_entry(entry->fname, privateInfo);
246 }
247}
static astreamer * astreamer_waldump_new(XLogDumpPrivate *privateInfo)
#define READ_CHUNK_SIZE
static bool read_archive_file(XLogDumpPrivate *privateInfo)
void free_archive_wal_entry(const char *fname, XLogDumpPrivate *privateInfo)
astreamer * astreamer_gzip_decompressor_new(astreamer *next)
astreamer * astreamer_lz4_decompressor_new(astreamer *next)
astreamer * astreamer_tar_parser_new(astreamer *next)
astreamer * astreamer_zstd_decompressor_new(astreamer *next)
#define ngettext(s, p, n)
Definition c.h:1270
@ PG_COMPRESSION_GZIP
Definition compression.h:24
@ PG_COMPRESSION_LZ4
Definition compression.h:25
@ PG_COMPRESSION_ZSTD
Definition compression.h:26
void * pg_malloc(size_t size)
Definition fe_memutils.c:47
#define pg_log_error_detail(...)
Definition logging.h:109
#define pg_fatal(...)
int open_file_in_directory(const char *directory, const char *fname)
Definition pg_waldump.c:182
static int fd(const char *x, int i)
XLogSegNo start_segno
Definition pg_waldump.h:67
XLogRecPtr endptr
Definition pg_waldump.h:30
XLogRecPtr startptr
Definition pg_waldump.h:29
TimeLineID timeline
Definition pg_waldump.h:27
char * archive_dir
Definition pg_waldump.h:35
XLogSegNo end_segno
Definition pg_waldump.h:68
size_t archive_read_buf_size
Definition pg_waldump.h:42
#define IsValidWalSegSize(size)
XLogLongPageHeaderData * XLogLongPageHeader
static void XLogFromFileName(const char *fname, TimeLineID *tli, XLogSegNo *logSegNo, int wal_segsz_bytes)
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)
#define XLogRecPtrIsInvalid(r)
Definition xlogdefs.h:30
uint32 TimeLineID
Definition xlogdefs.h:63
uint64 XLogSegNo
Definition xlogdefs.h:52

References XLogDumpPrivate::archive_dir, XLogDumpPrivate::archive_fd, XLogDumpPrivate::archive_fd_eof, XLogDumpPrivate::archive_name, XLogDumpPrivate::archive_read_buf, XLogDumpPrivate::archive_read_buf_size, XLogDumpPrivate::archive_streamer, XLogDumpPrivate::archive_wal_htab, Assert, astreamer_gzip_decompressor_new(), astreamer_lz4_decompressor_new(), astreamer_tar_parser_new(), astreamer_waldump_new(), astreamer_zstd_decompressor_new(), ArchivedWALFile::buf, StringInfoData::data, XLogDumpPrivate::end_segno, XLogDumpPrivate::endptr, fb(), fd(), ArchivedWALFile::fname, free_archive_wal_entry(), IsValidWalSegSize, ngettext, open_file_in_directory(), PG_COMPRESSION_GZIP, PG_COMPRESSION_LZ4, PG_COMPRESSION_ZSTD, pg_fatal, pg_log_error, pg_log_error_detail, pg_malloc(), read_archive_file(), READ_CHUNK_SIZE, ArchivedWALFile::read_len, XLogDumpPrivate::segsize, XLogDumpPrivate::start_segno, XLogDumpPrivate::startptr, XLogDumpPrivate::timeline, XLByteToSeg, XLogFromFileName(), and XLogRecPtrIsInvalid.

Referenced by main().

◆ open_file_in_directory()

int open_file_in_directory ( const char directory,
const char fname 
)
extern

Definition at line 182 of file pg_waldump.c.

183{
184 int fd = -1;
185 char fpath[MAXPGPATH];
186
188
189 snprintf(fpath, MAXPGPATH, "%s/%s", directory, fname);
190 fd = open(fpath, O_RDONLY | PG_BINARY, 0);
191
192 if (fd < 0 && errno != ENOENT)
193 pg_fatal("could not open file \"%s\": %m", fname);
194 return fd;
195}
#define PG_BINARY
Definition c.h:1374
static const char * directory
Definition zic.c:648

References Assert, directory, fb(), fd(), MAXPGPATH, PG_BINARY, pg_fatal, and snprintf.

Referenced by init_archive_reader(), main(), search_directory(), TarWALDumpReadPage(), and WALDumpOpenSegment().

◆ read_archive_wal_page()

int read_archive_wal_page ( XLogDumpPrivate privateInfo,
XLogRecPtr  targetPagePtr,
size_t  count,
char readBuff 
)
extern

Definition at line 301 of file archive_waldump.c.

303{
304 char *p = readBuff;
305 size_t nbytes = count;
307 int segsize = privateInfo->segsize;
308 XLogSegNo segno;
309 char fname[MAXFNAMELEN];
310 ArchivedWALFile *entry;
311
312 /* Identify the segment and locate its entry in the archive hash */
313 XLByteToSeg(targetPagePtr, segno, segsize);
314 XLogFileName(fname, privateInfo->timeline, segno, segsize);
315 entry = get_archive_wal_entry(fname, privateInfo);
316 Assert(!entry->spilled);
317
318 while (nbytes > 0)
319 {
320 char *buf = entry->buf->data;
321 int bufLen = entry->buf->len;
324
325 /*
326 * Calculate the LSN range currently residing in the buffer.
327 *
328 * read_len tracks total bytes received for this segment, so endPtr is
329 * the LSN just past the last buffered byte, and startPtr is the LSN
330 * of the first buffered byte.
331 */
332 XLogSegNoOffsetToRecPtr(segno, entry->read_len, segsize, endPtr);
334
335 /*
336 * Copy the requested WAL record if it exists in the buffer.
337 */
338 if (bufLen > 0 && startPtr <= recptr && recptr < endPtr)
339 {
340 int copyBytes;
341 int offset = recptr - startPtr;
342
343 /*
344 * Given startPtr <= recptr < endPtr and a total buffer size
345 * 'bufLen', the offset (recptr - startPtr) will always be less
346 * than 'bufLen'.
347 */
348 Assert(offset < bufLen);
349
350 copyBytes = Min(nbytes, bufLen - offset);
351 memcpy(p, buf + offset, copyBytes);
352
353 /* Update state for read */
354 recptr += copyBytes;
355 nbytes -= copyBytes;
356 p += copyBytes;
357 }
358 else
359 {
360 /*
361 * We evidently need to fetch more data. Raise an error if the
362 * archive streamer has moved past our segment (meaning the WAL
363 * file in the archive is shorter than expected) or if reading the
364 * archive reached EOF.
365 */
366 if (privateInfo->cur_file != entry)
367 pg_fatal("WAL segment \"%s\" in archive \"%s\" is too short: read %zu of %zu bytes",
368 fname, privateInfo->archive_name,
369 (count - nbytes), count);
370 if (!read_archive_file(privateInfo))
371 pg_fatal("unexpected end of archive \"%s\" while reading \"%s\": read %zu of %zu bytes",
372 privateInfo->archive_name, fname,
373 (count - nbytes), count);
374
375 /*
376 * Loading more data may have moved hash table entries, so we must
377 * re-look-up the one we are reading from.
378 */
379 entry = ArchivedWAL_lookup(privateInfo->archive_wal_htab, fname);
380 /* ... it had better still be there */
381 Assert(entry != NULL);
382 }
383 }
384
385 /*
386 * Should have successfully read all the requested bytes or reported a
387 * failure before this point.
388 */
389 Assert(nbytes == 0);
390
391 /*
392 * Return count unchanged; the caller expects this convention, matching
393 * the routine that reads WAL pages from physical files.
394 */
395 return count;
396}
static ArchivedWALFile * get_archive_wal_entry(const char *fname, XLogDumpPrivate *privateInfo)
#define Min(x, y)
Definition c.h:1091
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest)
#define MAXFNAMELEN
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
uint64 XLogRecPtr
Definition xlogdefs.h:21

References XLogDumpPrivate::archive_name, XLogDumpPrivate::archive_wal_htab, Assert, buf, ArchivedWALFile::buf, XLogDumpPrivate::cur_file, StringInfoData::data, fb(), get_archive_wal_entry(), StringInfoData::len, MAXFNAMELEN, memcpy(), Min, pg_fatal, read_archive_file(), ArchivedWALFile::read_len, XLogDumpPrivate::segsize, ArchivedWALFile::spilled, XLogDumpPrivate::timeline, XLByteToSeg, XLogFileName(), and XLogSegNoOffsetToRecPtr.

Referenced by TarWALDumpReadPage().

Variable Documentation

◆ TmpWalSegDir