Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf8ad8c2

Browse files
committed
draft
1 parent5190d57 commitf8ad8c2

File tree

6 files changed

+315
-35
lines changed

6 files changed

+315
-35
lines changed

‎contrib/pg_probackup/backup.c

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

1112+
/*
1113+
* Count bytes in file
1114+
*/
1115+
staticlong
1116+
file_size(constchar*file)
1117+
{
1118+
longr;
1119+
FILE*f=fopen(file,"r");
1120+
1121+
if (!f)
1122+
{
1123+
fprintf(stderr,_("%s: could not open file \"%s\" for reading: %s\n"),
1124+
progname,file,strerror(errno));
1125+
return-1;
1126+
}
1127+
fseek(f,0,SEEK_END);
1128+
r=ftell(f);
1129+
fclose(f);
1130+
returnr;
1131+
}
1132+
11121133
/*
11131134
* Take differential backup at page level.
11141135
*/
@@ -1117,7 +1138,6 @@ backup_files(void *arg)
11171138
{
11181139
inti;
11191140
structtimevaltv;
1120-
11211141
backup_files_args*arguments= (backup_files_args*)arg;
11221142

11231143
gettimeofday(&tv,NULL);
@@ -1221,39 +1241,56 @@ backup_files(void *arg)
12211241
}
12221242
else
12231243
{
1224-
/* Check if the file is a cfs relation's segment */
1244+
/* Checkfirstif the file is a cfs relation's segment */
12251245
boolis_cfs_relation_segment= false;
12261246
pgFiletmp_file;
12271247
pgFile**pre_search_file;
1248+
pgFile*prev_file=NULL;
1249+
12281250
tmp_file.path=psprintf("%s.cfm",file->path);
12291251
pre_search_file= (pgFile**)parray_bsearch(arguments->files,&tmp_file,pgFileComparePath);
12301252
if (pre_search_file!=NULL)
12311253
{
1232-
is_cfs_relation_segment= true;
1233-
/* TODO If we don't have ptrack simply copy the file */
1234-
if (file->pagemap.bitmapsize==0)
1254+
/* Now check if it's generation has changed since last backup */
1255+
if (arguments->prev_files)
12351256
{
1236-
is_cfs_relation_segment= false;
1237-
elog(NOTICE,"1 file '%s' is a cfs relation's segment, bitmapsize == 0 \n",file->path);
1257+
pgFile**p= (pgFile**)parray_bsearch(arguments->prev_files,file,pgFileComparePath);
1258+
if (p)
1259+
prev_file=*p;
1260+
elog(NOTICE,"file '%s' is a cfs relation's segment generation prev %d, now %d",
1261+
file->path,prev_file->generation,file->generation);
1262+
1263+
if (prev_file&&prev_file->generation==file->generation)
1264+
{
1265+
elog(NOTICE,"prev->write_size %lu, file_size %lu",prev_file->write_size,file_size(file->path));
1266+
if (prev_file->write_size==file_size(file->path))
1267+
{
1268+
elog(NOTICE,"File hasn't changed since last backup. Don't copy at all");
1269+
is_cfs_relation_segment= true;
1270+
}
1271+
else
1272+
{
1273+
elog(NOTICE,"Backup part of the file. %s",file->path);
1274+
is_cfs_relation_segment= true;
1275+
}
1276+
}
12381277
}
12391278
}
12401279
pg_free(tmp_file.path);
12411280

12421281

12431282
if (is_cfs_relation_segment)
12441283
{
1245-
/*
1246-
* TODO backup cfs segment
1247-
* see backup_data_file()
1248-
*/
1249-
elog(NOTICE,"2 file '%s' is a cfs relation's segment \n",file->path);
1250-
elog(NOTICE,"2 file->pagemap.bitmapsize = %d",file->pagemap.bitmapsize);
1251-
datapagemap_iterator_t*iter;
1252-
BlockNumberblknum=0;
1253-
1254-
iter=datapagemap_iterate(&file->pagemap);
1255-
while(datapagemap_next(iter,&blknum))
1256-
elog(NOTICE,"2 blknum %u",blknum);
1284+
/* backup cfs segment partly */
1285+
if (!copy_file_partly(arguments->from_root,
1286+
arguments->to_root,
1287+
file,prev_file->write_size))
1288+
{
1289+
/* record as skipped file in file_xxx.txt */
1290+
file->write_size=BYTES_INVALID;
1291+
elog(LOG,"skip");
1292+
continue;
1293+
}
12571294
}
12581295
elseif (!copy_file(arguments->from_root,
12591296
arguments->to_root,
@@ -1338,16 +1375,32 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
13381375
sprintf(tmp_file.path+path_len-7,".%d",segno);
13391376
else
13401377
tmp_file.path[path_len-7]='\0';
1378+
13411379
pre_search_file= (pgFile**)parray_bsearch(list_file,&tmp_file,pgFileComparePath);
1342-
if (pre_search_file!=NULL)
1380+
/* Use another scheme for compressed files */
1381+
pgFilemap_file;
1382+
pgFile**map_search_file;
1383+
map_file.path=pg_strdup(file->path);
1384+
if (segno>0)
1385+
sprintf(map_file.path+path_len-7,".%d.cfm",segno);
1386+
else
1387+
sprintf(map_file.path+path_len-7,".cfm");
1388+
map_search_file= (pgFile**)parray_bsearch(list_file,&map_file,pgFileComparePath);
1389+
1390+
if (pre_search_file!=NULL
1391+
&&map_search_file==NULL)
13431392
{
13441393
search_file=*pre_search_file;
13451394
search_file->ptrack_path=pg_strdup(file->path);
13461395
search_file->segno=segno;
1347-
}else {
1396+
}
1397+
else
1398+
{
13481399
pg_free(tmp_file.path);
1400+
pg_free(map_file.path);
13491401
break;
13501402
}
1403+
pg_free(map_file.path);
13511404
pg_free(tmp_file.path);
13521405
segno++;
13531406
}
@@ -1361,12 +1414,9 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
13611414
/* compress map file it is not data file */
13621415
if (path_len>4&&strncmp(file->path+(path_len-4),".cfm",4)==0)
13631416
{
1364-
if (current.backup_mode==BACKUP_MODE_DIFF_PTRACK||
1365-
current.backup_mode==BACKUP_MODE_DIFF_PAGE)
1366-
{
1367-
elog(NOTICE,"You can't use incremental backup with compress tablespace");
1368-
/* TODO Add here incremental backup for compressed tablespaces */
1369-
}
1417+
if (current.backup_mode==BACKUP_MODE_DIFF_PAGE)
1418+
elog(ERROR,"You can't use PAGE mode backup with compressed tablespace.\n"
1419+
"Try PTRACK mode instead.");
13701420
continue;
13711421
}
13721422

@@ -1420,8 +1470,34 @@ add_files(parray *files, const char *root, bool add_root, bool is_pgdata)
14201470
pre_search_file= (pgFile**)parray_bsearch(list_file,&tmp_file,pgFileComparePath);
14211471
if (pre_search_file!=NULL)
14221472
{
1473+
FileMap*map;
1474+
intmd=open(file->path,O_RDWR|PG_BINARY,0);
1475+
if (md<0)
1476+
elog(ERROR,"add_files(). cannot open cfm file '%s'",file->path);
1477+
1478+
map=cfs_mmap(md);
1479+
if (map==MAP_FAILED)
1480+
{
1481+
elog(LOG,"add_files(). cfs_compression_ration failed to map file %s: %m",file->path);
1482+
close(md);
1483+
break;
1484+
}
1485+
1486+
(*pre_search_file)->last_backup_write_size=map->last_backup_write_size;
1487+
(*pre_search_file)->generation=map->generation;
14231488
(*pre_search_file)->is_datafile= false;
1489+
map->last_backup_write_size=map->physSize;
1490+
1491+
if (cfs_msync(map)<0)
1492+
elog(LOG,"add_files(). CFS failed to sync map %s: %m",file->path);
1493+
if (cfs_munmap(map)<0)
1494+
elog(LOG,"add_files(). CFS failed to unmap file %s: %m",file->path);
1495+
if (close(md)<0)
1496+
elog(LOG,"add_files(). CFS failed to close file %s: %m",file->path);
14241497
}
1498+
else
1499+
elog(ERROR,"corresponding segment '%s' is not found",tmp_file.path);
1500+
14251501
pg_free(tmp_file.path);
14261502
}
14271503
}
@@ -1693,3 +1769,42 @@ StreamLog(void *arg)
16931769
PQfinish(conn);
16941770
conn=NULL;
16951771
}
1772+
1773+
1774+
FileMap*cfs_mmap(intmd)
1775+
{
1776+
FileMap*map;
1777+
#ifdefWIN32
1778+
HANDLEmh=CreateFileMapping(_get_osfhandle(md),NULL,PAGE_READWRITE,
1779+
0, (DWORD)sizeof(FileMap),NULL);
1780+
if (mh==NULL) {
1781+
return (FileMap*)MAP_FAILED;
1782+
}
1783+
map= (FileMap*)MapViewOfFile(mh,FILE_MAP_ALL_ACCESS,0,0,0);
1784+
CloseHandle(mh);
1785+
if (map==NULL) {
1786+
return (FileMap*)MAP_FAILED;
1787+
}
1788+
#else
1789+
map= (FileMap*)mmap(NULL,sizeof(FileMap),PROT_WRITE |PROT_READ,MAP_SHARED,md,0);
1790+
#endif
1791+
returnmap;
1792+
}
1793+
1794+
intcfs_munmap(FileMap*map)
1795+
{
1796+
#ifdefWIN32
1797+
returnUnmapViewOfFile(map) ?0 :-1;
1798+
#else
1799+
returnmunmap(map,sizeof(FileMap));
1800+
#endif
1801+
}
1802+
1803+
intcfs_msync(FileMap*map)
1804+
{
1805+
#ifdefWIN32
1806+
returnFlushViewOfFile(map,sizeof(FileMap)) ?0 :-1;
1807+
#else
1808+
returnmsync(map,sizeof(FileMap),MS_SYNC);
1809+
#endif
1810+
}

‎contrib/pg_probackup/data.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ backup_data_file(const char *from_root, const char *to_root,
113113
/* confirm server version */
114114
check_server_version();
115115

116+
/* TODO If file is the segment of compressed table,
117+
* read its generation from cfm,
118+
* compare this generation with one in the file_database.txt and
119+
* respectively backup all file or just changed part.
120+
*/
116121

117122
/*
118123
* Read each page and write the page excluding hole. If it has been
@@ -681,6 +686,131 @@ copy_file(const char *from_root, const char *to_root, pgFile *file)
681686
return true;
682687
}
683688

689+
bool
690+
copy_file_partly(constchar*from_root,constchar*to_root,
691+
pgFile*file,size_tskip_size)
692+
{
693+
charto_path[MAXPGPATH];
694+
FILE*in;
695+
FILE*out;
696+
size_tread_len=0;
697+
interrno_tmp;
698+
structstatst;
699+
charbuf[8192];
700+
701+
/* reset size summary */
702+
file->read_size=0;
703+
file->write_size=0;
704+
705+
/* open backup mode file for read */
706+
in=fopen(file->path,"r");
707+
if (in==NULL)
708+
{
709+
/* maybe deleted, it's not error */
710+
if (errno==ENOENT)
711+
return false;
712+
713+
elog(ERROR,"cannot open source file \"%s\": %s",file->path,
714+
strerror(errno));
715+
}
716+
717+
/* open backup file for write */
718+
if (check)
719+
snprintf(to_path,lengthof(to_path),"%s/tmp",backup_path);
720+
else
721+
join_path_components(to_path,to_root,file->path+strlen(from_root)+1);
722+
out=fopen(to_path,"w");
723+
if (out==NULL)
724+
{
725+
interrno_tmp=errno;
726+
fclose(in);
727+
elog(ERROR,"cannot open destination file \"%s\": %s",
728+
to_path,strerror(errno_tmp));
729+
}
730+
731+
/* stat source file to change mode of destination file */
732+
if (fstat(fileno(in),&st)==-1)
733+
{
734+
fclose(in);
735+
fclose(out);
736+
elog(ERROR,"cannot stat \"%s\": %s",file->path,
737+
strerror(errno));
738+
}
739+
740+
if (fseek(in,skip_size,SEEK_SET)<0)
741+
elog(ERROR,"cannot seek %lu of \"%s\": %s",
742+
skip_size,file->path,strerror(errno));
743+
744+
/* copy content and calc CRC */
745+
for (;;)
746+
{
747+
if ((read_len=fread(buf,1,sizeof(buf),in))!=sizeof(buf))
748+
break;
749+
750+
if (fwrite(buf,1,read_len,out)!=read_len)
751+
{
752+
errno_tmp=errno;
753+
/* oops */
754+
fclose(in);
755+
fclose(out);
756+
elog(ERROR,"cannot write to \"%s\": %s",to_path,
757+
strerror(errno_tmp));
758+
}
759+
760+
file->write_size+=sizeof(buf);
761+
file->read_size+=sizeof(buf);
762+
}
763+
764+
errno_tmp=errno;
765+
if (!feof(in))
766+
{
767+
fclose(in);
768+
fclose(out);
769+
elog(ERROR,"cannot read backup mode file \"%s\": %s",
770+
file->path,strerror(errno_tmp));
771+
}
772+
773+
/* copy odd part. */
774+
if (read_len>0)
775+
{
776+
if (fwrite(buf,1,read_len,out)!=read_len)
777+
{
778+
errno_tmp=errno;
779+
/* oops */
780+
fclose(in);
781+
fclose(out);
782+
elog(ERROR,"cannot write to \"%s\": %s",to_path,
783+
strerror(errno_tmp));
784+
}
785+
786+
file->write_size+=read_len;
787+
file->read_size+=read_len;
788+
}
789+
790+
/* update file permission */
791+
if (chmod(to_path,st.st_mode)==-1)
792+
{
793+
errno_tmp=errno;
794+
fclose(in);
795+
fclose(out);
796+
elog(ERROR,"cannot change mode of \"%s\": %s",to_path,
797+
strerror(errno_tmp));
798+
}
799+
800+
elog(NOTICE,"copy_file_partly(). %s file->write_size %lu",to_path,file->write_size);
801+
pgFilenewfile;
802+
newfile.path=pg_strdup(to_path);
803+
file->crc=pgFileGetCRC(&newfile);
804+
805+
fclose(in);
806+
fclose(out);
807+
808+
if (check)
809+
remove(to_path);
810+
811+
return true;
812+
}
813+
684814
bool
685815
calc_file(pgFile*file)
686816
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp