diff -Nrpcd a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml
*** a/doc/src/sgml/backup.sgml 2014-07-27 13:17:19.000000000 +0900
--- b/doc/src/sgml/backup.sgml 2014-08-12 15:08:16.000000000 +0900
*************** tar -cf backup.tar /usr/local/pgsql/data
*** 602,609 ****
character in the command. The simplest useful command is something
like:
! archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' # Unix
! archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"' # Windows
which will copy archivable WAL segments to the directory
/mnt/server/archivedir>. (This is an example, not a
--- 602,609 ----
character in the command. The simplest useful command is something
like:
! archive_command = 'test ! -f /mnt/server/archivedir/%f && pg_copy %p /mnt/server/archivedir/%f.tmp && mv /mnt/server/archivedir/%f.tmp /mnt/server/archivedir/%f' # Unix
! archive_command = 'pg_copy "%p" "C:\\server\\archivedir\\%f.tmp" && move "C:\\server\\archivedir\\%f.tmp" "C:\\server\\archivedir\\%f"' # Windows
which will copy archivable WAL segments to the directory
/mnt/server/archivedir>. (This is an example, not a
*************** archive_command = 'copy "%p" "C:\\server
*** 611,622 ****
%p> and %f> parameters have been replaced,
the actual command executed might look like this:
! test ! -f /mnt/server/archivedir/00000001000000A900000065 && cp pg_xlog/00000001000000A900000065 /mnt/server/archivedir/00000001000000A900000065
A similar command will be generated for each new file to be archived.
The archive command will be executed under the ownership of the same
user that the PostgreSQL> server is running as. Since
the series of WAL files being archived contains effectively everything
--- 611,634 ----
%p> and %f> parameters have been replaced,
the actual command executed might look like this:
! test ! -f /mnt/server/archivedir/00000001000000A900000065 && pg_copy pg_xlog/00000001000000A900000065 /mnt/server/archivedir/00000001000000A900000065.tmp && mv /mnt/server/archivedir/00000001000000A900000065.tmp /mnt/server/archivedir/00000001000000A900000065
A similar command will be generated for each new file to be archived.
+ It is recommended that you use pg_copy> instead of
+ standard operating system commands such as cp> or
+ copy>. Those commands do not synchronize the data
+ to disk, so the copied WAL files might be lost in case of power loss,
+ operating system failure, and hardware failure even when those commands
+ complete successfully. pg_copy> forces writes from the
+ operating system buffer cache to disk. Make sure to include the directory
+ for executable files in your shell's search path when you start the database
+ server, so that the server can find pg_copy>.
+
+
+
The archive command will be executed under the ownership of the same
user that the PostgreSQL> server is running as. Since
the series of WAL files being archived contains effectively everything
diff -Nrpcd a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
*** a/doc/src/sgml/ref/allfiles.sgml 2014-07-27 13:17:19.000000000 +0900
--- b/doc/src/sgml/ref/allfiles.sgml 2014-08-12 15:08:16.000000000 +0900
*************** Complete list of usable sgml source file
*** 179,184 ****
--- 179,185 ----
+
diff -Nrpcd a/doc/src/sgml/ref/pg_copy.sgml b/doc/src/sgml/ref/pg_copy.sgml
*** a/doc/src/sgml/ref/pg_copy.sgml 1970-01-01 09:00:00.000000000 +0900
--- b/doc/src/sgml/ref/pg_copy.sgml 2014-08-12 15:08:16.000000000 +0900
***************
*** 0 ****
--- 1,110 ----
+
+
+
+
+ pg_copy
+ 1
+ Application
+
+
+
+ pg_copy
+ copy regular files synchronously
+
+
+
+ pg_copy
+
+
+
+
+ pg_copy
+ option>
+ source
+ dest
+
+
+
+
+ Description
+
+
+ pg_copy copies a regular file from source to dest, forcing data to disk. This simple utility is intended to be used for archiving write-ahead log (WAL) files instead of standard operating system utilities such as cp or copy.
+
+
+
+
+
+
+ Options
+
+
+ pg_copy accepts the following command-line arguments:
+
+
+
+
+
+
+
+ Specifies the size in kilobytes of the buffer for copying data.
+ The default is 1024.
+
+
+
+
+
+
+
+
+
+ Use direct I/O for writing the destination file. Direct I/O
+ contributes to speedup by bypassing the file system cache.
+ If direct I/O is not available on the platform, this option has no effect.
+
+
+
+
+
+
+
+
+
+ Print the pg_copy version and exit.
+
+
+
+
+
+
+
+
+
+ Show help about pg_copy command line
+ arguments, and exit.
+
+
+
+
+
+
+
+
+
+
+
+ Notes
+
+
+ On UNIX/Linux systems, the permissions of the
+ destination file are 0600>, meaning that
+ only the user who executes this command can read
+ and write the file.
+
+
+
+
+
diff -Nrpcd a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
*** a/doc/src/sgml/reference.sgml 2014-07-27 13:17:19.000000000 +0900
--- b/doc/src/sgml/reference.sgml 2014-08-12 15:08:16.000000000 +0900
***************
*** 255,260 ****
--- 255,261 ----
&initdb;
&pgControldata;
+ &pgcopy;
&pgCtl;
&pgResetxlog;
&postgres;
diff -Nrpcd a/src/bin/Makefile b/src/bin/Makefile
*** a/src/bin/Makefile 2014-07-27 13:17:16.000000000 +0900
--- b/src/bin/Makefile 2014-08-12 15:08:16.000000000 +0900
*************** top_builddir = ../..
*** 14,20 ****
include $(top_builddir)/src/Makefile.global
SUBDIRS = initdb pg_ctl pg_dump \
! psql scripts pg_config pg_controldata pg_resetxlog pg_basebackup
ifeq ($(PORTNAME), win32)
SUBDIRS += pgevent
--- 14,20 ----
include $(top_builddir)/src/Makefile.global
SUBDIRS = initdb pg_ctl pg_dump \
! psql scripts pg_config pg_controldata pg_resetxlog pg_basebackup pg_copy
ifeq ($(PORTNAME), win32)
SUBDIRS += pgevent
diff -Nrpcd a/src/bin/pg_copy/.gitignore b/src/bin/pg_copy/.gitignore
*** a/src/bin/pg_copy/.gitignore 1970-01-01 09:00:00.000000000 +0900
--- b/src/bin/pg_copy/.gitignore 2014-08-12 15:08:16.000000000 +0900
***************
*** 0 ****
--- 1,2 ----
+ /pg_copy
+ /tmp_check/
diff -Nrpcd a/src/bin/pg_copy/Makefile b/src/bin/pg_copy/Makefile
*** a/src/bin/pg_copy/Makefile 1970-01-01 09:00:00.000000000 +0900
--- b/src/bin/pg_copy/Makefile 2014-08-12 15:08:16.000000000 +0900
***************
*** 0 ****
--- 1,42 ----
+ #-------------------------------------------------------------------------
+ #
+ # Makefile for src/bin/pg_copy
+ #
+ # Copyright (c) 2014, PostgreSQL Global Development Group
+ #
+ # src/bin/pg_copy/Makefile
+ #
+ #-------------------------------------------------------------------------
+
+ PGFILEDESC = "pg_copy - copy a regular file synchronously"
+ PGAPPICON=win32
+
+ subdir = src/bin/pg_copy
+ top_builddir = ../../..
+ include $(top_builddir)/src/Makefile.global
+
+ OBJS= pg_copy.o $(WIN32RES)
+
+ all: pg_copy
+
+ pg_copy: $(OBJS) | submake-libpgport
+ $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+
+ install: all installdirs
+ $(INSTALL_SCRIPT) pg_copy$(X) '$(DESTDIR)$(bindir)/pg_copy$(X)'
+
+ installdirs:
+ $(MKDIR_P) '$(DESTDIR)$(bindir)'
+
+ uninstall:
+ rm -f '$(DESTDIR)$(bindir)/pg_copy$(X)'
+
+ clean distclean maintainer-clean:
+ rm -f pg_copy$(X) $(OBJS)
+ rm -rf tmp_check
+
+ check: all
+ $(prove_check)
+
+ installcheck:
+ $(prove_installcheck)
diff -Nrpcd a/src/bin/pg_copy/nls.mk b/src/bin/pg_copy/nls.mk
*** a/src/bin/pg_copy/nls.mk 1970-01-01 09:00:00.000000000 +0900
--- b/src/bin/pg_copy/nls.mk 2014-08-12 15:08:16.000000000 +0900
***************
*** 0 ****
--- 1,4 ----
+ # src/bin/pg_copy/nls.mk
+ CATALOG_NAME = pg_copy
+ AVAIL_LANGUAGES = cs de es fr it ja ko nb pl pt_BR ro ru sv ta tr zh_CN zh_TW
+ GETTEXT_FILES = pg_copy.c
diff -Nrpcd a/src/bin/pg_copy/pg_copy.c b/src/bin/pg_copy/pg_copy.c
*** a/src/bin/pg_copy/pg_copy.c 1970-01-01 09:00:00.000000000 +0900
--- b/src/bin/pg_copy/pg_copy.c 2014-08-12 15:07:20.000000000 +0900
***************
*** 0 ****
--- 1,249 ----
+ /*-------------------------------------------------------------------------
+ *
+ * pg_copy.c
+ *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ *
+ * src/bin/pg_copy/pg_copy.c
+ */
+
+ #include "postgres_fe.h"
+
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ #include "getopt_long.h"
+
+ #define BUFFER_ALIGNMENT 8192
+
+ static const char *progname;
+
+ static void usage(void);
+ static void copy_file(char *fromfile, char *tofile, int buffer_size, bool directio);
+
+ static void sig_handler(int signum);
+
+ int
+ main(int argc, char **argv)
+ {
+ static struct option long_options[] = {
+ {"buffersize", required_argument, NULL, 'b'},
+ {"directio", no_argument, NULL, 'd'},
+ {"help", no_argument, NULL, '?'},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+ int c,
+ optindex;
+ bool directio = false;
+ int buffer_size = 1024 * 1024;
+ char *endptr;
+
+ set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_copy"));
+ progname = get_progname(argv[0]);
+
+ if (argc > 1)
+ {
+ if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0 ||
+ strcmp(argv[1], "-h") == 0)
+ {
+ usage();
+ exit(0);
+ }
+ if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
+ {
+ puts("pg_copy (PostgreSQL) " PG_VERSION);
+ exit(0);
+ }
+ }
+
+ while ((c = getopt_long(argc, argv, "b:d", long_options, &optindex)) != -1)
+ {
+ switch (c)
+ {
+ case 'b':
+ buffer_size = (int) strtol(optarg, &endptr, 10);
+ if (*endptr != '\0' ||
+ buffer_size < BUFFER_ALIGNMENT / 1024 ||
+ buffer_size % (BUFFER_ALIGNMENT / 1024) != 0)
+ {
+ fprintf(stderr, _("%s: buffer size is wrong\n"), progname);
+ exit(1);
+ }
+ buffer_size *= 1024;
+ break;
+ case 'd':
+ directio = true;
+ break;
+ default:
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+ exit(1);
+ }
+ }
+
+ if (argc - optind < 2)
+ {
+ fprintf(stderr, _("%s: source or destination file is not specified\n"), progname);
+ exit(1);
+ }
+ else if (argc - optind > 2)
+ {
+ fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
+ progname, argv[optind + 2]);
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+ exit(1);
+ }
+
+ /*
+ * postmaster sends SIGQUIT to its all descendants during immediate shutdown,
+ * and the default behavior of SIGQUIT is to dump core. To avoid dumping core,
+ * we register a signal handler which just calls exit().
+ */
+ signal(SIGQUIT, sig_handler);
+
+ copy_file(argv[optind], argv[optind + 1], buffer_size, directio);
+
+ return 0;
+ }
+
+ static void
+ usage(void)
+ {
+ printf(_("\n%s copies a regular file synchronously.\n\n"), progname);
+ printf(_("Usage:\n"));
+ printf(_(" %s [OPTION...] source_path dest_path\n"), progname);
+ printf(_("Options:\n"));
+ printf(_(" -b, --buffersize=BUFFERSIZE\n"));
+ printf(_(" buffer size (KB) for copying data\n"));
+ printf(_(" -d, --directio use direct I/O\n"));
+ printf(_(" -V, --version output version information, then exit\n"));
+ printf(_(" -?, --help show this help, then exit\n"));
+ printf(_("Report bugs to .\n"));
+ }
+
+ static void
+ copy_file(char *fromfile, char *tofile, int buffer_size, bool directio)
+ {
+ char *buffer, *orig_buffer;
+ int srcfd,
+ dstfd;
+ int nbytes;
+ int mode;
+
+ /*
+ * Allocate a buffer for file I/O, considering the alignment for O_DIRECT.
+ */
+ orig_buffer = malloc(buffer_size + BUFFER_ALIGNMENT);
+ if (orig_buffer == NULL)
+ {
+ fprintf(stderr, _("out of memory\n"));
+ exit(1);
+ }
+ buffer = (char *) TYPEALIGN(BUFFER_ALIGNMENT, orig_buffer);
+
+ mode = O_WRONLY | O_CREAT | O_TRUNC | PG_BINARY;
+ #ifdef O_SYNC
+ mode |= O_SYNC;
+ #endif
+
+ /*
+ * If direct I/O is available on the platform, and
+ * the file size is a multiple of the buffer alignment size, use it.
+ */
+ #ifdef O_DIRECT
+ if (directio)
+ {
+ struct stat stat_buf;
+
+ if (stat(fromfile, &stat_buf) == 0 &&
+ stat_buf.st_size % BUFFER_ALIGNMENT == 0)
+ mode |= O_DIRECT;
+ }
+ #endif
+
+ srcfd = open(fromfile, O_RDONLY | PG_BINARY, 0);
+ if (srcfd < 0)
+ {
+ fprintf(stderr, _("could not open file \"%s\": %s\n"),
+ fromfile, strerror(errno));
+ exit(1);
+ }
+
+ dstfd = open(tofile, mode,
+ S_IRUSR | S_IWUSR);
+ if (dstfd < 0)
+ {
+ fprintf(stderr, _("could not create file \"%s\": %s\n"),
+ tofile, strerror(errno));
+ exit(1);
+ }
+
+ /*
+ * Copy the file content.
+ */
+ for (;;)
+ {
+ nbytes = read(srcfd, buffer, buffer_size);
+ if (nbytes < 0)
+ {
+ fprintf(stderr, _("could not read file \"%s\": %s\n"),
+ fromfile, strerror(errno));
+ exit(1);
+ }
+ if (nbytes == 0)
+ break;
+
+ errno = 0;
+ if (write(dstfd, buffer, nbytes) != nbytes)
+ {
+ /* if write didn't set errno, assume problem is no disk space */
+ if (errno == 0)
+ errno = ENOSPC;
+ fprintf(stderr, _("could not write to file \"%s\": %s\n"),
+ tofile, strerror(errno));
+ exit(1);
+ }
+ }
+
+ /*
+ * Archived files will not be re-read in normal operation, so we advise the
+ * OS to release any cached pages.
+ */
+ #if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
+ (void) posix_fadvise(dstfd, 0, 0, POSIX_FADV_DONTNEED);
+ #endif
+
+ #ifndef O_SYNC
+ if (fsync(dstfd))
+ {
+ fprintf(stderr, _("could not fsync file \"%s\": %s\n"),
+ tofile, strerror(errno));
+ exit(1);
+ }
+ #endif
+
+ if (close(dstfd))
+ {
+ fprintf(stderr, _("could not close file \"%s\": %s\n"),
+ tofile, strerror(errno));
+ exit(1);
+ }
+
+ close(srcfd);
+
+ free(orig_buffer);
+ }
+
+ static void
+ sig_handler(int signum)
+ {
+ /* We leaves a file being copied just like cp. */
+ exit(signum);
+ }
diff -Nrpcd a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
*** a/src/tools/msvc/Mkvcbuild.pm 2014-07-27 13:17:18.000000000 +0900
--- b/src/tools/msvc/Mkvcbuild.pm 2014-08-12 15:08:16.000000000 +0900
*************** sub mkvcbuild
*** 379,384 ****
--- 379,386 ----
my $pgconfig = AddSimpleFrontend('pg_config');
+ my $pgcopy = AddSimpleFrontend('pg_copy');
+
my $pgcontrol = AddSimpleFrontend('pg_controldata');
my $pgctl = AddSimpleFrontend('pg_ctl', 1);