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>