2013-02-22 20:46:24 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
2017-02-09 22:23:46 +01:00
|
|
|
* pg_waldump.c - decode and display WAL
|
2013-02-22 20:46:24 +01:00
|
|
|
*
|
2020-01-01 18:21:45 +01:00
|
|
|
* Copyright (c) 2013-2020, PostgreSQL Global Development Group
|
2013-02-22 20:46:24 +01:00
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2017-02-09 22:23:46 +01:00
|
|
|
* src/bin/pg_waldump/pg_waldump.c
|
2013-02-22 20:46:24 +01:00
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define FRONTEND 1
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include <dirent.h>
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
#include <sys/stat.h>
|
2013-02-22 20:46:24 +01:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2019-11-25 03:38:57 +01:00
|
|
|
#include "access/transam.h"
|
2019-10-23 06:08:53 +02:00
|
|
|
#include "access/xlog_internal.h"
|
2013-02-22 20:46:24 +01:00
|
|
|
#include "access/xlogreader.h"
|
2014-11-06 12:52:08 +01:00
|
|
|
#include "access/xlogrecord.h"
|
2013-02-22 20:46:24 +01:00
|
|
|
#include "common/fe_memutils.h"
|
2019-05-14 20:19:49 +02:00
|
|
|
#include "common/logging.h"
|
2013-02-22 20:46:24 +01:00
|
|
|
#include "getopt_long.h"
|
|
|
|
#include "rmgrdesc.h"
|
|
|
|
|
|
|
|
static const char *progname;
|
|
|
|
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
static int WalSegSz;
|
|
|
|
|
2013-02-22 20:46:24 +01:00
|
|
|
typedef struct XLogDumpPrivate
|
|
|
|
{
|
|
|
|
TimeLineID timeline;
|
|
|
|
XLogRecPtr startptr;
|
|
|
|
XLogRecPtr endptr;
|
2014-03-26 12:48:20 +01:00
|
|
|
bool endptr_reached;
|
2013-02-22 20:46:24 +01:00
|
|
|
} XLogDumpPrivate;
|
|
|
|
|
|
|
|
typedef struct XLogDumpConfig
|
|
|
|
{
|
|
|
|
/* display options */
|
|
|
|
bool bkp_details;
|
|
|
|
int stop_after_records;
|
|
|
|
int already_displayed_records;
|
2014-03-26 12:48:20 +01:00
|
|
|
bool follow;
|
2014-09-19 16:33:16 +02:00
|
|
|
bool stats;
|
|
|
|
bool stats_per_record;
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
/* filter options */
|
|
|
|
int filter_by_rmgr;
|
|
|
|
TransactionId filter_by_xid;
|
2013-02-22 21:03:22 +01:00
|
|
|
bool filter_by_xid_enabled;
|
2013-02-22 20:46:24 +01:00
|
|
|
} XLogDumpConfig;
|
|
|
|
|
2014-09-19 16:33:16 +02:00
|
|
|
typedef struct Stats
|
|
|
|
{
|
|
|
|
uint64 count;
|
|
|
|
uint64 rec_len;
|
|
|
|
uint64 fpi_len;
|
|
|
|
} Stats;
|
|
|
|
|
|
|
|
#define MAX_XLINFO_TYPES 16
|
|
|
|
|
|
|
|
typedef struct XLogDumpStats
|
|
|
|
{
|
|
|
|
uint64 count;
|
|
|
|
Stats rmgr_stats[RM_NEXT_ID];
|
|
|
|
Stats record_stats[RM_NEXT_ID][MAX_XLINFO_TYPES];
|
|
|
|
} XLogDumpStats;
|
|
|
|
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
#define fatal_error(...) do { pg_log_fatal(__VA_ARGS__); exit(EXIT_FAILURE); } while(0)
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
static void
|
|
|
|
print_rmgr_list(void)
|
|
|
|
{
|
2013-05-29 22:58:43 +02:00
|
|
|
int i;
|
2013-02-22 20:46:24 +01:00
|
|
|
|
2013-06-04 17:51:43 +02:00
|
|
|
for (i = 0; i <= RM_MAX_ID; i++)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
|
|
|
printf("%s\n", RmgrDescTable[i].rm_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check whether directory exists and whether we can open it. Keep errno set so
|
|
|
|
* that the caller can report errors somewhat more accurately.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
verify_directory(const char *directory)
|
|
|
|
{
|
2013-05-29 22:58:43 +02:00
|
|
|
DIR *dir = opendir(directory);
|
|
|
|
|
2013-02-22 20:46:24 +01:00
|
|
|
if (dir == NULL)
|
|
|
|
return false;
|
|
|
|
closedir(dir);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Split a pathname as dirname(1) and basename(1) would.
|
|
|
|
*
|
|
|
|
* XXX this probably doesn't do very well on Windows. We probably need to
|
|
|
|
* apply canonicalize_path(), at the very least.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
split_path(const char *path, char **dir, char **fname)
|
|
|
|
{
|
|
|
|
char *sep;
|
|
|
|
|
|
|
|
/* split filepath into directory & filename */
|
|
|
|
sep = strrchr(path, '/');
|
|
|
|
|
|
|
|
/* directory path */
|
|
|
|
if (sep != NULL)
|
|
|
|
{
|
2019-12-04 23:36:06 +01:00
|
|
|
*dir = pnstrdup(path, sep - path);
|
2013-02-22 20:46:24 +01:00
|
|
|
*fname = pg_strdup(sep + 1);
|
|
|
|
}
|
|
|
|
/* local directory */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dir = NULL;
|
|
|
|
*fname = pg_strdup(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
* Open the file in the valid target directory.
|
2013-02-22 20:46:24 +01:00
|
|
|
*
|
|
|
|
* return a read only fd
|
|
|
|
*/
|
|
|
|
static int
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
open_file_in_directory(const char *directory, const char *fname)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
|
|
|
int fd = -1;
|
|
|
|
char fpath[MAXPGPATH];
|
|
|
|
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
Assert(directory != NULL);
|
|
|
|
|
|
|
|
snprintf(fpath, MAXPGPATH, "%s/%s", directory, fname);
|
|
|
|
fd = open(fpath, O_RDONLY | PG_BINARY, 0);
|
|
|
|
|
|
|
|
if (fd < 0 && errno != ENOENT)
|
2019-12-24 04:14:08 +01:00
|
|
|
fatal_error("could not open file \"%s\": %m", fname);
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Try to find fname in the given directory. Returns true if it is found,
|
|
|
|
* false otherwise. If fname is NULL, search the complete directory for any
|
|
|
|
* file with a valid WAL file name. If file is successfully opened, set the
|
|
|
|
* wal segment size.
|
|
|
|
*/
|
|
|
|
static bool
|
2017-10-31 15:34:31 +01:00
|
|
|
search_directory(const char *directory, const char *fname)
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
{
|
|
|
|
int fd = -1;
|
|
|
|
DIR *xldir;
|
|
|
|
|
|
|
|
/* open file if valid filename is provided */
|
|
|
|
if (fname != NULL)
|
|
|
|
fd = open_file_in_directory(directory, fname);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A valid file name is not passed, so search the complete directory. If
|
|
|
|
* we find any file whose name is a valid WAL file name then try to open
|
|
|
|
* it. If we cannot open it, bail out.
|
|
|
|
*/
|
|
|
|
else if ((xldir = opendir(directory)) != NULL)
|
|
|
|
{
|
|
|
|
struct dirent *xlde;
|
|
|
|
|
|
|
|
while ((xlde = readdir(xldir)) != NULL)
|
|
|
|
{
|
|
|
|
if (IsXLogFileName(xlde->d_name))
|
|
|
|
{
|
|
|
|
fd = open_file_in_directory(directory, xlde->d_name);
|
|
|
|
fname = xlde->d_name;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
closedir(xldir);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set WalSegSz if file is successfully opened */
|
|
|
|
if (fd >= 0)
|
|
|
|
{
|
2018-09-01 21:27:12 +02:00
|
|
|
PGAlignedXLogBlock buf;
|
Rework error messages around file handling
Some error messages related to file handling are using the code path
context to define their state. For example, 2PC-related errors are
referring to "two-phase status files", or "relation mapping file" is
used for catalog-to-filenode mapping, however those prove to be
difficult to translate, and are not more helpful than just referring to
the path of the file being worked on. So simplify all those error
messages by just referring to files with their path used. In some
cases, like the manipulation of WAL segments, the context is actually
helpful so those are kept.
Calls to the system function read() have also been rather inconsistent
with their error handling sometimes not reporting the number of bytes
read, and some other code paths trying to use an errno which has not
been set. The in-core functions are using a more consistent pattern
with this patch, which checks for both errno if set or if an
inconsistent read is happening.
So as to care about pluralization when reading an unexpected number of
byte(s), "could not read: read %d of %zu" is used as error message, with
%d field being the output result of read() and %zu the expected size.
This simplifies the work of translators with less variations of the same
message.
Author: Michael Paquier
Reviewed-by: Álvaro Herrera
Discussion: https://postgr.es/m/20180520000522.GB1603@paquier.xyz
2018-07-18 01:01:23 +02:00
|
|
|
int r;
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
|
2018-09-01 21:27:12 +02:00
|
|
|
r = read(fd, buf.data, XLOG_BLCKSZ);
|
Rework error messages around file handling
Some error messages related to file handling are using the code path
context to define their state. For example, 2PC-related errors are
referring to "two-phase status files", or "relation mapping file" is
used for catalog-to-filenode mapping, however those prove to be
difficult to translate, and are not more helpful than just referring to
the path of the file being worked on. So simplify all those error
messages by just referring to files with their path used. In some
cases, like the manipulation of WAL segments, the context is actually
helpful so those are kept.
Calls to the system function read() have also been rather inconsistent
with their error handling sometimes not reporting the number of bytes
read, and some other code paths trying to use an errno which has not
been set. The in-core functions are using a more consistent pattern
with this patch, which checks for both errno if set or if an
inconsistent read is happening.
So as to care about pluralization when reading an unexpected number of
byte(s), "could not read: read %d of %zu" is used as error message, with
%d field being the output result of read() and %zu the expected size.
This simplifies the work of translators with less variations of the same
message.
Author: Michael Paquier
Reviewed-by: Álvaro Herrera
Discussion: https://postgr.es/m/20180520000522.GB1603@paquier.xyz
2018-07-18 01:01:23 +02:00
|
|
|
if (r == XLOG_BLCKSZ)
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
{
|
2018-09-01 21:27:12 +02:00
|
|
|
XLogLongPageHeader longhdr = (XLogLongPageHeader) buf.data;
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
|
|
|
|
WalSegSz = longhdr->xlp_seg_size;
|
|
|
|
|
|
|
|
if (!IsValidWalSegSize(WalSegSz))
|
2018-05-18 05:05:27 +02:00
|
|
|
fatal_error(ngettext("WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" header specifies %d byte",
|
|
|
|
"WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" header specifies %d bytes",
|
|
|
|
WalSegSz),
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
fname, WalSegSz);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (errno != 0)
|
2019-12-24 04:14:08 +01:00
|
|
|
fatal_error("could not read file \"%s\": %m",
|
|
|
|
fname);
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
else
|
Rework error messages around file handling
Some error messages related to file handling are using the code path
context to define their state. For example, 2PC-related errors are
referring to "two-phase status files", or "relation mapping file" is
used for catalog-to-filenode mapping, however those prove to be
difficult to translate, and are not more helpful than just referring to
the path of the file being worked on. So simplify all those error
messages by just referring to files with their path used. In some
cases, like the manipulation of WAL segments, the context is actually
helpful so those are kept.
Calls to the system function read() have also been rather inconsistent
with their error handling sometimes not reporting the number of bytes
read, and some other code paths trying to use an errno which has not
been set. The in-core functions are using a more consistent pattern
with this patch, which checks for both errno if set or if an
inconsistent read is happening.
So as to care about pluralization when reading an unexpected number of
byte(s), "could not read: read %d of %zu" is used as error message, with
%d field being the output result of read() and %zu the expected size.
This simplifies the work of translators with less variations of the same
message.
Author: Michael Paquier
Reviewed-by: Álvaro Herrera
Discussion: https://postgr.es/m/20180520000522.GB1603@paquier.xyz
2018-07-18 01:01:23 +02:00
|
|
|
fatal_error("could not read file \"%s\": read %d of %zu",
|
|
|
|
fname, r, (Size) XLOG_BLCKSZ);
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
}
|
|
|
|
close(fd);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2019-09-24 21:08:31 +02:00
|
|
|
* Identify the target directory.
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
*
|
|
|
|
* Try to find the file in several places:
|
|
|
|
* if directory != NULL:
|
|
|
|
* directory /
|
|
|
|
* directory / XLOGDIR /
|
|
|
|
* else
|
|
|
|
* .
|
|
|
|
* XLOGDIR /
|
|
|
|
* $PGDATA / XLOGDIR /
|
|
|
|
*
|
2019-09-24 21:08:31 +02:00
|
|
|
* The valid target directory is returned.
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
*/
|
2019-09-24 21:08:31 +02:00
|
|
|
static char *
|
|
|
|
identify_target_directory(char *directory, char *fname)
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
{
|
|
|
|
char fpath[MAXPGPATH];
|
|
|
|
|
|
|
|
if (directory != NULL)
|
|
|
|
{
|
|
|
|
if (search_directory(directory, fname))
|
2019-09-24 21:08:31 +02:00
|
|
|
return pg_strdup(directory);
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
|
|
|
|
/* directory / XLOGDIR */
|
|
|
|
snprintf(fpath, MAXPGPATH, "%s/%s", directory, XLOGDIR);
|
|
|
|
if (search_directory(fpath, fname))
|
2019-09-24 21:08:31 +02:00
|
|
|
return pg_strdup(fpath);
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
}
|
|
|
|
else
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
|
|
|
const char *datadir;
|
|
|
|
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
/* current directory */
|
|
|
|
if (search_directory(".", fname))
|
2019-09-24 21:08:31 +02:00
|
|
|
return pg_strdup(".");
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
/* XLOGDIR */
|
|
|
|
if (search_directory(XLOGDIR, fname))
|
2019-09-24 21:08:31 +02:00
|
|
|
return pg_strdup(XLOGDIR);
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
datadir = getenv("PGDATA");
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
/* $PGDATA / XLOGDIR */
|
2013-02-22 20:46:24 +01:00
|
|
|
if (datadir != NULL)
|
|
|
|
{
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
snprintf(fpath, MAXPGPATH, "%s/%s", datadir, XLOGDIR);
|
|
|
|
if (search_directory(fpath, fname))
|
2019-09-24 21:08:31 +02:00
|
|
|
return pg_strdup(fpath);
|
2013-02-22 20:46:24 +01:00
|
|
|
}
|
|
|
|
}
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
|
|
|
|
/* could not locate WAL file */
|
|
|
|
if (fname)
|
|
|
|
fatal_error("could not locate WAL file \"%s\"", fname);
|
2013-02-22 20:46:24 +01:00
|
|
|
else
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
fatal_error("could not find any WAL file");
|
2019-09-24 21:08:31 +02:00
|
|
|
|
|
|
|
return NULL; /* not reached */
|
2013-02-22 20:46:24 +01:00
|
|
|
}
|
|
|
|
|
2019-11-25 19:04:54 +01:00
|
|
|
/* pg_waldump's openSegment callback for WALRead */
|
|
|
|
static int
|
|
|
|
WALDumpOpenSegment(XLogSegNo nextSegNo, WALSegmentContext *segcxt,
|
|
|
|
TimeLineID *tli_p)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
2019-11-25 19:04:54 +01:00
|
|
|
TimeLineID tli = *tli_p;
|
|
|
|
char fname[MAXPGPATH];
|
|
|
|
int fd;
|
|
|
|
int tries;
|
2013-02-22 20:46:24 +01:00
|
|
|
|
2019-11-25 19:04:54 +01:00
|
|
|
XLogFileName(fname, tli, nextSegNo, segcxt->ws_segsize);
|
2013-02-22 20:46:24 +01:00
|
|
|
|
2019-11-25 19:04:54 +01:00
|
|
|
/*
|
|
|
|
* In follow mode there is a short period of time after the server has
|
|
|
|
* written the end of the previous file before the new file is available.
|
|
|
|
* So we loop for 5 seconds looking for the file to appear before giving
|
|
|
|
* up.
|
|
|
|
*/
|
|
|
|
for (tries = 0; tries < 10; tries++)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
2019-11-25 19:04:54 +01:00
|
|
|
fd = open_file_in_directory(segcxt->ws_dir, fname);
|
|
|
|
if (fd >= 0)
|
|
|
|
return fd;
|
|
|
|
if (errno == ENOENT)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
Rework error messages around file handling
Some error messages related to file handling are using the code path
context to define their state. For example, 2PC-related errors are
referring to "two-phase status files", or "relation mapping file" is
used for catalog-to-filenode mapping, however those prove to be
difficult to translate, and are not more helpful than just referring to
the path of the file being worked on. So simplify all those error
messages by just referring to files with their path used. In some
cases, like the manipulation of WAL segments, the context is actually
helpful so those are kept.
Calls to the system function read() have also been rather inconsistent
with their error handling sometimes not reporting the number of bytes
read, and some other code paths trying to use an errno which has not
been set. The in-core functions are using a more consistent pattern
with this patch, which checks for both errno if set or if an
inconsistent read is happening.
So as to care about pluralization when reading an unexpected number of
byte(s), "could not read: read %d of %zu" is used as error message, with
%d field being the output result of read() and %zu the expected size.
This simplifies the work of translators with less variations of the same
message.
Author: Michael Paquier
Reviewed-by: Álvaro Herrera
Discussion: https://postgr.es/m/20180520000522.GB1603@paquier.xyz
2018-07-18 01:01:23 +02:00
|
|
|
int save_errno = errno;
|
2013-02-22 20:46:24 +01:00
|
|
|
|
2019-11-25 19:04:54 +01:00
|
|
|
/* File not there yet, try again */
|
|
|
|
pg_usleep(500 * 1000);
|
Rework error messages around file handling
Some error messages related to file handling are using the code path
context to define their state. For example, 2PC-related errors are
referring to "two-phase status files", or "relation mapping file" is
used for catalog-to-filenode mapping, however those prove to be
difficult to translate, and are not more helpful than just referring to
the path of the file being worked on. So simplify all those error
messages by just referring to files with their path used. In some
cases, like the manipulation of WAL segments, the context is actually
helpful so those are kept.
Calls to the system function read() have also been rather inconsistent
with their error handling sometimes not reporting the number of bytes
read, and some other code paths trying to use an errno which has not
been set. The in-core functions are using a more consistent pattern
with this patch, which checks for both errno if set or if an
inconsistent read is happening.
So as to care about pluralization when reading an unexpected number of
byte(s), "could not read: read %d of %zu" is used as error message, with
%d field being the output result of read() and %zu the expected size.
This simplifies the work of translators with less variations of the same
message.
Author: Michael Paquier
Reviewed-by: Álvaro Herrera
Discussion: https://postgr.es/m/20180520000522.GB1603@paquier.xyz
2018-07-18 01:01:23 +02:00
|
|
|
|
2019-11-25 19:04:54 +01:00
|
|
|
errno = save_errno;
|
|
|
|
continue;
|
2013-02-22 20:46:24 +01:00
|
|
|
}
|
2019-11-25 19:04:54 +01:00
|
|
|
/* Any other error, fall through and fail */
|
|
|
|
break;
|
2013-02-22 20:46:24 +01:00
|
|
|
}
|
2019-11-25 19:04:54 +01:00
|
|
|
|
2019-12-24 04:14:08 +01:00
|
|
|
fatal_error("could not find file \"%s\": %m", fname);
|
2019-11-25 19:04:54 +01:00
|
|
|
return -1; /* keep compiler quiet */
|
2013-02-22 20:46:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XLogReader read_page callback
|
|
|
|
*/
|
|
|
|
static int
|
2019-11-25 19:04:54 +01:00
|
|
|
WALDumpReadPage(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen,
|
|
|
|
XLogRecPtr targetPtr, char *readBuff)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
|
|
|
XLogDumpPrivate *private = state->private_data;
|
|
|
|
int count = XLOG_BLCKSZ;
|
2019-11-25 19:04:54 +01:00
|
|
|
WALReadError errinfo;
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
if (private->endptr != InvalidXLogRecPtr)
|
|
|
|
{
|
|
|
|
if (targetPagePtr + XLOG_BLCKSZ <= private->endptr)
|
|
|
|
count = XLOG_BLCKSZ;
|
|
|
|
else if (targetPagePtr + reqLen <= private->endptr)
|
|
|
|
count = private->endptr - targetPagePtr;
|
|
|
|
else
|
2014-03-26 12:48:20 +01:00
|
|
|
{
|
|
|
|
private->endptr_reached = true;
|
2013-02-22 20:46:24 +01:00
|
|
|
return -1;
|
2014-03-26 12:48:20 +01:00
|
|
|
}
|
2013-02-22 20:46:24 +01:00
|
|
|
}
|
|
|
|
|
2019-11-25 19:04:54 +01:00
|
|
|
if (!WALRead(readBuff, targetPagePtr, count, private->timeline,
|
|
|
|
&state->seg, &state->segcxt, WALDumpOpenSegment, &errinfo))
|
|
|
|
{
|
|
|
|
WALOpenSegment *seg = &errinfo.wre_seg;
|
|
|
|
char fname[MAXPGPATH];
|
|
|
|
|
|
|
|
XLogFileName(fname, seg->ws_tli, seg->ws_segno,
|
|
|
|
state->segcxt.ws_segsize);
|
|
|
|
|
|
|
|
if (errinfo.wre_errno != 0)
|
|
|
|
{
|
|
|
|
errno = errinfo.wre_errno;
|
|
|
|
fatal_error("could not read from file %s, offset %u: %m",
|
|
|
|
fname, errinfo.wre_off);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fatal_error("could not read from file %s, offset %u: read %d of %zu",
|
|
|
|
fname, errinfo.wre_off, errinfo.wre_read,
|
|
|
|
(Size) errinfo.wre_req);
|
|
|
|
}
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-06-06 00:56:58 +02:00
|
|
|
* Calculate the size of a record, split into !FPI and FPI parts.
|
2013-02-22 20:46:24 +01:00
|
|
|
*/
|
|
|
|
static void
|
2017-06-06 00:56:58 +02:00
|
|
|
XLogDumpRecordLen(XLogReaderState *record, uint32 *rec_len, uint32 *fpi_len)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
2014-12-05 10:39:40 +01:00
|
|
|
int block_id;
|
2014-09-19 16:33:16 +02:00
|
|
|
|
2014-12-05 10:39:40 +01:00
|
|
|
/*
|
Add GUC to enable compression of full page images stored in WAL.
When newly-added GUC parameter, wal_compression, is on, the PostgreSQL server
compresses a full page image written to WAL when full_page_writes is on or
during a base backup. A compressed page image will be decompressed during WAL
replay. Turning this parameter on can reduce the WAL volume without increasing
the risk of unrecoverable data corruption, but at the cost of some extra CPU
spent on the compression during WAL logging and on the decompression during
WAL replay.
This commit changes the WAL format (so bumping WAL version number) so that
the one-byte flag indicating whether a full page image is compressed or not is
included in its header information. This means that the commit increases the
WAL volume one-byte per a full page image even if WAL compression is not used
at all. We can save that one-byte by borrowing one-bit from the existing field
like hole_offset in the header and using it as the flag, for example. But which
would reduce the code readability and the extensibility of the feature.
Per discussion, it's not worth paying those prices to save only one-byte, so we
decided to add the one-byte flag to the header.
This commit doesn't introduce any new compression algorithm like lz4.
Currently a full page image is compressed using the existing PGLZ algorithm.
Per discussion, we decided to use it at least in the first version of the
feature because there were no performance reports showing that its compression
ratio is unacceptably lower than that of other algorithm. Of course,
in the future, it's worth considering the support of other compression
algorithm for the better compression.
Rahila Syed and Michael Paquier, reviewed in various versions by myself,
Andres Freund, Robert Haas, Abhijit Menon-Sen and many others.
2015-03-11 07:52:24 +01:00
|
|
|
* Calculate the amount of FPI data in the record.
|
2014-12-05 10:39:40 +01:00
|
|
|
*
|
|
|
|
* XXX: We peek into xlogreader's private decoded backup blocks for the
|
Add GUC to enable compression of full page images stored in WAL.
When newly-added GUC parameter, wal_compression, is on, the PostgreSQL server
compresses a full page image written to WAL when full_page_writes is on or
during a base backup. A compressed page image will be decompressed during WAL
replay. Turning this parameter on can reduce the WAL volume without increasing
the risk of unrecoverable data corruption, but at the cost of some extra CPU
spent on the compression during WAL logging and on the decompression during
WAL replay.
This commit changes the WAL format (so bumping WAL version number) so that
the one-byte flag indicating whether a full page image is compressed or not is
included in its header information. This means that the commit increases the
WAL volume one-byte per a full page image even if WAL compression is not used
at all. We can save that one-byte by borrowing one-bit from the existing field
like hole_offset in the header and using it as the flag, for example. But which
would reduce the code readability and the extensibility of the feature.
Per discussion, it's not worth paying those prices to save only one-byte, so we
decided to add the one-byte flag to the header.
This commit doesn't introduce any new compression algorithm like lz4.
Currently a full page image is compressed using the existing PGLZ algorithm.
Per discussion, we decided to use it at least in the first version of the
feature because there were no performance reports showing that its compression
ratio is unacceptably lower than that of other algorithm. Of course,
in the future, it's worth considering the support of other compression
algorithm for the better compression.
Rahila Syed and Michael Paquier, reviewed in various versions by myself,
Andres Freund, Robert Haas, Abhijit Menon-Sen and many others.
2015-03-11 07:52:24 +01:00
|
|
|
* bimg_len indicating the length of FPI data. It doesn't seem worth it to
|
|
|
|
* add an accessor macro for this.
|
2014-12-05 10:39:40 +01:00
|
|
|
*/
|
2017-06-06 00:56:58 +02:00
|
|
|
*fpi_len = 0;
|
2014-12-05 10:39:40 +01:00
|
|
|
for (block_id = 0; block_id <= record->max_block_id; block_id++)
|
|
|
|
{
|
|
|
|
if (XLogRecHasBlockImage(record, block_id))
|
2017-06-06 00:56:58 +02:00
|
|
|
*fpi_len += record->blocks[block_id].bimg_len;
|
2014-12-05 10:39:40 +01:00
|
|
|
}
|
|
|
|
|
2017-06-06 00:56:58 +02:00
|
|
|
/*
|
|
|
|
* Calculate the length of the record as the total length - the length of
|
|
|
|
* all the block images.
|
|
|
|
*/
|
|
|
|
*rec_len = XLogRecGetTotalLen(record) - *fpi_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Store per-rmgr and per-record statistics for a given record.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
XLogDumpCountRecord(XLogDumpConfig *config, XLogDumpStats *stats,
|
|
|
|
XLogReaderState *record)
|
|
|
|
{
|
|
|
|
RmgrId rmid;
|
|
|
|
uint8 recid;
|
|
|
|
uint32 rec_len;
|
|
|
|
uint32 fpi_len;
|
|
|
|
|
|
|
|
stats->count++;
|
|
|
|
|
|
|
|
rmid = XLogRecGetRmid(record);
|
|
|
|
|
|
|
|
XLogDumpRecordLen(record, &rec_len, &fpi_len);
|
|
|
|
|
2014-12-05 10:39:40 +01:00
|
|
|
/* Update per-rmgr statistics */
|
2013-02-22 20:46:24 +01:00
|
|
|
|
2014-09-19 16:33:16 +02:00
|
|
|
stats->rmgr_stats[rmid].count++;
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
stats->rmgr_stats[rmid].rec_len += rec_len;
|
|
|
|
stats->rmgr_stats[rmid].fpi_len += fpi_len;
|
2014-09-19 16:33:16 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Update per-record statistics, where the record is identified by a
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
* combination of the RmgrId and the four bits of the xl_info field that
|
|
|
|
* are the rmgr's domain (resulting in sixteen possible entries per
|
|
|
|
* RmgrId).
|
2014-09-19 16:33:16 +02:00
|
|
|
*/
|
|
|
|
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
recid = XLogRecGetInfo(record) >> 4;
|
2014-09-19 16:33:16 +02:00
|
|
|
|
|
|
|
stats->record_stats[rmid][recid].count++;
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
stats->record_stats[rmid][recid].rec_len += rec_len;
|
|
|
|
stats->record_stats[rmid][recid].fpi_len += fpi_len;
|
2014-09-19 16:33:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print a record to stdout
|
|
|
|
*/
|
|
|
|
static void
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
XLogDumpDisplayRecord(XLogDumpConfig *config, XLogReaderState *record)
|
2014-09-19 16:33:16 +02:00
|
|
|
{
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
const char *id;
|
|
|
|
const RmgrDescData *desc = &RmgrDescTable[XLogRecGetRmid(record)];
|
2017-06-06 00:56:58 +02:00
|
|
|
uint32 rec_len;
|
|
|
|
uint32 fpi_len;
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
RelFileNode rnode;
|
|
|
|
ForkNumber forknum;
|
|
|
|
BlockNumber blk;
|
|
|
|
int block_id;
|
|
|
|
uint8 info = XLogRecGetInfo(record);
|
|
|
|
XLogRecPtr xl_prev = XLogRecGetPrev(record);
|
Make StringInfo available to frontend code.
There's plenty places in frontend code that could benefit from a
string buffer implementation. Some because it yields simpler and
faster code, and some others because of the desire to share code
between backend and frontend.
While there is a string buffer implementation available to frontend
code, libpq's PQExpBuffer, it is clunkier than stringinfo, it
introduces a libpq dependency, doesn't allow for sharing between
frontend and backend code, and has a higher API/ABI stability
requirement due to being exposed via libpq.
Therefore it seems best to just making StringInfo being usable by
frontend code. There's not much to do for that, except for rewriting
two subsequent elog/ereport calls into others types of error
reporting, and deciding on a maximum string length.
For the maximum string size I decided to privately define MaxAllocSize
to the same value as used in the backend. It seems likely that we'll
want to reconsider this for both backend and frontend code in the not
too far away future.
For now I've left stringinfo.h in lib/, rather than common/, to reduce
the likelihood of unnecessary breakage. We could alternatively decide
to provide a redirecting stringinfo.h in lib/, or just not provide
compatibility.
Author: Andres Freund
Reviewed-By: Kyotaro Horiguchi, Daniel Gustafsson
Discussion: https://postgr.es/m/20190920051857.2fhnvhvx4qdddviz@alap3.anarazel.de
2019-11-05 23:56:40 +01:00
|
|
|
StringInfoData s;
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
|
2017-06-06 00:56:58 +02:00
|
|
|
XLogDumpRecordLen(record, &rec_len, &fpi_len);
|
|
|
|
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
printf("rmgr: %-11s len (rec/tot): %6u/%6u, tx: %10u, lsn: %X/%08X, prev %X/%08X, ",
|
2013-02-22 20:46:24 +01:00
|
|
|
desc->rm_name,
|
2017-06-06 00:56:58 +02:00
|
|
|
rec_len, XLogRecGetTotalLen(record),
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
XLogRecGetXid(record),
|
|
|
|
(uint32) (record->ReadRecPtr >> 32), (uint32) record->ReadRecPtr,
|
|
|
|
(uint32) (xl_prev >> 32), (uint32) xl_prev);
|
2019-10-30 03:18:07 +01:00
|
|
|
|
|
|
|
id = desc->rm_identify(info);
|
|
|
|
if (id == NULL)
|
|
|
|
printf("desc: UNKNOWN (%x) ", info & ~XLR_INFO_MASK);
|
|
|
|
else
|
|
|
|
printf("desc: %s ", id);
|
2013-02-22 20:46:24 +01:00
|
|
|
|
Make StringInfo available to frontend code.
There's plenty places in frontend code that could benefit from a
string buffer implementation. Some because it yields simpler and
faster code, and some others because of the desire to share code
between backend and frontend.
While there is a string buffer implementation available to frontend
code, libpq's PQExpBuffer, it is clunkier than stringinfo, it
introduces a libpq dependency, doesn't allow for sharing between
frontend and backend code, and has a higher API/ABI stability
requirement due to being exposed via libpq.
Therefore it seems best to just making StringInfo being usable by
frontend code. There's not much to do for that, except for rewriting
two subsequent elog/ereport calls into others types of error
reporting, and deciding on a maximum string length.
For the maximum string size I decided to privately define MaxAllocSize
to the same value as used in the backend. It seems likely that we'll
want to reconsider this for both backend and frontend code in the not
too far away future.
For now I've left stringinfo.h in lib/, rather than common/, to reduce
the likelihood of unnecessary breakage. We could alternatively decide
to provide a redirecting stringinfo.h in lib/, or just not provide
compatibility.
Author: Andres Freund
Reviewed-By: Kyotaro Horiguchi, Daniel Gustafsson
Discussion: https://postgr.es/m/20190920051857.2fhnvhvx4qdddviz@alap3.anarazel.de
2019-11-05 23:56:40 +01:00
|
|
|
initStringInfo(&s);
|
|
|
|
desc->rm_desc(&s, record);
|
|
|
|
printf("%s", s.data);
|
|
|
|
pfree(s.data);
|
2013-02-22 20:46:24 +01:00
|
|
|
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
if (!config->bkp_details)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
/* print block references (short format) */
|
|
|
|
for (block_id = 0; block_id <= record->max_block_id; block_id++)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
if (!XLogRecHasBlockRef(record, block_id))
|
2013-02-22 20:46:24 +01:00
|
|
|
continue;
|
|
|
|
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blk);
|
|
|
|
if (forknum != MAIN_FORKNUM)
|
|
|
|
printf(", blkref #%u: rel %u/%u/%u fork %s blk %u",
|
|
|
|
block_id,
|
|
|
|
rnode.spcNode, rnode.dbNode, rnode.relNode,
|
|
|
|
forkNames[forknum],
|
|
|
|
blk);
|
|
|
|
else
|
|
|
|
printf(", blkref #%u: rel %u/%u/%u blk %u",
|
|
|
|
block_id,
|
|
|
|
rnode.spcNode, rnode.dbNode, rnode.relNode,
|
|
|
|
blk);
|
|
|
|
if (XLogRecHasBlockImage(record, block_id))
|
2017-02-08 21:45:30 +01:00
|
|
|
{
|
|
|
|
if (XLogRecBlockImageApply(record, block_id))
|
|
|
|
printf(" FPW");
|
|
|
|
else
|
|
|
|
printf(" FPW for WAL verification");
|
|
|
|
}
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
}
|
|
|
|
putchar('\n');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* print block references (detailed format) */
|
|
|
|
putchar('\n');
|
|
|
|
for (block_id = 0; block_id <= record->max_block_id; block_id++)
|
|
|
|
{
|
|
|
|
if (!XLogRecHasBlockRef(record, block_id))
|
|
|
|
continue;
|
2013-02-22 20:46:24 +01:00
|
|
|
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blk);
|
|
|
|
printf("\tblkref #%u: rel %u/%u/%u fork %s blk %u",
|
|
|
|
block_id,
|
|
|
|
rnode.spcNode, rnode.dbNode, rnode.relNode,
|
|
|
|
forkNames[forknum],
|
|
|
|
blk);
|
|
|
|
if (XLogRecHasBlockImage(record, block_id))
|
|
|
|
{
|
Add GUC to enable compression of full page images stored in WAL.
When newly-added GUC parameter, wal_compression, is on, the PostgreSQL server
compresses a full page image written to WAL when full_page_writes is on or
during a base backup. A compressed page image will be decompressed during WAL
replay. Turning this parameter on can reduce the WAL volume without increasing
the risk of unrecoverable data corruption, but at the cost of some extra CPU
spent on the compression during WAL logging and on the decompression during
WAL replay.
This commit changes the WAL format (so bumping WAL version number) so that
the one-byte flag indicating whether a full page image is compressed or not is
included in its header information. This means that the commit increases the
WAL volume one-byte per a full page image even if WAL compression is not used
at all. We can save that one-byte by borrowing one-bit from the existing field
like hole_offset in the header and using it as the flag, for example. But which
would reduce the code readability and the extensibility of the feature.
Per discussion, it's not worth paying those prices to save only one-byte, so we
decided to add the one-byte flag to the header.
This commit doesn't introduce any new compression algorithm like lz4.
Currently a full page image is compressed using the existing PGLZ algorithm.
Per discussion, we decided to use it at least in the first version of the
feature because there were no performance reports showing that its compression
ratio is unacceptably lower than that of other algorithm. Of course,
in the future, it's worth considering the support of other compression
algorithm for the better compression.
Rahila Syed and Michael Paquier, reviewed in various versions by myself,
Andres Freund, Robert Haas, Abhijit Menon-Sen and many others.
2015-03-11 07:52:24 +01:00
|
|
|
if (record->blocks[block_id].bimg_info &
|
|
|
|
BKPIMAGE_IS_COMPRESSED)
|
|
|
|
{
|
2017-02-08 21:45:30 +01:00
|
|
|
printf(" (FPW%s); hole: offset: %u, length: %u, "
|
2019-10-30 06:46:40 +01:00
|
|
|
"compression saved: %u",
|
2017-02-08 21:45:30 +01:00
|
|
|
XLogRecBlockImageApply(record, block_id) ?
|
|
|
|
"" : " for WAL verification",
|
Add GUC to enable compression of full page images stored in WAL.
When newly-added GUC parameter, wal_compression, is on, the PostgreSQL server
compresses a full page image written to WAL when full_page_writes is on or
during a base backup. A compressed page image will be decompressed during WAL
replay. Turning this parameter on can reduce the WAL volume without increasing
the risk of unrecoverable data corruption, but at the cost of some extra CPU
spent on the compression during WAL logging and on the decompression during
WAL replay.
This commit changes the WAL format (so bumping WAL version number) so that
the one-byte flag indicating whether a full page image is compressed or not is
included in its header information. This means that the commit increases the
WAL volume one-byte per a full page image even if WAL compression is not used
at all. We can save that one-byte by borrowing one-bit from the existing field
like hole_offset in the header and using it as the flag, for example. But which
would reduce the code readability and the extensibility of the feature.
Per discussion, it's not worth paying those prices to save only one-byte, so we
decided to add the one-byte flag to the header.
This commit doesn't introduce any new compression algorithm like lz4.
Currently a full page image is compressed using the existing PGLZ algorithm.
Per discussion, we decided to use it at least in the first version of the
feature because there were no performance reports showing that its compression
ratio is unacceptably lower than that of other algorithm. Of course,
in the future, it's worth considering the support of other compression
algorithm for the better compression.
Rahila Syed and Michael Paquier, reviewed in various versions by myself,
Andres Freund, Robert Haas, Abhijit Menon-Sen and many others.
2015-03-11 07:52:24 +01:00
|
|
|
record->blocks[block_id].hole_offset,
|
|
|
|
record->blocks[block_id].hole_length,
|
|
|
|
BLCKSZ -
|
|
|
|
record->blocks[block_id].hole_length -
|
|
|
|
record->blocks[block_id].bimg_len);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-10-30 06:46:40 +01:00
|
|
|
printf(" (FPW%s); hole: offset: %u, length: %u",
|
2017-02-08 21:45:30 +01:00
|
|
|
XLogRecBlockImageApply(record, block_id) ?
|
|
|
|
"" : " for WAL verification",
|
Add GUC to enable compression of full page images stored in WAL.
When newly-added GUC parameter, wal_compression, is on, the PostgreSQL server
compresses a full page image written to WAL when full_page_writes is on or
during a base backup. A compressed page image will be decompressed during WAL
replay. Turning this parameter on can reduce the WAL volume without increasing
the risk of unrecoverable data corruption, but at the cost of some extra CPU
spent on the compression during WAL logging and on the decompression during
WAL replay.
This commit changes the WAL format (so bumping WAL version number) so that
the one-byte flag indicating whether a full page image is compressed or not is
included in its header information. This means that the commit increases the
WAL volume one-byte per a full page image even if WAL compression is not used
at all. We can save that one-byte by borrowing one-bit from the existing field
like hole_offset in the header and using it as the flag, for example. But which
would reduce the code readability and the extensibility of the feature.
Per discussion, it's not worth paying those prices to save only one-byte, so we
decided to add the one-byte flag to the header.
This commit doesn't introduce any new compression algorithm like lz4.
Currently a full page image is compressed using the existing PGLZ algorithm.
Per discussion, we decided to use it at least in the first version of the
feature because there were no performance reports showing that its compression
ratio is unacceptably lower than that of other algorithm. Of course,
in the future, it's worth considering the support of other compression
algorithm for the better compression.
Rahila Syed and Michael Paquier, reviewed in various versions by myself,
Andres Freund, Robert Haas, Abhijit Menon-Sen and many others.
2015-03-11 07:52:24 +01:00
|
|
|
record->blocks[block_id].hole_offset,
|
|
|
|
record->blocks[block_id].hole_length);
|
|
|
|
}
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
}
|
|
|
|
putchar('\n');
|
2013-02-22 20:46:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-19 16:33:16 +02:00
|
|
|
/*
|
|
|
|
* Display a single row of record counts and sizes for an rmgr or record.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
XLogDumpStatsRow(const char *name,
|
2015-04-26 18:02:32 +02:00
|
|
|
uint64 n, uint64 total_count,
|
|
|
|
uint64 rec_len, uint64 total_rec_len,
|
|
|
|
uint64 fpi_len, uint64 total_fpi_len,
|
|
|
|
uint64 tot_len, uint64 total_len)
|
2014-09-19 16:33:16 +02:00
|
|
|
{
|
2015-05-24 03:35:49 +02:00
|
|
|
double n_pct,
|
|
|
|
rec_len_pct,
|
|
|
|
fpi_len_pct,
|
|
|
|
tot_len_pct;
|
2015-04-26 18:02:32 +02:00
|
|
|
|
|
|
|
n_pct = 0;
|
|
|
|
if (total_count != 0)
|
|
|
|
n_pct = 100 * (double) n / total_count;
|
|
|
|
|
|
|
|
rec_len_pct = 0;
|
|
|
|
if (total_rec_len != 0)
|
|
|
|
rec_len_pct = 100 * (double) rec_len / total_rec_len;
|
|
|
|
|
|
|
|
fpi_len_pct = 0;
|
|
|
|
if (total_fpi_len != 0)
|
|
|
|
fpi_len_pct = 100 * (double) fpi_len / total_fpi_len;
|
|
|
|
|
|
|
|
tot_len_pct = 0;
|
|
|
|
if (total_len != 0)
|
|
|
|
tot_len_pct = 100 * (double) tot_len / total_len;
|
|
|
|
|
2014-09-19 16:33:16 +02:00
|
|
|
printf("%-27s "
|
|
|
|
"%20" INT64_MODIFIER "u (%6.02f) "
|
|
|
|
"%20" INT64_MODIFIER "u (%6.02f) "
|
|
|
|
"%20" INT64_MODIFIER "u (%6.02f) "
|
|
|
|
"%20" INT64_MODIFIER "u (%6.02f)\n",
|
|
|
|
name, n, n_pct, rec_len, rec_len_pct, fpi_len, fpi_len_pct,
|
2015-04-26 18:02:32 +02:00
|
|
|
tot_len, tot_len_pct);
|
2014-09-19 16:33:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Display summary statistics about the records seen so far.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
XLogDumpDisplayStats(XLogDumpConfig *config, XLogDumpStats *stats)
|
|
|
|
{
|
2015-05-24 03:35:49 +02:00
|
|
|
int ri,
|
|
|
|
rj;
|
2014-09-19 16:33:16 +02:00
|
|
|
uint64 total_count = 0;
|
|
|
|
uint64 total_rec_len = 0;
|
|
|
|
uint64 total_fpi_len = 0;
|
|
|
|
uint64 total_len = 0;
|
2015-05-24 03:35:49 +02:00
|
|
|
double rec_len_pct,
|
|
|
|
fpi_len_pct;
|
2014-09-19 16:33:16 +02:00
|
|
|
|
|
|
|
/* ---
|
|
|
|
* Make a first pass to calculate column totals:
|
|
|
|
* count(*),
|
|
|
|
* sum(xl_len+SizeOfXLogRecord),
|
|
|
|
* sum(xl_tot_len-xl_len-SizeOfXLogRecord), and
|
|
|
|
* sum(xl_tot_len).
|
|
|
|
* These are used to calculate percentages for each record type.
|
|
|
|
* ---
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (ri = 0; ri < RM_NEXT_ID; ri++)
|
|
|
|
{
|
|
|
|
total_count += stats->rmgr_stats[ri].count;
|
|
|
|
total_rec_len += stats->rmgr_stats[ri].rec_len;
|
|
|
|
total_fpi_len += stats->rmgr_stats[ri].fpi_len;
|
|
|
|
}
|
2015-05-24 03:35:49 +02:00
|
|
|
total_len = total_rec_len + total_fpi_len;
|
2014-09-19 16:33:16 +02:00
|
|
|
|
|
|
|
/*
|
2015-05-24 03:35:49 +02:00
|
|
|
* 27 is strlen("Transaction/COMMIT_PREPARED"), 20 is strlen(2^64), 8 is
|
|
|
|
* strlen("(100.00%)")
|
2014-09-19 16:33:16 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
printf("%-27s %20s %8s %20s %8s %20s %8s %20s %8s\n"
|
|
|
|
"%-27s %20s %8s %20s %8s %20s %8s %20s %8s\n",
|
|
|
|
"Type", "N", "(%)", "Record size", "(%)", "FPI size", "(%)", "Combined size", "(%)",
|
|
|
|
"----", "-", "---", "-----------", "---", "--------", "---", "-------------", "---");
|
|
|
|
|
|
|
|
for (ri = 0; ri < RM_NEXT_ID; ri++)
|
|
|
|
{
|
2015-05-24 03:35:49 +02:00
|
|
|
uint64 count,
|
|
|
|
rec_len,
|
|
|
|
fpi_len,
|
|
|
|
tot_len;
|
2014-09-19 16:33:16 +02:00
|
|
|
const RmgrDescData *desc = &RmgrDescTable[ri];
|
|
|
|
|
|
|
|
if (!config->stats_per_record)
|
|
|
|
{
|
|
|
|
count = stats->rmgr_stats[ri].count;
|
|
|
|
rec_len = stats->rmgr_stats[ri].rec_len;
|
|
|
|
fpi_len = stats->rmgr_stats[ri].fpi_len;
|
|
|
|
tot_len = rec_len + fpi_len;
|
|
|
|
|
|
|
|
XLogDumpStatsRow(desc->rm_name,
|
2015-04-26 18:02:32 +02:00
|
|
|
count, total_count, rec_len, total_rec_len,
|
|
|
|
fpi_len, total_fpi_len, tot_len, total_len);
|
2014-09-19 16:33:16 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (rj = 0; rj < MAX_XLINFO_TYPES; rj++)
|
|
|
|
{
|
|
|
|
const char *id;
|
|
|
|
|
|
|
|
count = stats->record_stats[ri][rj].count;
|
|
|
|
rec_len = stats->record_stats[ri][rj].rec_len;
|
|
|
|
fpi_len = stats->record_stats[ri][rj].fpi_len;
|
|
|
|
tot_len = rec_len + fpi_len;
|
|
|
|
|
|
|
|
/* Skip undefined combinations and ones that didn't occur */
|
|
|
|
if (count == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* the upper four bits in xl_info are the rmgr's */
|
|
|
|
id = desc->rm_identify(rj << 4);
|
|
|
|
if (id == NULL)
|
|
|
|
id = psprintf("UNKNOWN (%x)", rj << 4);
|
|
|
|
|
|
|
|
XLogDumpStatsRow(psprintf("%s/%s", desc->rm_name, id),
|
2015-04-26 18:02:32 +02:00
|
|
|
count, total_count, rec_len, total_rec_len,
|
|
|
|
fpi_len, total_fpi_len, tot_len, total_len);
|
2014-09-19 16:33:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("%-27s %20s %8s %20s %8s %20s %8s %20s\n",
|
|
|
|
"", "--------", "", "--------", "", "--------", "", "--------");
|
|
|
|
|
|
|
|
/*
|
2015-05-24 03:35:49 +02:00
|
|
|
* The percentages in earlier rows were calculated against the column
|
|
|
|
* total, but the ones that follow are against the row total. Note that
|
|
|
|
* these are displayed with a % symbol to differentiate them from the
|
|
|
|
* earlier ones, and are thus up to 9 characters long.
|
2014-09-19 16:33:16 +02:00
|
|
|
*/
|
|
|
|
|
2015-04-26 18:02:32 +02:00
|
|
|
rec_len_pct = 0;
|
|
|
|
if (total_len != 0)
|
|
|
|
rec_len_pct = 100 * (double) total_rec_len / total_len;
|
|
|
|
|
|
|
|
fpi_len_pct = 0;
|
|
|
|
if (total_len != 0)
|
|
|
|
fpi_len_pct = 100 * (double) total_fpi_len / total_len;
|
|
|
|
|
2014-09-19 16:33:16 +02:00
|
|
|
printf("%-27s "
|
|
|
|
"%20" INT64_MODIFIER "u %-9s"
|
|
|
|
"%20" INT64_MODIFIER "u %-9s"
|
|
|
|
"%20" INT64_MODIFIER "u %-9s"
|
|
|
|
"%20" INT64_MODIFIER "u %-6s\n",
|
|
|
|
"Total", stats->count, "",
|
2015-04-26 18:02:32 +02:00
|
|
|
total_rec_len, psprintf("[%.02f%%]", rec_len_pct),
|
|
|
|
total_fpi_len, psprintf("[%.02f%%]", fpi_len_pct),
|
2014-09-19 16:33:16 +02:00
|
|
|
total_len, "[100%]");
|
|
|
|
}
|
|
|
|
|
2013-02-22 20:46:24 +01:00
|
|
|
static void
|
|
|
|
usage(void)
|
|
|
|
{
|
2017-05-12 17:49:56 +02:00
|
|
|
printf(_("%s decodes and displays PostgreSQL write-ahead logs for debugging.\n\n"),
|
2013-02-22 20:46:24 +01:00
|
|
|
progname);
|
2016-10-15 18:00:00 +02:00
|
|
|
printf(_("Usage:\n"));
|
2017-04-14 05:15:52 +02:00
|
|
|
printf(_(" %s [OPTION]... [STARTSEG [ENDSEG]]\n"), progname);
|
2016-10-15 18:00:00 +02:00
|
|
|
printf(_("\nOptions:\n"));
|
|
|
|
printf(_(" -b, --bkp-details output detailed information about backup blocks\n"));
|
2017-05-12 19:51:27 +02:00
|
|
|
printf(_(" -e, --end=RECPTR stop reading at WAL location RECPTR\n"));
|
2016-10-15 18:00:00 +02:00
|
|
|
printf(_(" -f, --follow keep retrying after reaching end of WAL\n"));
|
|
|
|
printf(_(" -n, --limit=N number of records to display\n"));
|
2017-05-17 19:04:03 +02:00
|
|
|
printf(_(" -p, --path=PATH directory in which to find log segment files or a\n"
|
|
|
|
" directory with a ./pg_wal that contains such files\n"
|
2017-08-25 17:49:05 +02:00
|
|
|
" (default: current directory, ./pg_wal, $PGDATA/pg_wal)\n"));
|
|
|
|
printf(_(" -r, --rmgr=RMGR only show records generated by resource manager RMGR;\n"
|
2017-05-17 19:04:03 +02:00
|
|
|
" use --rmgr=list to list valid resource manager names\n"));
|
2017-05-12 19:51:27 +02:00
|
|
|
printf(_(" -s, --start=RECPTR start reading at WAL location RECPTR\n"));
|
2017-05-17 19:04:03 +02:00
|
|
|
printf(_(" -t, --timeline=TLI timeline from which to read log records\n"
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
" (default: 1 or the value used in STARTSEG)\n"));
|
2016-10-15 18:00:00 +02:00
|
|
|
printf(_(" -V, --version output version information, then exit\n"));
|
2017-08-25 17:49:05 +02:00
|
|
|
printf(_(" -x, --xid=XID only show records with transaction ID XID\n"));
|
2017-05-17 19:04:03 +02:00
|
|
|
printf(_(" -z, --stats[=record] show statistics instead of records\n"
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
" (optionally, show per-record statistics)\n"));
|
2016-10-15 18:00:00 +02:00
|
|
|
printf(_(" -?, --help show this help, then exit\n"));
|
2020-02-28 08:54:49 +01:00
|
|
|
printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
|
2020-02-28 08:54:49 +01:00
|
|
|
printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
|
2013-02-22 20:46:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
uint32 xlogid;
|
|
|
|
uint32 xrecoff;
|
|
|
|
XLogReaderState *xlogreader_state;
|
|
|
|
XLogDumpPrivate private;
|
|
|
|
XLogDumpConfig config;
|
2014-09-19 16:33:16 +02:00
|
|
|
XLogDumpStats stats;
|
2013-02-22 20:46:24 +01:00
|
|
|
XLogRecord *record;
|
|
|
|
XLogRecPtr first_record;
|
2019-09-24 21:08:31 +02:00
|
|
|
char *waldir = NULL;
|
2013-02-22 20:46:24 +01:00
|
|
|
char *errormsg;
|
|
|
|
|
|
|
|
static struct option long_options[] = {
|
|
|
|
{"bkp-details", no_argument, NULL, 'b'},
|
|
|
|
{"end", required_argument, NULL, 'e'},
|
2014-03-26 12:48:20 +01:00
|
|
|
{"follow", no_argument, NULL, 'f'},
|
2013-02-22 20:46:24 +01:00
|
|
|
{"help", no_argument, NULL, '?'},
|
|
|
|
{"limit", required_argument, NULL, 'n'},
|
|
|
|
{"path", required_argument, NULL, 'p'},
|
|
|
|
{"rmgr", required_argument, NULL, 'r'},
|
|
|
|
{"start", required_argument, NULL, 's'},
|
|
|
|
{"timeline", required_argument, NULL, 't'},
|
|
|
|
{"xid", required_argument, NULL, 'x'},
|
|
|
|
{"version", no_argument, NULL, 'V'},
|
2014-09-19 16:33:16 +02:00
|
|
|
{"stats", optional_argument, NULL, 'z'},
|
2013-02-22 20:46:24 +01:00
|
|
|
{NULL, 0, NULL, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
int option;
|
|
|
|
int optindex = 0;
|
|
|
|
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_logging_init(argv[0]);
|
2017-02-09 22:23:46 +01:00
|
|
|
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_waldump"));
|
2013-02-22 20:46:24 +01:00
|
|
|
progname = get_progname(argv[0]);
|
|
|
|
|
2019-06-05 22:55:16 +02:00
|
|
|
if (argc > 1)
|
|
|
|
{
|
|
|
|
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
|
|
|
|
{
|
|
|
|
usage();
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
|
|
|
|
{
|
|
|
|
puts("pg_waldump (PostgreSQL) " PG_VERSION);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-22 20:46:24 +01:00
|
|
|
memset(&private, 0, sizeof(XLogDumpPrivate));
|
|
|
|
memset(&config, 0, sizeof(XLogDumpConfig));
|
2014-09-19 16:33:16 +02:00
|
|
|
memset(&stats, 0, sizeof(XLogDumpStats));
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
private.timeline = 1;
|
|
|
|
private.startptr = InvalidXLogRecPtr;
|
|
|
|
private.endptr = InvalidXLogRecPtr;
|
2014-03-26 12:48:20 +01:00
|
|
|
private.endptr_reached = false;
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
config.bkp_details = false;
|
|
|
|
config.stop_after_records = -1;
|
|
|
|
config.already_displayed_records = 0;
|
2014-03-26 12:48:20 +01:00
|
|
|
config.follow = false;
|
2013-02-22 20:46:24 +01:00
|
|
|
config.filter_by_rmgr = -1;
|
|
|
|
config.filter_by_xid = InvalidTransactionId;
|
|
|
|
config.filter_by_xid_enabled = false;
|
2014-09-19 16:33:16 +02:00
|
|
|
config.stats = false;
|
|
|
|
config.stats_per_record = false;
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
if (argc <= 1)
|
|
|
|
{
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_log_error("no arguments specified");
|
2013-02-22 20:46:24 +01:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
|
2019-06-05 22:55:16 +02:00
|
|
|
while ((option = getopt_long(argc, argv, "be:fn:p:r:s:t:x:z",
|
2013-02-22 20:46:24 +01:00
|
|
|
long_options, &optindex)) != -1)
|
|
|
|
{
|
|
|
|
switch (option)
|
|
|
|
{
|
|
|
|
case 'b':
|
|
|
|
config.bkp_details = true;
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
if (sscanf(optarg, "%X/%X", &xlogid, &xrecoff) != 2)
|
|
|
|
{
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_log_error("could not parse end WAL location \"%s\"",
|
|
|
|
optarg);
|
2013-02-22 20:46:24 +01:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
private.endptr = (uint64) xlogid << 32 | xrecoff;
|
|
|
|
break;
|
2014-03-26 12:48:20 +01:00
|
|
|
case 'f':
|
|
|
|
config.follow = true;
|
|
|
|
break;
|
2013-02-22 20:46:24 +01:00
|
|
|
case 'n':
|
|
|
|
if (sscanf(optarg, "%d", &config.stop_after_records) != 1)
|
|
|
|
{
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_log_error("could not parse limit \"%s\"", optarg);
|
2013-02-22 20:46:24 +01:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'p':
|
2019-09-24 21:08:31 +02:00
|
|
|
waldir = pg_strdup(optarg);
|
2013-02-22 20:46:24 +01:00
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (pg_strcasecmp(optarg, "list") == 0)
|
|
|
|
{
|
|
|
|
print_rmgr_list();
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2013-06-04 17:51:43 +02:00
|
|
|
for (i = 0; i <= RM_MAX_ID; i++)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
|
|
|
if (pg_strcasecmp(optarg, RmgrDescTable[i].rm_name) == 0)
|
|
|
|
{
|
|
|
|
config.filter_by_rmgr = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config.filter_by_rmgr == -1)
|
|
|
|
{
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_log_error("resource manager \"%s\" does not exist",
|
|
|
|
optarg);
|
2013-02-22 20:46:24 +01:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
if (sscanf(optarg, "%X/%X", &xlogid, &xrecoff) != 2)
|
|
|
|
{
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_log_error("could not parse start WAL location \"%s\"",
|
|
|
|
optarg);
|
2013-02-22 20:46:24 +01:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
private.startptr = (uint64) xlogid << 32 | xrecoff;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
if (sscanf(optarg, "%d", &private.timeline) != 1)
|
|
|
|
{
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_log_error("could not parse timeline \"%s\"", optarg);
|
2013-02-22 20:46:24 +01:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
if (sscanf(optarg, "%u", &config.filter_by_xid) != 1)
|
|
|
|
{
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_log_error("could not parse \"%s\" as a transaction ID",
|
|
|
|
optarg);
|
2013-02-22 20:46:24 +01:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
config.filter_by_xid_enabled = true;
|
|
|
|
break;
|
2014-09-19 16:33:16 +02:00
|
|
|
case 'z':
|
|
|
|
config.stats = true;
|
|
|
|
config.stats_per_record = false;
|
|
|
|
if (optarg)
|
|
|
|
{
|
|
|
|
if (strcmp(optarg, "record") == 0)
|
|
|
|
config.stats_per_record = true;
|
|
|
|
else if (strcmp(optarg, "rmgr") != 0)
|
|
|
|
{
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_log_error("unrecognized argument to --stats: %s",
|
|
|
|
optarg);
|
2014-09-19 16:33:16 +02:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2013-02-22 20:46:24 +01:00
|
|
|
default:
|
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((optind + 2) < argc)
|
|
|
|
{
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_log_error("too many command-line arguments (first is \"%s\")",
|
|
|
|
argv[optind + 2]);
|
2013-02-22 20:46:24 +01:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
|
2019-09-24 21:08:31 +02:00
|
|
|
if (waldir != NULL)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
|
|
|
/* validate path points to directory */
|
2019-09-24 21:08:31 +02:00
|
|
|
if (!verify_directory(waldir))
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
2019-12-24 04:14:08 +01:00
|
|
|
pg_log_error("could not open directory \"%s\": %m", waldir);
|
2013-02-22 20:46:24 +01:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* parse files as start/end boundaries, extract path if not specified */
|
|
|
|
if (optind < argc)
|
|
|
|
{
|
|
|
|
char *directory = NULL;
|
|
|
|
char *fname = NULL;
|
|
|
|
int fd;
|
|
|
|
XLogSegNo segno;
|
|
|
|
|
|
|
|
split_path(argv[optind], &directory, &fname);
|
|
|
|
|
2019-09-24 21:08:31 +02:00
|
|
|
if (waldir == NULL && directory != NULL)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
2019-09-24 21:08:31 +02:00
|
|
|
waldir = directory;
|
2013-02-22 20:46:24 +01:00
|
|
|
|
2019-09-24 21:08:31 +02:00
|
|
|
if (!verify_directory(waldir))
|
2019-12-24 04:14:08 +01:00
|
|
|
fatal_error("could not open directory \"%s\": %m", waldir);
|
2013-02-22 20:46:24 +01:00
|
|
|
}
|
|
|
|
|
2019-09-24 21:08:31 +02:00
|
|
|
waldir = identify_target_directory(waldir, fname);
|
|
|
|
fd = open_file_in_directory(waldir, fname);
|
2013-02-22 20:46:24 +01:00
|
|
|
if (fd < 0)
|
|
|
|
fatal_error("could not open file \"%s\"", fname);
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
/* parse position from file */
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
XLogFromFileName(fname, &private.timeline, &segno, WalSegSz);
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
if (XLogRecPtrIsInvalid(private.startptr))
|
2018-07-09 20:28:21 +02:00
|
|
|
XLogSegNoOffsetToRecPtr(segno, 0, WalSegSz, private.startptr);
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
else if (!XLByteInSeg(private.startptr, segno, WalSegSz))
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_log_error("start WAL location %X/%X is not inside file \"%s\"",
|
2019-05-22 18:55:34 +02:00
|
|
|
(uint32) (private.startptr >> 32),
|
|
|
|
(uint32) private.startptr,
|
|
|
|
fname);
|
2013-02-22 20:46:24 +01:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* no second file specified, set end position */
|
|
|
|
if (!(optind + 1 < argc) && XLogRecPtrIsInvalid(private.endptr))
|
2018-07-09 20:28:21 +02:00
|
|
|
XLogSegNoOffsetToRecPtr(segno + 1, 0, WalSegSz, private.endptr);
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
/* parse ENDSEG if passed */
|
|
|
|
if (optind + 1 < argc)
|
|
|
|
{
|
|
|
|
XLogSegNo endsegno;
|
|
|
|
|
|
|
|
/* ignore directory, already have that */
|
|
|
|
split_path(argv[optind + 1], &directory, &fname);
|
|
|
|
|
2019-09-24 21:08:31 +02:00
|
|
|
fd = open_file_in_directory(waldir, fname);
|
2013-02-22 20:46:24 +01:00
|
|
|
if (fd < 0)
|
|
|
|
fatal_error("could not open file \"%s\"", fname);
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
/* parse position from file */
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
XLogFromFileName(fname, &private.timeline, &endsegno, WalSegSz);
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
if (endsegno < segno)
|
|
|
|
fatal_error("ENDSEG %s is before STARTSEG %s",
|
|
|
|
argv[optind + 1], argv[optind]);
|
|
|
|
|
|
|
|
if (XLogRecPtrIsInvalid(private.endptr))
|
2018-07-09 20:28:21 +02:00
|
|
|
XLogSegNoOffsetToRecPtr(endsegno + 1, 0, WalSegSz,
|
|
|
|
private.endptr);
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
/* set segno to endsegno for check of --end */
|
|
|
|
segno = endsegno;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
if (!XLByteInSeg(private.endptr, segno, WalSegSz) &&
|
|
|
|
private.endptr != (segno + 1) * WalSegSz)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_log_error("end WAL location %X/%X is not inside file \"%s\"",
|
2019-05-22 18:55:34 +02:00
|
|
|
(uint32) (private.endptr >> 32),
|
|
|
|
(uint32) private.endptr,
|
|
|
|
argv[argc - 1]);
|
2013-02-22 20:46:24 +01:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
}
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
else
|
2019-09-24 21:08:31 +02:00
|
|
|
waldir = identify_target_directory(waldir, NULL);
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
/* we don't know what to print */
|
|
|
|
if (XLogRecPtrIsInvalid(private.startptr))
|
|
|
|
{
|
Unified logging system for command-line programs
This unifies the various ad hoc logging (message printing, error
printing) systems used throughout the command-line programs.
Features:
- Program name is automatically prefixed.
- Message string does not end with newline. This removes a common
source of inconsistencies and omissions.
- Additionally, a final newline is automatically stripped, simplifying
use of PQerrorMessage() etc., another common source of mistakes.
- I converted error message strings to use %m where possible.
- As a result of the above several points, more translatable message
strings can be shared between different components and between
frontends and backend, without gratuitous punctuation or whitespace
differences.
- There is support for setting a "log level". This is not meant to be
user-facing, but can be used internally to implement debug or
verbose modes.
- Lazy argument evaluation, so no significant overhead if logging at
some level is disabled.
- Some color in the messages, similar to gcc and clang. Set
PG_COLOR=auto to try it out. Some colors are predefined, but can be
customized by setting PG_COLORS.
- Common files (common/, fe_utils/, etc.) can handle logging much more
simply by just using one API without worrying too much about the
context of the calling program, requiring callbacks, or having to
pass "progname" around everywhere.
- Some programs called setvbuf() to make sure that stderr is
unbuffered, even on Windows. But not all programs did that. This
is now done centrally.
Soft goals:
- Reduces vertical space use and visual complexity of error reporting
in the source code.
- Encourages more deliberate classification of messages. For example,
in some cases it wasn't clear without analyzing the surrounding code
whether a message was meant as an error or just an info.
- Concepts and terms are vaguely aligned with popular logging
frameworks such as log4j and Python logging.
This is all just about printing stuff out. Nothing affects program
flow (e.g., fatal exits). The uses are just too varied to do that.
Some existing code had wrappers that do some kind of print-and-exit,
and I adapted those.
I tried to keep the output mostly the same, but there is a lot of
historical baggage to unwind and special cases to consider, and I
might not always have succeeded. One significant change is that
pg_rewind used to write all error messages to stdout. That is now
changed to stderr.
Reviewed-by: Donald Dong <xdong@csumb.edu>
Reviewed-by: Arthur Zakirov <a.zakirov@postgrespro.ru>
Discussion: https://www.postgresql.org/message-id/flat/6a609b43-4f57-7348-6480-bd022f924310@2ndquadrant.com
2019-04-01 14:24:37 +02:00
|
|
|
pg_log_error("no start WAL location given");
|
2013-02-22 20:46:24 +01:00
|
|
|
goto bad_argument;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* done with argument parsing, do the actual work */
|
|
|
|
|
|
|
|
/* we have everything we need, start reading */
|
2019-11-25 19:04:54 +01:00
|
|
|
xlogreader_state = XLogReaderAllocate(WalSegSz, waldir, WALDumpReadPage,
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
&private);
|
2013-02-22 20:46:24 +01:00
|
|
|
if (!xlogreader_state)
|
|
|
|
fatal_error("out of memory");
|
|
|
|
|
|
|
|
/* first find a valid recptr to start from */
|
|
|
|
first_record = XLogFindNextRecord(xlogreader_state, private.startptr);
|
|
|
|
|
|
|
|
if (first_record == InvalidXLogRecPtr)
|
|
|
|
fatal_error("could not find a valid record after %X/%X",
|
|
|
|
(uint32) (private.startptr >> 32),
|
|
|
|
(uint32) private.startptr);
|
|
|
|
|
|
|
|
/*
|
2013-05-29 22:58:43 +02:00
|
|
|
* Display a message that we're skipping data if `from` wasn't a pointer
|
|
|
|
* to the start of a record and also wasn't a pointer to the beginning of
|
|
|
|
* a segment (e.g. we were used in file mode).
|
2013-02-22 20:46:24 +01:00
|
|
|
*/
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 07:03:48 +02:00
|
|
|
if (first_record != private.startptr &&
|
|
|
|
XLogSegmentOffset(private.startptr, WalSegSz) != 0)
|
2017-08-25 17:49:05 +02:00
|
|
|
printf(ngettext("first record is after %X/%X, at %X/%X, skipping over %u byte\n",
|
|
|
|
"first record is after %X/%X, at %X/%X, skipping over %u bytes\n",
|
|
|
|
(first_record - private.startptr)),
|
2013-02-22 20:46:24 +01:00
|
|
|
(uint32) (private.startptr >> 32), (uint32) private.startptr,
|
|
|
|
(uint32) (first_record >> 32), (uint32) first_record,
|
|
|
|
(uint32) (first_record - private.startptr));
|
|
|
|
|
2014-03-26 12:48:20 +01:00
|
|
|
for (;;)
|
2013-02-22 20:46:24 +01:00
|
|
|
{
|
2014-03-26 12:48:20 +01:00
|
|
|
/* try to read the next record */
|
2020-01-26 10:39:00 +01:00
|
|
|
record = XLogReadRecord(xlogreader_state, &errormsg);
|
2014-03-26 12:48:20 +01:00
|
|
|
if (!record)
|
|
|
|
{
|
|
|
|
if (!config.follow || private.endptr_reached)
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
{
|
2014-05-06 18:12:18 +02:00
|
|
|
pg_usleep(1000000L); /* 1 second */
|
2014-03-26 12:48:20 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-19 16:33:16 +02:00
|
|
|
/* apply all specified filters */
|
|
|
|
if (config.filter_by_rmgr != -1 &&
|
|
|
|
config.filter_by_rmgr != record->xl_rmid)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (config.filter_by_xid_enabled &&
|
|
|
|
config.filter_by_xid != record->xl_xid)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* process the record */
|
|
|
|
if (config.stats == true)
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
XLogDumpCountRecord(&config, &stats, xlogreader_state);
|
2014-09-19 16:33:16 +02:00
|
|
|
else
|
Revamp the WAL record format.
Each WAL record now carries information about the modified relation and
block(s) in a standardized format. That makes it easier to write tools that
need that information, like pg_rewind, prefetching the blocks to speed up
recovery, etc.
There's a whole new API for building WAL records, replacing the XLogRecData
chains used previously. The new API consists of XLogRegister* functions,
which are called for each buffer and chunk of data that is added to the
record. The new API also gives more control over when a full-page image is
written, by passing flags to the XLogRegisterBuffer function.
This also simplifies the XLogReadBufferForRedo() calls. The function can dig
the relation and block number from the WAL record, so they no longer need to
be passed as arguments.
For the convenience of redo routines, XLogReader now disects each WAL record
after reading it, copying the main data part and the per-block data into
MAXALIGNed buffers. The data chunks are not aligned within the WAL record,
but the redo routines can assume that the pointers returned by XLogRecGet*
functions are. Redo routines are now passed the XLogReaderState, which
contains the record in the already-disected format, instead of the plain
XLogRecord.
The new record format also makes the fixed size XLogRecord header smaller,
by removing the xl_len field. The length of the "main data" portion is now
stored at the end of the WAL record, and there's a separate header after
XLogRecord for it. The alignment padding at the end of XLogRecord is also
removed. This compansates for the fact that the new format would otherwise
be more bulky than the old format.
Reviewed by Andres Freund, Amit Kapila, Michael Paquier, Alvaro Herrera,
Fujii Masao.
2014-11-20 16:56:26 +01:00
|
|
|
XLogDumpDisplayRecord(&config, xlogreader_state);
|
2013-02-22 20:46:24 +01:00
|
|
|
|
|
|
|
/* check whether we printed enough */
|
2014-09-19 16:33:16 +02:00
|
|
|
config.already_displayed_records++;
|
2013-02-22 20:46:24 +01:00
|
|
|
if (config.stop_after_records > 0 &&
|
|
|
|
config.already_displayed_records >= config.stop_after_records)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-09-19 16:33:16 +02:00
|
|
|
if (config.stats == true)
|
|
|
|
XLogDumpDisplayStats(&config, &stats);
|
|
|
|
|
2013-02-22 20:46:24 +01:00
|
|
|
if (errormsg)
|
2017-03-08 15:57:17 +01:00
|
|
|
fatal_error("error in WAL record at %X/%X: %s",
|
2013-02-22 20:46:24 +01:00
|
|
|
(uint32) (xlogreader_state->ReadRecPtr >> 32),
|
|
|
|
(uint32) xlogreader_state->ReadRecPtr,
|
|
|
|
errormsg);
|
|
|
|
|
|
|
|
XLogReaderFree(xlogreader_state);
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
|
|
|
|
bad_argument:
|
2016-10-15 18:00:00 +02:00
|
|
|
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
|
2013-02-22 20:46:24 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|