Annotation of embedaddon/nginx/src/os/unix/ngx_file_aio_read.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (C) Igor Sysoev
4: * Copyright (C) Nginx, Inc.
5: */
6:
7:
8: #include <ngx_config.h>
9: #include <ngx_core.h>
10: #include <ngx_event.h>
11:
12:
13: /*
14: * FreeBSD file AIO features and quirks:
15: *
16: * if an asked data are already in VM cache, then aio_error() returns 0,
17: * and the data are already copied in buffer;
18: *
19: * aio_read() preread in VM cache as minimum 16K (probably BKVASIZE);
20: * the first AIO preload may be up to 128K;
21: *
22: * aio_read/aio_error() may return EINPROGRESS for just written data;
23: *
24: * kqueue EVFILT_AIO filter is level triggered only: an event repeats
25: * until aio_return() will be called;
26: *
27: * aio_cancel() cannot cancel file AIO: it returns AIO_NOTCANCELED always.
28: */
29:
30:
31: extern int ngx_kqueue;
32:
33:
34: static ssize_t ngx_file_aio_result(ngx_file_t *file, ngx_event_aio_t *aio,
35: ngx_event_t *ev);
36: static void ngx_file_aio_event_handler(ngx_event_t *ev);
37:
38:
39: ssize_t
40: ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset,
41: ngx_pool_t *pool)
42: {
43: int n;
44: ngx_event_t *ev;
45: ngx_event_aio_t *aio;
46:
47: if (!ngx_file_aio) {
48: return ngx_read_file(file, buf, size, offset);
49: }
50:
51: aio = file->aio;
52:
53: if (aio == NULL) {
54: aio = ngx_pcalloc(pool, sizeof(ngx_event_aio_t));
55: if (aio == NULL) {
56: return NGX_ERROR;
57: }
58:
59: aio->file = file;
60: aio->fd = file->fd;
61: aio->event.data = aio;
62: aio->event.ready = 1;
63: aio->event.log = file->log;
64: #if (NGX_HAVE_AIO_SENDFILE)
65: aio->last_offset = -1;
66: #endif
67: file->aio = aio;
68: }
69:
70: ev = &aio->event;
71:
72: if (!ev->ready) {
73: ngx_log_error(NGX_LOG_ALERT, file->log, 0,
74: "second aio post for \"%V\"", &file->name);
75: return NGX_AGAIN;
76: }
77:
78: ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
79: "aio complete:%d @%O:%z %V",
80: ev->complete, offset, size, &file->name);
81:
82: if (ev->complete) {
83: ev->complete = 0;
84: ngx_set_errno(aio->err);
85:
86: if (aio->err == 0) {
87: return aio->nbytes;
88: }
89:
90: ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
91: "aio read \"%s\" failed", file->name.data);
92:
93: return NGX_ERROR;
94: }
95:
96: ngx_memzero(&aio->aiocb, sizeof(struct aiocb));
97:
98: aio->aiocb.aio_fildes = file->fd;
99: aio->aiocb.aio_offset = offset;
100: aio->aiocb.aio_buf = buf;
101: aio->aiocb.aio_nbytes = size;
102: #if (NGX_HAVE_KQUEUE)
103: aio->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue;
104: aio->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT;
105: aio->aiocb.aio_sigevent.sigev_value.sigval_ptr = ev;
106: #endif
107: ev->handler = ngx_file_aio_event_handler;
108:
109: n = aio_read(&aio->aiocb);
110:
111: if (n == -1) {
112: n = ngx_errno;
113:
114: if (n == NGX_EAGAIN) {
115: return ngx_read_file(file, buf, size, offset);
116: }
117:
118: ngx_log_error(NGX_LOG_CRIT, file->log, n,
119: "aio_read(\"%V\") failed", &file->name);
120:
121: if (n == NGX_ENOSYS) {
122: ngx_file_aio = 0;
123: return ngx_read_file(file, buf, size, offset);
124: }
125:
126: return NGX_ERROR;
127: }
128:
129: ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0,
130: "aio_read: fd:%d %d", file->fd, n);
131:
132: ev->active = 1;
133: ev->ready = 0;
134: ev->complete = 0;
135:
136: return ngx_file_aio_result(aio->file, aio, ev);
137: }
138:
139:
140: static ssize_t
141: ngx_file_aio_result(ngx_file_t *file, ngx_event_aio_t *aio, ngx_event_t *ev)
142: {
143: int n;
144: ngx_err_t err;
145:
146: n = aio_error(&aio->aiocb);
147:
148: ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0,
149: "aio_error: fd:%d %d", file->fd, n);
150:
151: if (n == -1) {
152: err = ngx_errno;
153: aio->err = err;
154:
155: ngx_log_error(NGX_LOG_ALERT, file->log, err,
156: "aio_error(\"%V\") failed", &file->name);
157: return NGX_ERROR;
158: }
159:
160: if (n == NGX_EINPROGRESS) {
161: if (ev->ready) {
162: ev->ready = 0;
163: ngx_log_error(NGX_LOG_ALERT, file->log, n,
164: "aio_read(\"%V\") still in progress",
165: &file->name);
166: }
167:
168: return NGX_AGAIN;
169: }
170:
171: n = aio_return(&aio->aiocb);
172:
173: if (n == -1) {
174: err = ngx_errno;
175: aio->err = err;
176: ev->ready = 1;
177:
178: ngx_log_error(NGX_LOG_CRIT, file->log, err,
179: "aio_return(\"%V\") failed", &file->name);
180: return NGX_ERROR;
181: }
182:
183: aio->err = 0;
184: aio->nbytes = n;
185: ev->ready = 1;
186: ev->active = 0;
187:
188: ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0,
189: "aio_return: fd:%d %d", file->fd, n);
190:
191: return n;
192: }
193:
194:
195: static void
196: ngx_file_aio_event_handler(ngx_event_t *ev)
197: {
198: ngx_event_aio_t *aio;
199:
200: aio = ev->data;
201:
202: ngx_log_debug2(NGX_LOG_DEBUG_CORE, ev->log, 0,
203: "aio event handler fd:%d %V", aio->fd, &aio->file->name);
204:
205: if (ngx_file_aio_result(aio->file, aio, ev) != NGX_AGAIN) {
206: aio->handler(ev);
207: }
208: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>