Annotation of embedaddon/nginx/src/os/unix/ngx_file_aio_read.c, revision 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>