Mercurial > hg > nginx-quic
view src/http/ngx_http_busy_lock.c @ 3435:d65ba5392f59 stable-0.7
merge r3138, r3139, r3157, r3158, r3159, r3164, r3165,
r3202, r3203, r3383, r3388, r3417, r3418:
Win32 (mostly) and some Unix file related fixes:
*) preserve errno while ngx_free()
*) win32 ngx_file_info() utf8 support
*) delete Win95 code
*) log file name for read/write errors
*) test incomplete WriteFile()
*) handle short pwrite() to log an error cause: ENOSPC, EDQUOT, or EFBIG
*) uniform ngx_directio_on/off() interface with other file functions
*) do not create Win32 drive letter in ngx_create_full_path()
*) ignore EACCES errors for top level directories in ngx_create_full_path()
*) fix Win32 error messages when an temporary file replaces an existent file:
*) do not rename an already renamed file
*) now ngx_win32_rename_file() returns error code
*) do not log failure inside ngx_win32_rename_file()
*) fix Win32 error message when an temporary file replaces an existent file:
return at once if ngx_win32_rename_file() was not failed
and do not try to delete already the renamed temporary file
*) skip URI trailing spaces under Win32
*) disable Win32 short file names
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 01 Feb 2010 15:06:25 +0000 |
parents | 4c43e25d11ea |
children | d620f497c50f |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc, int lock); int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc) { if (bl->busy < bl->max_busy) { bl->busy++; if (bc->time) { bc->time = 0; bl->waiting--; } return NGX_OK; } if (bc->time) { if (bc->time < bl->timeout) { ngx_add_timer(bc->event, 1000); return NGX_AGAIN; } bl->waiting--; return NGX_DONE; } if (bl->timeout == 0) { return NGX_DONE; } if (bl->waiting < bl->max_waiting) { bl->waiting++; #if 0 ngx_add_timer(bc->event, 1000); bc->event->event_handler = bc->event_handler; #endif /* TODO: ngx_handle_level_read_event() */ return NGX_AGAIN; } return NGX_ERROR; } int ngx_http_busy_lock_cacheable(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc, int lock) { int rc; rc = ngx_http_busy_lock_look_cacheable(bl, bc, lock); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, bc->event->log, 0, "http busylock: %d w:%d mw::%d", rc, bl->waiting, bl->max_waiting); if (rc == NGX_OK) { /* no the same request, there's free slot */ return NGX_OK; } if (rc == NGX_ERROR && !lock) { /* no the same request, no free slot */ return NGX_OK; } /* rc == NGX_AGAIN: the same request */ if (bc->time) { if (bc->time < bl->timeout) { ngx_add_timer(bc->event, 1000); return NGX_AGAIN; } bl->waiting--; return NGX_DONE; } if (bl->timeout == 0) { return NGX_DONE; } if (bl->waiting < bl->max_waiting) { #if 0 bl->waiting++; ngx_add_timer(bc->event, 1000); bc->event->event_handler = bc->event_handler; #endif /* TODO: ngx_handle_level_read_event() */ return NGX_AGAIN; } return NGX_ERROR; } void ngx_http_busy_unlock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc) { if (bl == NULL) { return; } if (bl->md5) { bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7)); bl->cacheable--; } bl->busy--; } static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc, int lock) { int i, b, cacheable, free; u_int mask; b = 0; cacheable = 0; free = -1; #if (NGX_SUPPRESS_WARN) mask = 0; #endif for (i = 0; i < bl->max_busy; i++) { if ((b & 7) == 0) { mask = bl->md5_mask[i / 8]; } if (mask & 1) { if (ngx_memcmp(&bl->md5[i * 16], bc->md5, 16) == 0) { return NGX_AGAIN; } cacheable++; } else if (free == -1) { free = i; } #if 1 if (cacheable == bl->cacheable) { if (free == -1 && cacheable < bl->max_busy) { free = i + 1; } break; } #endif mask >>= 1; b++; } if (free == -1) { return NGX_ERROR; } if (lock) { if (bl->busy == bl->max_busy) { return NGX_ERROR; } ngx_memcpy(&bl->md5[free * 16], bc->md5, 16); bl->md5_mask[free / 8] |= 1 << (free & 7); bc->slot = free; bl->cacheable++; bl->busy++; } return NGX_OK; } char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_uint_t i, dup, invalid; ngx_str_t *value, line; ngx_http_busy_lock_t *bl, **blp; blp = (ngx_http_busy_lock_t **) (p + cmd->offset); if (*blp) { return "is duplicate"; } /* ngx_calloc_shared() */ bl = ngx_pcalloc(cf->pool, sizeof(ngx_http_busy_lock_t)); if (bl == NULL) { return NGX_CONF_ERROR; } *blp = bl; /* ngx_calloc_shared() */ bl->mutex = ngx_pcalloc(cf->pool, sizeof(ngx_event_mutex_t)); if (bl->mutex == NULL) { return NGX_CONF_ERROR; } dup = 0; invalid = 0; value = cf->args->elts; for (i = 1; i < cf->args->nelts; i++) { if (value[i].data[1] != '=') { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid value \"%s\"", value[i].data); return NGX_CONF_ERROR; } switch (value[i].data[0]) { case 'b': if (bl->max_busy) { dup = 1; break; } bl->max_busy = ngx_atoi(value[i].data + 2, value[i].len - 2); if (bl->max_busy == NGX_ERROR) { invalid = 1; break; } continue; case 'w': if (bl->max_waiting) { dup = 1; break; } bl->max_waiting = ngx_atoi(value[i].data + 2, value[i].len - 2); if (bl->max_waiting == NGX_ERROR) { invalid = 1; break; } continue; case 't': if (bl->timeout) { dup = 1; break; } line.len = value[i].len - 2; line.data = value[i].data + 2; bl->timeout = ngx_parse_time(&line, 1); if (bl->timeout == NGX_ERROR) { invalid = 1; break; } continue; default: invalid = 1; } if (dup) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate value \"%s\"", value[i].data); return NGX_CONF_ERROR; } if (invalid) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid value \"%s\"", value[i].data); return NGX_CONF_ERROR; } } if (bl->timeout == 0 && bl->max_waiting) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "busy lock waiting is useless with zero timeout, ignoring"); } return NGX_CONF_OK; }