Skip to content

Commit cb70503

Browse files
committed
[Issue #228] use one map per backup for all files
1 parent 367c91b commit cb70503

File tree

7 files changed

+143
-88
lines changed

7 files changed

+143
-88
lines changed

src/backup.c

+9-1
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool
523523
arg->prev_start_lsn = prev_backup_start_lsn;
524524
arg->conn_arg.conn = NULL;
525525
arg->conn_arg.cancel_conn = NULL;
526+
arg->hdr_map = &(current).hdr_map;
526527
arg->thread_num = i+1;
527528
/* By default there are some error */
528529
arg->ret = 1;
@@ -594,6 +595,10 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool
594595
set_min_recovery_point(pg_control, database_path, current.stop_lsn);
595596
}
596597

598+
/* close block header map */
599+
if (current.hdr_map.fp && fclose(current.hdr_map.fp))
600+
elog(ERROR, "Cannot close file \"%s\"", current.hdr_map.path);
601+
597602
/* close ssh session in main thread */
598603
fio_disconnect();
599604

@@ -704,6 +709,9 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool
704709
}
705710
}
706711

712+
if (fio_sync(current.hdr_map.path, FIO_BACKUP_HOST) != 0)
713+
elog(ERROR, "Cannot sync file \"%s\": %s", current.hdr_map.path, strerror(errno));
714+
707715
time(&end_time);
708716
pretty_time_interval(difftime(end_time, start_time),
709717
pretty_time, lengthof(pretty_time));
@@ -2153,7 +2161,7 @@ backup_files(void *arg)
21532161
arguments->nodeInfo->checksum_version,
21542162
arguments->nodeInfo->ptrack_version_num,
21552163
arguments->nodeInfo->ptrack_schema,
2156-
true);
2164+
arguments->hdr_map, true);
21572165
}
21582166
else
21592167
{

src/catalog.c

+21-8
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,11 @@ catalog_get_backup_list(const char *instance_name, time_t requested_backup_id)
474474
backup->database_dir = pgut_malloc(MAXPGPATH);
475475
join_path_components(backup->database_dir, backup->root_dir, DATABASE_DIR);
476476

477+
/* block header map */
478+
backup->hdr_map.path = pgut_malloc(MAXPGPATH);
479+
join_path_components(backup->hdr_map.path, backup->database_dir, HEADER_MAP);
480+
backup->hdr_map.fp = NULL;
481+
477482
/* TODO: save encoded backup id */
478483
backup->backup_id = backup->start_time;
479484
if (requested_backup_id != INVALID_BACKUP_ID
@@ -847,6 +852,11 @@ pgBackupCreateDir(pgBackup *backup)
847852
backup->database_dir = pgut_malloc(MAXPGPATH);
848853
join_path_components(backup->database_dir, backup->root_dir, DATABASE_DIR);
849854

855+
/* block header map */
856+
backup->hdr_map.path = pgut_malloc(MAXPGPATH);
857+
join_path_components(backup->hdr_map.path, backup->database_dir, HEADER_MAP);
858+
backup->hdr_map.fp = NULL;
859+
850860
/* create directories for actual backup files */
851861
for (i = 0; i < parray_num(subdirs); i++)
852862
{
@@ -1909,8 +1919,7 @@ write_backup_filelist(pgBackup *backup, parray *files, const char *root,
19091919
{
19101920
len += sprintf(line+len, ",\"n_headers\":\"%i\"", file->n_headers);
19111921
len += sprintf(line+len, ",\"hdr_crc\":\"%u\"", file->hdr_crc);
1912-
1913-
// elog(INFO, "CRC INT: %li, CRC UINT: %u", file->crc_hdr, file->crc_hdr);
1922+
len += sprintf(line+len, ",\"hdr_off\":\"%li\"", file->hdr_off);
19141923
}
19151924

19161925
sprintf(line+len, "}\n");
@@ -2272,6 +2281,9 @@ pgBackupInit(pgBackup *backup)
22722281
backup->note = NULL;
22732282
backup->content_crc = 0;
22742283

2284+
backup->hdr_map.path = NULL;
2285+
backup->hdr_map.fp = NULL;
2286+
backup->hdr_map.mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
22752287
}
22762288

22772289
/* free pgBackup object */
@@ -2280,12 +2292,13 @@ pgBackupFree(void *backup)
22802292
{
22812293
pgBackup *b = (pgBackup *) backup;
22822294

2283-
pfree(b->primary_conninfo);
2284-
pfree(b->external_dir_str);
2285-
pfree(b->root_dir);
2286-
pfree(b->database_dir);
2287-
pfree(b->note);
2288-
pfree(backup);
2295+
pg_free(b->primary_conninfo);
2296+
pg_free(b->external_dir_str);
2297+
pg_free(b->root_dir);
2298+
pg_free(b->database_dir);
2299+
pg_free(b->note);
2300+
pg_free(b->hdr_map.path);
2301+
pg_free(backup);
22892302
}
22902303

22912304
/* Compare two pgBackup with their IDs (start time) in ascending order */

src/data.c

+59-45
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ typedef struct DataPage
3131
char data[BLCKSZ];
3232
} DataPage;
3333

34-
static BackupPageHeader2* get_data_file_headers(const char *fullpath, pgFile *file, uint32 backup_version);
35-
static void write_page_headers(BackupPageHeader2 *headers, pgFile *file, const char* to_fullpath);
34+
static BackupPageHeader2* get_data_file_headers(HeaderMap *hdr_map, pgFile *file, uint32 backup_version);
35+
static void write_page_headers(BackupPageHeader2 *headers, pgFile *file, HeaderMap *hdr_map);
3636
static bool get_compressed_page_meta(FILE *in, const char *fullpath, BackupPageHeader* bph,
3737
pg_crc32 *crc, bool use_crc32c);
3838

@@ -537,7 +537,8 @@ backup_data_file(ConnectionArgs* conn_arg, pgFile *file,
537537
const char *from_fullpath, const char *to_fullpath,
538538
XLogRecPtr prev_backup_start_lsn, BackupMode backup_mode,
539539
CompressAlg calg, int clevel, uint32 checksum_version,
540-
int ptrack_version_num, const char *ptrack_schema, bool missing_ok)
540+
int ptrack_version_num, const char *ptrack_schema,
541+
HeaderMap *hdr_map, bool missing_ok)
541542
{
542543
int rc;
543544
bool use_pagemap;
@@ -684,7 +685,7 @@ backup_data_file(ConnectionArgs* conn_arg, pgFile *file,
684685
FIN_FILE_CRC32(true, file->crc);
685686

686687
/* dump page headers */
687-
write_page_headers(headers, file, to_fullpath);
688+
write_page_headers(headers, file, hdr_map);
688689

689690
pg_free(errmsg);
690691
pg_free(file->pagemap.bitmap);
@@ -740,7 +741,7 @@ backup_non_data_file(pgFile *file, pgFile *prev_file,
740741
size_t
741742
restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out,
742743
const char *to_fullpath, bool use_bitmap, PageState *checksum_map,
743-
XLogRecPtr shift_lsn, datapagemap_t *lsn_map, bool is_merge)
744+
XLogRecPtr shift_lsn, datapagemap_t *lsn_map, bool use_headers)
744745
{
745746
size_t total_write_len = 0;
746747
char *in_buf = pgut_malloc(STDIO_BUFSIZE);
@@ -818,10 +819,11 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out,
818819
setvbuf(in, in_buf, _IOFBF, STDIO_BUFSIZE);
819820

820821
/* get headers for this file */
821-
if (!is_merge)
822-
headers = get_data_file_headers(from_fullpath, tmp_file, parse_program_version(backup->program_version));
822+
if (use_headers)
823+
headers = get_data_file_headers(&(backup->hdr_map), tmp_file,
824+
parse_program_version(backup->program_version));
823825

824-
if (!is_merge && !headers && tmp_file->n_headers > 0)
826+
if (use_headers && !headers && tmp_file->n_headers > 0)
825827
elog(ERROR, "Failed to get headers for file \"%s\"", from_fullpath);
826828

827829
/*
@@ -1574,7 +1576,7 @@ check_data_file(ConnectionArgs *arguments, pgFile *file,
15741576
/* Valiate pages of datafile in backup one by one */
15751577
bool
15761578
validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
1577-
uint32 checksum_version, uint32 backup_version)
1579+
uint32 checksum_version, uint32 backup_version, HeaderMap *hdr_map)
15781580
{
15791581
size_t read_len = 0;
15801582
bool is_valid = true;
@@ -1595,7 +1597,7 @@ validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
15951597
elog(ERROR, "Cannot open file \"%s\": %s",
15961598
fullpath, strerror(errno));
15971599

1598-
headers = get_data_file_headers(fullpath, file, backup_version);
1600+
headers = get_data_file_headers(hdr_map, file, backup_version);
15991601

16001602
if (!headers && file->n_headers > 0)
16011603
elog(ERROR, "Failed to get headers for file \"%s\"", fullpath);
@@ -2120,12 +2122,11 @@ send_pages(ConnectionArgs* conn_arg, const char *to_fullpath, const char *from_f
21202122
* array of headers.
21212123
*/
21222124
BackupPageHeader2*
2123-
get_data_file_headers(const char *fullpath, pgFile *file, uint32 backup_version)
2125+
get_data_file_headers(HeaderMap *hdr_map, pgFile *file, uint32 backup_version)
21242126
{
2125-
int len;
2126-
FILE *in = NULL;
2127+
size_t read_len = 0;
2128+
FILE *in = NULL;
21272129
pg_crc32 hdr_crc;
2128-
char fullpath_hdr[MAXPGPATH];
21292130
BackupPageHeader2 *headers = NULL;
21302131

21312132
if (backup_version < 20400)
@@ -2134,70 +2135,83 @@ get_data_file_headers(const char *fullpath, pgFile *file, uint32 backup_version)
21342135
if (file->n_headers <= 0)
21352136
return NULL;
21362137

2137-
snprintf(fullpath_hdr, MAXPGPATH, "%s_hdr", fullpath);
2138-
2139-
in = fopen(fullpath_hdr, PG_BINARY_R);
2138+
in = fopen(hdr_map->path, PG_BINARY_R);
21402139

21412140
if (!in)
2142-
elog(ERROR, "Cannot open header file \"%s\": %s", fullpath_hdr, strerror(errno));
2141+
elog(ERROR, "Cannot open header file \"%s\": %s", hdr_map->path, strerror(errno));
2142+
2143+
/* disable buffering */
2144+
setvbuf(in, NULL, _IONBF, BUFSIZ);
2145+
2146+
if (fseek(in, file->hdr_off, SEEK_SET))
2147+
elog(ERROR, "Cannot seek to position %lu in header map \"%s\": %s",
2148+
file->hdr_off, hdr_map->path, strerror(errno));
21432149

21442150
/*
21452151
* the actual number of headers in header file is n+1, last one is a dummy header,
21462152
* used for calculation of compressed_size for actual last header.
21472153
*/
2148-
len = (file->n_headers+1) * sizeof(BackupPageHeader2);
2149-
headers = pgut_malloc(len);
2154+
read_len = (file->n_headers+1) * sizeof(BackupPageHeader2);
2155+
headers = pgut_malloc(read_len);
21502156

2151-
if (fread(headers, 1, len, in) != len)
2152-
elog(ERROR, "Cannot read header file \"%s\": %s", fullpath_hdr, strerror(errno));
2157+
if (fread(headers, 1, read_len, in) != read_len)
2158+
elog(ERROR, "Cannot read header file \"%s\": %s", hdr_map->path, strerror(errno));
21532159

21542160
/* validate checksum */
21552161
INIT_FILE_CRC32(true, hdr_crc);
2156-
COMP_FILE_CRC32(true, hdr_crc, headers, len);
2162+
COMP_FILE_CRC32(true, hdr_crc, headers, read_len);
21572163
FIN_FILE_CRC32(true, hdr_crc);
21582164

21592165
if (hdr_crc != file->hdr_crc)
21602166
elog(ERROR, "Header file crc mismatch \"%s\", current: %u, expected: %u",
2161-
fullpath_hdr, hdr_crc, file->hdr_crc);
2167+
hdr_map->path, hdr_crc, file->hdr_crc);
21622168

21632169
if (fclose(in))
2164-
elog(ERROR, "Cannot close header file \"%s\": %s", fullpath_hdr, strerror(errno));
2170+
elog(ERROR, "Cannot close header file \"%s\": %s", hdr_map->path, strerror(errno));
21652171

21662172
return headers;
21672173
}
21682174

21692175
void
2170-
write_page_headers(BackupPageHeader2 *headers, pgFile *file, const char* to_fullpath)
2176+
write_page_headers(BackupPageHeader2 *headers, pgFile *file, HeaderMap *hdr_map)
21712177
{
2172-
FILE *out = NULL;
2173-
size_t hdr_size = 0;
2174-
char to_fullpath_hdr[MAXPGPATH];
2178+
size_t read_len = 0;
21752179

21762180
if (file->n_headers <= 0)
21772181
return;
21782182

2179-
snprintf(to_fullpath_hdr, MAXPGPATH, "%s_hdr", to_fullpath);
2183+
/* writing to header map must be serialized */
2184+
pthread_lock(&(hdr_map->mutex)); /* what if we crash while trying to obtain mutex? */
21802185

2181-
out = fopen(to_fullpath_hdr, PG_BINARY_W);
2182-
if (out == NULL)
2183-
elog(ERROR, "Cannot open header file \"%s\": %s",
2184-
to_fullpath, strerror(errno));
2185-
2186-
/* update file permission */
2187-
if (chmod(to_fullpath_hdr, FILE_PERMISSION) == -1)
2188-
elog(ERROR, "Cannot change mode of \"%s\": %s", to_fullpath,
2189-
strerror(errno));
2186+
if (!hdr_map->fp)
2187+
{
2188+
hdr_map->fp = fopen(hdr_map->path, PG_BINARY_W);
2189+
if (hdr_map->fp == NULL)
2190+
elog(ERROR, "Cannot open header file \"%s\": %s",
2191+
hdr_map->path, strerror(errno));
2192+
2193+
/* disable buffering for header file */
2194+
setvbuf(hdr_map->fp, NULL, _IONBF, BUFSIZ);
2195+
2196+
/* update file permission */
2197+
if (chmod(hdr_map->path, FILE_PERMISSION) == -1)
2198+
elog(ERROR, "Cannot change mode of \"%s\": %s", hdr_map->path,
2199+
strerror(errno));
2200+
2201+
file->hdr_off = 0;
2202+
}
2203+
else
2204+
file->hdr_off = ftell(hdr_map->fp); /* TODO: replace by counter */
21902205

2191-
hdr_size = (file->n_headers+1) * sizeof(BackupPageHeader2);
2206+
read_len = (file->n_headers+1) * sizeof(BackupPageHeader2);
21922207

21932208
/* calculate checksums */
21942209
INIT_FILE_CRC32(true, file->hdr_crc);
2195-
COMP_FILE_CRC32(true, file->hdr_crc, headers, hdr_size);
2210+
COMP_FILE_CRC32(true, file->hdr_crc, headers, read_len);
21962211
FIN_FILE_CRC32(true, file->hdr_crc);
21972212

2198-
if (fwrite(headers, 1, hdr_size, out) != hdr_size)
2199-
elog(ERROR, "Cannot write to file \"%s\": %s", to_fullpath_hdr, strerror(errno));
2213+
if (fwrite(headers, 1, read_len, hdr_map->fp) != read_len)
2214+
elog(ERROR, "Cannot write to file \"%s\": %s", hdr_map->path, strerror(errno));
22002215

2201-
if (fclose(out))
2202-
elog(ERROR, "Cannot close file \"%s\": %s", to_fullpath_hdr, strerror(errno));
2216+
pthread_mutex_unlock(&(hdr_map->mutex));
22032217
}

src/dir.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -1566,7 +1566,8 @@ dir_read_file_list(const char *root, const char *external_prefix,
15661566
n_blocks,
15671567
n_headers,
15681568
dbOid, /* used for partial restore */
1569-
hdr_crc;
1569+
hdr_crc,
1570+
hdr_off;
15701571
pgFile *file;
15711572

15721573
COMP_FILE_CRC32(true, content_crc, buf, strlen(buf));
@@ -1613,6 +1614,9 @@ dir_read_file_list(const char *root, const char *external_prefix,
16131614
if (get_control_value(buf, "hdr_crc", NULL, &hdr_crc, false))
16141615
file->hdr_crc = (pg_crc32) hdr_crc;
16151616

1617+
if (get_control_value(buf, "hdr_off", NULL, &hdr_off, false))
1618+
file->hdr_off = hdr_off;
1619+
16161620
parray_append(files, file);
16171621
}
16181622

0 commit comments

Comments
 (0)