ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, ngx_pool_t *pool) { ssize_t total, n; ngx_iovec_t vec; struct iovec iovs[NGX_IOVS_PREALLOCATE]; /* use pwrite() if there is the only buf in a chain */ if (cl->next == NULL) { return ngx_write_file(file, cl->buf->pos, (size_t) (cl->buf->last - cl->buf->pos), offset); } total = 0; vec.iovs = iovs; vec.nalloc = NGX_IOVS_PREALLOCATE; do { /* create the iovec and coalesce the neighbouring bufs */ cl = ngx_chain_to_iovec(&vec, cl); /* use pwrite() if there is the only iovec buffer */ if (vec.count == 1) { n = ngx_write_file(file, (u_char *) iovs[0].iov_base, iovs[0].iov_len, offset); if (n == NGX_ERROR) { return n; } return total + n; } n = ngx_writev_file(file, &vec, offset); if (n == NGX_ERROR) { return n; } offset += n; total += n; } while (cl); return total; }
ngx_int_t ngx_rtmp_mpegts_write_header(ngx_file_t *file) { ssize_t rc; rc = ngx_write_file(file, ngx_rtmp_mpegts_header, sizeof(ngx_rtmp_mpegts_header), 0); return rc > 0 ? NGX_OK : rc; }
static ngx_int_t ngx_squ_file_aio_write(ngx_squ_thread_t *thr, ngx_lua_file_ctx_t *ctx) { ssize_t n; ngx_buf_t *b; ngx_file_t *file; ngx_log_debug0(NGX_LOG_DEBUG_CORE, thr->log, 0, "squ file aio write"); file = &ctx->file; b = ctx->out; #if (NGX_HAVE_FILE_AIO) && ((NGX_LINUX) || (NGX_WIN32)) n = ngx_file_aio_write(file, b->start, ctx->size, ctx->offset, ctx->pool); if (n == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, thr->log, ngx_errno, "ngx_file_aio_write() \"%V\" failed", &file->name); squ_pushboolean(thr->l, 0); squ_pushstring(thr->l, "ngx_file_aio_write() failed"); return 2; } if (n == NGX_AGAIN) { ctx->file.aio->data = ctx; ctx->file.aio->handler = ngx_squ_file_aio_write_handler; return NGX_AGAIN; } #else /* TODO: aio write for freebsd and solaris, etc */ n = ngx_write_file(file, b->start, ctx->size, ctx->offset); if (n == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, thr->log, ngx_errno, "ngx_write_file() \"%V\" failed", &file->name); squ_pushboolean(thr->l, 0); squ_pushstring(thr->l, "ngx_write_file() failed"); return 2; } #endif /* TODO: n != ctx->size */ ctx->offset += n; squ_pushinteger(thr->l, n); return 1; }
ngx_int_t ngx_http_small_light_imlib2_init(ngx_http_request_t *r, ngx_http_small_light_ctx_t *ctx) { ngx_http_small_light_imlib2_ctx_t *ictx; ictx = (ngx_http_small_light_imlib2_ctx_t *)ctx->ictx; ictx->image = ctx->content; ictx->image_len = ctx->content_length; ictx->type = ngx_http_small_light_type_detect(ictx->image, ictx->image_len); ictx->r = r; if (ictx->type == NGX_HTTP_SMALL_LIGHT_IMAGE_NONE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to get image type %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ictx->tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); if (ictx->tf == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ictx->tf->file.fd = NGX_INVALID_FILE; ictx->tf->file.log = r->connection->log; ictx->tf->path = ctx->imlib2_temp_dir; ictx->tf->pool = r->pool; if (ngx_create_temp_file(&ictx->tf->file, ictx->tf->path, ictx->tf->pool, 1, 0, 0600) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to create temporary file %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } if (ngx_write_file(&ictx->tf->file, ictx->image, ictx->image_len, 0) == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to save temporary file %s:%d", __FUNCTION__, __LINE__); ngx_http_small_light_imlib2_term(ctx); return NGX_ERROR; } return NGX_OK; }
/*创建pidfile,并写入当前进程id*/ ngx_int_t ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log) { size_t len; ngx_uint_t create; ngx_file_t file; u_char pid[NGX_INT64_LEN + 2]; if (ngx_process > NGX_PROCESS_MASTER) { return NGX_OK; } ngx_memzero(&file, sizeof(ngx_file_t)); file.name = *name; file.log = log; create = ngx_test_config ? NGX_FILE_CREATE_OR_OPEN : NGX_FILE_TRUNCATE; /*打开文件*/ file.fd = ngx_open_file(file.name.data, NGX_FILE_RDWR, create, NGX_FILE_DEFAULT_ACCESS); if (file.fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_open_file_n " \"%s\" failed", file.name.data); return NGX_ERROR; } if (!ngx_test_config) { len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid; /*将当前进程id写入到文件中*/ if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) { return NGX_ERROR; } } /*关闭文件*/ if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file.name.data); } return NGX_OK; }
ngx_int_t ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log) { size_t len; ngx_uint_t trunc; ngx_file_t file; u_char pid[NGX_INT64_LEN + 2]; ngx_memzero(&file, sizeof(ngx_file_t)); file.name = *name; file.log = log; trunc = ngx_test_config ? 0 : NGX_FILE_TRUNCATE; file.fd = ngx_open_file(file.name.data, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN|trunc, NGX_FILE_DEFAULT_ACCESS); if (file.fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_open_file_n " \"%s\" failed", file.name.data); return NGX_ERROR; } if (!ngx_test_config) { len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid; if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) { return NGX_ERROR; } } if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file.name.data); } return NGX_OK; }
static ngx_int_t ngx_rtmp_record_write_header(ngx_file_t *file) { static u_char flv_header[] = { 0x46, /* 'F' */ 0x4c, /* 'L' */ 0x56, /* 'V' */ 0x01, /* version = 1 */ 0x05, /* 00000 1 0 1 = has audio & video */ 0x00, 0x00, 0x00, 0x09, /* header size */ 0x00, 0x00, 0x00, 0x00 /* PreviousTagSize0 (not actually a header) */ }; return ngx_write_file(file, flv_header, sizeof(flv_header), 0) == NGX_ERROR ? NGX_ERROR : NGX_OK; }
ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, ngx_pool_t *pool) { u_char *prev; size_t size; ssize_t total, n; ngx_array_t vec; struct iovec *iov, iovs[NGX_IOVS]; /* use pwrite() if there is the only buf in a chain */ if (cl->next == NULL) { return ngx_write_file(file, cl->buf->pos, (size_t) (cl->buf->last - cl->buf->pos), offset); } total = 0; vec.elts = iovs; vec.size = sizeof(struct iovec); vec.nalloc = NGX_IOVS; vec.pool = pool; do { prev = NULL; iov = NULL; size = 0; vec.nelts = 0; /* create the iovec and coalesce the neighbouring bufs */ while (cl && vec.nelts < IOV_MAX) { if (prev == cl->buf->pos) { iov->iov_len += cl->buf->last - cl->buf->pos; } else { iov = ngx_array_push(&vec); if (iov == NULL) { return NGX_ERROR; } iov->iov_base = (void *) cl->buf->pos; iov->iov_len = cl->buf->last - cl->buf->pos; } size += cl->buf->last - cl->buf->pos; prev = cl->buf->last; cl = cl->next; } /* use pwrite() if there is the only iovec buffer */ if (vec.nelts == 1) { iov = vec.elts; n = ngx_write_file(file, (u_char *) iov[0].iov_base, iov[0].iov_len, offset); if (n == NGX_ERROR) { return n; } return total + n; } n = ngx_writev_file(file, &vec, size, offset); if (n == NGX_ERROR) { return n; } offset += n; total += n; } while (cl); return total; }
static ngx_int_t ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s, ngx_rtmp_record_rec_ctx_t *rctx, ngx_rtmp_header_t *h, ngx_chain_t *in, ngx_int_t inc_nframes) { u_char hdr[11], *p, *ph; uint32_t timestamp, tag_size; ngx_rtmp_record_app_conf_t *rracf; rracf = rctx->conf; ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "record: %V frame: mlen=%uD", &rracf->id, h->mlen); if (h->type == NGX_RTMP_MSG_VIDEO) { rctx->video = 1; } else { rctx->audio = 1; } timestamp = h->timestamp - rctx->epoch; if ((int32_t) timestamp < 0) { ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "record: %V cut timestamp=%D", &rracf->id, timestamp); timestamp = 0; } /* write tag header */ ph = hdr; *ph++ = (u_char)h->type; p = (u_char*)&h->mlen; *ph++ = p[2]; *ph++ = p[1]; *ph++ = p[0]; p = (u_char*)×tamp; *ph++ = p[2]; *ph++ = p[1]; *ph++ = p[0]; *ph++ = p[3]; *ph++ = 0; *ph++ = 0; *ph++ = 0; tag_size = (ph - hdr) + h->mlen; if (ngx_write_file(&rctx->file, hdr, ph - hdr, rctx->file.offset) == NGX_ERROR) { ngx_rtmp_record_notify_error(s, rctx); ngx_close_file(rctx->file.fd); return NGX_ERROR; } /* write tag body * FIXME: NGINX * ngx_write_chain seems to fit best * but it suffers from uncontrollable * allocations. * we're left with plain writing */ for(; in; in = in->next) { if (in->buf->pos == in->buf->last) { continue; } if (ngx_write_file(&rctx->file, in->buf->pos, in->buf->last - in->buf->pos, rctx->file.offset) == NGX_ERROR) { return NGX_ERROR; } } /* write tag size */ ph = hdr; p = (u_char*)&tag_size; *ph++ = p[3]; *ph++ = p[2]; *ph++ = p[1]; *ph++ = p[0]; if (ngx_write_file(&rctx->file, hdr, ph - hdr, rctx->file.offset) == NGX_ERROR) { return NGX_ERROR; } rctx->nframes += inc_nframes; /* watch max size */ if ((rracf->max_size && rctx->file.offset >= (ngx_int_t) rracf->max_size) || (rracf->max_frames && rctx->nframes >= rracf->max_frames)) { ngx_rtmp_record_node_close(s, rctx); } return NGX_OK; }
static ngx_int_t ngx_rtmp_record_node_close(ngx_rtmp_session_t *s, ngx_rtmp_record_rec_ctx_t *rctx) { ngx_rtmp_record_app_conf_t *rracf; ngx_err_t err; void **app_conf; ngx_int_t rc; ngx_rtmp_record_done_t v; u_char av; rracf = rctx->conf; if (rctx->file.fd == NGX_INVALID_FILE) { return NGX_AGAIN; } if (rctx->initialized) { av = 0; if (rctx->video) { av |= 0x01; } if (rctx->audio) { av |= 0x04; } if (ngx_write_file(&rctx->file, &av, 1, 4) == NGX_ERROR) { ngx_log_error(NGX_LOG_CRIT, s->connection->log, ngx_errno, "record: %V error writing av mask", &rracf->id); } } if (ngx_close_file(rctx->file.fd) == NGX_FILE_ERROR) { err = ngx_errno; ngx_log_error(NGX_LOG_CRIT, s->connection->log, err, "record: %V error closing file", &rracf->id); ngx_rtmp_record_notify_error(s, rctx); } rctx->file.fd = NGX_INVALID_FILE; ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "record: %V closed", &rracf->id); if (rracf->notify) { ngx_rtmp_send_status(s, "NetStream.Record.Stop", "status", rracf->id.data ? (char *) rracf->id.data : ""); } app_conf = s->app_conf; if (rracf->rec_conf) { s->app_conf = rracf->rec_conf; } v.recorder = rracf->id; ngx_rtmp_record_make_path(s, rctx, &v.path); rc = ngx_rtmp_record_done(s, &v); s->app_conf = app_conf; return rc; }
ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, ngx_pool_t *pool) { u_char *prev; size_t size; ssize_t total, n; ngx_array_t vec; struct iovec *iov, iovs[NGX_IOVS]; /* use pwrite() if there is the only buf in a chain */ if (cl->next == NULL) { return ngx_write_file(file, cl->buf->pos, (size_t) (cl->buf->last - cl->buf->pos), offset); } total = 0; vec.elts = iovs; vec.size = sizeof(struct iovec); vec.nalloc = NGX_IOVS; vec.pool = pool; do { prev = NULL; iov = NULL; size = 0; vec.nelts = 0; /* create the iovec and coalesce the neighbouring bufs */ while (cl && vec.nelts < IOV_MAX) { if (prev == cl->buf->pos) { iov->iov_len += cl->buf->last - cl->buf->pos; } else { iov = ngx_array_push(&vec); if (iov == NULL) { return NGX_ERROR; } iov->iov_base = (void *) cl->buf->pos; iov->iov_len = cl->buf->last - cl->buf->pos; } size += cl->buf->last - cl->buf->pos; prev = cl->buf->last; cl = cl->next; } /* use pwrite() if there is the only iovec buffer */ if (vec.nelts == 1) { iov = vec.elts; n = ngx_write_file(file, (u_char *) iov[0].iov_base, iov[0].iov_len, offset); if (n == NGX_ERROR) { return n; } return total + n; } if (file->sys_offset != offset) { if (lseek(file->fd, offset, SEEK_SET) == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() \"%s\" failed", file->name.data); return NGX_ERROR; } file->sys_offset = offset; } n = writev(file->fd, vec.elts, vec.nelts); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "writev() \"%s\" failed", file->name.data); return NGX_ERROR; } if ((size_t) n != size) { ngx_log_error(NGX_LOG_CRIT, file->log, 0, "writev() \"%s\" has written only %z of %uz", file->name.data, n, size); return NGX_ERROR; } ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0, "writev: %d, %z", file->fd, n); file->sys_offset += n; file->offset += n; offset += n; total += n; } while (cl); return total; }
ssize_t ngx_file_aio_write(ngx_file_t *file, u_char *buf, size_t size, off_t offset, ngx_pool_t *pool) { ngx_err_t err; struct iocb *piocb[1]; ngx_event_t *ev; ngx_event_aio_t *aio; if (!ngx_file_aio) { return ngx_write_file(file, buf, size, offset); } aio = file->aio; if (aio == NULL) { aio = ngx_pcalloc(pool, sizeof(ngx_event_aio_t)); if (aio == NULL) { return NGX_ERROR; } aio->file = file; aio->fd = file->fd; aio->event.data = aio; aio->event.ready = 1; aio->event.log = file->log; file->aio = aio; } ev = &aio->event; if (!ev->ready) { ngx_log_error(NGX_LOG_ALERT, file->log, 0, "second aio post for \"%V\"", &file->name); return NGX_AGAIN; } ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, "aio complete:%d @%O:%z %V", ev->complete, offset, size, &file->name); if (ev->complete) { ev->active = 0; ev->complete = 0; if (aio->res >= 0) { ngx_set_errno(0); return aio->res; } ngx_set_errno(-aio->res); ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "aio write \"%s\" failed", file->name.data); return NGX_ERROR; } ngx_memzero(&aio->aiocb, sizeof(struct iocb)); aio->aiocb.aio_data = (uint64_t) (uintptr_t) ev; aio->aiocb.aio_lio_opcode = IOCB_CMD_PWRITE; aio->aiocb.aio_fildes = file->fd; aio->aiocb.aio_buf = (uint64_t) (uintptr_t) buf; aio->aiocb.aio_nbytes = size; aio->aiocb.aio_offset = offset; aio->aiocb.aio_flags = IOCB_FLAG_RESFD; aio->aiocb.aio_resfd = ngx_eventfd; ev->handler = ngx_file_aio_event_handler; piocb[0] = &aio->aiocb; if (io_submit(ngx_aio_ctx, 1, piocb) == 1) { ev->active = 1; ev->ready = 0; ev->complete = 0; return NGX_AGAIN; } err = ngx_errno; if (err == NGX_EAGAIN) { return ngx_write_file(file, buf, size, offset); } ngx_log_error(NGX_LOG_CRIT, file->log, err, "io_submit(\"%V\") failed", &file->name); if (err == NGX_ENOSYS) { ngx_file_aio = 0; return ngx_write_file(file, buf, size, offset); } return NGX_ERROR; }
static ngx_int_t ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in) { u_char hdr[11], *p, *ph; uint32_t timestamp, tag_size; ngx_rtmp_record_ctx_t *ctx; ngx_rtmp_record_app_conf_t *racf; racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module); ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "record: av: mlen=%uD", h->mlen); timestamp = h->timestamp - ctx->epoch; /* write tag header */ ph = hdr; *ph++ = (u_char)h->type; p = (u_char*)&h->mlen; *ph++ = p[2]; *ph++ = p[1]; *ph++ = p[0]; p = (u_char*)×tamp; *ph++ = p[2]; *ph++ = p[1]; *ph++ = p[0]; *ph++ = p[3]; *ph++ = 0; *ph++ = 0; *ph++ = 0; tag_size = (ph - hdr) + h->mlen; if (ngx_write_file(&ctx->file, hdr, ph - hdr, ctx->file.offset) == NGX_ERROR) { return NGX_ERROR; } /* write tag body * FIXME: NGINX * ngx_write_chain seems to fit best * but it suffers from uncontrollable * allocations. * we're left with plain writing */ for(; in; in = in->next) { if (in->buf->pos == in->buf->last) { continue; } if (ngx_write_file(&ctx->file, in->buf->pos, in->buf->last - in->buf->pos, ctx->file.offset) == NGX_ERROR) { return NGX_ERROR; } } /* write tag size */ ph = hdr; p = (u_char*)&tag_size; *ph++ = p[3]; *ph++ = p[2]; *ph++ = p[1]; *ph++ = p[0]; if (ngx_write_file(&ctx->file, hdr, ph - hdr, ctx->file.offset) == NGX_ERROR) { return NGX_ERROR; } ++ctx->nframes; /* watch max size */ if ((racf->max_size && ctx->file.offset >= (ngx_int_t)racf->max_size) || (racf->max_frames && ctx->nframes >= racf->max_frames)) { ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "record: closed"); ngx_rtmp_record_close(s); } return NGX_OK; }
void ngx_http_file_cache_update_header(ngx_http_request_t *r) { ssize_t n; ngx_err_t err; ngx_file_t file; ngx_file_info_t fi; ngx_http_cache_t *c; ngx_http_file_cache_header_t h; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http file cache update header"); c = r->cache; ngx_memzero(&file, sizeof(ngx_file_t)); file.name = c->file.name; file.log = r->connection->log; file.fd = ngx_open_file(file.name.data, NGX_FILE_RDWR, NGX_FILE_OPEN, 0); if (file.fd == NGX_INVALID_FILE) { err = ngx_errno; /* cache file may have been deleted */ if (err == NGX_ENOENT) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http file cache \"%s\" not found", file.name.data); return; } ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_open_file_n " \"%s\" failed", file.name.data); return; } /* * make sure cache file wasn't replaced; * if it was, do nothing */ if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", file.name.data); goto done; } if (c->uniq != ngx_file_uniq(&fi) || c->length != ngx_file_size(&fi)) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http file cache \"%s\" changed", file.name.data); goto done; } n = ngx_read_file(&file, (u_char *) &h, sizeof(ngx_http_file_cache_header_t), 0); if (n == NGX_ERROR) { goto done; } if ((size_t) n != sizeof(ngx_http_file_cache_header_t)) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, ngx_read_file_n " read only %z of %z from \"%s\"", n, sizeof(ngx_http_file_cache_header_t), file.name.data); goto done; } if (h.last_modified != c->last_modified || h.crc32 != c->crc32 || h.header_start != c->header_start || h.body_start != c->body_start) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http file cache \"%s\" content changed", file.name.data); goto done; } /* * update cache file header with new data, * notably h.valid_sec and h.date */ ngx_memzero(&h, sizeof(ngx_http_file_cache_header_t)); h.valid_sec = c->valid_sec; h.last_modified = c->last_modified; h.date = c->date; h.crc32 = c->crc32; h.valid_msec = (u_short) c->valid_msec; h.header_start = (u_short) c->header_start; h.body_start = (u_short) c->body_start; (void) ngx_write_file(&file, (u_char *) &h, sizeof(ngx_http_file_cache_header_t), 0); done: if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file.name.data); } }
ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, ngx_pool_t *pool) { u_char *prev; size_t size; ssize_t total, n; ngx_array_t vec; struct iovec *iov, iovs[NGX_IOVS]; /* use pwrite() if there is the only buf in a chain */ if (cl->next == NULL) { //只有一个buf节点 return ngx_write_file(file, cl->buf->pos, (size_t) (cl->buf->last - cl->buf->pos), offset); } total = 0; //本次总共写道文件中的字节数,和cl中所有buf指向的内存空间大小相等 vec.elts = iovs; vec.size = sizeof(struct iovec); vec.nalloc = NGX_IOVS; vec.pool = pool; do { prev = NULL; iov = NULL; size = 0; vec.nelts = 0; /* create the iovec and coalesce the neighbouring bufs */ while (cl && vec.nelts < IOV_MAX) { //把cl链中的所有每一个chain节点连接到一个iov中 if (prev == cl->buf->pos) { //把一个chain链中的所有buf放到一个iov中 iov->iov_len += cl->buf->last - cl->buf->pos; } else { iov = ngx_array_push(&vec); if (iov == NULL) { return NGX_ERROR; } iov->iov_base = (void *) cl->buf->pos; iov->iov_len = cl->buf->last - cl->buf->pos; } size += cl->buf->last - cl->buf->pos; //cl为所有数据的长度和 prev = cl->buf->last; cl = cl->next; } //如果cl链中的所有chain个数超过了IOV_MAX个,则需要下次继续在后面while (cl);回过来处理 /* use pwrite() if there is the only iovec buffer */ if (vec.nelts == 1) { iov = vec.elts; n = ngx_write_file(file, (u_char *) iov[0].iov_base, iov[0].iov_len, offset); if (n == NGX_ERROR) { return n; } return total + n; } if (file->sys_offset != offset) { if (lseek(file->fd, offset, SEEK_SET) == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() \"%s\" failed", file->name.data); return NGX_ERROR; } file->sys_offset = offset; } n = writev(file->fd, vec.elts, vec.nelts); if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "writev() \"%s\" failed", file->name.data); return NGX_ERROR; } if ((size_t) n != size) { ngx_log_error(NGX_LOG_CRIT, file->log, 0, "writev() \"%s\" has written only %z of %uz", file->name.data, n, size); return NGX_ERROR; } ngx_log_debug3(NGX_LOG_DEBUG_CORE, file->log, 0, "writev to filename:%V,fd: %d, readsize: %z", &file->name, file->fd, n); file->sys_offset += n; file->offset += n; offset += n; total += n; } while (cl);//如果cl链中的所有chain个数超过了IOV_MAX个,则需要下次继续在后面while (cl);回过来处理 return total; }
static int ngx_proc_luashm_backup_backup(ngx_cycle_t *cycle,ngx_shm_zone_t *zone) { ngx_proc_luashm_backup_conf_t *pbcf; ngx_queue_t *q, *prev; ngx_http_lua_shdict_node_t *sd; ngx_http_lua_shdict_node_ext_t *extsd; ngx_http_lua_shdict_ctx_t *ctx; ngx_time_t *tp; int total = 0; uint64_t now; uint32_t content_size; size_t len; ngx_buf_t *buff; double *num_value; ngx_file_t file; u_char *shm_file_path; pbcf = ngx_proc_get_conf(cycle->conf_ctx, ngx_proc_luashm_backup_module); ctx = zone->data; buff = ngx_create_temp_buf(cycle->pool, zone->shm.size+65536); buff->last += sizeof(uint32_t); tp = ngx_timeofday(); now = (uint64_t) tp->sec * 1000 + tp->msec; ngx_shmtx_lock(&ctx->shpool->mutex); if (ngx_queue_empty(&ctx->sh->queue)) { ngx_shmtx_unlock(&ctx->shpool->mutex); return 1; } /* first run through: get total number of elements we need to allocate */ /* second run through: add keys to table */ total = 0; q = ngx_queue_last(&ctx->sh->queue); while (q != ngx_queue_sentinel(&ctx->sh->queue)) { prev = ngx_queue_prev(q); sd = ngx_queue_data(q, ngx_http_lua_shdict_node_t, queue); if (sd->expires == 0 || ((int64_t)(sd->expires - now)) > 60000) { //lua_pushlstring(L, (char *) sd->data, sd->key_len); //lua_rawseti(L, -2, ++total); extsd = (ngx_http_lua_shdict_node_ext_t*)buff->last; extsd->key_len=sd->key_len; extsd->expires=sd->expires; extsd->value_type=sd->value_type; extsd->user_flags=sd->user_flags; len = sd->key_len+sd->value_len; ngx_memcpy(extsd->data,sd->data,len); buff->last += sizeof(ngx_http_lua_shdict_node_ext_t)+len; switch (sd->value_type) { case LUA_TSTRING: extsd->value_len=sd->value_len; break; case LUA_TNUMBER: extsd->value_len=sizeof(double); num_value = extsd->data+extsd->key_len; //ngx_memcpy(num_value, extsd->data+extsd->key_len, extsd->value_len); break; case LUA_TBOOLEAN: extsd->value_len=sizeof(u_char); break; } //dd("key:%s, key_len:%d,value:%f,value_len:%d,expires:%lu,now:%lu",extsd->data,extsd->key_len,*num_value,extsd->value_len,extsd->expires,now); } q = prev; } ngx_shmtx_unlock(&ctx->shpool->mutex); shm_file_path=ngx_palloc(cycle->pool,pbcf->path.len + 5+ zone->shm.name.len); ngx_sprintf(shm_file_path,"%s/%s.dat",pbcf->path.data,zone->shm.name.data); content_size = buff->last-buff->pos; ngx_log_error(NGX_LOG_INFO,cycle->log,0,"save file:%s, content_size:%l bytes, nowtime:%l", shm_file_path,content_size,now); if(content_size > sizeof(uint32_t)) ngx_memcpy(buff->pos,&content_size,sizeof(uint32_t)); file.fd = open((char*)shm_file_path, O_TRUNC|O_RDWR, S_IWUSR|S_IWGRP|S_IRGRP|S_IRUSR); if (file.fd == NGX_INVALID_FILE) { //ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,ngx_open_file_n " \"%s\" failed",filename->data); ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,ngx_open_file_n " \"%s\" failed",shm_file_path); ngx_pfree(cycle->pool,buff); ngx_pfree(cycle->pool,shm_file_path); return NGX_ERROR; } file.name.len = pbcf->path.len; file.name.data = pbcf->path.data; file.offset = 0; file.log = cycle->log; file.offset=0; ngx_write_file(&file,buff->pos,content_size,0); ngx_close_file(file.fd); /* table is at top of stack */ ngx_pfree(cycle->pool,shm_file_path); ngx_pfree(cycle->pool,buff->start); ngx_pfree(cycle->pool,buff); return 1; }