ngx_http_cache_t *ngx_http_cache_get(ngx_http_cache_hash_t *hash, ngx_http_cleanup_t *cleanup, ngx_str_t *key, uint32_t *crc) { ngx_uint_t i; ngx_http_cache_t *c; *crc = ngx_crc(key->data, key->len); c = hash->elts + *crc % hash->hash * hash->nelts; if (ngx_mutex_lock(&hash->mutex) == NGX_ERROR) { return (void *) NGX_ERROR; } for (i = 0; i < hash->nelts; i++) { if (c[i].crc == *crc && c[i].key.len == key->len && ngx_rstrncmp(c[i].key.data, key->data, key->len) == 0) { #if 0 if (c[i].expired) { ngx_mutex_unlock(&hash->mutex); return (void *) NGX_AGAIN; } #endif c[i].refs++; if ((!(c[i].notify && (ngx_event_flags & NGX_USE_KQUEUE_EVENT))) && (ngx_cached_time - c[i].updated >= hash->update)) { c[i].expired = 1; } ngx_mutex_unlock(&hash->mutex); if (cleanup) { cleanup->data.cache.hash = hash; cleanup->data.cache.cache = &c[i]; cleanup->valid = 1; cleanup->cache = 1; } return &c[i]; } } ngx_mutex_unlock(&hash->mutex); return NULL; }
// |---------------------------------------------------------------------------------------------------------------------------- // |4 bytes | 1 byte | 1 byte | 4 bytes | 4 bytes | n bytes | 4 bytes | 4 bytes | 4 bytes | n bytes | 4 bytes | // |---------|--------|---------|---------|---------|---------|------------|------------|------------|------------|------------| // |head len | method | proto | ver | key len | key | key crc | ttl | tblen | tb | tb crc | // |---------------------------------------------------------------------------------------------------------------------------- static ngx_buf_t * __encode_head( uint8_t method, uint8_t proto, ngx_bool_t has_tb, const ngx_str_t * version, const char * key, const char * tb, uint32_t ttl, ngx_pool_t * pool) { if (!key || !pool || !version) { return NULL; } uint32_t ver = ngx_atoi(version->data, version->len); uint32_t key_len = strlen(key); uint32_t key_crc = ngx_crc((u_char *) key, (size_t) key_len); uint32_t tb_len = has_tb ? strlen(tb) : 0; uint32_t tb_crc = has_tb ? ngx_crc((u_char *) tb, (size_t) tb_len) : 0; uint32_t head_len = 0; typedef struct { const void * data; size_t len; } head_item_t; head_item_t heads[] = { { &head_len, sizeof(head_len) }, { &method, sizeof(method) }, { &proto, sizeof(proto) }, { &ver, sizeof(ver) }, { &key_len, sizeof(key_len) }, { key, (size_t) key_len }, { &key_crc, sizeof(key_crc) }, { &ttl, sizeof(ttl) }, { &tb_len, sizeof(tb_len) }, { tb, (size_t) tb_len }, { &tb_crc, sizeof(tb_crc) } }; size_t size = sizeof(heads) / sizeof(head_item_t); size_t i = 0; for (i = 0; i < size; ++i) { head_len += heads[i].len; } ngx_buf_t * buf = ngx_create_temp_buf(pool, head_len + 1); if (!buf) { return NULL; } memset(buf->pos, 0, head_len + 1); buf->last = buf->pos; for (i = 0; i < size; ++i) { if (heads[i].data && heads[i].len > 0) { buf->last = ngx_copy(buf->last, heads[i].data, heads[i].len); } } return buf; }