1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2024-11-28 09:33:54 +02:00

Remove date range and start use base36 from start_time as backup ID.

This commit is contained in:
stalkerg 2016-10-31 18:19:11 +03:00
parent d3f3110316
commit 9f2ad9d822
10 changed files with 78 additions and 198 deletions

View File

@ -497,7 +497,7 @@ do_backup(pgBackupOption bkupopt)
elog(LOG, "backup destination is initialized");
/* get list of backups already taken */
backup_list = catalog_get_backup_list(NULL);
backup_list = catalog_get_backup_list(0);
if (!backup_list)
elog(ERROR, "cannot process any more");

View File

@ -106,32 +106,14 @@ IsDir(const char *dirpath, const char *entry)
* The list is sorted in order of descending start time.
*/
parray *
catalog_get_backup_list(const pgBackupRange *range)
catalog_get_backup_list(time_t backup_id)
{
const pgBackupRange range_all = { 0, 0 };
DIR *date_dir = NULL;
struct dirent *date_ent = NULL;
DIR *time_dir = NULL;
struct dirent *time_ent = NULL;
char date_path[MAXPGPATH];
parray *backups = NULL;
pgBackup *backup = NULL;
struct tm *tm;
char begin_date[100];
char begin_time[100];
char end_date[100];
char end_time[100];
if (range == NULL)
range = &range_all;
/* make date/time string */
tm = localtime(&range->begin);
strftime(begin_date, lengthof(begin_date), "%Y%m%d", tm);
strftime(begin_time, lengthof(begin_time), "%H%M%S", tm);
tm = localtime(&range->end);
strftime(end_date, lengthof(end_date), "%Y%m%d", tm);
strftime(end_time, lengthof(end_time), "%H%M%S", tm);
/* open backup root directory */
date_dir = opendir(backup_path);
@ -146,6 +128,8 @@ catalog_get_backup_list(const pgBackupRange *range)
backups = parray_new();
for (; (date_ent = readdir(date_dir)) != NULL; errno = 0)
{
char ini_path[MAXPGPATH];
/* skip not-directory entries and hidden entries */
if (!IsDir(backup_path, date_ent->d_name) || date_ent->d_name[0] == '.')
continue;
@ -154,46 +138,23 @@ catalog_get_backup_list(const pgBackupRange *range)
if (strcmp(date_ent->d_name, RESTORE_WORK_DIR) == 0)
continue;
/* If the date is out of range, skip it. */
if (pgBackupRangeIsValid(range) &&
(strcmp(begin_date, date_ent->d_name) > 0 ||
strcmp(end_date, date_ent->d_name) < 0))
continue;
/* open subdirectory (date directory) and search time directory */
join_path_components(date_path, backup_path, date_ent->d_name);
time_dir = opendir(date_path);
if (time_dir == NULL)
/* read backup information from backup.ini */
snprintf(ini_path, MAXPGPATH, "%s/%s", date_path, BACKUP_INI_FILE);
backup = catalog_read_ini(ini_path);
/* ignore corrupted backup */
if (backup)
{
elog(WARNING, "cannot open directory \"%s\": %s",
date_ent->d_name, strerror(errno));
goto err_proc;
}
for (; (time_ent = readdir(time_dir)) != NULL; errno = 0)
{
char ini_path[MAXPGPATH];
/* skip entries that are directories and hidden directories */
if (!IsDir(date_path, time_ent->d_name) || time_ent->d_name[0] == '.')
continue;
/* If the time is out of range, skip it. */
if (pgBackupRangeIsValid(range) &&
(strcmp(begin_time, time_ent->d_name) > 0 ||
strcmp(end_time, time_ent->d_name) < 0))
continue;
/* read backup information from backup.ini */
snprintf(ini_path, MAXPGPATH, "%s/%s/%s", date_path,
time_ent->d_name, BACKUP_INI_FILE);
backup = catalog_read_ini(ini_path);
/* ignore corrupted backup */
if (backup)
if (backup_id != 0 && backup_id != backup->start_time)
{
parray_append(backups, backup);
backup = NULL;
pgBackupFree(backup);
continue;
}
parray_append(backups, backup);
backup = NULL;
}
if (errno && errno != ENOENT)
{
@ -201,8 +162,6 @@ catalog_get_backup_list(const pgBackupRange *range)
date_ent->d_name, strerror(errno));
goto err_proc;
}
closedir(time_dir);
time_dir = NULL;
}
if (errno)
{
@ -526,16 +485,14 @@ pgBackupCompareIdDesc(const void *l, const void *r)
void
pgBackupGetPath(const pgBackup *backup, char *path, size_t len, const char *subdir)
{
char datetime[20];
struct tm *tm;
char *datetime;
/* generate $BACKUP_PATH/date/time path */
tm = localtime(&backup->start_time);
strftime(datetime, lengthof(datetime), "%Y%m%d/%H%M%S", tm);
datetime = base36enc(backup->start_time);
if (subdir)
snprintf(path, len, "%s/%s/%s", backup_path, datetime, subdir);
else
snprintf(path, len, "%s/%s", backup_path, datetime);
free(datetime);
}
void

View File

@ -15,17 +15,17 @@
static int pgBackupDeleteFiles(pgBackup *backup);
int
do_delete(pgBackupRange *range)
do_delete(time_t backup_id)
{
int i;
int ret;
parray *backup_list;
parray *backup_list;
bool do_delete = false;
XLogRecPtr oldest_lsn = InvalidXLogRecPtr;
TimeLineID oldest_tli;
/* DATE are always required */
if (!pgBackupRangeIsValid(range))
if (backup_id == 0)
elog(ERROR, "required delete range option not specified: delete DATE");
/* Lock backup catalog */
@ -37,7 +37,7 @@ do_delete(pgBackupRange *range)
"another pg_arman is running, stop delete.");
/* Get complete list of backups */
backup_list = catalog_get_backup_list(NULL);
backup_list = catalog_get_backup_list(0);
if (!backup_list)
elog(ERROR, "No backup list found, can't process any more.");
@ -60,7 +60,7 @@ do_delete(pgBackupRange *range)
/* Found the latest full backup */
if (backup->backup_mode >= BACKUP_MODE_FULL &&
backup->status == BACKUP_STATUS_OK &&
backup->start_time <= range->begin)
backup->start_time <= backup_id)
{
do_delete = true;
oldest_lsn = backup->start_lsn;
@ -192,7 +192,7 @@ pgBackupDelete(int keep_generations, int keep_days)
}
/* Get a complete list of backups. */
backup_list = catalog_get_backup_list(NULL);
backup_list = catalog_get_backup_list(0);
/* Find target backups to be deleted */
backup_num = 0;

View File

@ -50,7 +50,6 @@ static TimeLineID target_tli;
static bool show_all = false;
static void opt_backup_mode(pgut_option *opt, const char *arg);
static void parse_range(pgBackupRange *range, const char *arg1, const char *arg2);
static pgut_option options[] =
{
@ -87,9 +86,8 @@ int
main(int argc, char *argv[])
{
const char *cmd = NULL;
const char *range1 = NULL;
const char *range2 = NULL;
pgBackupRange range;
const char *backup_id_string = NULL;
time_t backup_id = 0;
int i;
/* do not buffer progress messages */
@ -110,10 +108,8 @@ main(int argc, char *argv[])
strcmp(cmd, "validate") != 0 &&
strcmp(cmd, "delete") != 0)
break;
} else if (range1 == NULL)
range1 = argv[i];
else if (range2 == NULL)
range2 = argv[i];
} else if (backup_id_string == NULL)
backup_id_string = argv[i];
else
elog(ERROR, "too many arguments");
}
@ -125,13 +121,8 @@ main(int argc, char *argv[])
return 1;
}
/* get object range argument if any */
if (range1 && range2)
parse_range(&range, range1, range2);
else if (range1)
parse_range(&range, range1, "");
else
range.begin = range.end = 0;
if (backup_id_string != NULL)
backup_id = base36dec(backup_id_string);
/* Read default configuration from file. */
if (backup_path)
@ -195,20 +186,17 @@ main(int argc, char *argv[])
if (res != 0)
return res;
/* If validation has been requested, do it */
range.begin = current.start_time;
range.end = current.start_time + 1;
do_validate(&range);
do_validate(current.start_time);
}
else if (pg_strcasecmp(cmd, "restore") == 0)
return do_restore(target_time, target_xid,
target_inclusive, target_tli);
else if (pg_strcasecmp(cmd, "show") == 0)
return do_show(&range, show_all);
return do_show(backup_id, show_all);
else if (pg_strcasecmp(cmd, "validate") == 0)
return do_validate(&range);
return do_validate(backup_id);
else if (pg_strcasecmp(cmd, "delete") == 0)
return do_delete(&range);
return do_delete(backup_id);
else
elog(ERROR, "invalid command \"%s\"", cmd);
@ -253,83 +241,6 @@ pgut_help(bool details)
printf(_(" -a, --show-all show deleted backup too\n"));
}
/*
* Create range object from one or two arguments.
* All not-digit characters in the argument(s) are ignored.
* Both arg1 and arg2 must be valid pointer.
*/
static void
parse_range(pgBackupRange *range, const char *arg1, const char *arg2)
{
size_t len = strlen(arg1) + strlen(arg2) + 1;
char *tmp;
int num;
struct tm tm;
tmp = pgut_malloc(len);
tmp[0] = '\0';
if (arg1 != NULL)
remove_not_digit(tmp, len, arg1);
if (arg2 != NULL)
remove_not_digit(tmp + strlen(tmp), len - strlen(tmp), arg2);
memset(&tm, 0, sizeof(tm));
tm.tm_year = 0; /* tm_year is year - 1900 */
tm.tm_mon = 0; /* tm_mon is 0 - 11 */
tm.tm_mday = 1; /* tm_mday is 1 - 31 */
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
num = sscanf(tmp, "%04d %02d %02d %02d %02d %02d",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
&tm.tm_hour, &tm.tm_min, &tm.tm_sec);
if (num < 1)
{
if (strcmp(tmp,"") != 0)
elog(ERROR, "supplied id(%s) is invalid", tmp);
else
elog(ERROR, "arguments are invalid. near \"%s\"", arg1);
}
free(tmp);
/* adjust year and month to convert to time_t */
tm.tm_year -= 1900;
if (num > 1)
tm.tm_mon -= 1;
tm.tm_isdst = -1;
if (!IsValidTime(tm))
elog(ERROR, "supplied time(%s) is invalid.", arg1);
range->begin = mktime(&tm);
switch (num)
{
case 1:
tm.tm_year++;
break;
case 2:
tm.tm_mon++;
break;
case 3:
tm.tm_mday++;
break;
case 4:
tm.tm_hour++;
break;
case 5:
tm.tm_min++;
break;
case 6:
tm.tm_sec++;
break;
}
range->end = mktime(&tm);
range->end--;
}
static void
opt_backup_mode(pgut_option *opt, const char *arg)
{

View File

@ -66,17 +66,6 @@ typedef struct pgFile
datapagemap_t pagemap;
} pgFile;
typedef struct pgBackupRange
{
time_t begin;
time_t end; /* begin +1 when one backup is target */
} pgBackupRange;
#define pgBackupRangeIsValid(range) \
(((range)->begin != (time_t) 0) || ((range)->end != (time_t) 0))
#define pgBackupRangeIsSingle(range) \
(pgBackupRangeIsValid(range) && (range)->begin == ((range)->end))
#define IsValidTime(tm) \
((tm.tm_sec >= 0 && tm.tm_sec <= 60) && /* range check for tm_sec (0-60) */ \
(tm.tm_min >= 0 && tm.tm_min <= 59) && /* range check for tm_min (0-59) */ \
@ -233,10 +222,10 @@ extern int do_restore(const char *target_time,
extern int do_init(void);
/* in show.c */
extern int do_show(pgBackupRange *range, bool show_all);
extern int do_show(time_t backup_id, bool show_all);
/* in delete.c */
extern int do_delete(pgBackupRange *range);
extern int do_delete(time_t backup_id);
extern void pgBackupDelete(int keep_generations, int keep_days);
/* in fetch.c */
@ -246,14 +235,14 @@ extern char *slurpFile(const char *datadir,
bool safe);
/* in validate.c */
extern int do_validate(pgBackupRange *range);
extern int do_validate(time_t backup_id);
extern void pgBackupValidate(pgBackup *backup,
bool size_only,
bool for_get_timeline);
/* in catalog.c */
extern pgBackup *catalog_get_backup(time_t timestamp);
extern parray *catalog_get_backup_list(const pgBackupRange *range);
extern parray *catalog_get_backup_list(time_t backup_id);
extern pgBackup *catalog_get_last_data_backup(parray *backup_list,
TimeLineID tli);
@ -315,6 +304,8 @@ extern void remove_trailing_space(char *buf, int comment_mark);
extern void remove_not_digit(char *buf, size_t len, const char *str);
extern XLogRecPtr get_last_ptrack_lsn(void);
extern uint32 get_data_checksum_version(bool safe);
extern char *base36enc(long unsigned int value);
extern long unsigned int base36dec(const char *text);
/* in status.c */
extern bool is_pg_running(void);

View File

@ -89,7 +89,7 @@ do_restore(const char *target_time,
elog(ERROR, "cannot create recovery.conf. specified args are invalid.");
/* get list of backups. (index == 0) is the last backup */
backups = catalog_get_backup_list(NULL);
backups = catalog_get_backup_list(0);
if (!backups)
elog(ERROR, "cannot process any more.");

21
show.c
View File

@ -18,22 +18,22 @@ static void show_backup_detail(FILE *out, pgBackup *backup);
* backup indicated by id.
*/
int
do_show(pgBackupRange *range, bool show_all)
do_show(time_t backup_id, 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 (pgBackupRangeIsSingle(range))
if (backup_id != 0)
{
pgBackup *backup;
backup = catalog_get_backup(range->begin);
backup = catalog_get_backup(backup_id);
if (backup == NULL)
{
char timestamp[100];
time2iso(timestamp, lengthof(timestamp), range->begin);
time2iso(timestamp, lengthof(timestamp), backup_id);
elog(INFO, "backup taken at \"%s\" does not exist.",
timestamp);
/* This is not error case */
@ -48,7 +48,7 @@ do_show(pgBackupRange *range, bool show_all)
{
parray *backup_list;
backup_list = catalog_get_backup_list(range);
backup_list = catalog_get_backup_list(backup_id);
if (backup_list == NULL)
elog(ERROR, "can't process any more.");
@ -165,9 +165,9 @@ 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);
fputs("===================================================================================\n", out);
fputs("ID Stop Mode Current TLI Parent TLI Time Data Status \n", out);
fputs("===================================================================================\n", out);
for (i = 0; i < parray_num(backup_list); i++)
{
@ -184,7 +184,7 @@ show_backup_list(FILE *out, parray *backup_list, bool show_all)
if (backup->status == BACKUP_STATUS_DELETED && !show_all)
continue;
time2iso(timestamp, lengthof(timestamp), backup->start_time);
time2iso(timestamp, lengthof(timestamp), backup->end_time);
if (backup->end_time != (time_t) 0)
snprintf(duration, lengthof(duration), "%lum",
(backup->end_time - backup->start_time) / 60);
@ -200,7 +200,8 @@ show_backup_list(FILE *out, parray *backup_list, bool show_all)
/* Get parent timeline before printing */
parent_tli = get_parent_tli(backup->tli);
fprintf(out, "%-19s %-6s %10d %10d %5s %6s %s \n",
fprintf(out, "%-8s %-19s %-6s %10d %10d %5s %6s %s \n",
base36enc(backup->start_time),
timestamp,
modes[backup->backup_mode],
backup->tli,

View File

@ -95,8 +95,8 @@ function get_time_last_backup()
name_os=`uname`
if [ "$name_os" == "SunOS" ]
then
pg_arman -B ${BACKUP_PATH} show | gtail -n +4 | head -n 1 | awk '{print($1, $2)}'
pg_arman -B ${BACKUP_PATH} show | gtail -n +4 | head -n 1 | awk '{print($1)}'
else
pg_arman -B ${BACKUP_PATH} show | tail -n +4 | head -n 1 | awk '{print($1, $2)}'
pg_arman -B ${BACKUP_PATH} show | tail -n +4 | head -n 1 | awk '{print($1)}'
fi
}

22
util.c
View File

@ -13,6 +13,26 @@
#include "storage/bufpage.h"
char *base36enc(long unsigned int value)
{
char base36[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
/* log(2**64) / log(36) = 12.38 => max 13 char + '\0' */
char buffer[14];
unsigned int offset = sizeof(buffer);
buffer[--offset] = '\0';
do {
buffer[--offset] = base36[value % 36];
} while (value /= 36);
return strdup(&buffer[offset]); // warning: this must be free-d by the user
}
long unsigned int base36dec(const char *text)
{
return strtoul(text, NULL, 36);
}
static void
checkControlFile(ControlFileData *ControlFile)
{
@ -24,7 +44,7 @@ checkControlFile(ControlFileData *ControlFile)
FIN_CRC32C(crc);
/* Then compare it */
if (!EQ_CRC32C(crc, ControlFile->crc))
if (!EQ_CRC32C(crc, ControlFile->crc))
elog(ERROR, "Calculated CRC checksum does not match value stored in file.\n"
"Either the file is corrupt, or it has a different layout than this program\n"
"is expecting. The results below are untrustworthy.");

View File

@ -18,7 +18,7 @@ static bool pgBackupValidateFiles(parray *files, const char *root, bool size_onl
* If any of files are corrupted, update its stutus to CORRUPT.
*/
int
do_validate(pgBackupRange *range)
do_validate(time_t backup_id)
{
int i;
parray *backup_list;
@ -30,7 +30,7 @@ do_validate(pgBackupRange *range)
another_pg_arman = true;
/* get backup list matches given range */
backup_list = catalog_get_backup_list(range);
backup_list = catalog_get_backup_list(backup_id);
if (!backup_list)
elog(ERROR, "cannot process any more.");