From 9890dbd31017f8421b2ea33b22f4484c9a75ac86 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Fri, 1 May 2020 16:43:16 -0400 Subject: [PATCH v2 07/11] Introduce bbarchiver abstraction. --- src/backend/replication/Makefile | 1 + src/backend/replication/basebackup_archiver.c | 119 +++++++++++ src/include/replication/basebackup_archiver.h | 195 ++++++++++++++++++ 3 files changed, 315 insertions(+) create mode 100644 src/backend/replication/basebackup_archiver.c create mode 100644 src/include/replication/basebackup_archiver.h diff --git a/src/backend/replication/Makefile b/src/backend/replication/Makefile index 7de4f82882..aacccd350d 100644 --- a/src/backend/replication/Makefile +++ b/src/backend/replication/Makefile @@ -17,6 +17,7 @@ override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS) OBJS = \ backup_manifest.o \ basebackup.o \ + basebackup_archiver.o \ basebackup_libpq.o \ basebackup_progress.o \ basebackup_sink.o \ diff --git a/src/backend/replication/basebackup_archiver.c b/src/backend/replication/basebackup_archiver.c new file mode 100644 index 0000000000..045a8a088e --- /dev/null +++ b/src/backend/replication/basebackup_archiver.c @@ -0,0 +1,119 @@ +/*------------------------------------------------------------------------- + * + * basebackup_archiver.c + * general supporting code for basebackup archiver implementations + * + * Portions Copyright (c) 2010-2020, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/backend/replication/basebackup_archiver.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "replication/basebackup_archiver.h" + +/* Pass begin_tablespace callback to next bbarchiver. */ +void +bbarchiver_forward_begin_tablespace(bbarchiver *archiver, tablespaceinfo *tsinfo) +{ + Assert(archiver->bba_next != NULL); + bbarchiver_begin_tablespace(archiver->bba_next, tsinfo); +} + +/* Pass end_tablespace callback to next bbarchiver. */ +void +bbarchiver_forward_end_tablespace(bbarchiver *archiver) +{ + Assert(archiver->bba_next != NULL); + bbarchiver_end_tablespace(archiver->bba_next); +} + +/* Pass begin_file callback to next bbarchiver. */ +void +bbarchiver_forward_begin_file(bbarchiver *archiver, const char *relative_path, + struct stat *statbuf) +{ + Assert(archiver->bba_next != NULL); + bbarchiver_begin_file(archiver->bba_next, relative_path, statbuf); +} + +/* Pass file_contents callback to next bbarchiver. */ +void +bbarchiver_forward_file_contents(bbarchiver *archiver, const char *data, size_t len) +{ + Assert(archiver->bba_next != NULL); + bbarchiver_file_contents(archiver->bba_next, data, len); +} + +/* Pass end_file callback to next bbarchiver. */ +void +bbarchiver_forward_end_file(bbarchiver *archiver) +{ + Assert(archiver->bba_next != NULL); + bbarchiver_end_file(archiver->bba_next); +} + +/* Pass directory callback to next bbarchiver. */ +void +bbarchiver_forward_directory(bbarchiver *archiver, const char *relative_path, + struct stat *statbuf) +{ + Assert(archiver->bba_next != NULL); + bbarchiver_directory(archiver->bba_next, relative_path, statbuf); +} + +/* Pass symbolic_link callback to next bbarchiver. */ +void +bbarchiver_forward_symbolic_link(bbarchiver *archiver, const char *relative_path, + const char *linktarget, struct stat *statbuf) +{ + Assert(archiver->bba_next != NULL); + bbarchiver_symbolic_link(archiver->bba_next, relative_path, linktarget, statbuf); +} + +/* Ignore begin_tablespace callback. */ +void +bbarchiver_noop_begin_tablespace(bbarchiver *archiver, tablespaceinfo *tsinfo) +{ + /* Do nothing */ +} + +/* Ignore end_tablespace callback. */ +void +bbarchiver_noop_end_tablespace(bbarchiver *archiver) +{ + /* Do nothing */ +} + +/* Ignore begin_file callback. */ +void +bbarchiver_noop_begin_file(bbarchiver *archiver, const char *relative_path, + struct stat *statbuf) +{ + /* Do nothing */ +} + +/* Ignore end_file callback. */ +void +bbarchiver_noop_end_file(bbarchiver *archiver) +{ + /* Do nothing */ +} + +/* Ignore directory callback. */ +void +bbarchiver_noop_directory(bbarchiver *archiver, const char *relative_path, + struct stat *statbuf) +{ + /* Do nothing */ +} + +/* Ignore symbolic_link callback. */ +void +bbarchiver_noop_symbolic_link(bbarchiver *archiver, const char *relative_path, + const char *linktarget, struct stat *statbuf) +{ + /* Do nothing */ +} diff --git a/src/include/replication/basebackup_archiver.h b/src/include/replication/basebackup_archiver.h new file mode 100644 index 0000000000..fce0afa167 --- /dev/null +++ b/src/include/replication/basebackup_archiver.h @@ -0,0 +1,195 @@ +/*------------------------------------------------------------------------- + * + * bbarchiver.h + * iterate over files, directories, and symbolic links encountered as + * part of the base backup process + * + * Portions Copyright (c) 2010-2020, PostgreSQL Global Development Group + * + * src/include/replication/bbarchiver.h + * + *------------------------------------------------------------------------- + */ +#ifndef BASEBACKUP_ARCHIVER_H +#define BASEBACKUP_ARCHIVER_H + +#include + +#include "replication/basebackup.h" +#include "replication/basebackup_sink.h" + +struct bbarchiver; +struct bbarchiver_ops; +typedef struct bbarchiver bbarchiver; +typedef struct bbarchiver_ops bbarchiver_ops; + +/* + * Common data for any type of basebackup archiver. + * + * 'bba_ops' is the relevant callback table. + * + * 'bba_next' is a pointer to another bbarchiver to which this bbarchiver is + * forwarding some or all operations. + * + * If a barchiver needs to store additional state, it can allocate a larger + * structure whose first element is a bbarchiver. + */ +struct bbarchiver +{ + const bbarchiver_ops *bba_ops; + bbarchiver *bba_next; +}; + +/* + * Callbacks for a backup archiver. + * + * Except as otherwise noted, all of these callbacks are required. If a particular + * callback just needs to forward the call to archiver->bba_next, use + * bbarchiver_forward_ as the callback. If a particular (required) + * callback doesn't need to do anything at all, use bbarchiver_noop_ + * as the callback. + * + * Callers should always invoke these callbacks via the bbarchiver_* + * inline functions rather than calling them directly. + */ +struct bbarchiver_ops +{ + /* These callbacks are invoked just before and after visiting each tablespace. */ + void (*begin_tablespace)(bbarchiver *archiver, tablespaceinfo *tsinfo); + void (*end_tablespace)(bbarchiver *archiver); + + /* This callback is invoked each time we begin visiting a plain file. */ + void (*begin_file)(bbarchiver *archiver, const char *relative_path, + struct stat *statbuf); + + /* + * This callback is invoked one or more times for each plain file, with the + * contents of the file passed to it chunk by chunk. + * + * It is optional. If NULL, the file is not read. + */ + void (*file_contents)(bbarchiver *archiver, const char *data, + size_t len); + + /* This callback is invoked each time we finish visiting a plain file. */ + void (*end_file)(bbarchiver *archiver); + + /* This method gets called each time we visit a directory. */ + void (*directory)(bbarchiver *archiver, const char *relative_path, + struct stat *statbuf); + + /* This method gets called each time we visit a symbolic link. */ + void (*symbolic_link)(bbarchiver *archiver, const char *relative_path, + const char *linktarget, struct stat *statbuf); +}; + +/* Dummy callbacks for when a bbarchiver wants to forward operations. */ +extern void bbarchiver_forward_begin_tablespace(bbarchiver *archiver, + tablespaceinfo *tsinfo); +extern void bbarchiver_forward_end_tablespace(bbarchiver *archiver); +extern void bbarchiver_forward_begin_file(bbarchiver *archiver, + const char *relative_path, + struct stat *statbuf); +extern void bbarchiver_forward_file_contents(bbarchiver *archiver, + const char *data, size_t len); +extern void bbarchiver_forward_end_file(bbarchiver *archiver); +extern void bbarchiver_forward_directory(bbarchiver *archiver, + const char *relative_path, + struct stat *statbuf); +extern void bbarchiver_forward_symbolic_link(bbarchiver *archiver, + const char *relative_path, + const char *linktarget, + struct stat *statbuf); + +/* Dummy callbacks for when a bbarchiver wants to do nothing. */ +extern void bbarchiver_noop_begin_tablespace(bbarchiver *archiver, + tablespaceinfo *tsinfo); +extern void bbarchiver_noop_end_tablespace(bbarchiver *archiver); +extern void bbarchiver_noop_begin_file(bbarchiver *archiver, + const char *relative_path, + struct stat *statbuf); +/* if there's nothing to do for file contents, omit callback! */ +extern void bbarchiver_noop_end_file(bbarchiver *archiver); +extern void bbarchiver_noop_directory(bbarchiver *archiver, + const char *relative_path, + struct stat *statbuf); +extern void bbarchiver_noop_symbolic_link(bbarchiver *archiver, + const char *relative_path, + const char *linktarget, + struct stat *statbuf); + +/* Begin visiting a tablespace. */ +static inline void +bbarchiver_begin_tablespace(bbarchiver *archiver, tablespaceinfo *tsinfo) +{ + Assert(archiver->bba_ops->begin_tablespace != NULL); + archiver->bba_ops->begin_tablespace(archiver, tsinfo); +} + +/* Finish visiting a tablespace. */ +static inline void +bbarchiver_end_tablespace(bbarchiver *archiver) +{ + Assert(archiver->bba_ops->end_tablespace != NULL); + archiver->bba_ops->end_tablespace(archiver); +} + +/* Begin visiting a plain file. */ +static inline void +bbarchiver_begin_file(bbarchiver *archiver, const char *relative_path, + struct stat *statbuf) +{ + Assert(archiver->bba_ops->begin_file != NULL); + archiver->bba_ops->begin_file(archiver, relative_path, statbuf); +} + +/* Does this archiver need the contents of the files? */ +static inline bool +bbarchiver_needs_file_contents(bbarchiver *archiver) +{ + return archiver->bba_ops->file_contents != NULL; +} + +/* + * Process contents of a plain file. + * + * Don't call this unless bbarchiver_needs_file_contents returns true. + */ +static inline void +bbarchiver_file_contents(bbarchiver *archiver, const char *data, size_t len) +{ + Assert(archiver->bba_ops->file_contents != NULL); + archiver->bba_ops->file_contents(archiver, data, len); +} + +/* Finish visiting a plain file. */ +static inline void +bbarchiver_end_file(bbarchiver *archiver) +{ + Assert(archiver->bba_ops->end_file != NULL); + archiver->bba_ops->end_file(archiver); +} + +/* Visit a directory. */ +static inline void +bbarchiver_directory(bbarchiver *archiver, const char *relative_path, + struct stat *statbuf) +{ + Assert(archiver->bba_ops->directory != NULL); + archiver->bba_ops->directory(archiver, relative_path, statbuf); +} + +/* Visit a symbolic link. */ +static inline void +bbarchiver_symbolic_link(bbarchiver *archiver, const char *relative_path, + const char *linktarget, struct stat *statbuf) +{ + Assert(archiver->bba_ops->symbolic_link != NULL); + archiver->bba_ops->symbolic_link(archiver, relative_path, linktarget, statbuf); +} + +/* Constructors for various types of archivers. */ +extern bbarchiver *bbarchiver_tar_new(bbsink *sink); +extern bbarchiver *bbarchiver_tarsize_new(void); + +#endif -- 2.24.3 (Apple Git-128)