Annotation of embedaddon/nginx/src/http/ngx_http_busy_lock.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (C) Igor Sysoev
! 4: * Copyright (C) Nginx, Inc.
! 5: */
! 6:
! 7:
! 8: #include <ngx_config.h>
! 9: #include <ngx_core.h>
! 10: #include <ngx_http.h>
! 11:
! 12:
! 13:
! 14: static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t *bl,
! 15: ngx_http_busy_lock_ctx_t *bc,
! 16: int lock);
! 17:
! 18:
! 19: int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc)
! 20: {
! 21: if (bl->busy < bl->max_busy) {
! 22: bl->busy++;
! 23:
! 24: if (bc->time) {
! 25: bc->time = 0;
! 26: bl->waiting--;
! 27: }
! 28:
! 29: return NGX_OK;
! 30: }
! 31:
! 32: if (bc->time) {
! 33: if (bc->time < bl->timeout) {
! 34: ngx_add_timer(bc->event, 1000);
! 35: return NGX_AGAIN;
! 36: }
! 37:
! 38: bl->waiting--;
! 39: return NGX_DONE;
! 40:
! 41: }
! 42:
! 43: if (bl->timeout == 0) {
! 44: return NGX_DONE;
! 45: }
! 46:
! 47: if (bl->waiting < bl->max_waiting) {
! 48: bl->waiting++;
! 49:
! 50: #if 0
! 51: ngx_add_timer(bc->event, 1000);
! 52: bc->event->event_handler = bc->event_handler;
! 53: #endif
! 54:
! 55: /* TODO: ngx_handle_level_read_event() */
! 56:
! 57: return NGX_AGAIN;
! 58: }
! 59:
! 60: return NGX_ERROR;
! 61: }
! 62:
! 63:
! 64: int ngx_http_busy_lock_cacheable(ngx_http_busy_lock_t *bl,
! 65: ngx_http_busy_lock_ctx_t *bc, int lock)
! 66: {
! 67: int rc;
! 68:
! 69: rc = ngx_http_busy_lock_look_cacheable(bl, bc, lock);
! 70:
! 71: ngx_log_debug3(NGX_LOG_DEBUG_HTTP, bc->event->log, 0,
! 72: "http busylock: %d w:%d mw::%d",
! 73: rc, bl->waiting, bl->max_waiting);
! 74:
! 75: if (rc == NGX_OK) { /* no the same request, there's free slot */
! 76: return NGX_OK;
! 77: }
! 78:
! 79: if (rc == NGX_ERROR && !lock) { /* no the same request, no free slot */
! 80: return NGX_OK;
! 81: }
! 82:
! 83: /* rc == NGX_AGAIN: the same request */
! 84:
! 85: if (bc->time) {
! 86: if (bc->time < bl->timeout) {
! 87: ngx_add_timer(bc->event, 1000);
! 88: return NGX_AGAIN;
! 89: }
! 90:
! 91: bl->waiting--;
! 92: return NGX_DONE;
! 93:
! 94: }
! 95:
! 96: if (bl->timeout == 0) {
! 97: return NGX_DONE;
! 98: }
! 99:
! 100: if (bl->waiting < bl->max_waiting) {
! 101: #if 0
! 102: bl->waiting++;
! 103: ngx_add_timer(bc->event, 1000);
! 104: bc->event->event_handler = bc->event_handler;
! 105: #endif
! 106:
! 107: /* TODO: ngx_handle_level_read_event() */
! 108:
! 109: return NGX_AGAIN;
! 110: }
! 111:
! 112: return NGX_ERROR;
! 113: }
! 114:
! 115:
! 116: void ngx_http_busy_unlock(ngx_http_busy_lock_t *bl,
! 117: ngx_http_busy_lock_ctx_t *bc)
! 118: {
! 119: if (bl == NULL) {
! 120: return;
! 121: }
! 122:
! 123: if (bl->md5) {
! 124: bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7));
! 125: bl->cacheable--;
! 126: }
! 127:
! 128: bl->busy--;
! 129: }
! 130:
! 131:
! 132: static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t *bl,
! 133: ngx_http_busy_lock_ctx_t *bc,
! 134: int lock)
! 135: {
! 136: int i, b, cacheable, free;
! 137: u_int mask;
! 138:
! 139: b = 0;
! 140: cacheable = 0;
! 141: free = -1;
! 142:
! 143: #if (NGX_SUPPRESS_WARN)
! 144: mask = 0;
! 145: #endif
! 146:
! 147: for (i = 0; i < bl->max_busy; i++) {
! 148:
! 149: if ((b & 7) == 0) {
! 150: mask = bl->md5_mask[i / 8];
! 151: }
! 152:
! 153: if (mask & 1) {
! 154: if (ngx_memcmp(&bl->md5[i * 16], bc->md5, 16) == 0) {
! 155: return NGX_AGAIN;
! 156: }
! 157: cacheable++;
! 158:
! 159: } else if (free == -1) {
! 160: free = i;
! 161: }
! 162:
! 163: #if 1
! 164: if (cacheable == bl->cacheable) {
! 165: if (free == -1 && cacheable < bl->max_busy) {
! 166: free = i + 1;
! 167: }
! 168:
! 169: break;
! 170: }
! 171: #endif
! 172:
! 173: mask >>= 1;
! 174: b++;
! 175: }
! 176:
! 177: if (free == -1) {
! 178: return NGX_ERROR;
! 179: }
! 180:
! 181: if (lock) {
! 182: if (bl->busy == bl->max_busy) {
! 183: return NGX_ERROR;
! 184: }
! 185:
! 186: ngx_memcpy(&bl->md5[free * 16], bc->md5, 16);
! 187: bl->md5_mask[free / 8] |= 1 << (free & 7);
! 188: bc->slot = free;
! 189:
! 190: bl->cacheable++;
! 191: bl->busy++;
! 192: }
! 193:
! 194: return NGX_OK;
! 195: }
! 196:
! 197:
! 198: char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
! 199: void *conf)
! 200: {
! 201: char *p = conf;
! 202:
! 203: ngx_uint_t i, dup, invalid;
! 204: ngx_str_t *value, line;
! 205: ngx_http_busy_lock_t *bl, **blp;
! 206:
! 207: blp = (ngx_http_busy_lock_t **) (p + cmd->offset);
! 208: if (*blp) {
! 209: return "is duplicate";
! 210: }
! 211:
! 212: /* ngx_calloc_shared() */
! 213: bl = ngx_pcalloc(cf->pool, sizeof(ngx_http_busy_lock_t));
! 214: if (bl == NULL) {
! 215: return NGX_CONF_ERROR;
! 216: }
! 217: *blp = bl;
! 218:
! 219: /* ngx_calloc_shared() */
! 220: bl->mutex = ngx_pcalloc(cf->pool, sizeof(ngx_event_mutex_t));
! 221: if (bl->mutex == NULL) {
! 222: return NGX_CONF_ERROR;
! 223: }
! 224:
! 225: dup = 0;
! 226: invalid = 0;
! 227: value = cf->args->elts;
! 228:
! 229: for (i = 1; i < cf->args->nelts; i++) {
! 230:
! 231: if (value[i].data[1] != '=') {
! 232: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 233: "invalid value \"%s\"", value[i].data);
! 234: return NGX_CONF_ERROR;
! 235: }
! 236:
! 237: switch (value[i].data[0]) {
! 238:
! 239: case 'b':
! 240: if (bl->max_busy) {
! 241: dup = 1;
! 242: break;
! 243: }
! 244:
! 245: bl->max_busy = ngx_atoi(value[i].data + 2, value[i].len - 2);
! 246: if (bl->max_busy == NGX_ERROR) {
! 247: invalid = 1;
! 248: break;
! 249: }
! 250:
! 251: continue;
! 252:
! 253: case 'w':
! 254: if (bl->max_waiting) {
! 255: dup = 1;
! 256: break;
! 257: }
! 258:
! 259: bl->max_waiting = ngx_atoi(value[i].data + 2, value[i].len - 2);
! 260: if (bl->max_waiting == NGX_ERROR) {
! 261: invalid = 1;
! 262: break;
! 263: }
! 264:
! 265: continue;
! 266:
! 267: case 't':
! 268: if (bl->timeout) {
! 269: dup = 1;
! 270: break;
! 271: }
! 272:
! 273: line.len = value[i].len - 2;
! 274: line.data = value[i].data + 2;
! 275:
! 276: bl->timeout = ngx_parse_time(&line, 1);
! 277: if (bl->timeout == (time_t) NGX_ERROR) {
! 278: invalid = 1;
! 279: break;
! 280: }
! 281:
! 282: continue;
! 283:
! 284: default:
! 285: invalid = 1;
! 286: }
! 287:
! 288: if (dup) {
! 289: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 290: "duplicate value \"%s\"", value[i].data);
! 291: return NGX_CONF_ERROR;
! 292: }
! 293:
! 294: if (invalid) {
! 295: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 296: "invalid value \"%s\"", value[i].data);
! 297: return NGX_CONF_ERROR;
! 298: }
! 299: }
! 300:
! 301: if (bl->timeout == 0 && bl->max_waiting) {
! 302: ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
! 303: "busy lock waiting is useless with zero timeout, ignoring");
! 304: }
! 305:
! 306: return NGX_CONF_OK;
! 307: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>