1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2024-11-28 09:33:54 +02:00
pg_probackup/show.c
Michael Paquier f94c5ab447 Sanitize logging facility
--debug and --verbose had actually the same meaning as they were aimed
at giving to the user information regarding how the process is running,
hence both options are merged into --verbose and use elog(LOG) to decide
if a given message should be printed out depending on the verbosity of
the call. This makes a couple of routines more readable as they do not
depend on any boolean checks.

The "_()" have been removed from the code, those are aimed at being used
for translation but having them mandatorily in each log message is just
useless noise. If needed, pgut.c should be updated in consequence to
have a more portable facility.

At the same time this commit takes care of putting into correct shape
some code paths more in-line with PostgreSQL policy. There are surely
more of this kind of ugly stuff but at this stage things are more simple
and more manageable.
2016-01-14 16:36:39 +09:00

224 lines
5.0 KiB
C

/*-------------------------------------------------------------------------
*
* show.c: show backup catalog.
*
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
*
*-------------------------------------------------------------------------
*/
#include "pg_arman.h"
static void show_backup_list(FILE *out, parray *backup_list, bool show_all);
static void show_backup_detail(FILE *out, pgBackup *backup);
/*
* Show backup catalog information.
* If range is { 0, 0 }, show list of all backup, otherwise show detail of the
* backup indicated by id.
*/
int
do_show(pgBackupRange *range, bool show_all)
{
/*
* Safety check for archive folder, this is necessary to fetch
* the parent TLI from history field generated by server after
* child timeline is chosen.
*/
if (arclog_path == NULL)
elog(ERROR_ARGS,
"required parameter not specified: ARCLOG_PATH (-A, --arclog-path)");
if (pgBackupRangeIsSingle(range))
{
pgBackup *backup;
backup = catalog_get_backup(range->begin);
if (backup == NULL)
{
char timestamp[100];
time2iso(timestamp, lengthof(timestamp), range->begin);
elog(INFO, "backup taken at \"%s\" does not exist.",
timestamp);
/* This is not error case */
return 0;
}
show_backup_detail(stdout, backup);
/* cleanup */
pgBackupFree(backup);
}
else
{
parray *backup_list;
backup_list = catalog_get_backup_list(range);
if (backup_list == NULL)
elog(ERROR_SYSTEM, "can't process any more.");
show_backup_list(stdout, backup_list, show_all);
/* cleanup */
parray_walk(backup_list, pgBackupFree);
parray_free(backup_list);
}
return 0;
}
static void
pretty_size(int64 size, char *buf, size_t len)
{
int exp = 0;
/* minus means the size is invalid */
if (size < 0)
{
strncpy(buf, "----", len);
return;
}
/* determine postfix */
while (size > 9999)
{
++exp;
size /= 1000;
}
switch (exp)
{
case 0:
snprintf(buf, len, INT64_FORMAT "B", size);
break;
case 1:
snprintf(buf, len, INT64_FORMAT "kB", size);
break;
case 2:
snprintf(buf, len, INT64_FORMAT "MB", size);
break;
case 3:
snprintf(buf, len, INT64_FORMAT "GB", size);
break;
case 4:
snprintf(buf, len, INT64_FORMAT "TB", size);
break;
case 5:
snprintf(buf, len, INT64_FORMAT "PB", size);
break;
default:
strncpy(buf, "***", len);
break;
}
}
static TimeLineID
get_parent_tli(TimeLineID child_tli)
{
TimeLineID result = 0;
char path[MAXPGPATH];
char fline[MAXPGPATH];
FILE *fd;
/* Search history file in archives */
snprintf(path, lengthof(path), "%s/%08X.history", arclog_path,
child_tli);
fd = fopen(path, "rt");
if (fd == NULL)
{
if (errno != ENOENT)
elog(ERROR_SYSTEM, "could not open file \"%s\": %s", path,
strerror(errno));
return 0;
}
/*
* Parse the file...
*/
while (fgets(fline, sizeof(fline), fd) != NULL)
{
/* skip leading whitespace and check for # comment */
char *ptr;
char *endptr;
for (ptr = fline; *ptr; ptr++)
{
if (!IsSpace(*ptr))
break;
}
if (*ptr == '\0' || *ptr == '#')
continue;
/* expect a numeric timeline ID as first field of line */
result = (TimeLineID) strtoul(ptr, &endptr, 0);
if (endptr == ptr)
elog(ERROR_CORRUPTED,
"syntax error(timeline ID) in history file: %s",
fline);
}
fclose(fd);
/* TLI of the last line is parent TLI */
return result;
}
static void
show_backup_list(FILE *out, parray *backup_list, bool show_all)
{
int i;
/* show header */
fputs("==========================================================================\n", out);
fputs("Start Mode Current TLI Parent TLI Time Data Status \n", out);
fputs("==========================================================================\n", out);
for (i = 0; i < parray_num(backup_list); i++)
{
pgBackup *backup;
const char *modes[] = { "", "PAGE", "FULL"};
TimeLineID parent_tli;
char timestamp[20];
char duration[20] = "----";
char data_bytes_str[10] = "----";
backup = parray_get(backup_list, i);
/* skip deleted backup */
if (backup->status == BACKUP_STATUS_DELETED && !show_all)
continue;
time2iso(timestamp, lengthof(timestamp), backup->start_time);
if (backup->end_time != (time_t) 0)
snprintf(duration, lengthof(duration), "%lum",
(backup->end_time - backup->start_time) / 60);
/*
* Calculate Data field, in the case of full backup this shows the
* total amount of data. For an differential backup, this size is only
* the difference of data accumulated.
*/
pretty_size(backup->data_bytes, data_bytes_str,
lengthof(data_bytes_str));
/* Get parent timeline before printing */
parent_tli = get_parent_tli(backup->tli);
fprintf(out, "%-19s %-4s %10d %10d %5s %6s %s \n",
timestamp,
modes[backup->backup_mode],
backup->tli,
parent_tli,
duration,
data_bytes_str,
status2str(backup->status));
}
}
static void
show_backup_detail(FILE *out, pgBackup *backup)
{
pgBackupWriteConfigSection(out, backup);
pgBackupWriteResultSection(out, backup);
}