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>