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

Commit fed1ec6

Browse files
committed
Merge branch 'PGPRO-177_cfs_backup' into PGPROEE9_6
2 parents 8c4bd45 + b2184c6 commit fed1ec6

File tree

5 files changed

+508
-23
lines changed

5 files changed

+508
-23
lines changed

contrib/pg_probackup/backup.c

Lines changed: 177 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,76 @@ backup_cleanup(bool fatal, void *userdata)
11091109
}
11101110
}
11111111

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

12091279
/* copy the file into backup */
1210-
if (!(file->is_datafile
1211-
? backup_data_file(arguments->from_root, arguments->to_root, file, arguments->lsn)
1212-
: copy_file(arguments->from_root, arguments->to_root, file)))
1280+
if (file->is_datafile)
1281+
{
1282+
if (!backup_data_file(arguments->from_root,
1283+
arguments->to_root, file,
1284+
arguments->lsn))
1285+
{
1286+
/* record as skipped file in file_xxx.txt */
1287+
file->write_size = BYTES_INVALID;
1288+
elog(LOG, "skip");
1289+
continue;
1290+
}
1291+
}
1292+
else if (is_compressed_data_file(file))
1293+
{
1294+
size_t skip_size = 0;
1295+
if (backup_compressed_file_partially(file, arguments, &skip_size))
1296+
{
1297+
/* backup cfs segment partly */
1298+
if (!copy_file_partly(arguments->from_root,
1299+
arguments->to_root,
1300+
file, skip_size))
1301+
{
1302+
/* record as skipped file in file_xxx.txt */
1303+
file->write_size = BYTES_INVALID;
1304+
elog(LOG, "skip");
1305+
continue;
1306+
}
1307+
}
1308+
else if (!copy_file(arguments->from_root,
1309+
arguments->to_root,
1310+
file))
1311+
{
1312+
/* record as skipped file in file_xxx.txt */
1313+
file->write_size = BYTES_INVALID;
1314+
elog(LOG, "skip");
1315+
continue;
1316+
}
1317+
}
1318+
else if (!copy_file(arguments->from_root,
1319+
arguments->to_root,
1320+
file))
12131321
{
12141322
/* record as skipped file in file_xxx.txt */
12151323
file->write_size = BYTES_INVALID;
@@ -1258,14 +1366,14 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
12581366
relative = file->path + strlen(root) + 1;
12591367
if (is_pgdata &&
12601368
!path_is_prefix_of_path("base", relative) &&
1261-
/*!path_is_prefix_of_path("global", relative) &&*/
1369+
/*!path_is_prefix_of_path("global", relative) &&*/ //TODO What's wrong with this line?
12621370
!path_is_prefix_of_path("pg_tblspc", relative))
12631371
continue;
12641372

12651373
/* Get file name from path */
12661374
fname = last_dir_separator(relative);
12671375

1268-
/* Remove temp tables */
1376+
/* Remove temp tables from the list */
12691377
if (fname[0] == 't' && isdigit(fname[1]))
12701378
{
12711379
pgFileFree(file);
@@ -1275,7 +1383,7 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
12751383
}
12761384

12771385
path_len = strlen(file->path);
1278-
/* Get link ptrack file to realations files */
1386+
/* Get link ptrack file to relations files */
12791387
if (path_len > 6 && strncmp(file->path+(path_len-6), "ptrack", 6) == 0)
12801388
{
12811389
pgFile *search_file;
@@ -1284,12 +1392,15 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
12841392
while(true) {
12851393
pgFile tmp_file;
12861394
tmp_file.path = pg_strdup(file->path);
1287-
/* I hope segno not more than 999999 */
1395+
1396+
/* Segno fits into 6 digits since it is not more than 4000 */
12881397
if (segno > 0)
12891398
sprintf(tmp_file.path+path_len-7, ".%d", segno);
12901399
else
12911400
tmp_file.path[path_len-7] = '\0';
1401+
12921402
pre_search_file = (pgFile **) parray_bsearch(list_file, &tmp_file, pgFileComparePath);
1403+
12931404
if (pre_search_file != NULL)
12941405
{
12951406
search_file = *pre_search_file;
@@ -1303,6 +1414,7 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
13031414
segno++;
13041415
}
13051416

1417+
/* Remove ptrack file itself from backup list */
13061418
pgFileFree(file);
13071419
parray_remove(list_file, i);
13081420
i--;
@@ -1312,9 +1424,9 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
13121424
/* compress map file it is not data file */
13131425
if (path_len > 4 && strncmp(file->path+(path_len-4), ".cfm", 4) == 0)
13141426
{
1315-
if (current.backup_mode == BACKUP_MODE_DIFF_PTRACK ||
1316-
current.backup_mode == BACKUP_MODE_DIFF_PAGE)
1317-
elog(ERROR, "You can't use incremental backup with compress tablespace");
1427+
if (current.backup_mode == BACKUP_MODE_DIFF_PAGE)
1428+
elog(ERROR, "You can't use PAGE mode backup with compressed tablespace.\n"
1429+
"Try FULL or PTRACK mode instead.");
13181430
continue;
13191431
}
13201432

@@ -1362,11 +1474,34 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
13621474
pgFile tmp_file;
13631475
tmp_file.path = pg_strdup(file->path);
13641476
tmp_file.path[path_len-4] = '\0';
1365-
pre_search_file = (pgFile **) parray_bsearch(list_file, &tmp_file, pgFileComparePath);
1477+
pre_search_file = (pgFile **) parray_bsearch(list_file,
1478+
&tmp_file, pgFileComparePath);
13661479
if (pre_search_file != NULL)
13671480
{
1481+
FileMap* map;
1482+
int md = open(file->path, O_RDWR|PG_BINARY, 0);
1483+
if (md < 0)
1484+
elog(ERROR, "add_files(). cannot open cfm file '%s'", file->path);
1485+
1486+
map = cfs_mmap(md);
1487+
if (map == MAP_FAILED)
1488+
{
1489+
elog(LOG, "add_files(). cfs_compression_ration failed to map file %s: %m", file->path);
1490+
close(md);
1491+
break;
1492+
}
1493+
1494+
(*pre_search_file)->generation = map->generation;
13681495
(*pre_search_file)->is_datafile = false;
1496+
1497+
if (cfs_munmap(map) < 0)
1498+
elog(LOG, "add_files(). CFS failed to unmap file %s: %m", file->path);
1499+
if (close(md) < 0)
1500+
elog(LOG, "add_files(). CFS failed to close file %s: %m", file->path);
13691501
}
1502+
else
1503+
elog(ERROR, "corresponding segment '%s' is not found", tmp_file.path);
1504+
13701505
pg_free(tmp_file.path);
13711506
}
13721507
}
@@ -1638,3 +1773,34 @@ StreamLog(void *arg)
16381773
PQfinish(conn);
16391774
conn = NULL;
16401775
}
1776+
1777+
1778+
FileMap* cfs_mmap(int md)
1779+
{
1780+
FileMap* map;
1781+
#ifdef WIN32
1782+
HANDLE mh = CreateFileMapping(_get_osfhandle(md), NULL, PAGE_READWRITE,
1783+
0, (DWORD)sizeof(FileMap), NULL);
1784+
if (mh == NULL)
1785+
return (FileMap*)MAP_FAILED;
1786+
1787+
map = (FileMap*)MapViewOfFile(mh, FILE_MAP_ALL_ACCESS, 0, 0, 0);
1788+
CloseHandle(mh);
1789+
if (map == NULL)
1790+
return (FileMap*)MAP_FAILED;
1791+
1792+
#else
1793+
map = (FileMap*)mmap(NULL, sizeof(FileMap),
1794+
PROT_WRITE | PROT_READ, MAP_SHARED, md, 0);
1795+
#endif
1796+
return map;
1797+
}
1798+
1799+
int cfs_munmap(FileMap* map)
1800+
{
1801+
#ifdef WIN32
1802+
return UnmapViewOfFile(map) ? 0 : -1;
1803+
#else
1804+
return munmap(map, sizeof(FileMap));
1805+
#endif
1806+
}

0 commit comments

Comments
 (0)