24 #define FSYNC_FILENAME "./pg_test_fsync.out" 26 #define XLOG_BLCKSZ_K (XLOG_BLCKSZ / 1024) 28 #define LABEL_FORMAT " %-30s" 29 #define NA_FORMAT "%21s\n" 31 #define OPS_FORMAT gettext_noop("%13.3f ops/sec %6.0f usecs/op\n") 32 #define USECS_SEC 1000000 38 alarm_triggered = false; \ 39 alarm(secs_per_test); \ 40 gettimeofday(&start_t, NULL); \ 46 alarm_triggered = false; \ 47 if (CreateThread(NULL, 0, process_alarm, NULL, 0, NULL) == \ 48 INVALID_HANDLE_VALUE) \ 50 pg_log_error("could not create thread for alarm"); \ 53 gettimeofday(&start_t, NULL); \ 59 gettimeofday(&stop_t, NULL); \ 60 print_elapse(start_t, stop_t, ops); \ 71 static struct timeval start_t,
92 #ifdef HAVE_FSYNC_WRITETHROUGH 97 #define die(msg) do { pg_log_error("%s: %m", _(msg)); exit(1); } while(0) 144 static struct option long_options[] = {
152 unsigned long optval;
157 if (strcmp(argv[1],
"--help") == 0 || strcmp(argv[1],
"-?") == 0)
162 if (strcmp(argv[1],
"--version") == 0 || strcmp(argv[1],
"-V") == 0)
164 puts(
"pg_test_fsync (PostgreSQL) " PG_VERSION);
170 long_options, &optindex)) != -1)
180 optval = strtoul(
optarg, &endptr, 10);
182 if (endptr ==
optarg || *endptr !=
'\0' ||
183 errno != 0 || optval != (
unsigned int) optval)
185 pg_log_error(
"invalid argument for option %s",
"--secs-per-test");
194 "--secs-per-test", 1, UINT_MAX);
200 fprintf(stderr,
_(
"Try \"%s --help\" for more information.\n"),
209 pg_log_error(
"too many command-line arguments (first is \"%s\")",
211 fprintf(stderr,
_(
"Try \"%s --help\" for more information.\n"),
217 "%u seconds per test\n",
221 printf(
_(
"O_DIRECT supported on this platform for open_datasync and open_sync.\n"));
223 printf(
_(
"Direct I/O is not supported on this platform.\n"));
248 die(
"could not open output file");
255 if (
fsync(tmpfile) != 0)
267 bool fs_warning =
false;
269 if (writes_per_op == 1)
273 printf(
_(
"(in wal_sync_method preference order, except fdatasync is Linux's default)\n"));
281 #ifdef OPEN_DATASYNC_FLAG 292 for (writes = 0; writes < writes_per_op; writes++)
296 writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
312 #ifdef HAVE_FDATASYNC 314 die(
"could not open output file");
318 for (writes = 0; writes < writes_per_op; writes++)
322 writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
339 die(
"could not open output file");
343 for (writes = 0; writes < writes_per_op; writes++)
347 writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
349 if (
fsync(tmpfile) != 0)
361 #ifdef HAVE_FSYNC_WRITETHROUGH 363 die(
"could not open output file");
367 for (writes = 0; writes < writes_per_op; writes++)
371 writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
388 #ifdef OPEN_SYNC_FLAG 399 for (writes = 0; writes < writes_per_op; writes++)
403 writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
421 printf(
_(
"* This file system and its mount options do not support direct\n" 422 " I/O, e.g. ext4 in journaled mode.\n"));
429 printf(
_(
"\nCompare open_sync with different write sizes:\n"));
430 printf(
_(
"(This is designed to compare the cost of writing 16kB in different write\n" 431 "open_sync sizes.)\n"));
446 #ifdef OPEN_SYNC_FLAG 455 #ifdef OPEN_SYNC_FLAG 463 for (writes = 0; writes < 16 / writes_size; writes++)
467 writes * writes_size * 1024) !=
491 printf(
_(
"\nTest if fsync on non-write file descriptor is honored:\n"));
492 printf(
_(
"(If the times are similar, fsync() can sync data written on a different\n" 506 die(
"could not open output file");
507 if (
write(tmpfile,
buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
509 if (
fsync(tmpfile) != 0)
518 die(
"could not open output file");
534 die(
"could not open output file");
535 if (
write(tmpfile,
buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
540 die(
"could not open output file");
541 if (
fsync(tmpfile) != 0)
562 die(
"could not open output file");
566 if (
pg_pwrite(tmpfile,
buf, XLOG_BLCKSZ, 0) != XLOG_BLCKSZ)
584 #ifdef HAVE_FSYNC_WRITETHROUGH 591 #elif defined(F_FULLFSYNC) 592 return (fcntl(fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
606 double total_time = (stop_t.tv_sec - start_t.tv_sec) +
607 (stop_t.tv_usec - start_t.tv_usec) * 0.000001;
608 double per_second = ops / total_time;
609 double avg_op_time_us = (total_time / ops) *
USECS_SEC;
static void test_sync(int writes_per_op)
const char * get_progname(const char *argv0)
#define pg_log_error(...)
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
int pg_fsync_writethrough(int fd)
void pg_logging_init(const char *argv0)
#define DEFAULT_XLOG_SEG_SIZE
static int fd(const char *x, int i)
ssize_t pg_pwrite(int fd, const void *buf, size_t nbyte, off_t offset)
static char full_buf[DEFAULT_XLOG_SEG_SIZE]
static void test_open(void)
static bool alarm_triggered
static void prepare_buf(void)
#define required_argument
static const char * progname
char * pg_strdup(const char *in)
#define ngettext(s, p, n)
#define PG_TEXTDOMAIN(domain)
static void print_elapse(struct timeval start_t, struct timeval stop_t, int ops)
static void test_open_syncs(void)
static void test_non_sync(void)
static unsigned int secs_per_test
static struct timeval start_t stop_t
#define TYPEALIGN(ALIGNVAL, LEN)
static void process_alarm(int sig)
pqsigfunc pqsignal(int signum, pqsigfunc handler)
static void signal_cleanup(int sig)
int main(int argc, char *argv[])
void set_pglocale_pgservice(const char *argv0, const char *app)
static void test_file_descriptor_sync(void)
static void test_open_sync(const char *msg, int writes_size)
static void handle_args(int argc, char *argv[])