25 #define FSYNC_FILENAME "./pg_test_fsync.out"
27 #define XLOG_BLCKSZ_K (XLOG_BLCKSZ / 1024)
29 #define LABEL_FORMAT " %-30s"
30 #define NA_FORMAT "%21s\n"
32 #define OPS_FORMAT gettext_noop("%13.3f ops/sec %6.0f usecs/op\n")
33 #define USECS_SEC 1000000
39 alarm_triggered = false; \
40 alarm(secs_per_test); \
41 gettimeofday(&start_t, NULL); \
47 alarm_triggered = false; \
48 if (CreateThread(NULL, 0, process_alarm, NULL, 0, NULL) == \
49 INVALID_HANDLE_VALUE) \
50 pg_fatal("could not create thread for alarm"); \
51 gettimeofday(&start_t, NULL); \
57 gettimeofday(&stop_t, NULL); \
58 print_elapse(start_t, stop_t, ops); \
69 static struct timeval start_t,
90 #ifdef HAVE_FSYNC_WRITETHROUGH
95 #define die(msg) pg_fatal("%s: %m", _(msg))
99 main(
int argc,
char *argv[])
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");
192 pg_fatal(
"%s must be in range %u..%u",
193 "--secs-per-test", 1, UINT_MAX);
205 pg_log_error(
"too many command-line arguments (first is \"%s\")",
212 "%u seconds per test\n",
215 #if defined(O_DIRECT)
216 printf(
_(
"O_DIRECT supported on this platform for open_datasync and open_sync.\n"));
217 #elif defined(F_NOCACHE)
218 printf(
_(
"F_NOCACHE supported on this platform for open_datasync and open_sync.\n"));
220 printf(
_(
"Direct I/O is not supported on this platform.\n"));
245 die(
"could not open output file");
252 if (
fsync(tmpfile) != 0)
267 fd = open(path, flags,
mode);
269 #if !defined(O_DIRECT) && defined(F_NOCACHE)
270 if (
fd >= 0 && fcntl(
fd, F_NOCACHE, 1) < 0)
272 int save_errno = errno;
289 bool fs_warning =
false;
291 if (writes_per_op == 1)
295 printf(
_(
"(in wal_sync_method preference order, except fdatasync is Linux's default)\n"));
314 for (writes = 0; writes < writes_per_op; writes++)
318 writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
335 die(
"could not open output file");
339 for (writes = 0; writes < writes_per_op; writes++)
343 writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
357 die(
"could not open output file");
361 for (writes = 0; writes < writes_per_op; writes++)
365 writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
367 if (
fsync(tmpfile) != 0)
379 #ifdef HAVE_FSYNC_WRITETHROUGH
381 die(
"could not open output file");
385 for (writes = 0; writes < writes_per_op; writes++)
389 writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
417 for (writes = 0; writes < writes_per_op; writes++)
421 writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
440 printf(
_(
"* This file system and its mount options do not support direct\n"
441 " I/O, e.g. ext4 in journaled mode.\n"));
448 printf(
_(
"\nCompare open_sync with different write sizes:\n"));
449 printf(
_(
"(This is designed to compare the cost of writing 16kB in different write\n"
450 "open_sync sizes.)\n"));
482 for (writes = 0; writes < 16 / writes_size; writes++)
486 writes * writes_size * 1024) !=
510 printf(
_(
"\nTest if fsync on non-write file descriptor is honored:\n"));
511 printf(
_(
"(If the times are similar, fsync() can sync data written on a different\n"
525 die(
"could not open output file");
526 if (
write(tmpfile,
buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
528 if (
fsync(tmpfile) != 0)
537 die(
"could not open output file");
553 die(
"could not open output file");
554 if (
write(tmpfile,
buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
559 die(
"could not open output file");
560 if (
fsync(tmpfile) != 0)
581 die(
"could not open output file");
585 if (
pg_pwrite(tmpfile,
buf, XLOG_BLCKSZ, 0) != XLOG_BLCKSZ)
603 #ifdef HAVE_FSYNC_WRITETHROUGH
608 #if defined(F_FULLFSYNC)
609 return (fcntl(
fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
623 double total_time = (
stop_t.tv_sec - start_t.tv_sec) +
624 (
stop_t.tv_usec - start_t.tv_usec) * 0.000001;
625 double per_second = ops / total_time;
626 double avg_op_time_us = (total_time / ops) *
USECS_SEC;
#define TYPEALIGN(ALIGNVAL, LEN)
#define ngettext(s, p, n)
#define PG_TEXTDOMAIN(domain)
int fdatasync(int fildes)
void set_pglocale_pgservice(const char *argv0, const char *app)
int pg_fsync_writethrough(int fd)
char * pg_strdup(const char *in)
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
#define required_argument
static void const char fflush(stdout)
void pg_logging_init(const char *argv0)
#define pg_log_error(...)
#define pg_log_error_hint(...)
static PgChecksumMode mode
#define DEFAULT_XLOG_SEG_SIZE
PGDLLIMPORT char * optarg
int32 pg_prng_int32(pg_prng_state *state)
void pg_prng_seed(pg_prng_state *state, uint64 seed)
pg_prng_state pg_global_prng_state
static void test_file_descriptor_sync(void)
int main(int argc, char *argv[])
static char full_buf[DEFAULT_XLOG_SEG_SIZE]
static void prepare_buf(void)
static void print_elapse(struct timeval start_t, struct timeval stop_t, int ops)
static void test_open_syncs(void)
static void handle_args(int argc, char *argv[])
static int open_direct(const char *path, int flags, mode_t mode)
static void test_sync(int writes_per_op)
static void test_open(void)
static void test_non_sync(void)
static struct timeval start_t stop_t
static void test_open_sync(const char *msg, int writes_size)
static const char * progname
static void process_alarm(SIGNAL_ARGS)
static sig_atomic_t alarm_triggered
static unsigned int secs_per_test
static void signal_cleanup(SIGNAL_ARGS)
const char * get_progname(const char *argv0)
pqsigfunc pqsignal(int signo, pqsigfunc func)
static int fd(const char *x, int i)