1/*-------------------------------------------------------------------------
4 * store basebackup archives on the server
7 * src/backend/backup/basebackup_server.c
9 *-------------------------------------------------------------------------
23 /* Common information for all types of sink. */
26 /* Directory in which backup is to be stored. */
29 /* Currently open file (or 0 if nothing open). */
32 /* Current file position. */
37 const char *archive_name);
57 * Create a new 'server' bbsink.
68 /* Replication permission is not sufficient in this case. */
72 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
73 errmsg(
"permission denied to create backup stored on server"),
74 errdetail(
"Only roles with privileges of the \"%s\" role may create a backup stored on the server.",
75 "pg_write_server_files")));
79 * It's not a good idea to store your backups in the same directory that
80 * you're backing up. If we allowed a relative path here, that could
81 * easily happen accidentally, so we don't. The user could still
82 * accomplish the same thing by including the absolute path to $PGDATA in
83 * the pathname, but that's likely an intentional bad decision rather than
89 errmsg(
"relative path not allowed for backup stored on server")));
96 * Does not exist, so create it using the same permissions we'd
97 * use for a new subdirectory of the data directory itself.
102 errmsg(
"could not create directory \"%s\": %m", pathname)));
112 /* Exists, not empty. */
114 (
errcode(ERRCODE_DUPLICATE_FILE),
115 errmsg(
"directory \"%s\" exists but is not empty",
120 /* Access problem. */
123 errmsg(
"could not access directory \"%s\": %m",
131 * Open the correct output file for this archive.
145 O_CREAT | O_EXCL | O_WRONLY |
PG_BINARY);
146 if (mysink->
file <= 0)
157 * Write the data to the output file.
166 mysink->
filepos, WAIT_EVENT_BASEBACKUP_WRITE);
173 errmsg(
"could not write file \"%s\": %m",
175 errhint(
"Check free disk space.")));
176 /* short write: complain appropriately */
179 errmsg(
"could not write file \"%s\": wrote only %d of %d bytes at offset %u",
181 nbytes, (
int)
len, (
unsigned) mysink->
filepos),
182 errhint(
"Check free disk space.")));
191 * fsync and close the current output file.
199 * We intentionally don't use data_sync_elevel here, because the server
200 * shouldn't PANIC just because we can't guarantee that the backup has
201 * been written down to disk. Running recovery won't fix anything in this
204 if (
FileSync(mysink->
file, WAIT_EVENT_BASEBACKUP_SYNC) < 0)
207 errmsg(
"could not fsync file \"%s\": %m",
211 /* We're done with this file now. */
220 * Open the output file to which we will write the manifest.
222 * Just like pg_basebackup, we write the manifest first under a temporary
223 * name and then rename it into place after fsync. That way, if the manifest
224 * is there and under the correct name, the user can be sure that the backup
238 O_CREAT | O_EXCL | O_WRONLY |
PG_BINARY);
239 if (mysink->
file <= 0)
242 errmsg(
"could not create file \"%s\": %m", tmp_filename)));
250 * Each chunk of manifest data is sent using a CopyData message.
259 mysink->
filepos, WAIT_EVENT_BASEBACKUP_WRITE);
266 errmsg(
"could not write file \"%s\": %m",
268 errhint(
"Check free disk space.")));
269 /* short write: complain appropriately */
272 errmsg(
"could not write file \"%s\": wrote only %d of %d bytes at offset %u",
274 nbytes, (
int)
len, (
unsigned) mysink->
filepos),
275 errhint(
"Check free disk space.")));
284 * fsync the backup manifest, close the file, and then rename it into place.
293 /* We're done with this file now. */
298 * Rename it into place. This also fsyncs the temporary file, so we don't
299 * need to do that here. We don't use data_sync_elevel here for the same
300 * reasons as in bbsink_server_end_archive.
bool has_privs_of_role(Oid member, Oid role)
struct bbsink_server bbsink_server
static void bbsink_server_end_manifest(bbsink *sink)
static const bbsink_ops bbsink_server_ops
static void bbsink_server_archive_contents(bbsink *sink, size_t len)
static void bbsink_server_end_archive(bbsink *sink)
static void bbsink_server_manifest_contents(bbsink *sink, size_t len)
static void bbsink_server_begin_manifest(bbsink *sink)
bbsink * bbsink_server_new(bbsink *next, char *pathname)
static void bbsink_server_begin_archive(bbsink *sink, const char *archive_name)
void bbsink_forward_begin_backup(bbsink *sink)
void bbsink_forward_begin_manifest(bbsink *sink)
void bbsink_forward_end_backup(bbsink *sink, XLogRecPtr endptr, TimeLineID endtli)
void bbsink_forward_cleanup(bbsink *sink)
void bbsink_forward_manifest_contents(bbsink *sink, size_t len)
void bbsink_forward_end_archive(bbsink *sink)
void bbsink_forward_archive_contents(bbsink *sink, size_t len)
void bbsink_forward_begin_archive(bbsink *sink, const char *archive_name)
void bbsink_forward_end_manifest(bbsink *sink)
int errcode_for_file_access(void)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
int MakePGDirectory(const char *directoryName)
int durable_rename(const char *oldfile, const char *newfile, int elevel)
char * FilePathName(File file)
int FileSync(File file, uint32 wait_event_info)
void FileClose(File file)
File PathNameOpenFile(const char *fileName, int fileFlags)
static ssize_t FileWrite(File file, const void *buffer, size_t amount, off_t offset, uint32 wait_event_info)
Assert(PointerIsAligned(start, uint64))
void pfree(void *pointer)
void * palloc0(Size size)
#define is_absolute_path(filename)
int pg_check_dir(const char *dir)
char * psprintf(const char *fmt,...)
void(* begin_backup)(bbsink *sink)
const bbsink_ops * bbs_ops
void StartTransactionCommand(void)
void CommitTransactionCommand(void)