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

Commitcada1af

Browse files
committed
Add compression support to pg_receivexlog
Author: Michael Paquier, review and small changes by me
1 parent974ece5 commitcada1af

File tree

5 files changed

+197
-20
lines changed

5 files changed

+197
-20
lines changed

‎doc/src/sgml/ref/pg_receivexlog.sgml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,19 @@ PostgreSQL documentation
180180
</para>
181181
</listitem>
182182
</varlistentry>
183+
184+
<varlistentry>
185+
<term><option>-Z <replaceable class="parameter">level</replaceable></option></term>
186+
<term><option>--compress=<replaceable class="parameter">level</replaceable></option></term>
187+
<listitem>
188+
<para>
189+
Enables gzip compression of transaction logs, and specifies the
190+
compression level (0 through 9, 0 being no compression and 9 being best
191+
compression). The suffix <filename>.gz</filename> will
192+
automatically be added to all filenames.
193+
</para>
194+
</listitem>
195+
</varlistentry>
183196
</variablelist>
184197

185198
<para>

‎src/bin/pg_basebackup/pg_basebackup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ LogStreamerMain(logstreamer_param *param)
494494
stream.replication_slot=psprintf("pg_basebackup_%d", (int)getpid());
495495

496496
if (format=='p')
497-
stream.walmethod=CreateWalDirectoryMethod(param->xlog,do_sync);
497+
stream.walmethod=CreateWalDirectoryMethod(param->xlog,0,do_sync);
498498
else
499499
stream.walmethod=CreateWalTarMethod(param->xlog,compresslevel,do_sync);
500500

‎src/bin/pg_basebackup/pg_receivexlog.c

Lines changed: 100 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
/* Global options */
3535
staticchar*basedir=NULL;
3636
staticintverbose=0;
37+
staticintcompresslevel=0;
3738
staticintnoloop=0;
3839
staticintstandby_message_timeout=10*1000;/* 10 sec = default */
3940
staticvolatilebooltime_to_abort= false;
@@ -58,6 +59,15 @@ static bool stop_streaming(XLogRecPtr segendpos, uint32 timeline,
5859
exit(code);\
5960
}
6061

62+
/* Routines to evaluate segment file format */
63+
#defineIsCompressXLogFileName(fname) \
64+
(strlen(fname) == XLOG_FNAME_LEN + strlen(".gz") &&\
65+
strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&\
66+
strcmp((fname) + XLOG_FNAME_LEN, ".gz") == 0)
67+
#defineIsPartialCompressXLogFileName(fname) \
68+
(strlen(fname) == XLOG_FNAME_LEN + strlen(".gz.partial") &&\
69+
strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&\
70+
strcmp((fname) + XLOG_FNAME_LEN, ".gz.partial") == 0)
6171

6272
staticvoid
6373
usage(void)
@@ -76,6 +86,7 @@ usage(void)
7686
printf(_(" --synchronous flush transaction log immediately after writing\n"));
7787
printf(_(" -v, --verbose output verbose messages\n"));
7888
printf(_(" -V, --version output version information, then exit\n"));
89+
printf(_(" -Z, --compress=0-9 compress logs with given compression level\n"));
7990
printf(_(" -?, --help show this help, then exit\n"));
8091
printf(_("\nConnection options:\n"));
8192
printf(_(" -d, --dbname=CONNSTR connection string\n"));
@@ -188,14 +199,31 @@ FindStreamingStart(uint32 *tli)
188199
uint32tli;
189200
XLogSegNosegno;
190201
boolispartial;
202+
booliscompress;
191203

192204
/*
193205
* Check if the filename looks like an xlog file, or a .partial file.
194206
*/
195207
if (IsXLogFileName(dirent->d_name))
208+
{
196209
ispartial= false;
210+
iscompress= false;
211+
}
197212
elseif (IsPartialXLogFileName(dirent->d_name))
213+
{
214+
ispartial= true;
215+
iscompress= false;
216+
}
217+
elseif (IsCompressXLogFileName(dirent->d_name))
218+
{
219+
ispartial= false;
220+
iscompress= true;
221+
}
222+
elseif (IsPartialCompressXLogFileName(dirent->d_name))
223+
{
198224
ispartial= true;
225+
iscompress= true;
226+
}
199227
else
200228
continue;
201229

@@ -206,9 +234,15 @@ FindStreamingStart(uint32 *tli)
206234

207235
/*
208236
* Check that the segment has the right size, if it's supposed to be
209-
* completed.
237+
* completed. For non-compressed segments just check the on-disk size
238+
* and see if it matches a completed segment.
239+
* For compressed segments, look at the last 4 bytes of the compressed
240+
* file, which is where the uncompressed size is located for gz files
241+
* with a size lower than 4GB, and then compare it to the size of a
242+
* completed segment. The 4 last bytes correspond to the ISIZE member
243+
* according to http://www.zlib.org/rfc-gzip.html.
210244
*/
211-
if (!ispartial)
245+
if (!ispartial&& !iscompress)
212246
{
213247
structstatstatbuf;
214248
charfullpath[MAXPGPATH];
@@ -229,6 +263,47 @@ FindStreamingStart(uint32 *tli)
229263
continue;
230264
}
231265
}
266+
elseif (!ispartial&&iscompress)
267+
{
268+
intfd;
269+
charbuf[4];
270+
intbytes_out;
271+
charfullpath[MAXPGPATH];
272+
273+
snprintf(fullpath,sizeof(fullpath),"%s/%s",basedir,dirent->d_name);
274+
275+
fd=open(fullpath,O_RDONLY |PG_BINARY);
276+
if (fd<0)
277+
{
278+
fprintf(stderr,_("%s: could not open compressed file \"%s\": %s\n"),
279+
progname,fullpath,strerror(errno));
280+
disconnect_and_exit(1);
281+
}
282+
if (lseek(fd, (off_t)(-4),SEEK_END)<0)
283+
{
284+
fprintf(stderr,_("%s: could not seek compressed file \"%s\": %s\n"),
285+
progname,fullpath,strerror(errno));
286+
disconnect_and_exit(1);
287+
}
288+
if (read(fd, (char*)buf,sizeof(buf))!=sizeof(buf))
289+
{
290+
fprintf(stderr,_("%s: could not read compressed file \"%s\": %s\n"),
291+
progname,fullpath,strerror(errno));
292+
disconnect_and_exit(1);
293+
}
294+
295+
close(fd);
296+
bytes_out= (buf[3] <<24) | (buf[2] <<16) |
297+
(buf[1] <<8) |buf[0];
298+
299+
if (bytes_out!=XLOG_SEG_SIZE)
300+
{
301+
fprintf(stderr,
302+
_("%s: compressed segment file \"%s\" has incorrect uncompressed size %d, skipping\n"),
303+
progname,dirent->d_name,bytes_out);
304+
continue;
305+
}
306+
}
232307

233308
/* Looks like a valid segment. Remember that we saw it. */
234309
if ((segno>high_segno)||
@@ -339,7 +414,8 @@ StreamLog(void)
339414
stream.synchronous=synchronous;
340415
stream.do_sync= true;
341416
stream.mark_done= false;
342-
stream.walmethod=CreateWalDirectoryMethod(basedir,stream.do_sync);
417+
stream.walmethod=CreateWalDirectoryMethod(basedir,compresslevel,
418+
stream.do_sync);
343419
stream.partial_suffix=".partial";
344420
stream.replication_slot=replication_slot;
345421
stream.temp_slot= false;
@@ -392,6 +468,7 @@ main(int argc, char **argv)
392468
{"status-interval",required_argument,NULL,'s'},
393469
{"slot",required_argument,NULL,'S'},
394470
{"verbose",no_argument,NULL,'v'},
471+
{"compress",required_argument,NULL,'Z'},
395472
/* action */
396473
{"create-slot",no_argument,NULL,1},
397474
{"drop-slot",no_argument,NULL,2},
@@ -422,7 +499,7 @@ main(int argc, char **argv)
422499
}
423500
}
424501

425-
while ((c=getopt_long(argc,argv,"D:d:h:p:U:s:S:nwWv",
502+
while ((c=getopt_long(argc,argv,"D:d:h:p:U:s:S:nwWvZ:",
426503
long_options,&option_index))!=-1)
427504
{
428505
switch (c)
@@ -472,6 +549,15 @@ main(int argc, char **argv)
472549
case'v':
473550
verbose++;
474551
break;
552+
case'Z':
553+
compresslevel=atoi(optarg);
554+
if (compresslevel<0||compresslevel>9)
555+
{
556+
fprintf(stderr,_("%s: invalid compression level \"%s\"\n"),
557+
progname,optarg);
558+
exit(1);
559+
}
560+
break;
475561
/* action */
476562
case1:
477563
do_create_slot= true;
@@ -538,6 +624,16 @@ main(int argc, char **argv)
538624
exit(1);
539625
}
540626

627+
#ifndefHAVE_LIBZ
628+
if (compresslevel!=0)
629+
{
630+
fprintf(stderr,
631+
_("%s: this build does not support compression\n"),
632+
progname);
633+
exit(1);
634+
}
635+
#endif
636+
541637
/*
542638
* Check existence of destination folder.
543639
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp