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++)
293 if (
write(tmpfile,
buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
295 if (lseek(tmpfile, 0, SEEK_SET) == -1)
311 #ifdef HAVE_FDATASYNC 313 die(
"could not open output file");
317 for (writes = 0; writes < writes_per_op; writes++)
318 if (
write(tmpfile,
buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
321 if (lseek(tmpfile, 0, SEEK_SET) == -1)
337 die(
"could not open output file");
341 for (writes = 0; writes < writes_per_op; writes++)
342 if (
write(tmpfile,
buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
344 if (
fsync(tmpfile) != 0)
346 if (lseek(tmpfile, 0, SEEK_SET) == -1)
358 #ifdef HAVE_FSYNC_WRITETHROUGH 360 die(
"could not open output file");
364 for (writes = 0; writes < writes_per_op; writes++)
365 if (
write(tmpfile,
buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
369 if (lseek(tmpfile, 0, SEEK_SET) == -1)
384 #ifdef OPEN_SYNC_FLAG 395 for (writes = 0; writes < writes_per_op; writes++)
396 if (
write(tmpfile,
buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
405 if (lseek(tmpfile, 0, SEEK_SET) == -1)
417 printf(
_(
"* This file system and its mount options do not support direct\n" 418 " I/O, e.g. ext4 in journaled mode.\n"));
425 printf(
_(
"\nCompare open_sync with different write sizes:\n"));
426 printf(
_(
"(This is designed to compare the cost of writing 16kB in different write\n" 427 "open_sync sizes.)\n"));
442 #ifdef OPEN_SYNC_FLAG 451 #ifdef OPEN_SYNC_FLAG 459 for (writes = 0; writes < 16 / writes_size; writes++)
460 if (
write(tmpfile,
buf, writes_size * 1024) !=
463 if (lseek(tmpfile, 0, SEEK_SET) == -1)
486 printf(
_(
"\nTest if fsync on non-write file descriptor is honored:\n"));
487 printf(
_(
"(If the times are similar, fsync() can sync data written on a different\n" 501 die(
"could not open output file");
502 if (
write(tmpfile,
buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
504 if (
fsync(tmpfile) != 0)
513 die(
"could not open output file");
529 die(
"could not open output file");
530 if (
write(tmpfile,
buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
535 die(
"could not open output file");
536 if (
fsync(tmpfile) != 0)
560 die(
"could not open output file");
561 if (
write(tmpfile,
buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
579 #ifdef HAVE_FSYNC_WRITETHROUGH 586 #elif defined(F_FULLFSYNC) 587 return (fcntl(fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
601 double total_time = (stop_t.tv_sec - start_t.tv_sec) +
602 (stop_t.tv_usec - start_t.tv_usec) * 0.000001;
603 double per_second = ops / total_time;
604 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)
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[])