static void ngx_conf_flush_files(ngx_cycle_t *cycle) { ssize_t n, len; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "flush files"); part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } len = file[i].pos - file[i].buffer; if (file[i].buffer == NULL || len == 0) { continue; } n = ngx_write_fd(file[i].fd, file[i].buffer, len); if (n == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_write_fd_n " to \"%s\" failed", file[i].name.data); } else if (n != len) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", file[i].name.data, n, len); } } }
static void ngx_rtmp_log_write(ngx_rtmp_session_t *s, ngx_rtmp_log_t *log, u_char *buf, size_t len) { u_char *name; time_t now; ssize_t n; int err; err = 0; name = log->file->name.data; n = ngx_write_fd(log->file->fd, buf, len); if (n == (ssize_t) len) { return; } now = ngx_time(); if (n == -1) { err = ngx_errno; if (err == NGX_ENOSPC) { log->disk_full_time = now; } if (now - log->error_log_time > 59) { ngx_log_error(NGX_LOG_ALERT, s->connection->log, err, ngx_write_fd_n " to \"%s\" failed", name); log->error_log_time = now; } } if (now - log->error_log_time > 59) { ngx_log_error(NGX_LOG_ALERT, s->connection->log, err, ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", name, n, len); log->error_log_time = now; } }
static void ngx_http_groonga_write_fd(ngx_fd_t fd, u_char *buffer, size_t buffer_size, const char *message, size_t message_size) { size_t rest_message_size = message_size; const char *current_message = message; while (rest_message_size > 0) { size_t current_message_size; if (rest_message_size > NGX_MAX_ERROR_STR) { current_message_size = NGX_MAX_ERROR_STR; } else { current_message_size = rest_message_size; } grn_memcpy(buffer, current_message, current_message_size); ngx_write_fd(fd, buffer, current_message_size); rest_message_size -= current_message_size; current_message += current_message_size; } }
static void ngx_http_groonga_logger_log(grn_ctx *ctx, grn_log_level level, const char *timestamp, const char *title, const char *message, const char *location, void *user_data) { ngx_http_groonga_logger_data_t *logger_data = user_data; const char level_marks[] = " EACewnid-"; u_char buffer[NGX_MAX_ERROR_STR]; u_char *last; if (location && *location) { last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR, "%s|%c|%s %s %s\n", timestamp, *(level_marks + level), title, message, location); } else { last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR, "%s|%c|%s %s\n", timestamp, *(level_marks + level), title, message); } ngx_write_fd(logger_data->file->fd, buffer, last - buffer); }
static ngx_int_t ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s) { ngx_fd_t fd; ngx_int_t rc; ngx_buf_t b; ngx_rtmp_dash_ctx_t *ctx; ngx_rtmp_codec_ctx_t *codec_ctx; static u_char buffer[NGX_RTMP_DASH_BUFSIZE]; ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); if (ctx == NULL || codec_ctx == NULL) { return NGX_ERROR; } /* init video */ *ngx_sprintf(ctx->stream.data + ctx->stream.len, "init.m4v") = 0; fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: error creating video init file"); return NGX_ERROR; } b.start = buffer; b.end = b.start + sizeof(buffer); b.pos = b.last = b.start; ngx_rtmp_mp4_write_ftyp(&b); ngx_rtmp_mp4_write_moov(s, &b, NGX_RTMP_MP4_VIDEO_TRACK); rc = ngx_write_fd(fd, b.start, (size_t) (b.last - b.start)); if (rc == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: writing video init failed"); } ngx_close_file(fd); /* init audio */ *ngx_sprintf(ctx->stream.data + ctx->stream.len, "init.m4a") = 0; fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: error creating dash audio init file"); return NGX_ERROR; } b.pos = b.last = b.start; ngx_rtmp_mp4_write_ftyp(&b); ngx_rtmp_mp4_write_moov(s, &b, NGX_RTMP_MP4_AUDIO_TRACK); rc = ngx_write_fd(fd, b.start, (size_t) (b.last - b.start)); if (rc == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: writing audio init failed"); } ngx_close_file(fd); return NGX_OK; }
static ngx_int_t ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s) { char *sep; u_char *p, *last; ssize_t n; ngx_fd_t fd; struct tm tm; ngx_str_t noname, *name; ngx_uint_t i, frame_rate_num, frame_rate_denom; ngx_rtmp_dash_ctx_t *ctx; ngx_rtmp_codec_ctx_t *codec_ctx; ngx_rtmp_dash_frag_t *f; ngx_rtmp_dash_app_conf_t *dacf; static u_char buffer[NGX_RTMP_DASH_BUFSIZE]; static u_char start_time[sizeof("1970-09-28T12:00:00+06:00")]; static u_char end_time[sizeof("1970-09-28T12:00:00+06:00")]; static u_char frame_rate[(NGX_INT_T_LEN * 2) + 2]; dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); if (dacf == NULL || ctx == NULL || codec_ctx == NULL) { return NGX_ERROR; } if (ctx->id == 0) { ngx_rtmp_dash_write_init_segments(s); } fd = ngx_open_file(ctx->playlist_bak.data, NGX_FILE_WRONLY, NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: open failed: '%V'", &ctx->playlist_bak); return NGX_ERROR; } #define NGX_RTMP_DASH_MANIFEST_HEADER \ "<?xml version=\"1.0\"?>\n" \ "<MPD\n" \ " type=\"dynamic\"\n" \ " xmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n" \ " availabilityStartTime=\"%s\"\n" \ " availabilityEndTime=\"%s\"\n" \ " minimumUpdatePeriod=\"PT%uiS\"\n" \ " minBufferTime=\"PT%uiS\"\n" \ " timeShiftBufferDepth=\"PT0H0M0.00S\"\n" \ " suggestedPresentationDelay=\"PT%uiS\"\n" \ " profiles=\"urn:hbbtv:dash:profile:isoff-live:2012," \ "urn:mpeg:dash:profile:isoff-live:2011\"\n" \ " xmlns:xsi=\"http://www.w3.org/2011/XMLSchema-instance\"\n" \ " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\">\n" \ " <Period start=\"PT0S\" id=\"dash\">\n" #define NGX_RTMP_DASH_MANIFEST_VIDEO \ " <AdaptationSet\n" \ " id=\"1\"\n" \ " segmentAlignment=\"true\"\n" \ " maxWidth=\"%ui\"\n" \ " maxHeight=\"%ui\"\n" \ " maxFrameRate=\"%s\">\n" \ " <Representation\n" \ " id=\"%V_H264\"\n" \ " mimeType=\"video/mp4\"\n" \ " codecs=\"avc1.%02uxi%02uxi%02uxi\"\n" \ " width=\"%ui\"\n" \ " height=\"%ui\"\n" \ " frameRate=\"%s\"\n" \ " sar=\"1:1\"\n" \ " startWithSAP=\"1\"\n" \ " bandwidth=\"%ui\">\n" \ " <SegmentTemplate\n" \ " presentationTimeOffset=\"0\"\n" \ " timescale=\"1000\"\n" \ " media=\"%V%s$Time$.m4v\"\n" \ " initialization=\"%V%sinit.m4v\">\n" \ " <SegmentTimeline>\n" #define NGX_RTMP_DASH_MANIFEST_VIDEO_FOOTER \ " </SegmentTimeline>\n" \ " </SegmentTemplate>\n" \ " </Representation>\n" \ " </AdaptationSet>\n" #define NGX_RTMP_DASH_MANIFEST_TIME \ " <S t=\"%uD\" d=\"%uD\"/>\n" #define NGX_RTMP_DASH_MANIFEST_AUDIO \ " <AdaptationSet\n" \ " id=\"2\"\n" \ " segmentAlignment=\"true\">\n" \ " <AudioChannelConfiguration\n" \ " schemeIdUri=\"urn:mpeg:dash:" \ "23003:3:audio_channel_configuration:2011\"\n" \ " value=\"1\"/>\n" \ " <Representation\n" \ " id=\"%V_AAC\"\n" \ " mimeType=\"audio/mp4\"\n" \ " codecs=\"mp4a.%s\"\n" \ " audioSamplingRate=\"%ui\"\n" \ " startWithSAP=\"1\"\n" \ " bandwidth=\"%ui\">\n" \ " <SegmentTemplate\n" \ " presentationTimeOffset=\"0\"\n" \ " timescale=\"1000\"\n" \ " media=\"%V%s$Time$.m4a\"\n" \ " initialization=\"%V%sinit.m4a\">\n" \ " <SegmentTimeline>\n" #define NGX_RTMP_DASH_MANIFEST_AUDIO_FOOTER \ " </SegmentTimeline>\n" \ " </SegmentTemplate>\n" \ " </Representation>\n" \ " </AdaptationSet>\n" #define NGX_RTMP_DASH_MANIFEST_FOOTER \ " </Period>\n" \ "</MPD>\n" ngx_libc_localtime(ctx->start_time.sec + ngx_rtmp_dash_get_frag(s, 0)->timestamp / 1000, &tm); *ngx_sprintf(start_time, "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, ctx->start_time.gmtoff < 0 ? '-' : '+', ngx_abs(ctx->start_time.gmtoff / 60), ngx_abs(ctx->start_time.gmtoff % 60)) = 0; ngx_libc_localtime(ctx->start_time.sec + (ngx_rtmp_dash_get_frag(s, ctx->nfrags - 1)->timestamp + ngx_rtmp_dash_get_frag(s, ctx->nfrags - 1)->duration) / 1000, &tm); *ngx_sprintf(end_time, "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, ctx->start_time.gmtoff < 0 ? '-' : '+', ngx_abs(ctx->start_time.gmtoff / 60), ngx_abs(ctx->start_time.gmtoff % 60)) = 0; last = buffer + sizeof(buffer); p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_HEADER, start_time, end_time, (ngx_uint_t) (dacf->fraglen / 1000), (ngx_uint_t) (dacf->fraglen / 1000), (ngx_uint_t) (dacf->fraglen / 500)); n = ngx_write_fd(fd, buffer, p - buffer); ngx_str_null(&noname); name = (dacf->nested ? &noname : &ctx->name); sep = (dacf->nested ? "" : "-"); if (ctx->has_video) { frame_rate_num = (ngx_uint_t) (codec_ctx->frame_rate * 1000.); if (frame_rate_num % 1000 == 0) { *ngx_sprintf(frame_rate, "%ui", frame_rate_num / 1000) = 0; } else { frame_rate_denom = 1000; switch (frame_rate_num) { case 23976: frame_rate_num = 24000; frame_rate_denom = 1001; break; case 29970: frame_rate_num = 30000; frame_rate_denom = 1001; break; case 59940: frame_rate_num = 60000; frame_rate_denom = 1001; break; } *ngx_sprintf(frame_rate, "%ui/%ui", frame_rate_num, frame_rate_denom) = 0; } p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_VIDEO, codec_ctx->width, codec_ctx->height, frame_rate, &ctx->name, codec_ctx->avc_profile, codec_ctx->avc_compat, codec_ctx->avc_level, codec_ctx->width, codec_ctx->height, frame_rate, (ngx_uint_t) (codec_ctx->video_data_rate * 1000), name, sep, name, sep); for (i = 0; i < ctx->nfrags; i++) { f = ngx_rtmp_dash_get_frag(s, i); p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_TIME, f->timestamp, f->duration); } p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_VIDEO_FOOTER); n = ngx_write_fd(fd, buffer, p - buffer); } if (ctx->has_audio) { p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_AUDIO, &ctx->name, codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC ? (codec_ctx->aac_sbr ? "40.5" : "40.2") : "6b", codec_ctx->sample_rate, (ngx_uint_t) (codec_ctx->audio_data_rate * 1000), name, sep, name, sep); for (i = 0; i < ctx->nfrags; i++) { f = ngx_rtmp_dash_get_frag(s, i); p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_TIME, f->timestamp, f->duration); } p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_AUDIO_FOOTER); n = ngx_write_fd(fd, buffer, p - buffer); } p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_FOOTER); n = ngx_write_fd(fd, buffer, p - buffer); if (n < 0) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: write failed: '%V'", &ctx->playlist_bak); ngx_close_file(fd); return NGX_ERROR; } ngx_close_file(fd); if (ngx_rtmp_dash_rename_file(ctx->playlist_bak.data, ctx->playlist.data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: rename failed: '%V'->'%V'", &ctx->playlist_bak, &ctx->playlist); return NGX_ERROR; } return NGX_OK; }
static void ngx_pipe_log(ngx_cycle_t *cycle, ngx_open_pipe_t *op) { ngx_int_t n_bytes_read; u_char *read_buf; size_t read_buf_len = 65536; ngx_fd_t log_fd = NGX_INVALID_FILE; #ifdef T_PIPE_NO_DISPLAY size_t title_len; #endif ngx_pipe_rollback_conf_t rbcf; ngx_file_info_t sb; size_t one_day = 24 * 60 * 60; ngx_pid = ngx_getpid(); rbcf.last_open_time = 0; rbcf.last_suit_time = 0; rbcf.log_size = 0; if (ngx_pipe_rollback_parse_args(cycle, op, &rbcf) != NGX_OK) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "log rollback parse error"); return; } read_buf = ngx_pcalloc(cycle->pool, read_buf_len); if (read_buf == NULL) { return; } //set title ngx_setproctitle((char *) op->cmd); #ifdef T_PIPE_NO_DISPLAY title_len = ngx_strlen(ngx_os_argv[0]); #if (NGX_SOLARIS) #else ngx_memset((u_char *) ngx_os_argv[0], NGX_SETPROCTITLE_PAD, title_len); ngx_cpystrn((u_char *) ngx_os_argv[0], op->cmd, title_len); #endif #endif for (;;) { if (ngx_terminate == 1) { return; } n_bytes_read = ngx_read_fd(0, read_buf, read_buf_len); if (n_bytes_read == 0) { return; } if (errno == EINTR) { continue; } else if (n_bytes_read < 0) { return; } rbcf.time_now = ngx_pipe_get_now_sec(); if (NULL != rbcf.suitpath) { if (rbcf.time_now / one_day > rbcf.last_suit_time / one_day) { ngx_pipe_create_suitpath(cycle, &rbcf); } } if (log_fd >= 0) { if (rbcf.interval > 0) { if (((rbcf.time_now - rbcf.adjust_time) / rbcf.interval) > (rbcf.last_open_time / rbcf.interval)) { //need check rollback ngx_close_file(log_fd); log_fd = NGX_INVALID_FILE; ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "need check rollback time [%s]", rbcf.logname); ngx_pipe_do_rollback(cycle, &rbcf); } } } if (log_fd >= 0 && rbcf.log_max_size > 0 && rbcf.log_size >= rbcf.log_max_size) { ngx_close_file(log_fd); log_fd = NGX_INVALID_FILE; ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "need check rollback size [%s] [%d]", rbcf.logname, rbcf.log_size); ngx_pipe_do_rollback(cycle, &rbcf); } /* If there is no log file open then open a new one. * */ if (log_fd < 0) { ngx_pipe_create_subdirs(rbcf.logname, cycle); if (rbcf.interval > 0 && rbcf.last_open_time == 0 && ((rbcf.time_now - rbcf.adjust_time_raw) / rbcf.interval < rbcf.time_now / rbcf.interval)) { /*just check when time is after interval and befor adjust_time_raw, fix when no backup file, do rollback */ //need check last rollback time, because other process may do rollback after when it adjust time more than this process ngx_pipe_get_last_rollback_time(&rbcf); } else { rbcf.last_open_time = ngx_pipe_get_now_sec(); } log_fd = ngx_open_file(rbcf.logname, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_PIPE_FILE_ACCESS); if (log_fd < 0) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "open [%s] failed", rbcf.logname); return; } if (0 == ngx_fd_info(log_fd, &sb)) { rbcf.log_size = sb.st_size; } } if (ngx_write_fd(log_fd, read_buf, n_bytes_read) != n_bytes_read) { if (errno != EINTR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "write to [%s] failed", rbcf.logname); return; } } rbcf.log_size += n_bytes_read; } }
static ssize_t ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len) { size_t root; ssize_t n; ngx_str_t log, path; ngx_open_file_info_t of; ngx_http_log_loc_conf_t *llcf; ngx_http_core_loc_conf_t *clcf; if (!r->root_tested) { /* test root directory existance */ if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) { /* simulate successfull logging */ return len; } path.data[root] = '\0'; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ngx_memzero(&of, sizeof(ngx_open_file_info_t)); of.valid = clcf->open_file_cache_valid; of.min_uses = clcf->open_file_cache_min_uses; of.test_dir = 1; of.test_only = 1; of.errors = clcf->open_file_cache_errors; of.events = clcf->open_file_cache_events; if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) != NGX_OK) { if (of.err == 0) { /* simulate successfull logging */ return len; } ngx_log_error(NGX_LOG_ERR, r->connection->log, of.err, "testing \"%s\" existence failed", path.data); /* simulate successfull logging */ return len; } if (!of.is_dir) { ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ENOTDIR, "testing \"%s\" existence failed", path.data); /* simulate successfull logging */ return len; } } if (ngx_http_script_run(r, &log, script->lengths->elts, 1, script->values->elts) == NULL) { /* simulate successfull logging */ return len; } log.data[log.len - 1] = '\0'; *name = log.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http log \"%s\"", log.data); llcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module); ngx_memzero(&of, sizeof(ngx_open_file_info_t)); of.log = 1; of.valid = llcf->open_file_cache_valid; of.min_uses = llcf->open_file_cache_min_uses; of.directio = NGX_OPEN_FILE_DIRECTIO_OFF; if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool) != NGX_OK) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, "%s \"%s\" failed", of.failed, log.data); /* simulate successfull logging */ return len; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http log #%d", of.fd); n = ngx_write_fd(of.fd, buf, len); return n; }
static ngx_int_t ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, u_char *from, u_char *to) { off_t size; ssize_t n; ngx_fd_t fd, cfd; ngx_int_t rc; u_char buf[NGX_HTTP_DAV_COPY_BLOCK]; fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, from); return NGX_ERROR; } cfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN, ctx->access); rc = NGX_ERROR; if (cfd == NGX_INVALID_FILE) { (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, to); goto failed; } for (size = ctx->size; size > 0; size -= n) { n = ngx_read_fd(fd, buf, NGX_HTTP_DAV_COPY_BLOCK); if (n == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_read_fd_n " \"%s\" failed", from); goto failed; } if (ngx_write_fd(cfd, buf, n) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_write_fd_n " \"%s\" failed", to); goto failed; } } if (ngx_set_file_time(to, cfd, ctx->mtime) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_set_file_time_n " \"%s\" failed", to); goto failed; } if (ngx_close_file(cfd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_close_file_n " \"%s\" failed", to); goto failed; } rc = NGX_OK; failed: if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_close_file_n " \"%s\" failed", from); } return rc; }
static void * xml_log_write(ngx_http_request_t *r) { char *ptr,*wptr; wptr=buf; r->server_name.data[r->server_name.len]=0; r->uri.data[r->uri.len]=0; wptr=ngx_sprintf(wptr,"<log time=\"%d\" ip=\"%d\" host=\"%s\" path=\"%s\">\n",ngx_time(),((struct sockaddr_in *) r->connection->sockaddr)->sin_addr.s_addr,r->server_name.data,r->uri.data); unsigned off=0; if(r->method == NGX_HTTP_POST) { if(r->request_body && r->request_body->buf && (len=r->request_body->buf->last - r->request_body->buf->start) && len > 0) { pos.key=0; pos.value=0; ptr=r->request_body->buf->start; for(;len > 0;ptr++,len--) { if(pos.key == 0 && pos.value == 0) { pos.key=1; wptr=cpy(wptr,"\t<query method=\"POST\" name=\""); } if(pos.key ==1 && pos.value == 0) { if(*ptr == '=') { wptr=cpy(wptr,"\" empty=\"0\"><![CDATA["); pos.key=0; pos.value=1; } else if(*ptr == '&') { wptr=cpy(wptr,"\" empty=\"1\"/>\n"); pos.key=pos.value=0; } else { wptr[0]=*ptr; wptr++; } } else if(pos.key ==0 && pos.value == 1) { if(*ptr == '&') { wptr=cpy(wptr,"]]></query>\n"); pos.key=pos.value=0; } else { wptr[0]=*ptr; wptr++; } } } if(pos.key == 1) wptr=cpy(wptr,"\" empty=\"1\" />\n"); else wptr=cpy(wptr,"]]></query>\n"); } } if(r->args.len > 0) { pos.key=0; pos.value=0; ptr=r->args.data; len=r->args.len; for(;len > 0;ptr++,len--) { if(pos.key == 0 && pos.value == 0) { pos.key=1; wptr=cpy(wptr,"\t<query method=\"GET\" name=\""); } if(pos.key ==1 && pos.value == 0) { if(*ptr == '=') { wptr=cpy(wptr,"\" empty=\"0\"><![CDATA["); pos.key=0; pos.value=1; } else if(*ptr == '&') { wptr=cpy(wptr,"\" empty=\"1\"/>\n"); pos.key=pos.value=0; } else { wptr[0]=*ptr; wptr++; } } else if(pos.key ==0 && pos.value == 1) { if(*ptr == '&') { wptr=cpy(wptr,"]]></query>\n"); pos.key=pos.value=0; } else { wptr[0]=*ptr; wptr++; } } } if(pos.key == 1) wptr=cpy(wptr,"\" empty=\"1\" />\n"); else wptr=cpy(wptr,"]]></query>\n"); } wptr=cpy(wptr,"</log>\n"); wptr[0]=0; len=(unsigned)(wptr-buf); ngx_write_fd(fd,buf,wptr-buf); }
int ngx_cdecl main(int argc, char *const *argv) { ngx_buf_t *b; ngx_log_t *log; ngx_uint_t i; ngx_cycle_t *cycle, init_cycle; ngx_conf_dump_t *cd; ngx_core_conf_t *ccf; ngx_debug_init(); if (ngx_strerror_init() != NGX_OK) { return 1; } if (ngx_get_options(argc, argv) != NGX_OK) { return 1; } if (ngx_show_version) { ngx_show_version_info(); if (!ngx_test_config) { return 0; } } /* TODO */ ngx_max_sockets = -1; ngx_time_init(); #if (NGX_PCRE) ngx_regex_init(); #endif ngx_pid = ngx_getpid(); log = ngx_log_init(ngx_prefix); if (log == NULL) { return 1; } /* STUB */ #if (NGX_OPENSSL) ngx_ssl_init(log); #endif /* * init_cycle->log is required for signal handlers and * ngx_process_options() */ ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); init_cycle.log = log; ngx_cycle = &init_cycle; init_cycle.pool = ngx_create_pool(1024, log); if (init_cycle.pool == NULL) { return 1; } if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; } if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; } if (ngx_os_init(log) != NGX_OK) { return 1; } /* * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init() */ if (ngx_crc32_table_init() != NGX_OK) { return 1; } if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; } cycle = ngx_init_cycle(&init_cycle); if (cycle == NULL) { if (ngx_test_config) { ngx_log_stderr(0, "configuration file %s test failed", init_cycle.conf_file.data); } return 1; } if (ngx_test_config) { if (!ngx_quiet_mode) { ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data); } if (ngx_dump_config) { cd = cycle->config_dump.elts; for (i = 0; i < cycle->config_dump.nelts; i++) { ngx_write_stdout("# configuration file "); (void) ngx_write_fd(ngx_stdout, cd[i].name.data, cd[i].name.len); ngx_write_stdout(":" NGX_LINEFEED); b = cd[i].buffer; (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos); ngx_write_stdout(NGX_LINEFEED); } } return 0; } if (ngx_signal) { return ngx_signal_process(cycle, ngx_signal); } ngx_os_status(cycle->log); ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER; } #if !(NGX_WIN32) if (ngx_init_signals(cycle->log) != NGX_OK) { return 1; } if (!ngx_inherited && ccf->daemon) { if (ngx_daemon(cycle->log) != NGX_OK) { return 1; } ngx_daemonized = 1; } if (ngx_inherited) { ngx_daemonized = 1; } #endif if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; } if (ngx_log_redirect_stderr(cycle) != NGX_OK) { return 1; } if (log->file->fd != ngx_stderr) { if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_close_file_n " built-in log failed"); } } ngx_use_stderr = 0; if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); } return 0; }
void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, va_list args) #endif { #if (NGX_HAVE_VARIADIC_MACROS) va_list args; #endif u_char errstr[NGX_MAX_ERROR_STR], *p, *last; if (log->file->fd == NGX_INVALID_FILE) { return; } last = errstr + NGX_MAX_ERROR_STR; ngx_memcpy(errstr, ngx_cached_err_log_time.data, ngx_cached_err_log_time.len); p = errstr + ngx_cached_err_log_time.len; p = ngx_snprintf(p, last - p, " [%s] ", err_levels[level]); /* pid#tid */ p = ngx_snprintf(p, last - p, "%P#" NGX_TID_T_FMT ": ", ngx_log_pid, ngx_log_tid); if (log->connection) { p = ngx_snprintf(p, last - p, "*%uA ", log->connection); } #if (NGX_HAVE_VARIADIC_MACROS) va_start(args, fmt); p = ngx_vsnprintf(p, last - p, fmt, args); va_end(args); #else p = ngx_vsnprintf(p, last - p, fmt, args); #endif if (err) { if (p > last - 50) { /* leave a space for an error code */ p = last - 50; *p++ = '.'; *p++ = '.'; *p++ = '.'; } #if (NGX_WIN32) if ((unsigned) err >= 0x80000000) { p = ngx_snprintf(p, last - p, " (%Xd: ", err); } else { p = ngx_snprintf(p, last - p, " (%d: ", err); } #else p = ngx_snprintf(p, last - p, " (%d: ", err); #endif p = ngx_strerror_r(err, p, last - p); if (p < last) { *p++ = ')'; } } if (level != NGX_LOG_DEBUG && log->handler) { p = log->handler(log, p, last - p); } if (p > last - NGX_LINEFEED_SIZE) { p = last - NGX_LINEFEED_SIZE; } ngx_linefeed(p); (void) ngx_write_fd(log->file->fd, errstr, p - errstr); }
static ngx_buf_t * ngx_http_pngquant_quantize(ngx_http_request_t *r, ngx_http_pngquant_ctx_t *ctx) { u_char *out; ngx_buf_t *b; ngx_pool_cleanup_t *cln; ngx_http_pngquant_conf_t *conf; gdImagePtr img; int size; ngx_int_t rc; ngx_temp_file_t *tf; ssize_t n; ngx_ext_rename_file_t ext; ngx_str_t dest; ngx_str_t value; img = gdImageCreateFromPngPtr(ctx->length, ctx->image); if (img == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "gdImageCreateFromPngPtr() failed"); return NULL; } conf = ngx_http_get_module_loc_conf(r, ngx_http_pngquant_module); /* * gdImageTrueColorToPaletteSetMethod(img, GD_QUANT_LIQ, conf->speed); * gdImageTrueColorToPalette(img, conf->dither, conf->colors); */ ngx_pngquant_gd_image(img, conf->dither, conf->colors, conf->speed); out = gdImagePngPtr(img, &size); gdImageDestroy(img); ngx_pfree(r->pool, ctx->image); if (out == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "gdImagePngPtr() failed"); return NULL; } if (conf->store) { if(ngx_http_complex_value(r, conf->store, &value) != NGX_OK) { goto failed; } dest.len = value.len + 1; dest.data = ngx_pnalloc(r->pool, dest.len); if (dest.data == NULL) { goto failed; } ngx_memzero(dest.data, dest.len); ngx_memcpy(dest.data, value.data, value.len); ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "pngquant_store (%s)", dest.data); tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); if (tf == NULL) { goto failed; } tf->file.fd = NGX_INVALID_FILE; tf->file.log = r->connection->log; tf->path = conf->temp_path; tf->pool = r->pool; tf->persistent = 1; rc = ngx_create_temp_file(&tf->file, tf->path, tf->pool, tf->persistent, tf->clean, tf->access); if (rc != NGX_OK) { goto failed; } n = ngx_write_fd(tf->file.fd, out, size); if (n == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_write_fd_n " \"%s\" failed", tf->file.name.data); goto failed; } if ((int) n != size) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_write_fd_n " has written only %z of %uz bytes", n, size); goto failed; } ext.access = conf->store_access; ext.path_access = conf->store_access; ext.time = -1; ext.create_path = 1; ext.delete_file = 1; ext.log = r->connection->log; rc = ngx_ext_rename_file(&tf->file.name, &dest, &ext); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_ext_rename_file() failed"); goto failed; } } cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { goto failed; } b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { goto failed; } cln->handler = ngx_http_pngquant_cleanup; cln->data = out; b->pos = out; b->last = out + size; b->memory = 1; b->last_buf = 1; ngx_http_pngquant_length(r, b); #if defined(nginx_version) && (nginx_version >= 1007003) ngx_http_weak_etag(r); #endif return b; failed: gdFree(out); return NULL; }
void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, va_list args) #endif { #if (NGX_HAVE_VARIADIC_MACROS) va_list args; #endif u_char *p, *last, *msg; ssize_t n; ngx_uint_t wrote_stderr, debug_connection; u_char errstr[NGX_MAX_ERROR_STR]; // 错误消息的最大长度,2k字节 last = errstr + NGX_MAX_ERROR_STR; // 先拷贝当前的时间 // 格式是"1970/09/28 12:00:00" p = ngx_cpymem(errstr, ngx_cached_err_log_time.data, ngx_cached_err_log_time.len); // 打印错误等级的字符串描述信息,使用关联数组err_levels p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]); // 打印pid和tid // #define ngx_log_pid ngx_pid // #define ngx_log_tid ngx_thread_tid() // in os/unix /* pid#tid */ p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ", ngx_log_pid, ngx_log_tid); // 如果有连接计数则打印 if (log->connection) { p = ngx_slprintf(p, last, "*%uA ", log->connection); } // 前面输出的是基本的信息:当前时间+[错误级别]+pid#tid: msg = p; // 打印可变参数 #if (NGX_HAVE_VARIADIC_MACROS) va_start(args, fmt); p = ngx_vslprintf(p, last, fmt, args); va_end(args); #else p = ngx_vslprintf(p, last, fmt, args); #endif // 如果有系统错误码,那么记录(err) if (err) { p = ngx_log_errno(p, last, err); } // 记录错误日志时可以执行的回调函数 // 参数是消息缓冲区里剩余的空间 // 只有高于debug才会执行 if (level != NGX_LOG_DEBUG && log->handler) { p = log->handler(log, p, last - p); } // #define NGX_LINEFEED_SIZE 1 if (p > last - NGX_LINEFEED_SIZE) { p = last - NGX_LINEFEED_SIZE; } // #define ngx_linefeed(p) *p++ = LF; ngx_linefeed(p); wrote_stderr = 0; debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0; // 对整个日志链表执行写入操作 while (log) { if (log->log_level < level && !debug_connection) { break; } if (log->writer) { log->writer(log, level, errstr, p - errstr); goto next; } if (ngx_time() == log->disk_full_time) { /* * on FreeBSD writing to a full filesystem with enabled softupdates * may block process for much longer time than writing to non-full * filesystem, so we skip writing to a log for one second */ goto next; } // 写错误日志消息到关联的文件 // 实际上就是系统调用write,见ngx_files.h n = ngx_write_fd(log->file->fd, errstr, p - errstr); // 写入失败,且错误是磁盘满 if (n == -1 && ngx_errno == NGX_ENOSPC) { log->disk_full_time = ngx_time(); } if (log->file->fd == ngx_stderr) { wrote_stderr = 1; } next: // 使用下一个日志对象记录日志 log = log->next; } if (!ngx_use_stderr || level > NGX_LOG_WARN || wrote_stderr) { return; } msg -= (7 + err_levels[level].len + 3); (void) ngx_sprintf(msg, "nginx: [%V] ", &err_levels[level]); (void) ngx_write_console(ngx_stderr, msg, p - msg); }
/* * __cdecl表示C语言默认的函数调用方法,即所有参数从右到左依次入栈,这些参数有调用者负责清除,被调用函数不会要求 * 调用者传递多少参数,调用者传递过多或过少的参数都不会引起编译错误。 */ int ngx_cdecl main(int argc, char *const *argv) { ngx_buf_t *b; ngx_log_t *log; ngx_uint_t i; ngx_cycle_t *cycle, init_cycle; ngx_conf_dump_t *cd; ngx_core_conf_t *ccf; ngx_debug_init(); //设置全局变量ngx_debug_malloc /*初始化系统错误码对应的描述性字符串*/ if (ngx_strerror_init() != NGX_OK) { return 1; } /*ngx_get_options()函数用于解析命令行参数,并设置命令行参数相应的标志位*/ if (ngx_get_options(argc, argv) != NGX_OK) { return 1; } /*根据ngx_get_options()函数中设置的标志位打印相关信息到标准输出上*/ if (ngx_show_version) { ngx_show_version_info(); if (!ngx_test_config) { return 0; } } /* TODO */ ngx_max_sockets = -1; /*初始化并更新nginx内核使用的时间*/ ngx_time_init(); #if (NGX_PCRE) ngx_regex_init(); #endif /*获取master进程ID*/ ngx_pid = ngx_getpid(); /*初始化全局错误日志对象ngx_log及前缀ngx_prefix*/ log = ngx_log_init(ngx_prefix); if (log == NULL) { return 1; } /* STUB */ #if (NGX_OPENSSL) ngx_ssl_init(log); #endif /* * init_cycle->log is required for signal handlers and * ngx_process_options() */ ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); init_cycle.log = log; ngx_cycle = &init_cycle; /*为进程唯一核心结构体ngx_cycle_t的创建内存池*/ init_cycle.pool = ngx_create_pool(1024, log); if (init_cycle.pool == NULL) { return 1; } /*保存命令行参数*/ if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; } /*ngx_process_options()用于初始化ngx_cycle的prefix, conf_prefix, conf_file, conf_param等*/ if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; } /*对Nginx内核中用到的一些和操作系统相关性大的全局变量进行初始化*/ if (ngx_os_init(log) != NGX_OK) { return 1; } /* * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init() */ /*初始化循环冗余校验表,后续校验可以直接通过查表法*/ if (ngx_crc32_table_init() != NGX_OK) { return 1; } /*平滑升级时新版本master进程对旧版本master进程的监听句柄做继承处理*/ if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } /*ngx_preinit_modules()初始化模块的一些信息和部分相关全局变量*/ if (ngx_preinit_modules() != NGX_OK) { return 1; } /*初始化全局唯一的ngx_cycle_t*/ cycle = ngx_init_cycle(&init_cycle); if (cycle == NULL) { if (ngx_test_config) { ngx_log_stderr(0, "configuration file %s test failed", init_cycle.conf_file.data); } return 1; } if (ngx_test_config) { if (!ngx_quiet_mode) { ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data); } if (ngx_dump_config) { cd = cycle->config_dump.elts; for (i = 0; i < cycle->config_dump.nelts; i++) { ngx_write_stdout("# configuration file "); (void) ngx_write_fd(ngx_stdout, cd[i].name.data, cd[i].name.len); ngx_write_stdout(":" NGX_LINEFEED); b = cd[i].buffer; (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos); ngx_write_stdout(NGX_LINEFEED); } } return 0; } /*"nginx -s xxx"*/ if (ngx_signal) { return ngx_signal_process(cycle, ngx_signal); } ngx_os_status(cycle->log); ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER; } #if !(NGX_WIN32) /*初始化信号*/ if (ngx_init_signals(cycle->log) != NGX_OK) { return 1; } if (!ngx_inherited && ccf->daemon) { if (ngx_daemon(cycle->log) != NGX_OK) { return 1; } ngx_daemonized = 1; } if (ngx_inherited) { ngx_daemonized = 1; } #endif /*创建pidfile,并写入当前进程id*/ if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; } if (ngx_log_redirect_stderr(cycle) != NGX_OK) { return 1; } /*关闭日志文件流*/ if (log->file->fd != ngx_stderr) { if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_close_file_n " built-in log failed"); } } ngx_use_stderr = 0; /*单进程模式运行*/ if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { /*以一个master进程多个woker进程运行*/ ngx_master_process_cycle(cycle); } return 0; }
// nginx启动的入口函数 // 相关文件ngx_process_cycle.c/ngx_posix_init.c/ngx_process.c // 设置重要的指针volatile ngx_cycle_t *ngx_cycle; // // 1)解析命令行参数,显示帮助信息 // 2)初始化操作系统调用接口函数ngx_os_io = ngx_linux_io; // 3)根据命令行参数等建立一个基本的cycle // 4)初始化模块数组ngx_modules // 5)核心操作,调用ngx_init_cycle创建进程使用的cycle,解析配置文件,启动监听端口 // 6)启动单进程或多进程 int ngx_cdecl main(int argc, char *const *argv) { ngx_buf_t *b; ngx_log_t *log; ngx_uint_t i; ngx_cycle_t *cycle, init_cycle; //cycle结构体 ngx_conf_dump_t *cd; ngx_core_conf_t *ccf; //获得ngx_core_module的配置结构体 ngx_debug_init(); if (ngx_strerror_init() != NGX_OK) { return 1; } // 解析命令行参数, 本文件内查找ngx_get_options // 设置ngx_show_version/ngx_show_help等变量 if (ngx_get_options(argc, argv) != NGX_OK) { return 1; } // 1.9.x改到ngx_show_version_info() if (ngx_show_version) { ngx_show_version_info(); // 1.9.x ngx_show_version_info()结束 if (!ngx_test_config) { //如果是-t参数,那么接下来要走流程检查配置但不启动 return 0; } } // 在ngx_os_init函数里设置(os/unix/ngx_posix_init.c) // 使用系统调用getrlimit(RLIMIT_NOFILE, &rlmt) // 是nginx能够打开的最多描述数量,但似乎并没有使用 /* TODO */ ngx_max_sockets = -1; // ngx_times.c,初始化各个cache时间变量 // 调用ngx_time_update(),得到当前的时间 ngx_time_init(); #if (NGX_PCRE) ngx_regex_init(); // 正则表达式库初始化 #endif // 定义在os/unix/ngx_process_cycle.c : ngx_pid_t ngx_pid; // ngx_process.h : #define ngx_getpid getpid // 获取当前进程也就是master进程的pid // 如果是master/worker,会fork出新的子进程,见os/unix/ngx_daemon.c ngx_pid = ngx_getpid(); // 初始化log // ngx_prefix是-p后的参数,即nginx的工作目录 // 默认是NGX_CONF_PREFIX,即/usr/local/nginx log = ngx_log_init(ngx_prefix); if (log == NULL) { return 1; } /* STUB */ #if (NGX_OPENSSL) ngx_ssl_init(log); #endif /* * init_cycle->log is required for signal handlers and * ngx_process_options() */ // 设置最开始的cycle ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); init_cycle.log = log; // 定义在ngx_cycle.c, // volatile ngx_cycle_t *ngx_cycle; // nginx生命周期使用的超重要对象 // ngx_cycle指针指向第一个cycle结构体 ngx_cycle = &init_cycle; //创建cycle使用的内存池,用于之后所有的内存分配,必须成功 init_cycle.pool = ngx_create_pool(1024, log); if (init_cycle.pool == NULL) { return 1; } // 分配内存,拷贝参数,没有使用内存池 // 拷贝到全局变量ngx_argc/ngx.argv if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; } // 设置cycle->prefix/cycle->conf_prefix等成员 if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; } // os/unix/ngx_posix_init.c // 初始化ngx_os_io结构体,设置基本的收发函数 // 基本的页大小,ngx_pagesize = getpagesize() // 最多描述符数量,ngx_max_sockets // 初始化随机数 // ngx_os_io = ngx_linux_io;重要的操作,设置为linux的接口函数 if (ngx_os_init(log) != NGX_OK) { return 1; } /* * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init() */ // 初始化用于crc32计算的表,在ngx_crc32.c if (ngx_crc32_table_init() != NGX_OK) { return 1; } // 检查NGINX环境变量,获取之前监听的socket if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } // 开始计算所有的静态模块数量 // ngx_modules是nginx模块数组,存储所有的模块指针,由make生成在objs/ngx_modules.c // 这里赋值每个模块的index成员 // ngx_modules_n保存了最后一个可用的序号 // ngx_max_module是模块数量的上限 if (ngx_preinit_modules() != NGX_OK) { return 1; } // ngx_cycle.c // 初始化cycle,800多行 // 由之前最基本的init_cycle产生出真正使用的cycle // 解析配置文件,配置所有的模块 // 创建共享内存,打开文件,监听配置的端口 cycle = ngx_init_cycle(&init_cycle); if (cycle == NULL) { if (ngx_test_config) { ngx_log_stderr(0, "configuration file %s test failed", init_cycle.conf_file.data); } return 1; } // 如果用了-t参数要测试配置,在这里就结束了 // 定义在ngx_cycle.c if (ngx_test_config) { //非安静模式,输出测试信息 if (!ngx_quiet_mode) { ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data); } // 1.10, dump整个配置文件 if (ngx_dump_config) { cd = cycle->config_dump.elts; for (i = 0; i < cycle->config_dump.nelts; i++) { ngx_write_stdout("# configuration file "); (void) ngx_write_fd(ngx_stdout, cd[i].name.data, cd[i].name.len); ngx_write_stdout(":" NGX_LINEFEED); b = cd[i].buffer; (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos); ngx_write_stdout(NGX_LINEFEED); } } return 0; } // 如果用了-s参数,那么就要发送reload/stop等信号,然后结束 if (ngx_signal) { // ngx_cycle.c // 最后调用os/unix/ngx_process.c里的函数ngx_os_signal_process() return ngx_signal_process(cycle, ngx_signal); } // ngx_posix_init.c // 使用NGX_LOG_NOTICE记录操作系统的一些信息,通常不会显示 ngx_os_status(cycle->log); // 定义在ngx_cycle.c, // volatile ngx_cycle_t *ngx_cycle; // nginx生命周期使用的超重要对象 ngx_cycle = cycle; // 检查core模块的配置 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); // master on且单进程 // 如果master_process off那么就不是master进程 // ngx_process定义在os/unix/ngx_process_cycle.c if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { // 设置为master进程状态 ngx_process = NGX_PROCESS_MASTER; } // unix/linux将进程守护进程化 #if !(NGX_WIN32) // os/unix/ngx_process.c // 使用signals数组,初始化信号处理handler if (ngx_init_signals(cycle->log) != NGX_OK) { return 1; } // 守护进程 if (!ngx_inherited && ccf->daemon) { // os/unix/ngx_daemon.c // 经典的daemon操作,使用fork if (ngx_daemon(cycle->log) != NGX_OK) { return 1; } ngx_daemonized = 1; } if (ngx_inherited) { ngx_daemonized = 1; } #endif // ngx_cycle.c // 把ngx_pid字符串化,写入pid文件 // 在daemon后,此时的pid是真正的master进程pid if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; } if (ngx_log_redirect_stderr(cycle) != NGX_OK) { return 1; } if (log->file->fd != ngx_stderr) { if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_close_file_n " built-in log failed"); } } ngx_use_stderr = 0; // 启动单进程或者master/worker多进程,内部会调用fork // 子进程完全复制父进程的cycle,包括打开的文件、共享内存、监听的端口 if (ngx_process == NGX_PROCESS_SINGLE) { // 如果master_process off那么就不是master进程 // ngx_process_cycle.c ngx_single_process_cycle(cycle); } else { // ngx_process_cycle.c // 启动worker进程,数量由配置决定,即worker_processes指令 // 核心操作是sigsuspend,暂时挂起进程,不占用CPU,只有收到信号时才被唤醒 ngx_master_process_cycle(cycle); } // 只有退出无限循环才会走到这里,进程结束 return 0; }
static void ngx_rtmp_dash_close_fragment(ngx_rtmp_session_t *s, ngx_rtmp_dash_track_t *t) { u_char *pos, *pos1; size_t left; ssize_t n; ngx_fd_t fd; ngx_buf_t b; ngx_rtmp_dash_ctx_t *ctx; ngx_rtmp_dash_frag_t *f; static u_char buffer[NGX_RTMP_DASH_BUFSIZE]; if (!t->opened) { return; } ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "dash: close fragment id=%ui, type=%c, pts=%uD", t->id, t->type, t->earliest_pres_time); ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); b.start = buffer; b.end = buffer + sizeof(buffer); b.pos = b.last = b.start; ngx_rtmp_mp4_write_styp(&b); pos = b.last; b.last += 44; /* leave room for sidx */ ngx_rtmp_mp4_write_moof(&b, t->earliest_pres_time, t->sample_count, t->samples, t->sample_mask, t->id); pos1 = b.last; b.last = pos; ngx_rtmp_mp4_write_sidx(&b, t->mdat_size + 8 + (pos1 - (pos + 44)), t->earliest_pres_time, t->latest_pres_time); b.last = pos1; ngx_rtmp_mp4_write_mdat(&b, t->mdat_size + 8); /* move the data down to make room for the headers */ f = ngx_rtmp_dash_get_frag(s, ctx->nfrags); *ngx_sprintf(ctx->stream.data + ctx->stream.len, "%uD.m4%c", f->timestamp, t->type) = 0; fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: error creating dash temp video file"); goto done; } if (ngx_write_fd(fd, b.pos, (size_t) (b.last - b.pos)) == NGX_ERROR) { goto done; } left = (size_t) t->mdat_size; #if (NGX_WIN32) if (SetFilePointer(t->fd, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "dash: SetFilePointer error"); goto done; } #else if (lseek(t->fd, 0, SEEK_SET) == -1) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, "dash: lseek error"); goto done; } #endif while (left > 0) { n = ngx_read_fd(t->fd, buffer, ngx_min(sizeof(buffer), left)); if (n == NGX_ERROR) { break; } n = ngx_write_fd(fd, buffer, (size_t) n); if (n == NGX_ERROR) { break; } left -= n; } done: if (fd != NGX_INVALID_FILE) { ngx_close_file(fd); } ngx_close_file(t->fd); t->fd = NGX_INVALID_FILE; t->opened = 0; }
int ngx_cdecl main(int argc, char *const *argv) { ngx_buf_t *b; ngx_log_t *log; ngx_uint_t i; ngx_cycle_t *cycle, init_cycle; ngx_conf_dump_t *cd; ngx_core_conf_t *ccf; ngx_debug_init(); if (ngx_strerror_init() != NGX_OK) { return 1; } if (ngx_get_options(argc, argv) != NGX_OK) { return 1; } if (ngx_show_version) { ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED); if (ngx_show_help) { ngx_write_stderr( "Usage: nginx [-?hvVtTq] [-s signal] [-c filename] " "[-p prefix] [-g directives]" NGX_LINEFEED NGX_LINEFEED "Options:" NGX_LINEFEED " -?,-h : this help" NGX_LINEFEED " -v : show version and exit" NGX_LINEFEED " -V : show version and configure options then exit" NGX_LINEFEED " -t : test configuration and exit" NGX_LINEFEED " -T : test configuration, dump it and exit" NGX_LINEFEED " -q : suppress non-error messages " "during configuration testing" NGX_LINEFEED " -s signal : send signal to a master process: " "stop, quit, reopen, reload" NGX_LINEFEED #ifdef NGX_PREFIX " -p prefix : set prefix path (default: " NGX_PREFIX ")" NGX_LINEFEED #else " -p prefix : set prefix path (default: NONE)" NGX_LINEFEED #endif " -c filename : set configuration file (default: " NGX_CONF_PATH ")" NGX_LINEFEED " -g directives : set global directives out of configuration " "file" NGX_LINEFEED NGX_LINEFEED ); } if (ngx_show_configure) { #ifdef NGX_COMPILER ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED); #endif #if (NGX_SSL) if (SSLeay() == SSLEAY_VERSION_NUMBER) { ngx_write_stderr("built with " OPENSSL_VERSION_TEXT NGX_LINEFEED); } else { ngx_write_stderr("built with " OPENSSL_VERSION_TEXT " (running with "); ngx_write_stderr((char *) (uintptr_t) SSLeay_version(SSLEAY_VERSION)); ngx_write_stderr(")" NGX_LINEFEED); } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED); #else ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED); #endif #endif ngx_write_stderr("configure arguments:" NGX_CONFIGURE NGX_LINEFEED); } if (!ngx_test_config) { return 0; } } /* TODO */ ngx_max_sockets = -1; ngx_time_init(); #if (NGX_PCRE) ngx_regex_init(); #endif ngx_pid = ngx_getpid(); log = ngx_log_init(ngx_prefix); if (log == NULL) { return 1; } /* STUB */ #if (NGX_OPENSSL) ngx_ssl_init(log); #endif /* * init_cycle->log is required for signal handlers and * ngx_process_options() */ ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)); init_cycle.log = log; ngx_cycle = &init_cycle; init_cycle.pool = ngx_create_pool(1024, log); if (init_cycle.pool == NULL) { return 1; } if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; } if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; } if (ngx_os_init(log) != NGX_OK) { return 1; } /* * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init() */ if (ngx_crc32_table_init() != NGX_OK) { return 1; } if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; } cycle = ngx_init_cycle(&init_cycle); if (cycle == NULL) { if (ngx_test_config) { ngx_log_stderr(0, "configuration file %s test failed", init_cycle.conf_file.data); } return 1; } if (ngx_test_config) { if (!ngx_quiet_mode) { ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data); } if (ngx_dump_config) { cd = cycle->config_dump.elts; for (i = 0; i < cycle->config_dump.nelts; i++) { ngx_write_stdout("# configuration file "); (void) ngx_write_fd(ngx_stdout, cd[i].name.data, cd[i].name.len); ngx_write_stdout(":" NGX_LINEFEED); b = cd[i].buffer; (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos); ngx_write_stdout(NGX_LINEFEED); } } return 0; } if (ngx_signal) { return ngx_signal_process(cycle, ngx_signal); } ngx_os_status(cycle->log); ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER; } #if !(NGX_WIN32) if (ngx_init_signals(cycle->log) != NGX_OK) { return 1; } if (!ngx_inherited && ccf->daemon) { if (ngx_daemon(cycle->log) != NGX_OK) { return 1; } ngx_daemonized = 1; } if (ngx_inherited) { ngx_daemonized = 1; } #endif if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; } if (ngx_log_redirect_stderr(cycle) != NGX_OK) { return 1; } if (log->file->fd != ngx_stderr) { if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_close_file_n " built-in log failed"); } } ngx_use_stderr = 0; if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); } return 0; }
char * ngx_xconf_include_uri(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *arg, uri, filename, scheme_name; ngx_xconf_ctx_t ctx; ngx_flag_t is_last_elt; ngx_uint_t i; ngx_str_t *cmd_name; u_char need_next; ngx_str_t ofilename_prefix = ngx_string("$file"), ofilename_suffix = ngx_string("l$line.conf"), ofilename_suffix2 = ngx_string("conf"); char *rv; u_char *s; /* 用于临时分配内存用 */; lua_State *L; ngx_xconf_scheme_t *scheme; arg = cf->args->elts; cmd_name = &arg[0]; scheme = ngx_xconf_schemes; if ((scheme == NULL) || (scheme->name.len == 0)) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: no scheme define.", cmd_name); return NGX_CONF_ERROR; } /* 参数说明见 README */ uri.len = 0; /* 如果没设定报错 */ filename.len = 0; /* 如果没设定就默认给一个 */ ctx.evaluri = 1; /* 默认 eval uri */ ctx.keep_error_cachefile = 0; /* 默认删除解析出错的 cachefile */ ctx.pre_usecache = -1; /* 默认不使用 cachefile */ ctx.fail_usecache = -1; /* 默认不使用 cachefile */ ctx.fetch_content = NULL; ctx.do_cachefile = 0; need_next = 0; is_last_elt = 0; /* 解析参数 {{{ */ for (i = 1; i < cf->args->nelts; i++) { if (! (arg[i].len)) { continue; } is_last_elt = i == cf->args->nelts - 1; if (need_next) { switch(need_next) { case 'o': filename.data = arg[i].data; filename.len = arg[i].len; break; case 'O': filename.len = ofilename_prefix.len + arg[i].len + ofilename_suffix.len + sizeof("..") - 1; filename.data = ngx_palloc(cf->pool, filename.len + 1); ngx_snprintf(filename.data, filename.len, "%V.%V.%V", &ofilename_prefix, &arg[i], &ofilename_suffix); break; case 'I': filename.len = ofilename_prefix.len + arg[i].len + ofilename_suffix2.len + sizeof("..") - 1; filename.data = ngx_palloc(cf->pool, filename.len + 1); ngx_snprintf(filename.data, filename.len, "%V.%V.%V", &ofilename_prefix, &arg[i], &ofilename_suffix2); break; case 't': ctx.timeout = ngx_parse_time(&arg[i], 1); if (ctx.timeout == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: option [-t %V] value error.", cmd_name, &arg[i]); return NGX_CONF_ERROR; } break; case 'c': if (arg[i].len == 2 && arg[i].data[0] == '-' && arg[i].data[1] == '1') { ctx.pre_usecache = -1 * (arg[i].data[1] - '0'); } else { ctx.pre_usecache = ngx_parse_time(&arg[i], 1); if (ctx.pre_usecache == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: option [-c %V] value error.", cmd_name, &arg[i]); return NGX_CONF_ERROR; } } break; case 'C': if (arg[i].len == 2 && arg[i].data[0] == '-' && (arg[i].data[1] >= '1' && arg[i].data[1] <= '2')) { ctx.fail_usecache = -1 * (arg[i].data[1] - '0'); } else { ctx.fail_usecache = ngx_parse_time(&arg[i], 1); if (ctx.fail_usecache == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: option [-C %V] value error.", cmd_name, &arg[i]); return NGX_CONF_ERROR; } } break; default: /* 通常不会到这里 */ ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: unknown option [%c] .", cmd_name, need_next); return NGX_CONF_ERROR; } need_next = 0; continue; } else { if (arg[i].data[0] == '-') { /* 现在只支持 -x */ if (arg[i].len != 2) { goto unknow_opt; } switch(arg[i].data[1]) { case 'K': ctx.keep_error_cachefile = 1; break; case 'n': ctx.evaluri = 0; break; case 'c': case 'C': case 'o': case 'I': case 'O': case 't': need_next = arg[i].data[1]; if (is_last_elt) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: option [-%c] need a value.", cmd_name, need_next); return NGX_CONF_ERROR; } break; default: goto unknow_opt; } continue; } else { /* this will be the uri */ uri.data = arg[i].data; uri.len = arg[i].len; continue; } } goto unknow_opt; } /* }}} */ /* 因为上面不需要用到 lua 的功能,所有此刻才初始化 lua vm {{{ */ L = luaL_newstate(); if (L == NULL) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: create lua vm fail.", cmd_name); return NGX_CONF_ERROR; } /* XXX 从这以下如果出错,需要 goto error; 因为要 close lua vm */ ctx.lua = L; luaL_openlibs(L); { int rc; ngx_str_t msg; rc = luaL_loadbuffer(L, (const char*) xconf_util_lua, sizeof(xconf_util_lua), "ngx_xconf_util.lua(embed)"); if (rc != 0) { msg.data = (u_char *) lua_tolstring(L, -1, &msg.len); if (msg.data == NULL) { msg.data = (u_char *) "unknown reason"; msg.len = sizeof("unknown reason") - 1; } ngx_log_error(NGX_LOG_ERR, cf->log, 0, "xconf load lua code error: %V.", &msg); lua_pop(L, 1); rv = NULL; goto error; } } /* 这个 lua 文件会创建 若干个 全局函数,如: format */ if (ngx_xconf_util_lua_pcall(cf, L, 0, 0, 0, 0) != NGX_OK) { rv = NULL; goto error; } /* }}} */ /* 创建变量 table 到 lua vm (var_ctx) 里,用于变量插值 {{{ */ lua_createtable(L, /* i */0, /* key */10); /* var_ctx */ lua_pushlstring(L, (char *)cf->conf_file->file.name.data, cf->conf_file->file.name.len); lua_setfield(L, -2, "file"); lua_pushnumber(L, cf->conf_file->line); lua_setfield(L, -2, "line"); lua_pushlstring(L, (char *)cf->cycle->prefix.data, cf->cycle->prefix.len); lua_setfield(L, -2, "prefix"); lua_pushlstring(L, (char *)cf->cycle->conf_prefix.data, cf->cycle->conf_prefix.len); lua_setfield(L, -2, "conf_prefix"); lua_pushnumber(L, (int) ngx_pid); lua_setfield(L, -2, "pid"); lua_pushlstring(L, (char *)cf->cycle->hostname.data, cf->cycle->hostname.len); lua_setfield(L, -2, "hostname"); { ngx_time_t *tp = ngx_timeofday(); lua_pushnumber(L, (int) (tp->sec)); lua_setfield(L, -2, "time"); /* var_ctx */ } lua_setfield(L, LUA_GLOBALSINDEX, "var_ctx"); /* }}} */ /* 对 uri 进行变量插值 {{{ */ if (ctx.evaluri) { lua_getfield(L, LUA_GLOBALSINDEX, "format"); /* got the format function */ lua_pushlstring(L, (char *) uri.data, uri.len); if (ngx_xconf_util_lua_pcall(cf, L, 1, 1, 0, 0) != NGX_OK) { rv = NULL; goto error; } uri.data = (u_char *) lua_tolstring(L, -1, &uri.len); s = ngx_palloc(cf->pool, uri.len); ngx_memcpy(s, uri.data, uri.len); uri.data = s; s = NULL; lua_pop(L, 1); } if (! (uri.len)) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: must give us uri.", cmd_name); rv = NULL; goto error; } ctx.uri.len = uri.len; ctx.uri.data = uri.data; /* }}} */ /* 计算 uri 的 scheme_name {{{ */ /* 如果以 '//' 开头 认为是 http: */ if (uri.len > 2 && uri.data[0] == '/' && uri.data[1] == '/') { ctx.noscheme_uri.data = uri.data; ctx.noscheme_uri.len = uri.len; scheme_name.len = sizeof("http") - 1; scheme_name.data = ngx_palloc(cf->pool, scheme_name.len + 1); ngx_cpystrn(scheme_name.data, (u_char *)"http", scheme_name.len + 1); /* 如果以 '/' 或 './' 开头 认为是 file: */ } else if (uri.data[0] == '/' || (uri.len > 2 && uri.data[0] == '.' && uri.data[1] == '/')) { size_t is_abs = uri.data[0] == '/'; u_char *data = uri.data + (is_abs ? 0 : 2); size_t len = uri.len - (is_abs ? 0 : 2); ctx.noscheme_uri.len = len + 2; ctx.noscheme_uri.data = ngx_palloc(cf->pool, len + 2 + 1); ctx.noscheme_uri.data[0] = '/'; ctx.noscheme_uri.data[1] = '/'; ngx_cpystrn(ctx.noscheme_uri.data + 2, data, len + 1); scheme_name.len = sizeof("file") - 1; scheme_name.data = ngx_palloc(cf->pool, scheme_name.len + 1); ngx_cpystrn(scheme_name.data, (u_char *)"file", scheme_name.len + 1); } else { u_char c; ngx_str_t tmp_scheme; size_t i, maxi, found; /* find scheme: [a-z_][a-z_0-9+.-]: , max_scheme_len */ tmp_scheme.data = ngx_palloc(cf->pool, max_scheme_len); tmp_scheme.len = 0; i = 0; maxi = uri.len - 1; found = 0; while (i < max_scheme_len && i <= maxi) { c = uri.data[i]; if (c == ':') { found = 1; break; } tmp_scheme.data[i] = c; tmp_scheme.len++; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.') { } else { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: uri (%V...) have no valid scheme name.", cmd_name, &tmp_scheme); rv = NULL; goto error; } /* XXX important */ i++; } if (! (found && tmp_scheme.len)) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: uri (%V) have no valid scheme name.", cmd_name, &uri); rv = NULL; goto error; } scheme_name.len = tmp_scheme.len; scheme_name.data = tmp_scheme.data; scheme_name.data[tmp_scheme.len] = '\0'; /* 1 -> the ':' after scheme name */ ctx.noscheme_uri.len = uri.len - tmp_scheme.len - 1; ctx.noscheme_uri.data = uri.data + tmp_scheme.len + 1; } /* }}} */ /* 查找当前 scheme {{{ */ for ( /* void */ ; scheme->name.len; scheme++) { if (scheme_name.len == scheme->name.len && ngx_strcmp(scheme_name.data, scheme->name.data) == 0) { break; } } if (! scheme->name.len) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: no scheme found for \"%V\".", cmd_name, &ctx.scheme); rv = NULL; goto error; } /* }}} */ ctx.scheme = scheme; /* 如果 scheme usecache 则计算 filename 并 判断 pre_usecache {{{ */ if (scheme->usecache) { /* filename 计算, 插值, 展开 {{{ */ if (! (filename.len)) { filename.len = ofilename_prefix.len + ofilename_suffix.len + sizeof(".") - 1; filename.data = ngx_palloc(cf->pool, filename.len + 1); ngx_snprintf(filename.data, filename.len, "%V.%V", &ofilename_prefix, &ofilename_suffix); } /* FIXME filename.data 是否需要 free ?? */ lua_getfield(L, LUA_GLOBALSINDEX, "format"); /* got the format function */ lua_pushlstring(L, (char *) filename.data, filename.len); if (ngx_xconf_util_lua_pcall(cf, L, 1, 1, 0, 0) != NGX_OK) { rv = NULL; goto error; } filename.data = (u_char *) lua_tolstring(L, -1, &filename.len); s = ngx_palloc(cf->pool, filename.len + 1); ngx_cpystrn(s, filename.data, filename.len + 1); /* 让 ngx_cpystrn 帮忙添加个 \0 */ filename.data = s; s = NULL; lua_pop(L, 1); if (ngx_conf_full_name(cf->cycle, &filename, 1) != NGX_OK) { rv = NULL; goto error; } /* }}} */ ctx.cachefile = ngx_palloc(cf->pool, sizeof(ngx_file_t)); if (ctx.cachefile == NULL) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: alloc cachefile error.", cmd_name); rv = NULL; goto error; } ngx_memzero(ctx.cachefile, sizeof(ngx_file_t)); ctx.cachefile->name = filename; ctx.cachefile->log = cf->log; dd("pre-usecache: %d, %d", (int)ctx.scheme->pre_usecache, (int)ctx.pre_usecache); if (ctx.scheme->pre_usecache && ctx.pre_usecache > -1) { ngx_file_t *file; file = ctx.cachefile; /* 获取文件信息 FAIL */ if (ngx_file_info(file->name.data, &file->info) == -1) { /* 如果文件不存在则忽略,否则报错 */ if (errno != ENOENT) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: get file \"%V\" info error: %s.", cmd_name, file->name, strerror(errno)); rv = NULL; goto error; } /* 获取文件信息 OK, 有没可能是个 目录 ?? ,如果谁这么配置 !!! */ } else { int now; /* 只要文件存在就用 */ if (ctx.pre_usecache == 0) { goto do_cachefile; } ngx_time_update(); now = (int)ngx_time(); dd("pre-usecache now: %d, mtime: %d, diff: %d, pref: %d.", now, (int)file->info.st_mtime, now - (int)file->info.st_mtime, (int)ctx.pre_usecache); if (now - file->info.st_mtime <= ctx.pre_usecache) { goto do_cachefile; } } } } /* }}} */ ngx_log_error(NGX_LOG_INFO, cf->log, 0, "\n- - - - - - - -\ncmd_name: %V\nfileneme: %V\nuri: %V\npre_usecache: %d\nfail_usecache: %d\nevaluri: %d\nscheme: %V\nnoscheme_uri: %V\n- - - - - - - -", cmd_name, &filename, &uri, ctx.pre_usecache, ctx.fail_usecache, ctx.evaluri, &ctx.scheme->name, &ctx.noscheme_uri); /* 执行具体 scheme {{{ */ rv = scheme->handler(cf, cmd, conf, &ctx); if (rv == NGX_CONF_OK) { goto done; } else if (rv == NGX_XCONF_FETCH_ERROR) { /* do fail_usecache */ if (scheme->usecache) { goto fetch_fail; } else { /* 不可能 */ ngx_log_error(NGX_LOG_ERR, cf->log, 0, "if you see this error, please report it to author with \"%V\".", &scheme->name); rv = NULL; goto error; } } else if (rv == NGX_XCONF_FETCH_OK) { if (scheme->usecache) { if (ctx.fetch_content != NULL) { goto save_cachefile; } else if (ctx.do_cachefile) { goto do_cachefile; } } goto done; } else { goto error; } /* }}} */ goto done; fetch_fail: dd("fail-usecache: %d, %d", (int)ctx.scheme->fail_usecache, (int)ctx.fail_usecache); if (ctx.scheme->fail_usecache && ctx.fail_usecache != -1) { /* 删除 */ if (ctx.fail_usecache != -2) { ngx_delete_file(ctx.cachefile->name.data); rv = NULL; goto error; } else if (ctx.fail_usecache >= 0) { ngx_file_t *file; file = ctx.cachefile; /* 获取文件信息 FAIL */ if (ngx_file_info(file->name.data, &file->info) == -1) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: get file \"%V\" info in fetch_fail error: %s.", cmd_name, file->name, strerror(errno)); rv = NULL; goto error; /* 获取文件信息 OK, 有没可能是个 目录 ?? ,如果谁这么配置 !!! */ } else { int now; /* 只要文件存在就用 */ if (ctx.fail_usecache == 0) { goto do_cachefile; } ngx_time_update(); now = (int)ngx_time(); dd("fail-usecache now: %d, mtime: %d, diff: %d, pref: %d.", now, (int)file->info.st_mtime, now - (int)file->info.st_mtime, (int)ctx.fail_usecache); if (now - file->info.st_mtime <= ctx.fail_usecache) { goto do_cachefile; } } } else { /* 不可能 */ rv = NULL; goto error; } } rv = NULL; goto error; save_cachefile: { int rc; ctx.cachefile->fd = ngx_open_file(ctx.cachefile->name.data, O_WRONLY, O_CREAT | O_TRUNC , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); if (ctx.cachefile->fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: open (%V) error: \"%s\".", cmd_name, &ctx.cachefile->name, strerror(errno)); rv = NULL; goto error; } dd("open cachefd: %s, %d", (char *)ctx.cachefile->name.data, ctx.cachefile->fd); rc = ngx_write_fd(ctx.cachefile->fd, ctx.fetch_content->data, ctx.fetch_content->len); if (rc == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: write data to (%V) error: \"%s\".", cmd_name, ctx.cachefile->name, strerror(errno)); rv = NULL; goto error; } else if ((size_t)rc != ctx.fetch_content->len) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: write data to (%V) incomplete: %z of %uz.", cmd_name, ctx.cachefile->name, rc, ctx.fetch_content->len); rv = NULL; goto error; } if (ngx_close_file(ctx.cachefile->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%: close cachefile error.", cmd_name); rv = NULL; goto error; } goto do_cachefile; } do_cachefile: if (! scheme->usecache) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: current scheme \"%V\" can not usecache.", cmd_name, &scheme->name); rv = NULL; goto error; } dd("do cachefile"); rv = ngx_conf_parse(cf, &ctx.cachefile->name); if (rv != NGX_CONF_OK) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "%V: do cachefile \"%V\" error.", cmd_name, &ctx.cachefile->name); /* 删除解析出错的 cachefile */ if (! ctx.keep_error_cachefile) { if (ngx_delete_file(ctx.cachefile->name.data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "%V: delete cachefile \"%V\" error.", cmd_name, &ctx.cachefile->name); } } goto error; } goto done; done: lua_close(L); return NGX_CONF_OK; unknow_opt: ngx_log_error(NGX_LOG_ERR, cf->log, 0, "%V: unknown option [%V].", cmd_name, &arg[i]); return NGX_CONF_ERROR; error: lua_close(L); return rv == NULL ? NGX_CONF_ERROR : rv; }
void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, va_list args) #endif { #if (NGX_HAVE_VARIADIC_MACROS) va_list args; #endif u_char *p, *last, *msg; u_char errstr[NGX_MAX_ERROR_STR]; ngx_uint_t wrote_stderr, debug_connection; last = errstr + NGX_MAX_ERROR_STR; ngx_memcpy(errstr, ngx_cached_err_log_time.data, ngx_cached_err_log_time.len); p = errstr + ngx_cached_err_log_time.len; p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]); /* pid#tid */ p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ", ngx_log_pid, ngx_log_tid); if (log->connection) { p = ngx_slprintf(p, last, "*%uA ", log->connection); } msg = p; #if (NGX_HAVE_VARIADIC_MACROS) va_start(args, fmt); p = ngx_vslprintf(p, last, fmt, args); va_end(args); #else p = ngx_vslprintf(p, last, fmt, args); #endif if (err) { p = ngx_log_errno(p, last, err); } if (level != NGX_LOG_DEBUG && log->handler) { p = log->handler(log, p, last - p); } if (p > last - NGX_LINEFEED_SIZE) { p = last - NGX_LINEFEED_SIZE; } ngx_linefeed(p); wrote_stderr = 0; debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0; while (log) { if (log->log_level < level && !debug_connection) { break; } (void) ngx_write_fd(log->file->fd, errstr, p - errstr); if (log->file->fd == ngx_stderr) { wrote_stderr = 1; } log = log->next; } if (!ngx_use_stderr || level > NGX_LOG_WARN || wrote_stderr) { return; } msg -= (7 + err_levels[level].len + 3); (void) ngx_sprintf(msg, "nginx: [%V] ", &err_levels[level]); (void) ngx_write_console(ngx_stderr, msg, p - msg); }
inline void NWriteDebugLog(const char* log, int size){ if(g_biz_debuger!=NULL && g_biz_debuger->fd > 0){ ngx_write_fd(g_biz_debuger->fd, (void*)log,size); } }
void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) { ssize_t n, len; ngx_fd_t fd; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].name.data == NULL) { continue; } len = file[i].pos - file[i].buffer; if (file[i].buffer && len != 0) { n = ngx_write_fd(file[i].fd, file[i].buffer, len); if (n == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_write_fd_n " to \"%s\" failed", file[i].name.data); } else if (n != len) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", file[i].name.data, n, len); } file[i].pos = file[i].buffer; } fd = ngx_open_file(file[i].name.data, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reopen file \"%s\", old:%d new:%d", file[i].name.data, file[i].fd, fd); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); continue; } #if (NGX_WIN32) if (ngx_file_append_mode(fd) == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_append_mode_n " \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } #else if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) { ngx_file_info_t fi; if (ngx_file_info((const char *) file[i].name.data, &fi) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_info_n " \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } if (fi.st_uid != user) { if (chown((const char *) file[i].name.data, user, -1) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chown(\"%s\", %d) failed", file[i].name.data, user); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } if ((fi.st_mode & (S_IRUSR|S_IWUSR)) != (S_IRUSR|S_IWUSR)) { fi.st_mode |= (S_IRUSR|S_IWUSR); if (chmod((const char *) file[i].name.data, fi.st_mode) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chmod() \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } } if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } #endif if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } file[i].fd = fd; } #if !(NGX_WIN32) if (cycle->log->file->fd != STDERR_FILENO) { if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "dup2(STDERR) failed"); } } #endif }
static ngx_int_t ngx_http_prelog_handler(ngx_http_request_t* r){ ngx_http_prelog_loc_conf_t *prelog_loc_conf; size_t len; ssize_t ret; u_char *line, *p; ngx_http_log_op_t *op; ngx_uint_t i; time_t now; ngx_err_t err; u_char *name; prelog_loc_conf = ngx_http_get_module_loc_conf(r, ngx_http_prelog_module); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http prelog handler"); if (prelog_loc_conf->enable == 0){ return NGX_DECLINED; } if (r->internal == 1){ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http prelog hit internal redirect, pass"); return NGX_DECLINED; } len = 0; op = prelog_loc_conf->format->ops->elts; for (i = 0; i < prelog_loc_conf->format->ops->nelts; i++) { if (op[i].len == 0) { len += op[i].getlen(r, op[i].data); } else { len += op[i].len; } } len += NGX_LINEFEED_SIZE; line = ngx_pnalloc(r->pool, len); if (line == NULL) { return NGX_ERROR; } p = line; for (i = 0; i < prelog_loc_conf->format->ops->nelts; i++) { p = op[i].run(r, p, &op[i]); } ngx_linefeed(p); ret = ngx_write_fd(prelog_loc_conf->file->fd, line, p - line); name = prelog_loc_conf->file->name.data; now = ngx_time(); if (ret == (ssize_t)len){ goto ok; } if (ret == -1) { err = ngx_errno; if (now - prelog_loc_conf->error_log_time > 59) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, err, ngx_write_fd_n " to \"%s\" failed", name); prelog_loc_conf->error_log_time = now; } goto ok; } if (now - prelog_loc_conf->error_log_time > 59) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", name, ret, len); prelog_loc_conf->error_log_time = now; } ok: return NGX_DECLINED; }
void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) { ssize_t n, len; ngx_fd_t fd; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) {//大于等于总文件数 if (part->next == NULL) { break;//如果没有了,就返回 } part = part->next;//如果还有,标记i = 0,重新来 file = part->elts; i = 0; } if (file[i].name.len == 0) { continue; } len = file[i].pos - file[i].buffer; if (file[i].buffer && len != 0) {//要写进去吗,确认? n = ngx_write_fd(file[i].fd, file[i].buffer, len); if (n == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_write_fd_n " to \"%s\" failed", file[i].name.data); } else if (n != len) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", file[i].name.data, n, len); } file[i].pos = file[i].buffer; } //再次打开以下这个文件 fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reopen file \"%s\", old:%d new:%d", file[i].name.data, file[i].fd, fd); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); continue; } #if !(NGX_WIN32)//如果是unix系的操作系统,需要设置文件拥有者啥的 if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) { ngx_file_info_t fi; //得到文件的信息 if (ngx_file_info((const char *) file[i].name.data, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_info_n " \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } //修改文件所有者 if (fi.st_uid != user) { if (chown((const char *) file[i].name.data, user, -1) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chown(\"%s\", %d) failed", file[i].name.data, user); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } //修改文件权限 if ((fi.st_mode & (S_IRUSR|S_IWUSR)) != (S_IRUSR|S_IWUSR)) { fi.st_mode |= (S_IRUSR|S_IWUSR); if (chmod((const char *) file[i].name.data, fi.st_mode) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chmod() \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } } } if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } continue; } #endif if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {//关闭掉老的文件句柄 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed",file[i].name.data); } //赋值为新的文件句柄。放心吧,没有别的地方使用这个fd的,就我一个进程,多线程版本不在此 file[i].fd = fd; } #if !(NGX_WIN32) if (cycle->log->file->fd != STDERR_FILENO) {//int dup2(int oldfd, int newfd); if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {//标准错误输出也设置为日志.那程序的fprint(stderr,)将输出到日志文件 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,"dup2(STDERR) failed"); } } #endif }
static ngx_int_t ngx_rtmp_mpegts_write_file(ngx_rtmp_mpegts_file_t *file, u_char *in, size_t in_size) { u_char *out; size_t out_size, n; ssize_t rc; static u_char buf[1024]; if (!file->encrypt) { ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0, "mpegts: write %uz bytes", in_size); rc = ngx_write_fd(file->fd, in, in_size); if (rc < 0) { return NGX_ERROR; } return NGX_OK; } /* encrypt */ ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0, "mpegts: write %uz encrypted bytes", in_size); out = buf; out_size = sizeof(buf); if (file->size > 0 && file->size + in_size >= 16) { ngx_memcpy(file->buf + file->size, in, 16 - file->size); in += 16 - file->size; in_size -= 16 - file->size; AES_cbc_encrypt(file->buf, out, 16, &file->key, file->iv, AES_ENCRYPT); out += 16; out_size -= 16; file->size = 0; } for ( ;; ) { n = in_size & ~0x0f; if (n > 0) { if (n > out_size) { n = out_size; } AES_cbc_encrypt(in, out, n, &file->key, file->iv, AES_ENCRYPT); in += n; in_size -= n; } else if (out == buf) { break; } rc = ngx_write_fd(file->fd, buf, out - buf + n); if (rc < 0) { return NGX_ERROR; } out = buf; out_size = sizeof(buf); } if (in_size) { ngx_memcpy(file->buf + file->size, in, in_size); file->size += in_size; } return NGX_OK; }
static void ngx_http_groonga_logger_log(grn_ctx *ctx, grn_log_level level, const char *timestamp, const char *title, const char *message, const char *location, void *user_data) { ngx_open_file_t *file = user_data; const char level_marks[] = " EACewnid-"; u_char buffer[NGX_MAX_ERROR_STR]; u_char *last; size_t prefix_size; size_t message_size; size_t location_size; size_t postfix_size; size_t log_message_size; if (!file) { return; } #define LOG_PREFIX_FORMAT "%s|%c|%s" prefix_size = strlen(timestamp) + 1 /* | */ + 1 /* %c */ + 1 /* | */ + strlen(title) + 1 /* a space */; message_size = strlen(message); if (location && *location) { location_size = 1 /* a space */ + strlen(location); } else { location_size = 0; } postfix_size = 1 /* \n */; log_message_size = prefix_size + message_size + location_size + postfix_size; if (log_message_size > NGX_MAX_ERROR_STR) { last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR, LOG_PREFIX_FORMAT, timestamp, *(level_marks + level), title); ngx_write_fd(file->fd, buffer, last - buffer); ngx_http_groonga_write_fd(file->fd, buffer, NGX_MAX_ERROR_STR, message, message_size); if (location_size > 0) { ngx_write_fd(file->fd, " ", 1); ngx_http_groonga_write_fd(file->fd, buffer, NGX_MAX_ERROR_STR, location, location_size); } ngx_write_fd(file->fd, "\n", 1); } else { if (location && *location) { last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR, LOG_PREFIX_FORMAT " %s %s\n", timestamp, *(level_marks + level), title, message, location); } else { last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR, LOG_PREFIX_FORMAT " %s\n", timestamp, *(level_marks + level), title, message); } ngx_write_fd(file->fd, buffer, last - buffer); } #undef LOG_PREFIX_FORMAT }
ngx_int_t ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf) { char *buf; off_t size; size_t len; ssize_t n; ngx_fd_t fd, nfd; ngx_int_t rc; ngx_file_info_t fi; rc = NGX_ERROR; buf = NULL; nfd = NGX_INVALID_FILE; fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_CRIT, cf->log, ngx_errno, ngx_open_file_n " \"%s\" failed", from); goto failed; } if (cf->size != -1) { size = cf->size; } else { if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", from); goto failed; } size = ngx_file_size(&fi); } len = cf->buf_size ? cf->buf_size : 65536; if ((off_t) len > size) { len = (size_t) size; } buf = ngx_alloc(len, cf->log); if (buf == NULL) { goto failed; } nfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN, cf->access); if (nfd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_CRIT, cf->log, ngx_errno, ngx_open_file_n " \"%s\" failed", to); goto failed; } while (size > 0) { if ((off_t) len > size) { len = (size_t) size; } n = ngx_read_fd(fd, buf, len); if (n == -1) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_read_fd_n " \"%s\" failed", from); goto failed; } if ((size_t) n != len) { ngx_log_error(NGX_LOG_ALERT, cf->log, 0, ngx_read_fd_n " has read only %z of %uz from %s", n, size, from); goto failed; } n = ngx_write_fd(nfd, buf, len); if (n == -1) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_write_fd_n " \"%s\" failed", to); goto failed; } if ((size_t) n != len) { ngx_log_error(NGX_LOG_ALERT, cf->log, 0, ngx_write_fd_n " has written only %z of %uz to %s", n, size, to); goto failed; } size -= n; } if (cf->time != -1) { if (ngx_set_file_time(to, nfd, cf->time) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_set_file_time_n " \"%s\" failed", to); goto failed; } } rc = NGX_OK; failed: if (nfd != NGX_INVALID_FILE) { if (ngx_close_file(nfd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_close_file_n " \"%s\" failed", to); } } if (fd != NGX_INVALID_FILE) { if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_close_file_n " \"%s\" failed", from); } } if (buf) { ngx_free(buf); } return rc; }
void ngx_log_error_coreall(ngx_uint_t level, ngx_log_t *log, const char* filename, int lineno, ngx_err_t err, const char *fmt, va_list args) #endif { #if (NGX_HAVE_VARIADIC_MACROS) va_list args; #endif u_char *p, *last, *msg; ssize_t n; ngx_uint_t wrote_stderr, debug_connection; u_char errstr[NGX_MAX_ERROR_STR]; char filebuf[52]; last = errstr + NGX_MAX_ERROR_STR; p = ngx_cpymem(errstr, ngx_cached_err_log_time.data, ngx_cached_err_log_time.len); snprintf(filebuf, sizeof(filebuf), "[%35s, %5d][yangyazhou @@@ test]", filename, lineno); p = ngx_slprintf(p, last, "%s ", filebuf); p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]); /* pid#tid */ p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ", ngx_log_pid, ngx_log_tid); //进程ID和线程ID(在开启线程池的时候线程ID和进程ID不同) if (log->connection) { p = ngx_slprintf(p, last, "*%uA ", log->connection); } msg = p; #if (NGX_HAVE_VARIADIC_MACROS) va_start(args, fmt); p = ngx_vslprintf(p, last, fmt, args); va_end(args); #else p = ngx_vslprintf(p, last, fmt, args); #endif if (err) { p = ngx_log_errno(p, last, err); } if (level != NGX_LOG_DEBUG && log->handler) { p = log->handler(log, p, last - p); } if (p > last - NGX_LINEFEED_SIZE) { p = last - NGX_LINEFEED_SIZE; } ngx_linefeed(p); wrote_stderr = 0; debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0; while (log) { if (log->writer) { log->writer(log, level, errstr, p - errstr); goto next; } if (ngx_time() == log->disk_full_time) { /* * on FreeBSD writing to a full filesystem with enabled softupdates * may block process for much longer time than writing to non-full * filesystem, so we skip writing to a log for one second */ goto next; } n = ngx_write_fd(log->file->fd, errstr, p - errstr); //写到log文件中 if (n == -1 && ngx_errno == NGX_ENOSPC) { log->disk_full_time = ngx_time(); } if (log->file->fd == ngx_stderr) { wrote_stderr = 1; } next: log = log->next; } if (!ngx_use_stderr || level > NGX_LOG_WARN || wrote_stderr) /* 如果满足这些条件,则不会输出打印到前台,只会写到errlog文件中 */ { return; } msg -= (7 + err_levels[level].len + 3); (void) ngx_sprintf(msg, "nginx: [%V] ", &err_levels[level]); (void) ngx_write_console(ngx_stderr, msg, p - msg); }
void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, va_list args) #endif { #if (NGX_HAVE_VARIADIC_MACROS) va_list args; #endif u_char *p, *last, *msg; u_char errstr[NGX_MAX_ERROR_STR]; if (log->file->fd == NGX_INVALID_FILE) { return; } last = errstr + NGX_MAX_ERROR_STR; p = errstr ; p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]); /* pid#tid */ p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ", ngx_log_pid, ngx_log_tid); msg = p; #if (NGX_HAVE_VARIADIC_MACROS) va_start(args, fmt); p = ngx_vslprintf(p, last, fmt, args); va_end(args); #else p = ngx_vslprintf(p, last, fmt, args); #endif if (err) { p = ngx_log_errno(p, last, err); } if (level != NGX_LOG_DEBUG && log->handler) { p = log->handler(log, p, last - p); } if (p > last - NGX_LINEFEED_SIZE) { p = last - NGX_LINEFEED_SIZE; } ngx_linefeed(p); (void) ngx_write_fd(log->file->fd, errstr, p - errstr); if (!ngx_use_stderr || level > NGX_LOG_WARN || log->file->fd == ngx_stderr) { return; } msg -= (err_levels[level].len + 4); (void) ngx_sprintf(msg, "[%V]: ", &err_levels[level]); (void) ngx_write_console(ngx_stderr, msg, p - msg); }
void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, ...){ #else void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, va_list args){ #endif #if (NGX_HAVE_VARIADIC_MACROS) va_list args; #endif u_char *p,*last,*msg; ssize_t n; ngx_uint_t wrote_stderr,debug_connection; u_char errstr[NGX_MAX_ERROR_STR]; last = errstr + NGX_MAX_ERROR_STR; //it seems do not set the ngx_cached_err_log_time.len value p = ngx_cpymem(errstr,ngx_cached_err_log_time.data, ngx_cached_err_log_time.len); p = ngx_slprintf(p,last,"[%V]",&err_levels[level]); //just for making the datastructure can work correctly,comment the next function /* pid#tid */ // p = ngx_slprintf(p,last,"%P#" NGX_TID_T_FMT ": ", // ngx_log_pid,ngx_log_tid); if (log->connection) { p = ngx_slprintf(p,last,"*%uA ",log->connection); } msg = p; #if (NGX_HAVE_VARIADIC_MACROS) va_start (args,fmt); p = ngx_vslprintf(p,last,fmt,args); va_end (args); #else p = ngx_vslprintf(p,last,fmt,args); #endif if (err) { p = ngx_log_errno(p,last,err); } if (level != NGX_LOG_DEBUG && log->handler){ p = log->handler(log,p,last - p); } if (p > last - NGX_LINEFEED_SIZE){ p = last - NGX_LINEFEED_SIZE; } ngx_linefeed(p); wrote_stderr = 0; debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0; while(log){ if (log->log_level < level && !debug_connection){ break; } if(log->writer){ log->writer(log,level,errstr,p - errstr); goto next; } if (ngx_time() == log->disk_full_time){ /* * on FreeBSD writing to a full filesystem with enabled softupdates * may block process for much longer time than writing to non-full * filesystem, so we skip writing to a log for one second */ goto next; } n = ngx_write_fd(log->file->fd,errstr,p - errstr); if (n == -1 && ngx_errno == NGX_ENOSPC){ log->disk_full_time = ngx_time(); } if (log->file->fd == ngx_stderr){ wrote_stderr = 1; } next: log = log->next; } if (!ngx_use_stderr || level > NGX_LOG_WARN || wrote_stderr){ return; } msg -= (7 + err_levels[level].len + 3); (void)ngx_sprintf(msg,"nginx: [%V]",&err_levels[level]); (void) ngx_write_console(ngx_stderr,msg,p - msg); }