diff --git a/src/backup.c b/src/backup.c index be5db7a4..d0471590 100644 --- a/src/backup.c +++ b/src/backup.c @@ -755,7 +755,7 @@ do_backup_instance(void) * Entry point of pg_probackup BACKUP subcommand. */ int -do_backup(void) +do_backup(time_t start_time) { bool is_ptrack_support; @@ -839,7 +839,7 @@ do_backup(void) /* Start backup. Update backup status. */ current.status = BACKUP_STATUS_RUNNING; - current.start_time = time(NULL); + current.start_time = start_time; /* Create backup directory and BACKUP_CONTROL_FILE */ if (pgBackupCreateDir(¤t)) diff --git a/src/catalog.c b/src/catalog.c index 43d78f6a..a5bc8ff0 100644 --- a/src/catalog.c +++ b/src/catalog.c @@ -602,6 +602,24 @@ parse_backup_mode(const char *value) return BACKUP_MODE_INVALID; } +const char * +deparse_backup_mode(BackupMode mode) +{ + switch (mode) + { + case BACKUP_MODE_FULL: + return "full"; + case BACKUP_MODE_DIFF_PAGE: + return "page"; + case BACKUP_MODE_DIFF_PTRACK: + return "ptrack"; + case BACKUP_MODE_INVALID: + return "invalid"; + } + + return NULL; +} + /* free pgBackup object */ void pgBackupFree(void *backup) diff --git a/src/pg_probackup.c b/src/pg_probackup.c index 3a5cd047..4b7d837e 100644 --- a/src/pg_probackup.c +++ b/src/pg_probackup.c @@ -170,6 +170,7 @@ static pgut_option options[] = int main(int argc, char *argv[]) { + char *command; char path[MAXPGPATH]; /* Check if backup_path is directory. */ struct stat stat_buf; @@ -235,6 +236,33 @@ main(int argc, char *argv[]) elog(ERROR, "Unknown subcommand"); } + /* + * Make command string before getopt_long() will call. It permutes the + * content of argv. + */ + if (backup_subcmd == BACKUP) + { + int i, + len = 0; + + command = (char *) palloc(sizeof(char) * MAXPGPATH); + command[0] = '\0'; + + for (i = 0; i < argc; i++) + { + int arglen = strlen(argv[i]); + + if (arglen + len > MAXPGPATH) + break; + + strncpy((command +len), argv[i], arglen); + len += arglen; + command[len++] = ' '; + } + + command[len] = '\0'; + } + /* Parse command line arguments */ pgut_getopt(argc, argv, options); @@ -382,7 +410,23 @@ main(int argc, char *argv[]) case INIT: return do_init(); case BACKUP: - return do_backup(); + { + char *backup_id; + const char *backup_mode; + time_t start_time; + + start_time = time(NULL); + backup_id = base36enc(start_time); + backup_mode = deparse_backup_mode(current.backup_mode); + + elog_file(INFO, "pg_probackup version: %s, backup ID: %s, backup mode: %s, instance: %s", + PROGRAM_VERSION, backup_id, backup_mode, instance_name); + elog_file(INFO, "command: %s", command); + + pfree(backup_id); + + return do_backup(start_time); + } case RESTORE: return do_restore_or_validate(current.backup_id, target_time, target_xid, diff --git a/src/pg_probackup.h b/src/pg_probackup.h index 8f0dd345..7c41df86 100644 --- a/src/pg_probackup.h +++ b/src/pg_probackup.h @@ -313,8 +313,9 @@ extern ProbackupSubcmd backup_subcmd; extern const char *pgdata_exclude_dir[]; /* in backup.c */ -extern int do_backup(void); +extern int do_backup(time_t start_time); extern BackupMode parse_backup_mode(const char *value); +extern const char *deparse_backup_mode(BackupMode mode); extern bool fileExists(const char *path); extern void process_block_change(ForkNumber forknum, RelFileNode rnode, BlockNumber blkno); diff --git a/src/utils/logger.c b/src/utils/logger.c index d56e6bcd..75de8583 100644 --- a/src/utils/logger.c +++ b/src/utils/logger.c @@ -48,8 +48,8 @@ typedef enum void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2, 3); -static void elog_internal(int elevel, const char *fmt, va_list args) - pg_attribute_printf(2, 0); +static void elog_internal(int elevel, bool file_only, const char *fmt, va_list args) + pg_attribute_printf(3, 0); /* Functions to work with log files */ static void open_logfile(FILE **file, const char *filename_format); @@ -122,7 +122,7 @@ write_elevel(FILE *stream, int elevel) * Actual implementation for elog() and pg_log(). */ static void -elog_internal(int elevel, const char *fmt, va_list args) +elog_internal(int elevel, bool file_only, const char *fmt, va_list args) { bool write_to_file, write_to_error_log, @@ -135,7 +135,7 @@ elog_internal(int elevel, const char *fmt, va_list args) write_to_file = !logging_to_file && elevel >= LOG_LEVEL_FILE; write_to_error_log = !logging_to_file && elevel >= ERROR && error_log_filename; - write_to_stderr = elevel >= LOG_LEVEL_CONSOLE; + write_to_stderr = elevel >= LOG_LEVEL_CONSOLE && !file_only; /* * There is no need to lock if this is elog() from upper elog() and @@ -251,7 +251,27 @@ elog(int elevel, const char *fmt, ...) return; va_start(args, fmt); - elog_internal(elevel, fmt, args); + elog_internal(elevel, false, fmt, args); + va_end(args); +} + +/* + * Logs only to log file and exit if ERROR or FATAL. + */ +void +elog_file(int elevel, const char *fmt, ...) +{ + va_list args; + + /* + * Do not log message if severity level is less than log_level. + * It is the little optimisation to put it here not in elog_internal(). + */ + if (elevel < LOG_LEVEL_FILE && elevel < ERROR) + return; + + va_start(args, fmt); + elog_internal(elevel, true, fmt, args); va_end(args); } @@ -292,7 +312,7 @@ pg_log(eLogType type, const char *fmt, ...) return; va_start(args, fmt); - elog_internal(elevel, fmt, args); + elog_internal(elevel, false, fmt, args); va_end(args); } diff --git a/src/utils/logger.h b/src/utils/logger.h index dd71f439..315c337a 100644 --- a/src/utils/logger.h +++ b/src/utils/logger.h @@ -44,6 +44,7 @@ extern int log_rotation_age; #undef elog extern void elog(int elevel, const char *fmt, ...) pg_attribute_printf(2, 3); +extern void elog_file(int elevel, const char *fmt, ...) pg_attribute_printf(2, 3); extern void init_logger(const char *root_path);