PostgreSQL Source Code  git master
pg_iovec.h
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * pg_iovec.h
4  * Header for vectored I/O functions, to use in place of <sys/uio.h>.
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * src/include/port/pg_iovec.h
10  *
11  *-------------------------------------------------------------------------
12  */
13 #ifndef PG_IOVEC_H
14 #define PG_IOVEC_H
15 
16 #ifndef WIN32
17 
18 #include <limits.h>
19 #include <sys/uio.h>
20 #include <unistd.h>
21 
22 #else
23 
24 /* POSIX requires at least 16 as a maximum iovcnt. */
25 #define IOV_MAX 16
26 
27 /* Define our own POSIX-compatible iovec struct. */
28 struct iovec
29 {
30  void *iov_base;
31  size_t iov_len;
32 };
33 
34 #endif
35 
36 /* Define a reasonable maximum that is safe to use on the stack. */
37 #define PG_IOV_MAX Min(IOV_MAX, 32)
38 
39 /*
40  * Like preadv(), but with a prefix to remind us of a side-effect: on Windows
41  * this changes the current file position.
42  */
43 static inline ssize_t
44 pg_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
45 {
46 #if HAVE_DECL_PREADV
47  /*
48  * Avoid a small amount of argument copying overhead in the kernel if
49  * there is only one iovec.
50  */
51  if (iovcnt == 1)
52  return pread(fd, iov[0].iov_base, iov[0].iov_len, offset);
53  else
54  return preadv(fd, iov, iovcnt, offset);
55 #else
56  ssize_t sum = 0;
57  ssize_t part;
58 
59  for (int i = 0; i < iovcnt; ++i)
60  {
61  part = pg_pread(fd, iov[i].iov_base, iov[i].iov_len, offset);
62  if (part < 0)
63  {
64  if (i == 0)
65  return -1;
66  else
67  return sum;
68  }
69  sum += part;
70  offset += part;
71  if (part < iov[i].iov_len)
72  return sum;
73  }
74  return sum;
75 #endif
76 }
77 
78 /*
79  * Like pwritev(), but with a prefix to remind us of a side-effect: on Windows
80  * this changes the current file position.
81  */
82 static inline ssize_t
83 pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
84 {
85 #if HAVE_DECL_PWRITEV
86  /*
87  * Avoid a small amount of argument copying overhead in the kernel if
88  * there is only one iovec.
89  */
90  if (iovcnt == 1)
91  return pwrite(fd, iov[0].iov_base, iov[0].iov_len, offset);
92  else
93  return pwritev(fd, iov, iovcnt, offset);
94 #else
95  ssize_t sum = 0;
96  ssize_t part;
97 
98  for (int i = 0; i < iovcnt; ++i)
99  {
100  part = pg_pwrite(fd, iov[i].iov_base, iov[i].iov_len, offset);
101  if (part < 0)
102  {
103  if (i == 0)
104  return -1;
105  else
106  return sum;
107  }
108  sum += part;
109  offset += part;
110  if (part < iov[i].iov_len)
111  return sum;
112  }
113  return sum;
114 #endif
115 }
116 
117 #endif /* PG_IOVEC_H */
int i
Definition: isn.c:73
static ssize_t pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
Definition: pg_iovec.h:83
static ssize_t pg_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
Definition: pg_iovec.h:44
#define pg_pwrite
Definition: port.h:226
#define pg_pread
Definition: port.h:225
static int fd(const char *x, int i)
Definition: preproc-init.c:105