Age Owner Branch data TLA Line data Source code
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
137 tmunro@postgresql.or 44 :GNC 1505916 : 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 [ + + ]: 1505916 : if (iovcnt == 1)
52 : 1505530 : return pread(fd, iov[0].iov_base, iov[0].iov_len, offset);
53 : : else
54 : 386 : 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 : 931283 : 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 [ + + ]: 931283 : if (iovcnt == 1)
91 : 898180 : return pwrite(fd, iov[0].iov_base, iov[0].iov_len, offset);
92 : : else
93 : 33103 : 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 */
|