1 | #if defined(__linux__) |
2 | |
3 | #include <boost/noncopyable.hpp> |
4 | #include <Common/Exception.h> |
5 | #include <sys/syscall.h> |
6 | #include <unistd.h> |
7 | |
8 | #include <IO/AIO.h> |
9 | |
10 | |
11 | /** Small wrappers for asynchronous I/O. |
12 | */ |
13 | |
14 | namespace DB |
15 | { |
16 | namespace ErrorCodes |
17 | { |
18 | extern const int CANNOT_IOSETUP; |
19 | } |
20 | } |
21 | |
22 | |
23 | int io_setup(unsigned nr, aio_context_t * ctxp) |
24 | { |
25 | return syscall(__NR_io_setup, nr, ctxp); |
26 | } |
27 | |
28 | int io_destroy(aio_context_t ctx) |
29 | { |
30 | return syscall(__NR_io_destroy, ctx); |
31 | } |
32 | |
33 | int io_submit(aio_context_t ctx, long nr, struct iocb * iocbpp[]) |
34 | { |
35 | return syscall(__NR_io_submit, ctx, nr, iocbpp); |
36 | } |
37 | |
38 | int io_getevents(aio_context_t ctx, long min_nr, long max_nr, io_event * events, struct timespec * timeout) |
39 | { |
40 | return syscall(__NR_io_getevents, ctx, min_nr, max_nr, events, timeout); |
41 | } |
42 | |
43 | |
44 | AIOContext::AIOContext(unsigned int nr_events) |
45 | { |
46 | ctx = 0; |
47 | if (io_setup(nr_events, &ctx) < 0) |
48 | DB::throwFromErrno("io_setup failed" , DB::ErrorCodes::CANNOT_IOSETUP); |
49 | } |
50 | |
51 | AIOContext::~AIOContext() |
52 | { |
53 | io_destroy(ctx); |
54 | } |
55 | |
56 | #elif defined(__FreeBSD__) |
57 | |
58 | # include <aio.h> |
59 | # include <boost/noncopyable.hpp> |
60 | # include <sys/event.h> |
61 | # include <sys/time.h> |
62 | # include <sys/types.h> |
63 | # include <Common/Exception.h> |
64 | |
65 | # include <IO/AIO.h> |
66 | |
67 | |
68 | /** Small wrappers for asynchronous I/O. |
69 | */ |
70 | |
71 | namespace DB |
72 | { |
73 | namespace ErrorCodes |
74 | { |
75 | extern const int CANNOT_IOSETUP; |
76 | } |
77 | } |
78 | |
79 | |
80 | int io_setup(void) |
81 | { |
82 | return kqueue(); |
83 | } |
84 | |
85 | int io_destroy(int ctx) |
86 | { |
87 | return close(ctx); |
88 | } |
89 | |
90 | int io_submit(int ctx, long nr, struct iocb * iocbpp[]) |
91 | { |
92 | for (long i = 0; i < nr; i++) |
93 | { |
94 | struct aiocb * iocb = &iocbpp[i]->aio; |
95 | |
96 | struct sigevent * se = &iocb->aio_sigevent; |
97 | se->sigev_notify_kqueue = ctx; |
98 | se->sigev_notify_kevent_flags = 0; |
99 | se->sigev_notify = SIGEV_KEVENT; |
100 | se->sigev_value.sival_ptr = iocbpp[i]; |
101 | |
102 | switch (iocb->aio_lio_opcode) |
103 | { |
104 | case LIO_READ: |
105 | { |
106 | int r = aio_read(iocb); |
107 | if (r < 0) |
108 | return r; |
109 | break; |
110 | } |
111 | case LIO_WRITE: |
112 | { |
113 | int r = aio_write(iocb); |
114 | if (r < 0) |
115 | return r; |
116 | break; |
117 | } |
118 | } |
119 | } |
120 | |
121 | return nr; |
122 | } |
123 | |
124 | int io_getevents(int ctx, long, long max_nr, struct kevent * events, struct timespec * timeout) |
125 | { |
126 | return kevent(ctx, NULL, 0, events, max_nr, timeout); |
127 | } |
128 | |
129 | |
130 | AIOContext::AIOContext(unsigned int) |
131 | { |
132 | ctx = io_setup(); |
133 | if (ctx < 0) |
134 | DB::throwFromErrno("io_setup failed" , DB::ErrorCodes::CANNOT_IOSETUP); |
135 | } |
136 | |
137 | AIOContext::~AIOContext() |
138 | { |
139 | io_destroy(ctx); |
140 | } |
141 | |
142 | #endif |
143 | |