Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0bdffbc

Browse files
author
Artur Zakirov
committed
Merge branch 'simplify_backup_data_file' into ptrack
2 parents 4cb028c + 547470a commit 0bdffbc

File tree

5 files changed

+649
-300
lines changed

5 files changed

+649
-300
lines changed

backup.c

Lines changed: 173 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,75 @@ backup_cleanup(bool fatal, void *userdata)
11051105
}
11061106
}
11071107

1108+
/* Count bytes in file */
1109+
static long
1110+
file_size(const char *file)
1111+
{
1112+
long r;
1113+
FILE *f = fopen(file, "r");
1114+
1115+
if (!f)
1116+
{
1117+
elog(ERROR, "pg_probackup: could not open file \"%s\" for reading: %s\n",
1118+
file, strerror(errno));
1119+
return -1;
1120+
}
1121+
fseek(f, 0, SEEK_END);
1122+
r = ftell(f);
1123+
fclose(f);
1124+
return r;
1125+
}
1126+
1127+
/*
1128+
* Find corresponding file in previous backup.
1129+
* Compare generations and return true if we don't need full copy
1130+
* of the file, but just part of it.
1131+
*
1132+
* skip_size - size of the file in previous backup. We can skip it
1133+
* and copy just remaining part of the file.
1134+
*/
1135+
bool
1136+
backup_compressed_file_partially(pgFile *file, void *arg, size_t *skip_size)
1137+
{
1138+
bool result = false;
1139+
pgFile *prev_file = NULL;
1140+
size_t current_file_size;
1141+
backup_files_args *arguments = (backup_files_args *) arg;
1142+
1143+
if (arguments->prev_files)
1144+
{
1145+
pgFile **p = (pgFile **) parray_bsearch(arguments->prev_files,
1146+
file, pgFileComparePath);
1147+
if (p)
1148+
prev_file = *p;
1149+
1150+
/* If file's gc generation has changed since last backup, just copy it*/
1151+
if (prev_file && prev_file->generation == file->generation)
1152+
{
1153+
current_file_size = file_size(file->path);
1154+
1155+
if (prev_file->write_size == BYTES_INVALID)
1156+
return false;
1157+
1158+
*skip_size = prev_file->write_size;
1159+
1160+
if (current_file_size >= prev_file->write_size)
1161+
{
1162+
elog(LOG, "Backup file %s partially: prev_size %lu, current_size %lu",
1163+
file->path, prev_file->write_size, current_file_size);
1164+
result = true;
1165+
}
1166+
else
1167+
elog(ERROR, "Something is wrong with %s. current_file_size %lu, prev %lu",
1168+
file->path, current_file_size, prev_file->write_size);
1169+
}
1170+
else
1171+
elog(LOG, "Copy full %s.", file->path);
1172+
}
1173+
1174+
return result;
1175+
}
1176+
11081177
/*
11091178
* Take differential backup at page level.
11101179
*/
@@ -1203,9 +1272,47 @@ backup_files(void *arg)
12031272
}
12041273

12051274
/* copy the file into backup */
1206-
if (!(file->is_datafile
1207-
? backup_data_file(arguments->from_root, arguments->to_root, file, arguments->lsn)
1208-
: copy_file(arguments->from_root, arguments->to_root, file)))
1275+
if (file->is_datafile)
1276+
{
1277+
if (!backup_data_file(arguments->from_root,
1278+
arguments->to_root, file,
1279+
arguments->lsn))
1280+
{
1281+
/* record as skipped file in file_xxx.txt */
1282+
file->write_size = BYTES_INVALID;
1283+
elog(LOG, "skip");
1284+
continue;
1285+
}
1286+
}
1287+
else if (is_compressed_data_file(file))
1288+
{
1289+
size_t skip_size = 0;
1290+
if (backup_compressed_file_partially(file, arguments, &skip_size))
1291+
{
1292+
/* backup cfs segment partly */
1293+
if (!copy_file_partly(arguments->from_root,
1294+
arguments->to_root,
1295+
file, skip_size))
1296+
{
1297+
/* record as skipped file in file_xxx.txt */
1298+
file->write_size = BYTES_INVALID;
1299+
elog(LOG, "skip");
1300+
continue;
1301+
}
1302+
}
1303+
else if (!copy_file(arguments->from_root,
1304+
arguments->to_root,
1305+
file))
1306+
{
1307+
/* record as skipped file in file_xxx.txt */
1308+
file->write_size = BYTES_INVALID;
1309+
elog(LOG, "skip");
1310+
continue;
1311+
}
1312+
}
1313+
else if (!copy_file(arguments->from_root,
1314+
arguments->to_root,
1315+
file))
12091316
{
12101317
/* record as skipped file in file_xxx.txt */
12111318
file->write_size = BYTES_INVALID;
@@ -1254,14 +1361,14 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
12541361
relative = file->path + strlen(root) + 1;
12551362
if (is_pgdata &&
12561363
!path_is_prefix_of_path("base", relative) &&
1257-
/*!path_is_prefix_of_path("global", relative) &&*/
1364+
/*!path_is_prefix_of_path("global", relative) &&*/ //TODO What's wrong with this line?
12581365
!path_is_prefix_of_path("pg_tblspc", relative))
12591366
continue;
12601367

12611368
/* Get file name from path */
12621369
fname = last_dir_separator(relative);
12631370

1264-
/* Remove temp tables */
1371+
/* Remove temp tables from the list */
12651372
if (fname[0] == 't' && isdigit(fname[1]))
12661373
{
12671374
pgFileFree(file);
@@ -1271,7 +1378,7 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
12711378
}
12721379

12731380
path_len = strlen(file->path);
1274-
/* Get link ptrack file to realations files */
1381+
/* Get link ptrack file to relations files */
12751382
if (path_len > 6 && strncmp(file->path+(path_len-6), "ptrack", 6) == 0)
12761383
{
12771384
pgFile *search_file;
@@ -1280,12 +1387,15 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
12801387
while(true) {
12811388
pgFile tmp_file;
12821389
tmp_file.path = pg_strdup(file->path);
1283-
/* I hope segno not more than 999999 */
1390+
1391+
/* Segno fits into 6 digits since it is not more than 4000 */
12841392
if (segno > 0)
12851393
sprintf(tmp_file.path+path_len-7, ".%d", segno);
12861394
else
12871395
tmp_file.path[path_len-7] = '\0';
1396+
12881397
pre_search_file = (pgFile **) parray_bsearch(list_file, &tmp_file, pgFileComparePath);
1398+
12891399
if (pre_search_file != NULL)
12901400
{
12911401
search_file = *pre_search_file;
@@ -1299,6 +1409,7 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
12991409
segno++;
13001410
}
13011411

1412+
/* Remove ptrack file itself from backup list */
13021413
pgFileFree(file);
13031414
parray_remove(list_file, i);
13041415
i--;
@@ -1307,12 +1418,7 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
13071418

13081419
/* compress map file it is not data file */
13091420
if (path_len > 4 && strncmp(file->path+(path_len-4), ".cfm", 4) == 0)
1310-
{
1311-
if (current.backup_mode == BACKUP_MODE_DIFF_PTRACK ||
1312-
current.backup_mode == BACKUP_MODE_DIFF_PAGE)
1313-
elog(ERROR, "You can't use incremental backup with compress tablespace");
13141421
continue;
1315-
}
13161422

13171423
/* name of data file start with digit */
13181424
if (fname == NULL)
@@ -1358,11 +1464,34 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
13581464
pgFile tmp_file;
13591465
tmp_file.path = pg_strdup(file->path);
13601466
tmp_file.path[path_len-4] = '\0';
1361-
pre_search_file = (pgFile **) parray_bsearch(list_file, &tmp_file, pgFileComparePath);
1467+
pre_search_file = (pgFile **) parray_bsearch(list_file,
1468+
&tmp_file, pgFileComparePath);
13621469
if (pre_search_file != NULL)
13631470
{
1471+
FileMap* map;
1472+
int md = open(file->path, O_RDWR|PG_BINARY, 0);
1473+
if (md < 0)
1474+
elog(ERROR, "add_files(). cannot open cfm file '%s'", file->path);
1475+
1476+
map = cfs_mmap(md);
1477+
if (map == MAP_FAILED)
1478+
{
1479+
elog(LOG, "add_files(). cfs_compression_ration failed to map file %s: %m", file->path);
1480+
close(md);
1481+
break;
1482+
}
1483+
1484+
(*pre_search_file)->generation = map->generation;
13641485
(*pre_search_file)->is_datafile = false;
1486+
1487+
if (cfs_munmap(map) < 0)
1488+
elog(LOG, "add_files(). CFS failed to unmap file %s: %m", file->path);
1489+
if (close(md) < 0)
1490+
elog(LOG, "add_files(). CFS failed to close file %s: %m", file->path);
13651491
}
1492+
else
1493+
elog(ERROR, "corresponding segment '%s' is not found", tmp_file.path);
1494+
13661495
pg_free(tmp_file.path);
13671496
}
13681497
}
@@ -1636,3 +1765,34 @@ StreamLog(void *arg)
16361765
PQfinish(conn);
16371766
conn = NULL;
16381767
}
1768+
1769+
1770+
FileMap* cfs_mmap(int md)
1771+
{
1772+
FileMap* map;
1773+
#ifdef WIN32
1774+
HANDLE mh = CreateFileMapping(_get_osfhandle(md), NULL, PAGE_READWRITE,
1775+
0, (DWORD)sizeof(FileMap), NULL);
1776+
if (mh == NULL)
1777+
return (FileMap*)MAP_FAILED;
1778+
1779+
map = (FileMap*)MapViewOfFile(mh, FILE_MAP_ALL_ACCESS, 0, 0, 0);
1780+
CloseHandle(mh);
1781+
if (map == NULL)
1782+
return (FileMap*)MAP_FAILED;
1783+
1784+
#else
1785+
map = (FileMap*)mmap(NULL, sizeof(FileMap),
1786+
PROT_WRITE | PROT_READ, MAP_SHARED, md, 0);
1787+
#endif
1788+
return map;
1789+
}
1790+
1791+
int cfs_munmap(FileMap* map)
1792+
{
1793+
#ifdef WIN32
1794+
return UnmapViewOfFile(map) ? 0 : -1;
1795+
#else
1796+
return munmap(map, sizeof(FileMap));
1797+
#endif
1798+
}

0 commit comments

Comments
 (0)