0001
0002
0003
0004
0005
0006
0007
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 extern int ngx_kqueue;
0032
0033
0034 static ssize_t ngx_file_aio_result(ngx_file_t *file, ngx_event_aio_t *aio,
0035 ngx_event_t *ev);
0036 static void ngx_file_aio_event_handler(ngx_event_t *ev);
0037
0038
0039 ngx_int_t
0040 ngx_file_aio_init(ngx_file_t *file, ngx_pool_t *pool)
0041 {
0042 ngx_event_aio_t *aio;
0043
0044 aio = ngx_pcalloc(pool, sizeof(ngx_event_aio_t));
0045 if (aio == NULL) {
0046 return NGX_ERROR;
0047 }
0048
0049 aio->file = file;
0050 aio->fd = file->fd;
0051 aio->event.data = aio;
0052 aio->event.ready = 1;
0053 aio->event.log = file->log;
0054
0055 file->aio = aio;
0056
0057 return NGX_OK;
0058 }
0059
0060
0061 ssize_t
0062 ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset,
0063 ngx_pool_t *pool)
0064 {
0065 int n;
0066 ngx_event_t *ev;
0067 ngx_event_aio_t *aio;
0068
0069 if (!ngx_file_aio) {
0070 return ngx_read_file(file, buf, size, offset);
0071 }
0072
0073 if (file->aio == NULL && ngx_file_aio_init(file, pool) != NGX_OK) {
0074 return NGX_ERROR;
0075 }
0076
0077 aio = file->aio;
0078 ev = &aio->event;
0079
0080 if (!ev->ready) {
0081 ngx_log_error(NGX_LOG_ALERT, file->log, 0,
0082 "second aio post for \"%V\"", &file->name);
0083 return NGX_AGAIN;
0084 }
0085
0086 ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
0087 "aio complete:%d @%O:%uz %V",
0088 ev->complete, offset, size, &file->name);
0089
0090 if (ev->complete) {
0091 ev->complete = 0;
0092 ngx_set_errno(aio->err);
0093
0094 if (aio->err == 0) {
0095 return aio->nbytes;
0096 }
0097
0098 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
0099 "aio read \"%s\" failed", file->name.data);
0100
0101 return NGX_ERROR;
0102 }
0103
0104 ngx_memzero(&aio->aiocb, sizeof(struct aiocb));
0105
0106 aio->aiocb.aio_fildes = file->fd;
0107 aio->aiocb.aio_offset = offset;
0108 aio->aiocb.aio_buf = buf;
0109 aio->aiocb.aio_nbytes = size;
0110 #if (NGX_HAVE_KQUEUE)
0111 aio->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue;
0112 aio->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT;
0113 aio->aiocb.aio_sigevent.sigev_value.sigval_ptr = ev;
0114 #endif
0115 ev->handler = ngx_file_aio_event_handler;
0116
0117 n = aio_read(&aio->aiocb);
0118
0119 if (n == -1) {
0120 n = ngx_errno;
0121
0122 if (n == NGX_EAGAIN) {
0123 return ngx_read_file(file, buf, size, offset);
0124 }
0125
0126 ngx_log_error(NGX_LOG_CRIT, file->log, n,
0127 "aio_read(\"%V\") failed", &file->name);
0128
0129 if (n == NGX_ENOSYS) {
0130 ngx_file_aio = 0;
0131 return ngx_read_file(file, buf, size, offset);
0132 }
0133
0134 return NGX_ERROR;
0135 }
0136
0137 ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0,
0138 "aio_read: fd:%d %d", file->fd, n);
0139
0140 ev->active = 1;
0141 ev->ready = 0;
0142 ev->complete = 0;
0143
0144 return ngx_file_aio_result(aio->file, aio, ev);
0145 }
0146
0147
0148 static ssize_t
0149 ngx_file_aio_result(ngx_file_t *file, ngx_event_aio_t *aio, ngx_event_t *ev)
0150 {
0151 int n;
0152 ngx_err_t err;
0153
0154 n = aio_error(&aio->aiocb);
0155
0156 ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0,
0157 "aio_error: fd:%d %d", file->fd, n);
0158
0159 if (n == -1) {
0160 err = ngx_errno;
0161 aio->err = err;
0162
0163 ngx_log_error(NGX_LOG_ALERT, file->log, err,
0164 "aio_error(\"%V\") failed", &file->name);
0165 return NGX_ERROR;
0166 }
0167
0168 if (n == NGX_EINPROGRESS) {
0169 if (ev->ready) {
0170 ev->ready = 0;
0171 ngx_log_error(NGX_LOG_ALERT, file->log, n,
0172 "aio_read(\"%V\") still in progress",
0173 &file->name);
0174 }
0175
0176 return NGX_AGAIN;
0177 }
0178
0179 n = aio_return(&aio->aiocb);
0180
0181 if (n == -1) {
0182 err = ngx_errno;
0183 aio->err = err;
0184 ev->ready = 1;
0185
0186 ngx_log_error(NGX_LOG_CRIT, file->log, err,
0187 "aio_return(\"%V\") failed", &file->name);
0188 return NGX_ERROR;
0189 }
0190
0191 aio->err = 0;
0192 aio->nbytes = n;
0193 ev->ready = 1;
0194 ev->active = 0;
0195
0196 ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0,
0197 "aio_return: fd:%d %d", file->fd, n);
0198
0199 return n;
0200 }
0201
0202
0203 static void
0204 ngx_file_aio_event_handler(ngx_event_t *ev)
0205 {
0206 ngx_event_aio_t *aio;
0207
0208 aio = ev->data;
0209
0210 ngx_log_debug2(NGX_LOG_DEBUG_CORE, ev->log, 0,
0211 "aio event handler fd:%d %V", aio->fd, &aio->file->name);
0212
0213 if (ngx_file_aio_result(aio->file, aio, ev) != NGX_AGAIN) {
0214 aio->handler(ev);
0215 }
0216 }