Skip to content

Commit 3e63ceb

Browse files
committed
feature: added pure C API for FFI-based implementations for storing operations in the shared dictionaries.
1 parent 6e0a5c5 commit 3e63ceb

File tree

2 files changed

+250
-11
lines changed

2 files changed

+250
-11
lines changed

src/ngx_http_lua_shdict.c

Lines changed: 247 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,6 @@ static int
805805
ngx_http_lua_shdict_set_helper(lua_State *L, int flags)
806806
{
807807
int i, n;
808-
ngx_str_t name;
809808
ngx_str_t key;
810809
uint32_t hash;
811810
ngx_int_t rc;
@@ -841,8 +840,6 @@ ngx_http_lua_shdict_set_helper(lua_State *L, int flags)
841840

842841
ctx = zone->data;
843842

844-
name = ctx->name;
845-
846843
key.data = (u_char *) luaL_checklstring(L, 2, &key.len);
847844

848845
if (key.len == 0) {
@@ -886,7 +883,7 @@ ngx_http_lua_shdict_set_helper(lua_State *L, int flags)
886883

887884
default:
888885
return luaL_error(L, "unsupported value type for key \"%s\" in "
889-
"shared_dict \"%s\": %s", key.data, name.data,
886+
"shared_dict: %s", key.data,
890887
lua_typename(L, value_type));
891888
}
892889

@@ -1042,14 +1039,14 @@ ngx_http_lua_shdict_set_helper(lua_State *L, int flags)
10421039
if (flags & NGX_HTTP_LUA_SHDICT_SAFE_STORE) {
10431040
ngx_shmtx_unlock(&ctx->shpool->mutex);
10441041

1045-
lua_pushnil(L);
1042+
lua_pushboolean(L, 0);
10461043
lua_pushliteral(L, "no memory");
10471044
return 2;
10481045
}
10491046

10501047
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
10511048
"lua shared dict set: overriding non-expired items "
1052-
"due to memory shortage for entry \"%V\"", &name);
1049+
"due to memory shortage for entry \"%V\"", &key);
10531050

10541051
for (i = 0; i < 30; i++) {
10551052
if (ngx_http_lua_shdict_expire(ctx, 0) == 0) {
@@ -1347,6 +1344,249 @@ ngx_http_lua_find_zone(u_char *name_data, size_t name_len)
13471344

13481345

13491346
#ifndef NGX_HTTP_LUA_NO_FFI_API
1347+
int
1348+
ngx_http_lua_ffi_shdict_store(ngx_shm_zone_t *zone, int op, u_char *key,
1349+
size_t key_len, int value_type, u_char *str_value_buf,
1350+
size_t str_value_len, double num_value, int exptime, int user_flags,
1351+
char **errmsg, int *forcible)
1352+
{
1353+
int i, n;
1354+
u_char c, *p;
1355+
uint32_t hash;
1356+
ngx_int_t rc;
1357+
ngx_time_t *tp;
1358+
ngx_rbtree_node_t *node;
1359+
ngx_http_lua_shdict_ctx_t *ctx;
1360+
ngx_http_lua_shdict_node_t *sd;
1361+
1362+
if (zone == NULL) {
1363+
return NGX_ERROR;
1364+
}
1365+
1366+
dd("exptime: %d", exptime);
1367+
1368+
ctx = zone->data;
1369+
1370+
*forcible = 0;
1371+
1372+
hash = ngx_crc32_short(key, key_len);
1373+
1374+
switch (value_type) {
1375+
case LUA_TSTRING:
1376+
/* do nothing */
1377+
break;
1378+
1379+
case LUA_TNUMBER:
1380+
dd("num value: %lf", num_value);
1381+
str_value_buf = (u_char *) &num_value;
1382+
str_value_len = sizeof(double);
1383+
break;
1384+
1385+
case LUA_TBOOLEAN:
1386+
c = num_value ? 1 : 0;
1387+
str_value_buf = &c;
1388+
str_value_len = sizeof(u_char);
1389+
break;
1390+
1391+
case LUA_TNIL:
1392+
if (op & (NGX_HTTP_LUA_SHDICT_ADD|NGX_HTTP_LUA_SHDICT_REPLACE)) {
1393+
*errmsg = "attempt to add or replace nil values";
1394+
return NGX_ERROR;
1395+
}
1396+
1397+
str_value_buf = NULL;
1398+
str_value_len = 0;
1399+
break;
1400+
1401+
default:
1402+
*errmsg = "unsupported value type";
1403+
return NGX_ERROR;
1404+
}
1405+
1406+
ngx_shmtx_lock(&ctx->shpool->mutex);
1407+
1408+
#if 1
1409+
ngx_http_lua_shdict_expire(ctx, 1);
1410+
#endif
1411+
1412+
rc = ngx_http_lua_shdict_lookup(zone, hash, key, key_len, &sd);
1413+
1414+
dd("lookup returns %d", (int) rc);
1415+
1416+
if (op & NGX_HTTP_LUA_SHDICT_REPLACE) {
1417+
1418+
if (rc == NGX_DECLINED || rc == NGX_DONE) {
1419+
ngx_shmtx_unlock(&ctx->shpool->mutex);
1420+
*errmsg = "not found";
1421+
return NGX_DECLINED;
1422+
}
1423+
/* rc == NGX_OK */
1424+
1425+
goto replace;
1426+
}
1427+
1428+
if (op & NGX_HTTP_LUA_SHDICT_ADD) {
1429+
1430+
if (rc == NGX_OK) {
1431+
ngx_shmtx_unlock(&ctx->shpool->mutex);
1432+
*errmsg = "exists";
1433+
return NGX_DECLINED;
1434+
}
1435+
1436+
if (rc == NGX_DONE) {
1437+
/* exists but expired */
1438+
1439+
dd("go to replace");
1440+
goto replace;
1441+
}
1442+
1443+
/* rc == NGX_DECLINED */
1444+
1445+
dd("go to insert");
1446+
goto insert;
1447+
}
1448+
1449+
if (rc == NGX_OK || rc == NGX_DONE) {
1450+
1451+
if (value_type == LUA_TNIL) {
1452+
goto remove;
1453+
}
1454+
1455+
replace:
1456+
if (str_value_buf && str_value_len == (size_t) sd->value_len) {
1457+
1458+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
1459+
"lua shared dict set: found old entry and value "
1460+
"size matched, reusing it");
1461+
1462+
ngx_queue_remove(&sd->queue);
1463+
ngx_queue_insert_head(&ctx->sh->queue, &sd->queue);
1464+
1465+
sd->key_len = (u_short) key_len;
1466+
1467+
if (exptime > 0) {
1468+
tp = ngx_timeofday();
1469+
sd->expires = (uint64_t) tp->sec * 1000 + tp->msec
1470+
+ (uint64_t) exptime;
1471+
1472+
} else {
1473+
sd->expires = 0;
1474+
}
1475+
1476+
sd->user_flags = user_flags;
1477+
1478+
sd->value_len = (uint32_t) str_value_len;
1479+
1480+
dd("setting value type to %d", value_type);
1481+
1482+
sd->value_type = (uint8_t) value_type;
1483+
1484+
p = ngx_copy(sd->data, key, key_len);
1485+
ngx_memcpy(p, str_value_buf, str_value_len);
1486+
1487+
ngx_shmtx_unlock(&ctx->shpool->mutex);
1488+
1489+
return NGX_OK;
1490+
}
1491+
1492+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
1493+
"lua shared dict set: found old entry bug value size "
1494+
"NOT matched, removing it first");
1495+
1496+
remove:
1497+
ngx_queue_remove(&sd->queue);
1498+
1499+
node = (ngx_rbtree_node_t *)
1500+
((u_char *) sd - offsetof(ngx_rbtree_node_t, color));
1501+
1502+
ngx_rbtree_delete(&ctx->sh->rbtree, node);
1503+
1504+
ngx_slab_free_locked(ctx->shpool, node);
1505+
1506+
}
1507+
1508+
insert:
1509+
/* rc == NGX_DECLINED or value size unmatch */
1510+
1511+
if (str_value_buf == NULL) {
1512+
ngx_shmtx_unlock(&ctx->shpool->mutex);
1513+
return NGX_OK;
1514+
}
1515+
1516+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
1517+
"lua shared dict set: creating a new entry");
1518+
1519+
n = offsetof(ngx_rbtree_node_t, color)
1520+
+ offsetof(ngx_http_lua_shdict_node_t, data)
1521+
+ key_len
1522+
+ str_value_len;
1523+
1524+
node = ngx_slab_alloc_locked(ctx->shpool, n);
1525+
1526+
if (node == NULL) {
1527+
1528+
if (op & NGX_HTTP_LUA_SHDICT_SAFE_STORE) {
1529+
ngx_shmtx_unlock(&ctx->shpool->mutex);
1530+
1531+
*errmsg = "no memory";
1532+
return NGX_ERROR;
1533+
}
1534+
1535+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
1536+
"lua shared dict set: overriding non-expired items "
1537+
"due to memory shortage for entry \"%*s\"", key_len,
1538+
key);
1539+
1540+
for (i = 0; i < 30; i++) {
1541+
if (ngx_http_lua_shdict_expire(ctx, 0) == 0) {
1542+
break;
1543+
}
1544+
1545+
*forcible = 1;
1546+
1547+
node = ngx_slab_alloc_locked(ctx->shpool, n);
1548+
if (node != NULL) {
1549+
goto allocated;
1550+
}
1551+
}
1552+
1553+
ngx_shmtx_unlock(&ctx->shpool->mutex);
1554+
1555+
*errmsg = "no memory";
1556+
return NGX_ERROR;
1557+
}
1558+
1559+
allocated:
1560+
sd = (ngx_http_lua_shdict_node_t *) &node->color;
1561+
1562+
node->key = hash;
1563+
sd->key_len = (u_short) key_len;
1564+
1565+
if (exptime > 0) {
1566+
tp = ngx_timeofday();
1567+
sd->expires = (uint64_t) tp->sec * 1000 + tp->msec
1568+
+ (uint64_t) exptime;
1569+
1570+
} else {
1571+
sd->expires = 0;
1572+
}
1573+
1574+
sd->user_flags = user_flags;
1575+
sd->value_len = (uint32_t) str_value_len;
1576+
dd("setting value type to %d", value_type);
1577+
sd->value_type = (uint8_t) value_type;
1578+
1579+
p = ngx_copy(sd->data, key, key_len);
1580+
ngx_memcpy(p, str_value_buf, str_value_len);
1581+
1582+
ngx_rbtree_insert(&ctx->sh->rbtree, node);
1583+
ngx_queue_insert_head(&ctx->sh->queue, &sd->queue);
1584+
ngx_shmtx_unlock(&ctx->shpool->mutex);
1585+
1586+
return NGX_OK;
1587+
}
1588+
1589+
13501590
int
13511591
ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key,
13521592
size_t key_len, int *value_type, u_char **str_value_buf,
@@ -1532,8 +1772,7 @@ ngx_http_lua_ffi_shdict_incr(ngx_shm_zone_t *zone, u_char *key,
15321772
*value = num;
15331773
return NGX_OK;
15341774
}
1535-
1536-
15371775
#endif /* NGX_HTTP_LUA_NO_FFI_API */
15381776

1777+
15391778
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

t/043-shdict.t

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ false the key argument is more than 65535 bytes: 65536
423423
--- request
424424
GET /test
425425
--- response_body
426-
false unsupported value type for key "foo" in shared_dict "dogs": userdata
426+
false unsupported value type for key "foo" in shared_dict: userdata
427427

428428

429429

@@ -1410,7 +1410,7 @@ GET /t
14101410
--- pipelined_requests eval
14111411
["GET /test", "GET /test"]
14121412
--- response_body eval
1413-
my $a = "nil no memory\nabort at (353|705)\ncur value: nil\n1st value: " . (" hello" x 10) . "1\n2nd value: " . (" hello" x 10) . "2\n";
1413+
my $a = "false no memory\nabort at (353|705)\ncur value: nil\n1st value: " . (" hello" x 10) . "1\n2nd value: " . (" hello" x 10) . "2\n";
14141414
[qr/$a/, qr/$a/]
14151415
--- no_error_log
14161416
[error]
@@ -1447,7 +1447,7 @@ my $a = "nil no memory\nabort at (353|705)\ncur value: nil\n1st value: " . (" he
14471447
--- pipelined_requests eval
14481448
["GET /test", "GET /test"]
14491449
--- response_body eval
1450-
my $a = "nil no memory\nabort at (353|705)\ncur value: nil\n1st value: " . (" hello" x 10) . "1\n2nd value: " . (" hello" x 10) . "2\n";
1450+
my $a = "false no memory\nabort at (353|705)\ncur value: nil\n1st value: " . (" hello" x 10) . "1\n2nd value: " . (" hello" x 10) . "2\n";
14511451
[qr/$a/,
14521452
q{false exists
14531453
abort at 1

0 commit comments

Comments
 (0)