Skip to content

Commit

Permalink
feature: implemented shdict:lindex method.
Browse files Browse the repository at this point in the history
  • Loading branch information
tokers committed Feb 23, 2019
1 parent ee47e55 commit d86e1c6
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 0 deletions.
21 changes: 21 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -3185,6 +3185,7 @@ Nginx API for Lua
* [ngx.shared.DICT.lpop](#ngxshareddictlpop)
* [ngx.shared.DICT.rpop](#ngxshareddictrpop)
* [ngx.shared.DICT.llen](#ngxshareddictllen)
* [ngx.shared.DICT.lindex](#ngxshareddictlindex)
* [ngx.shared.DICT.ttl](#ngxshareddictttl)
* [ngx.shared.DICT.expire](#ngxshareddictexpire)
* [ngx.shared.DICT.flush_all](#ngxshareddictflush_all)
Expand Down Expand Up @@ -6235,6 +6236,7 @@ The resulting object `dict` has the following methods:
* [lpop](#ngxshareddictlpop)
* [rpop](#ngxshareddictrpop)
* [llen](#ngxshareddictllen)
* [lindex](#ngxshareddictlindex)
* [ttl](#ngxshareddictttl)
* [expire](#ngxshareddictexpire)
* [flush_all](#ngxshareddictflush_all)
Expand Down Expand Up @@ -6607,6 +6609,25 @@ See also [ngx.shared.DICT](#ngxshareddict).

[Back to TOC](#nginx-api-for-lua)

ngx.shared.DICT.lindex
----------------------

**syntax:** *val, err = ngx.shared.DICT:lindex(key, index)*

**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua**

Returns the element which at the index `index` of the list named `key` in the shm-base dictionary [ngx.shared.DICT](#ngxshareddict).

The index is zero-based, so `0` means the first element, `1` for the second element and so forth. Also, negative index can be used to designate elements starting at the tail of the list, here `-1` means the last element and `-2` means the penultimate and so on.

If `key` does not exist or `index` is out of the list bound, it will return `nil`. When the `key` already takes a value that is not a list, it will return `nil` and `"value not a list"`.

**Note:** This method requires the `resty.core.shdict` or `resty.core` modules from the [lua-resty-core](https://github.com/openresty/lua-resty-core) library.

See also [ngx.shared.DICT](#ngxshareddict).

[Back to TOC](#nginx-api-for-lua)

ngx.shared.DICT.ttl
-------------------
**syntax:** *ttl, err = ngx.shared.DICT:ttl(key)*
Expand Down
17 changes: 17 additions & 0 deletions doc/HttpLuaModule.wiki
Original file line number Diff line number Diff line change
Expand Up @@ -5232,6 +5232,7 @@ The resulting object <code>dict</code> has the following methods:
* [[#ngx.shared.DICT.lpop|lpop]]
* [[#ngx.shared.DICT.rpop|rpop]]
* [[#ngx.shared.DICT.llen|llen]]
* [[#ngx.shared.DICT.lindex|lindex]]
* [[#ngx.shared.DICT.ttl|ttl]]
* [[#ngx.shared.DICT.expire|expire]]
* [[#ngx.shared.DICT.flush_all|flush_all]]
Expand Down Expand Up @@ -5553,6 +5554,22 @@ This feature was first introduced in the <code>v0.10.6</code> release.
See also [[#ngx.shared.DICT|ngx.shared.DICT]].
== ngx.shared.DICT.lindex ==
'''syntax:''' ''val, err = ngx.shared.DICT:lindex(key, index)''
'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*''
Returns the element which at the index <code>index</code> of the list named <code>key</code> in the shm-base dictionary [[#ngx.shared.DICT|ngx.shared.DICT]].
The index is zero-based, so <code>0</code> means the first element, <code>1</code> for the second element and so forth. Also, negative index can be used to designate elements starting at the tail of the list, here <code>-1</code> means the last element and <code>-2</code> means the penultimate and so on.
If <code>key</code> does not exist or <code>index</code> is out of the list bound, it will return <code>nil</code>. When the <code>key</code> already takes a value that is not a list, it will return <code>nil</code> and <code>"value not a list"</code>.
'''Note:''' This method requires the <code>resty.core.shdict</code> or <code>resty.core</code> modules from the [https://github.com/openresty/lua-resty-core lua-resty-core] library.
See also [[#ngx.shared.DICT|ngx.shared.DICT]].
== ngx.shared.DICT.ttl ==
'''syntax:''' ''ttl, err = ngx.shared.DICT:ttl(key)''
Expand Down
133 changes: 133 additions & 0 deletions src/ngx_http_lua_shdict.c
Original file line number Diff line number Diff line change
Expand Up @@ -3021,6 +3021,139 @@ ngx_http_lua_ffi_shdict_free_space(ngx_shm_zone_t *zone)
# endif /* nginx_version >= 1011007 */


int
ngx_http_lua_ffi_shdict_lindex(ngx_shm_zone_t *zone, u_char *key,
size_t key_len, int *value_type, u_char **str_value_buf,
size_t *str_value_len, double *num_value, int index, char **err)
{
int i;
uint32_t hash;
ngx_int_t rc;
ngx_str_t name, value;
ngx_queue_t *queue;
ngx_http_lua_shdict_ctx_t *ctx;
ngx_http_lua_shdict_node_t *sd;
ngx_http_lua_shdict_list_node_t *lnode;

ctx = zone->data;
name = ctx->name;

hash = ngx_crc32_short(key, key_len);

ngx_shmtx_lock(&ctx->shpool->mutex);

#if 1
ngx_http_lua_shdict_expire(ctx, 1);
#endif

rc = ngx_http_lua_shdict_lookup(zone, hash, key, key_len, &sd);

dd("shdict lookup returned %d", (int) rc);

if (rc == NGX_DECLINED || rc == NGX_DONE) {
ngx_shmtx_unlock(&ctx->shpool->mutex);

*value_type = LUA_TNIL;
return NGX_OK;
}

/* rc == NGX_OK */

if (sd->value_type != SHDICT_TLIST) {
ngx_shmtx_unlock(&ctx->shpool->mutex);

*err = "value not a list";
return NGX_ERROR;
}

ngx_queue_remove(&sd->queue);
ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue);

if (index >= (int) sd->value_len || -index > (int) sd->value_len) {
ngx_shmtx_unlock(&ctx->shpool->mutex);

*value_type = LUA_TNIL;
return NGX_OK;
}

queue = ngx_http_lua_shdict_get_list_head(sd, key_len);

if (index >= 0) { /* forward */

for (i = 0; i <= index; i++) {
queue = ngx_queue_next(queue);
}

} else { /* backward */

for (i = -1; i >= index; i--) {
queue = ngx_queue_prev(queue);
}
}

lnode = ngx_queue_data(queue, ngx_http_lua_shdict_list_node_t, queue);

*value_type = lnode->value_type;

dd("data: %p", lnode->data);
dd("value len: %d", (int) lnode->value_len);

value.data = lnode->data;
value.len = (size_t) lnode->value_len;

if (*str_value_len < (size_t) value.len) {
if (*value_type == SHDICT_TSTRING) {
*str_value_buf = malloc(value.len);
if (*str_value_buf == NULL) {
ngx_shmtx_unlock(&ctx->shpool->mutex);
return NGX_ERROR;
}
}
}

switch (*value_type) {

case SHDICT_TSTRING:
*str_value_len = value.len;
ngx_memcpy(*str_value_buf, lnode->data, value.len);
break;

case SHDICT_TNUMBER:

if (value.len != sizeof(double)) {
ngx_shmtx_unlock(&ctx->shpool->mutex);

ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"bad lua list node number value size found "
"for key %*s in shared_dict %V: %z",
key_len, key, &name, value.len);

return NGX_ERROR;
}

*str_value_len = value.len;
ngx_memcpy(num_value, value.data, sizeof(double));

break;

default:

ngx_shmtx_unlock(&ctx->shpool->mutex);

ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"bad list node value type found "
"for key %*s in shared_dict %V: %d",
key_len, key, &name, *value_type);

return NGX_ERROR;
}

ngx_shmtx_unlock(&ctx->shpool->mutex);

return NGX_OK;
}


#endif /* NGX_LUA_NO_FFI_API */


Expand Down

0 comments on commit d86e1c6

Please sign in to comment.