Example #1
0
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;
}