Annotation of embedaddon/nginx/src/http/ngx_http_busy_lock.c, revision 1.1.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>