~spuul/nginx/trunk

« back to all changes in this revision

Viewing changes to debian/modules/nginx-lua/src/ngx_http_lua_shdict.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2014-02-15 03:05:42 UTC
  • mfrom: (4.3.10 sid)
  • Revision ID: package-import@ubuntu.com-20140215030542-71ubtowl24vf7nfn
Tags: 1.4.5-1ubuntu1
* Resynchronise with Debian (LP: #1280511).  Remaining changes:
  - debian/patches/ubuntu-branding.patch:
    + Add Ubuntu branding to server_tokens.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
static int ngx_http_lua_shdict_set(lua_State *L);
19
19
static int ngx_http_lua_shdict_safe_set(lua_State *L);
20
20
static int ngx_http_lua_shdict_get(lua_State *L);
 
21
static int ngx_http_lua_shdict_get_stale(lua_State *L);
 
22
static int ngx_http_lua_shdict_get_helper(lua_State *L, int get_stale);
21
23
static int ngx_http_lua_shdict_expire(ngx_http_lua_shdict_ctx_t *ctx,
22
24
    ngx_uint_t n);
23
25
static ngx_int_t ngx_http_lua_shdict_lookup(ngx_shm_zone_t *shm_zone,
291
293
        lua_createtable(L, 0, lmcf->shm_zones->nelts /* nrec */);
292
294
                /* ngx.shared */
293
295
 
294
 
        lua_createtable(L, 0 /* narr */, 12 /* nrec */); /* shared mt */
 
296
        lua_createtable(L, 0 /* narr */, 13 /* nrec */); /* shared mt */
295
297
 
296
298
        lua_pushcfunction(L, ngx_http_lua_shdict_get);
297
299
        lua_setfield(L, -2, "get");
298
300
 
 
301
        lua_pushcfunction(L, ngx_http_lua_shdict_get_stale);
 
302
        lua_setfield(L, -2, "get_stale");
 
303
 
299
304
        lua_pushcfunction(L, ngx_http_lua_shdict_set);
300
305
        lua_setfield(L, -2, "set");
301
306
 
356
361
static int
357
362
ngx_http_lua_shdict_get(lua_State *L)
358
363
{
 
364
  return ngx_http_lua_shdict_get_helper(L, 0 /* stale */);
 
365
}
 
366
 
 
367
 
 
368
static int
 
369
ngx_http_lua_shdict_get_stale(lua_State *L)
 
370
{
 
371
  return ngx_http_lua_shdict_get_helper(L, 1 /* stale */);
 
372
}
 
373
 
 
374
 
 
375
static int
 
376
ngx_http_lua_shdict_get_helper(lua_State *L, int get_stale)
 
377
{
359
378
    int                          n;
360
379
    ngx_str_t                    name;
361
380
    ngx_str_t                    key;
365
384
    ngx_http_lua_shdict_node_t  *sd;
366
385
    ngx_str_t                    value;
367
386
    int                          value_type;
368
 
    lua_Number                   num;
 
387
    double                       num;
369
388
    u_char                       c;
370
389
    ngx_shm_zone_t              *zone;
371
390
    uint32_t                     user_flags = 0;
377
396
                          "but only seen %d", n);
378
397
    }
379
398
 
380
 
    luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
381
 
 
382
399
    zone = lua_touserdata(L, 1);
383
400
    if (zone == NULL) {
384
 
        return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer");
 
401
        return luaL_error(L, "bad \"zone\" argument");
385
402
    }
386
403
 
387
404
    ctx = zone->data;
388
 
 
389
405
    name = ctx->name;
390
406
 
 
407
    if (lua_isnil(L, 2)) {
 
408
        lua_pushnil(L);
 
409
        lua_pushliteral(L, "nil key");
 
410
        return 2;
 
411
    }
 
412
 
391
413
    key.data = (u_char *) luaL_checklstring(L, 2, &key.len);
392
414
 
393
415
    if (key.len == 0) {
394
416
        lua_pushnil(L);
395
 
        return 1;
 
417
        lua_pushliteral(L, "empty key");
 
418
        return 2;
396
419
    }
397
420
 
398
421
    if (key.len > 65535) {
399
 
        return luaL_error(L,
400
 
                          "the key argument is more than 65535 bytes: \"%s\"",
401
 
                          key.data);
 
422
        lua_pushnil(L);
 
423
        lua_pushliteral(L, "key too long");
 
424
        return 2;
402
425
    }
403
426
 
404
427
    hash = ngx_crc32_short(key.data, key.len);
411
434
    ngx_shmtx_lock(&ctx->shpool->mutex);
412
435
 
413
436
#if 1
414
 
    ngx_http_lua_shdict_expire(ctx, 1);
 
437
    if (!get_stale) {
 
438
        ngx_http_lua_shdict_expire(ctx, 1);
 
439
    }
415
440
#endif
416
441
 
417
442
    rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len, &sd);
418
443
 
419
444
    dd("shdict lookup returns %d", (int) rc);
420
445
 
421
 
    if (rc == NGX_DECLINED || rc == NGX_DONE) {
 
446
    if (rc == NGX_DECLINED || (rc == NGX_DONE && !get_stale)) {
422
447
        ngx_shmtx_unlock(&ctx->shpool->mutex);
423
448
        lua_pushnil(L);
424
449
        return 1;
425
450
    }
426
451
 
427
 
    /* rc == NGX_OK */
 
452
    /* rc == NGX_OK || (rc == NGX_DONE && get_stale) */
428
453
 
429
454
    value_type = sd->value_type;
430
455
 
442
467
 
443
468
    case LUA_TNUMBER:
444
469
 
445
 
        if (value.len != sizeof(lua_Number)) {
 
470
        if (value.len != sizeof(double)) {
446
471
 
447
472
            ngx_shmtx_unlock(&ctx->shpool->mutex);
448
473
 
451
476
                              (unsigned long) value.len);
452
477
        }
453
478
 
454
 
        num = *(lua_Number *) value.data;
 
479
        num = *(double *) value.data;
455
480
 
456
481
        lua_pushnumber(L, num);
457
482
        break;
485
510
 
486
511
    ngx_shmtx_unlock(&ctx->shpool->mutex);
487
512
 
 
513
    if (get_stale) {
 
514
 
 
515
        /* always return value, flags, stale */
 
516
 
 
517
        if (user_flags) {
 
518
            lua_pushinteger(L, (lua_Integer) user_flags);
 
519
 
 
520
        } else {
 
521
            lua_pushnil(L);
 
522
        }
 
523
 
 
524
        lua_pushboolean(L, rc == NGX_DONE);
 
525
        return 3;
 
526
    }
 
527
 
488
528
    if (user_flags) {
489
529
        lua_pushinteger(L, (lua_Integer) user_flags);
490
530
        return 2;
582
622
    }
583
623
 
584
624
    if (n == 2) {
585
 
        attempts = luaL_checknumber(L, 2);
 
625
        attempts = luaL_checkint(L, 2);
586
626
    }
587
627
 
588
628
    ctx = zone->data;
663
703
    }
664
704
 
665
705
    if (n == 2) {
666
 
        attempts = luaL_checknumber(L, 2);
 
706
        attempts = luaL_checkint(L, 2);
667
707
    }
668
708
 
669
709
    ctx = zone->data;
769
809
ngx_http_lua_shdict_set_helper(lua_State *L, int flags)
770
810
{
771
811
    int                          i, n;
772
 
    ngx_str_t                    name;
773
812
    ngx_str_t                    key;
774
813
    uint32_t                     hash;
775
814
    ngx_int_t                    rc;
777
816
    ngx_http_lua_shdict_node_t  *sd;
778
817
    ngx_str_t                    value;
779
818
    int                          value_type;
780
 
    lua_Number                   num;
 
819
    double                       num;
781
820
    u_char                       c;
782
821
    lua_Number                   exptime = 0;
783
822
    u_char                      *p;
796
835
                          "but only seen %d", n);
797
836
    }
798
837
 
799
 
    luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
800
 
 
801
838
    zone = lua_touserdata(L, 1);
802
839
    if (zone == NULL) {
803
 
        return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer");
 
840
        return luaL_error(L, "bad \"zone\" argument");
804
841
    }
805
842
 
806
843
    ctx = zone->data;
807
844
 
808
 
    name = ctx->name;
 
845
    if (lua_isnil(L, 2)) {
 
846
        lua_pushnil(L);
 
847
        lua_pushliteral(L, "nil key");
 
848
        return 2;
 
849
    }
809
850
 
810
851
    key.data = (u_char *) luaL_checklstring(L, 2, &key.len);
811
852
 
812
853
    if (key.len == 0) {
813
 
        return luaL_error(L, "attempt to use empty keys");
 
854
        lua_pushnil(L);
 
855
        lua_pushliteral(L, "empty key");
 
856
        return 2;
814
857
    }
815
858
 
816
859
    if (key.len > 65535) {
817
 
        return luaL_error(L, "the key argument is more than 65535 bytes: %d",
818
 
                          (int) key.len);
 
860
        lua_pushnil(L);
 
861
        lua_pushliteral(L, "key too long");
 
862
        return 2;
819
863
    }
820
864
 
821
865
    hash = ngx_crc32_short(key.data, key.len);
828
872
        break;
829
873
 
830
874
    case LUA_TNUMBER:
831
 
        value.len = sizeof(lua_Number);
 
875
        value.len = sizeof(double);
832
876
        num = lua_tonumber(L, 3);
833
877
        value.data = (u_char *) #
834
878
        break;
841
885
 
842
886
    case LUA_TNIL:
843
887
        if (flags & (NGX_HTTP_LUA_SHDICT_ADD|NGX_HTTP_LUA_SHDICT_REPLACE)) {
844
 
            return luaL_error(L, "attempt to add or replace nil values");
 
888
            lua_pushnil(L);
 
889
            lua_pushliteral(L, "attempt to add or replace nil values");
 
890
            return 2;
845
891
        }
846
892
 
847
893
        value.len = 0;
849
895
        break;
850
896
 
851
897
    default:
852
 
        return luaL_error(L, "unsupported value type for key \"%s\" in "
853
 
                          "shared_dict \"%s\": %s", key.data, name.data,
854
 
                          lua_typename(L, value_type));
 
898
        lua_pushnil(L);
 
899
        lua_pushliteral(L, "bad value type");
 
900
        return 2;
855
901
    }
856
902
 
857
903
    if (n >= 4) {
865
911
        user_flags = (uint32_t) luaL_checkinteger(L, 5);
866
912
    }
867
913
 
868
 
    dd("looking up key %s in shared dict %s", key.data, name.data);
869
 
 
870
914
    ngx_shmtx_lock(&ctx->shpool->mutex);
871
915
 
872
916
#if 1
933
977
            ngx_queue_remove(&sd->queue);
934
978
            ngx_queue_insert_head(&ctx->sh->queue, &sd->queue);
935
979
 
936
 
            sd->key_len = key.len;
 
980
            sd->key_len = (u_short) key.len;
937
981
 
938
982
            if (exptime > 0) {
939
983
                tp = ngx_timeofday();
940
984
                sd->expires = (uint64_t) tp->sec * 1000 + tp->msec
941
 
                              + exptime * 1000;
 
985
                              + (uint64_t) (exptime * 1000);
942
986
 
943
987
            } else {
944
988
                sd->expires = 0;
950
994
 
951
995
            dd("setting value type to %d", value_type);
952
996
 
953
 
            sd->value_type = value_type;
 
997
            sd->value_type = (uint8_t) value_type;
954
998
 
955
999
            p = ngx_copy(sd->data, key.data, key.len);
956
1000
            ngx_memcpy(p, value.data, value.len);
1006
1050
        if (flags & NGX_HTTP_LUA_SHDICT_SAFE_STORE) {
1007
1051
            ngx_shmtx_unlock(&ctx->shpool->mutex);
1008
1052
 
1009
 
            lua_pushnil(L);
 
1053
            lua_pushboolean(L, 0);
1010
1054
            lua_pushliteral(L, "no memory");
1011
1055
            return 2;
1012
1056
        }
1013
1057
 
1014
1058
        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
1015
1059
                       "lua shared dict set: overriding non-expired items "
1016
 
                       "due to memory shortage for entry \"%V\"", &name);
 
1060
                       "due to memory shortage for entry \"%V\"", &key);
1017
1061
 
1018
1062
        for (i = 0; i < 30; i++) {
1019
1063
            if (ngx_http_lua_shdict_expire(ctx, 0) == 0) {
1040
1084
    sd = (ngx_http_lua_shdict_node_t *) &node->color;
1041
1085
 
1042
1086
    node->key = hash;
1043
 
    sd->key_len = key.len;
 
1087
    sd->key_len = (u_short) key.len;
1044
1088
 
1045
1089
    if (exptime > 0) {
1046
1090
        tp = ngx_timeofday();
1047
1091
        sd->expires = (uint64_t) tp->sec * 1000 + tp->msec
1048
 
                      + exptime * 1000;
 
1092
                      + (uint64_t) (exptime * 1000);
1049
1093
 
1050
1094
    } else {
1051
1095
        sd->expires = 0;
1057
1101
 
1058
1102
    dd("setting value type to %d", value_type);
1059
1103
 
1060
 
    sd->value_type = value_type;
 
1104
    sd->value_type = (uint8_t) value_type;
1061
1105
 
1062
1106
    p = ngx_copy(sd->data, key.data, key.len);
1063
1107
    ngx_memcpy(p, value.data, value.len);
1084
1128
    ngx_int_t                    rc;
1085
1129
    ngx_http_lua_shdict_ctx_t   *ctx;
1086
1130
    ngx_http_lua_shdict_node_t  *sd;
1087
 
    lua_Number                   num;
 
1131
    double                       num;
1088
1132
    u_char                      *p;
1089
1133
    ngx_shm_zone_t              *zone;
1090
 
    lua_Number                   value;
 
1134
    double                       value;
1091
1135
 
1092
1136
    n = lua_gettop(L);
1093
1137
 
1095
1139
        return luaL_error(L, "expecting 3 arguments, but only seen %d", n);
1096
1140
    }
1097
1141
 
1098
 
    luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 
1142
    if (lua_type(L, 1) != LUA_TLIGHTUSERDATA) {
 
1143
        return luaL_error(L, "bad \"zone\" argument");
 
1144
    }
1099
1145
 
1100
1146
    zone = lua_touserdata(L, 1);
1101
1147
    if (zone == NULL) {
1104
1150
 
1105
1151
    ctx = zone->data;
1106
1152
 
 
1153
    if (lua_isnil(L, 2)) {
 
1154
        lua_pushnil(L);
 
1155
        lua_pushliteral(L, "nil key");
 
1156
        return 2;
 
1157
    }
 
1158
 
1107
1159
    key.data = (u_char *) luaL_checklstring(L, 2, &key.len);
1108
1160
 
1109
1161
    if (key.len == 0) {
1110
 
        return luaL_error(L, "attempt to use empty keys");
 
1162
        lua_pushnil(L);
 
1163
        lua_pushliteral(L, "empty key");
 
1164
        return 2;
1111
1165
    }
1112
1166
 
1113
1167
    if (key.len > 65535) {
1114
 
        return luaL_error(L, "the key argument is more than 65535 bytes: %d",
1115
 
                          (int) key.len);
 
1168
        lua_pushnil(L);
 
1169
        lua_pushliteral(L, "key too long");
 
1170
        return 2;
1116
1171
    }
1117
1172
 
1118
1173
    hash = ngx_crc32_short(key.data, key.len);
1142
1197
 
1143
1198
    /* rc == NGX_OK */
1144
1199
 
1145
 
    if (sd->value_type != LUA_TNUMBER || sd->value_len != sizeof(lua_Number)) {
 
1200
    if (sd->value_type != LUA_TNUMBER || sd->value_len != sizeof(double)) {
1146
1201
        ngx_shmtx_unlock(&ctx->shpool->mutex);
1147
1202
 
1148
1203
        lua_pushnil(L);
1157
1212
 
1158
1213
    p = sd->data + key.len;
1159
1214
 
1160
 
    num = *(lua_Number *) p;
 
1215
    num = *(double *) p;
1161
1216
    num += value;
1162
1217
 
1163
 
    ngx_memcpy(p, (lua_Number *) &num, sizeof(lua_Number));
 
1218
    ngx_memcpy(p, (double *) &num, sizeof(double));
1164
1219
 
1165
1220
    ngx_shmtx_unlock(&ctx->shpool->mutex);
1166
1221
 
1231
1286
 
1232
1287
    case LUA_TNUMBER:
1233
1288
 
1234
 
        if (len != sizeof(lua_Number)) {
 
1289
        if (len != sizeof(double)) {
1235
1290
            ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad lua number "
1236
1291
                          "value size found for key %*s: %lu", key_len,
1237
1292
                          key_data, (unsigned long) len);
1309
1364
    return NULL;
1310
1365
}
1311
1366
 
 
1367
 
 
1368
#ifndef NGX_HTTP_LUA_NO_FFI_API
 
1369
int
 
1370
ngx_http_lua_ffi_shdict_store(ngx_shm_zone_t *zone, int op, u_char *key,
 
1371
    size_t key_len, int value_type, u_char *str_value_buf,
 
1372
    size_t str_value_len, double num_value, int exptime, int user_flags,
 
1373
    char **errmsg, int *forcible)
 
1374
{
 
1375
    int                          i, n;
 
1376
    u_char                       c, *p;
 
1377
    uint32_t                     hash;
 
1378
    ngx_int_t                    rc;
 
1379
    ngx_time_t                  *tp;
 
1380
    ngx_rbtree_node_t           *node;
 
1381
    ngx_http_lua_shdict_ctx_t   *ctx;
 
1382
    ngx_http_lua_shdict_node_t  *sd;
 
1383
 
 
1384
    if (zone == NULL) {
 
1385
        return NGX_ERROR;
 
1386
    }
 
1387
 
 
1388
    dd("exptime: %d", exptime);
 
1389
 
 
1390
    ctx = zone->data;
 
1391
 
 
1392
    *forcible = 0;
 
1393
 
 
1394
    hash = ngx_crc32_short(key, key_len);
 
1395
 
 
1396
    switch (value_type) {
 
1397
    case LUA_TSTRING:
 
1398
        /* do nothing */
 
1399
        break;
 
1400
 
 
1401
    case LUA_TNUMBER:
 
1402
        dd("num value: %lf", num_value);
 
1403
        str_value_buf = (u_char *) &num_value;
 
1404
        str_value_len = sizeof(double);
 
1405
        break;
 
1406
 
 
1407
    case LUA_TBOOLEAN:
 
1408
        c = num_value ? 1 : 0;
 
1409
        str_value_buf = &c;
 
1410
        str_value_len = sizeof(u_char);
 
1411
        break;
 
1412
 
 
1413
    case LUA_TNIL:
 
1414
        if (op & (NGX_HTTP_LUA_SHDICT_ADD|NGX_HTTP_LUA_SHDICT_REPLACE)) {
 
1415
            *errmsg = "attempt to add or replace nil values";
 
1416
            return NGX_ERROR;
 
1417
        }
 
1418
 
 
1419
        str_value_buf = NULL;
 
1420
        str_value_len = 0;
 
1421
        break;
 
1422
 
 
1423
    default:
 
1424
        *errmsg = "unsupported value type";
 
1425
        return NGX_ERROR;
 
1426
    }
 
1427
 
 
1428
    ngx_shmtx_lock(&ctx->shpool->mutex);
 
1429
 
 
1430
#if 1
 
1431
    ngx_http_lua_shdict_expire(ctx, 1);
 
1432
#endif
 
1433
 
 
1434
    rc = ngx_http_lua_shdict_lookup(zone, hash, key, key_len, &sd);
 
1435
 
 
1436
    dd("lookup returns %d", (int) rc);
 
1437
 
 
1438
    if (op & NGX_HTTP_LUA_SHDICT_REPLACE) {
 
1439
 
 
1440
        if (rc == NGX_DECLINED || rc == NGX_DONE) {
 
1441
            ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1442
            *errmsg = "not found";
 
1443
            return NGX_DECLINED;
 
1444
        }
 
1445
        /* rc == NGX_OK */
 
1446
 
 
1447
        goto replace;
 
1448
    }
 
1449
 
 
1450
    if (op & NGX_HTTP_LUA_SHDICT_ADD) {
 
1451
 
 
1452
        if (rc == NGX_OK) {
 
1453
            ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1454
            *errmsg = "exists";
 
1455
            return NGX_DECLINED;
 
1456
        }
 
1457
 
 
1458
        if (rc == NGX_DONE) {
 
1459
            /* exists but expired */
 
1460
 
 
1461
            dd("go to replace");
 
1462
            goto replace;
 
1463
        }
 
1464
 
 
1465
        /* rc == NGX_DECLINED */
 
1466
 
 
1467
        dd("go to insert");
 
1468
        goto insert;
 
1469
    }
 
1470
 
 
1471
    if (rc == NGX_OK || rc == NGX_DONE) {
 
1472
 
 
1473
        if (value_type == LUA_TNIL) {
 
1474
            goto remove;
 
1475
        }
 
1476
 
 
1477
replace:
 
1478
        if (str_value_buf && str_value_len == (size_t) sd->value_len) {
 
1479
 
 
1480
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
 
1481
                           "lua shared dict set: found old entry and value "
 
1482
                           "size matched, reusing it");
 
1483
 
 
1484
            ngx_queue_remove(&sd->queue);
 
1485
            ngx_queue_insert_head(&ctx->sh->queue, &sd->queue);
 
1486
 
 
1487
            sd->key_len = (u_short) key_len;
 
1488
 
 
1489
            if (exptime > 0) {
 
1490
                tp = ngx_timeofday();
 
1491
                sd->expires = (uint64_t) tp->sec * 1000 + tp->msec
 
1492
                              + (uint64_t) exptime;
 
1493
 
 
1494
            } else {
 
1495
                sd->expires = 0;
 
1496
            }
 
1497
 
 
1498
            sd->user_flags = user_flags;
 
1499
 
 
1500
            sd->value_len = (uint32_t) str_value_len;
 
1501
 
 
1502
            dd("setting value type to %d", value_type);
 
1503
 
 
1504
            sd->value_type = (uint8_t) value_type;
 
1505
 
 
1506
            p = ngx_copy(sd->data, key, key_len);
 
1507
            ngx_memcpy(p, str_value_buf, str_value_len);
 
1508
 
 
1509
            ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1510
 
 
1511
            return NGX_OK;
 
1512
        }
 
1513
 
 
1514
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
 
1515
                       "lua shared dict set: found old entry bug value size "
 
1516
                       "NOT matched, removing it first");
 
1517
 
 
1518
remove:
 
1519
        ngx_queue_remove(&sd->queue);
 
1520
 
 
1521
        node = (ngx_rbtree_node_t *)
 
1522
                   ((u_char *) sd - offsetof(ngx_rbtree_node_t, color));
 
1523
 
 
1524
        ngx_rbtree_delete(&ctx->sh->rbtree, node);
 
1525
 
 
1526
        ngx_slab_free_locked(ctx->shpool, node);
 
1527
 
 
1528
    }
 
1529
 
 
1530
insert:
 
1531
    /* rc == NGX_DECLINED or value size unmatch */
 
1532
 
 
1533
    if (str_value_buf == NULL) {
 
1534
        ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1535
        return NGX_OK;
 
1536
    }
 
1537
 
 
1538
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
 
1539
                   "lua shared dict set: creating a new entry");
 
1540
 
 
1541
    n = offsetof(ngx_rbtree_node_t, color)
 
1542
        + offsetof(ngx_http_lua_shdict_node_t, data)
 
1543
        + key_len
 
1544
        + str_value_len;
 
1545
 
 
1546
    node = ngx_slab_alloc_locked(ctx->shpool, n);
 
1547
 
 
1548
    if (node == NULL) {
 
1549
 
 
1550
        if (op & NGX_HTTP_LUA_SHDICT_SAFE_STORE) {
 
1551
            ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1552
 
 
1553
            *errmsg = "no memory";
 
1554
            return NGX_ERROR;
 
1555
        }
 
1556
 
 
1557
        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
 
1558
                       "lua shared dict set: overriding non-expired items "
 
1559
                       "due to memory shortage for entry \"%*s\"", key_len,
 
1560
                       key);
 
1561
 
 
1562
        for (i = 0; i < 30; i++) {
 
1563
            if (ngx_http_lua_shdict_expire(ctx, 0) == 0) {
 
1564
                break;
 
1565
            }
 
1566
 
 
1567
            *forcible = 1;
 
1568
 
 
1569
            node = ngx_slab_alloc_locked(ctx->shpool, n);
 
1570
            if (node != NULL) {
 
1571
                goto allocated;
 
1572
            }
 
1573
        }
 
1574
 
 
1575
        ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1576
 
 
1577
        *errmsg = "no memory";
 
1578
        return NGX_ERROR;
 
1579
    }
 
1580
 
 
1581
allocated:
 
1582
    sd = (ngx_http_lua_shdict_node_t *) &node->color;
 
1583
 
 
1584
    node->key = hash;
 
1585
    sd->key_len = (u_short) key_len;
 
1586
 
 
1587
    if (exptime > 0) {
 
1588
        tp = ngx_timeofday();
 
1589
        sd->expires = (uint64_t) tp->sec * 1000 + tp->msec
 
1590
                      + (uint64_t) exptime;
 
1591
 
 
1592
    } else {
 
1593
        sd->expires = 0;
 
1594
    }
 
1595
 
 
1596
    sd->user_flags = user_flags;
 
1597
    sd->value_len = (uint32_t) str_value_len;
 
1598
    dd("setting value type to %d", value_type);
 
1599
    sd->value_type = (uint8_t) value_type;
 
1600
 
 
1601
    p = ngx_copy(sd->data, key, key_len);
 
1602
    ngx_memcpy(p, str_value_buf, str_value_len);
 
1603
 
 
1604
    ngx_rbtree_insert(&ctx->sh->rbtree, node);
 
1605
    ngx_queue_insert_head(&ctx->sh->queue, &sd->queue);
 
1606
    ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1607
 
 
1608
    return NGX_OK;
 
1609
}
 
1610
 
 
1611
 
 
1612
int
 
1613
ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key,
 
1614
    size_t key_len, int *value_type, u_char **str_value_buf,
 
1615
    size_t *str_value_len, double *num_value, int *user_flags,
 
1616
    int get_stale, int *is_stale)
 
1617
{
 
1618
    ngx_str_t                    name;
 
1619
    uint32_t                     hash;
 
1620
    ngx_int_t                    rc;
 
1621
    ngx_http_lua_shdict_ctx_t   *ctx;
 
1622
    ngx_http_lua_shdict_node_t  *sd;
 
1623
    ngx_str_t                    value;
 
1624
 
 
1625
    if (zone == NULL) {
 
1626
        return NGX_ERROR;
 
1627
    }
 
1628
 
 
1629
    ctx = zone->data;
 
1630
    name = ctx->name;
 
1631
 
 
1632
    hash = ngx_crc32_short(key, key_len);
 
1633
 
 
1634
#if (NGX_DEBUG)
 
1635
    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
 
1636
                   "fetching key \"%*s\" in shared dict \"%V\"", key_len,
 
1637
                   key, &name);
 
1638
#endif /* NGX_DEBUG */
 
1639
 
 
1640
    ngx_shmtx_lock(&ctx->shpool->mutex);
 
1641
 
 
1642
#if 1
 
1643
    if (!get_stale) {
 
1644
        ngx_http_lua_shdict_expire(ctx, 1);
 
1645
    }
 
1646
#endif
 
1647
 
 
1648
    rc = ngx_http_lua_shdict_lookup(zone, hash, key, key_len, &sd);
 
1649
 
 
1650
    dd("shdict lookup returns %d", (int) rc);
 
1651
 
 
1652
    if (rc == NGX_DECLINED || (rc == NGX_DONE && !get_stale)) {
 
1653
        ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1654
        *value_type = LUA_TNIL;
 
1655
        return NGX_OK;
 
1656
    }
 
1657
 
 
1658
    /* rc == NGX_OK || (rc == NGX_DONE && get_stale) */
 
1659
 
 
1660
    *value_type = sd->value_type;
 
1661
 
 
1662
    dd("data: %p", sd->data);
 
1663
    dd("key len: %d", (int) sd->key_len);
 
1664
 
 
1665
    value.data = sd->data + sd->key_len;
 
1666
    value.len = (size_t) sd->value_len;
 
1667
 
 
1668
    if (*str_value_len < (size_t) value.len) {
 
1669
        if (*value_type != LUA_TSTRING) {
 
1670
            return NGX_ERROR;
 
1671
        }
 
1672
 
 
1673
        *str_value_buf = malloc(value.len);
 
1674
        if (*str_value_buf == NULL) {
 
1675
            ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1676
            return NGX_ERROR;
 
1677
        }
 
1678
    }
 
1679
 
 
1680
    *str_value_len = value.len;
 
1681
 
 
1682
    switch (*value_type) {
 
1683
    case LUA_TSTRING:
 
1684
        ngx_memcpy(*str_value_buf, value.data, value.len);
 
1685
        break;
 
1686
 
 
1687
    case LUA_TNUMBER:
 
1688
 
 
1689
        if (value.len != sizeof(double)) {
 
1690
            ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1691
            ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
 
1692
                          "bad lua number value size found for key %*s "
 
1693
                          "in shared_dict %V: %z", key_len, key,
 
1694
                          &name, value.len);
 
1695
            return NGX_ERROR;
 
1696
        }
 
1697
 
 
1698
        *num_value = *(double *) value.data;
 
1699
        break;
 
1700
 
 
1701
    case LUA_TBOOLEAN:
 
1702
 
 
1703
        if (value.len != sizeof(u_char)) {
 
1704
            ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1705
            ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
 
1706
                          "bad lua boolean value size found for key %*s "
 
1707
                          "in shared_dict %V: %z", key_len, key, &name,
 
1708
                          value.len);
 
1709
            return NGX_ERROR;
 
1710
        }
 
1711
 
 
1712
        ngx_memcpy(*str_value_buf, value.data, value.len);
 
1713
        break;
 
1714
 
 
1715
    default:
 
1716
 
 
1717
        ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1718
        ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
 
1719
                      "bad value type found for key %*s in "
 
1720
                      "shared_dict %V: %d", key_len, key, &name,
 
1721
                      *value_type);
 
1722
    }
 
1723
 
 
1724
    *user_flags = sd->user_flags;
 
1725
    dd("user flags: %d", *user_flags);
 
1726
 
 
1727
    ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1728
 
 
1729
    if (get_stale) {
 
1730
 
 
1731
        /* always return value, flags, stale */
 
1732
 
 
1733
        *is_stale = (rc == NGX_DONE);
 
1734
        return NGX_OK;
 
1735
    }
 
1736
 
 
1737
    return NGX_OK;
 
1738
}
 
1739
 
 
1740
 
 
1741
int
 
1742
ngx_http_lua_ffi_shdict_incr(ngx_shm_zone_t *zone, u_char *key,
 
1743
    size_t key_len, double *value, char **err)
 
1744
{
 
1745
    uint32_t                     hash;
 
1746
    ngx_int_t                    rc;
 
1747
    ngx_http_lua_shdict_ctx_t   *ctx;
 
1748
    ngx_http_lua_shdict_node_t  *sd;
 
1749
    double                       num;
 
1750
    u_char                      *p;
 
1751
 
 
1752
    ctx = zone->data;
 
1753
    hash = ngx_crc32_short(key, key_len);
 
1754
 
 
1755
    dd("looking up key %.*s in shared dict %.*s", (int) key_len, key,
 
1756
       (int) ctx->name.len, ctx->name.data);
 
1757
 
 
1758
    ngx_shmtx_lock(&ctx->shpool->mutex);
 
1759
#if 1
 
1760
    ngx_http_lua_shdict_expire(ctx, 1);
 
1761
#endif
 
1762
    rc = ngx_http_lua_shdict_lookup(zone, hash, key, key_len, &sd);
 
1763
 
 
1764
    dd("shdict lookup returned %d", (int) rc);
 
1765
 
 
1766
    if (rc == NGX_DECLINED || rc == NGX_DONE) {
 
1767
        ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1768
        *err = "not found";
 
1769
        return NGX_ERROR;
 
1770
    }
 
1771
 
 
1772
    /* rc == NGX_OK */
 
1773
 
 
1774
    if (sd->value_type != LUA_TNUMBER || sd->value_len != sizeof(double)) {
 
1775
        ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1776
        *err = "not a number";
 
1777
        return NGX_ERROR;
 
1778
    }
 
1779
 
 
1780
    ngx_queue_remove(&sd->queue);
 
1781
    ngx_queue_insert_head(&ctx->sh->queue, &sd->queue);
 
1782
 
 
1783
    dd("setting value type to %d", (int) sd->value_type);
 
1784
 
 
1785
    p = sd->data + key_len;
 
1786
 
 
1787
    num = *(double *) p;
 
1788
    num += *value;
 
1789
 
 
1790
    ngx_memcpy(p, (double *) &num, sizeof(double));
 
1791
 
 
1792
    ngx_shmtx_unlock(&ctx->shpool->mutex);
 
1793
 
 
1794
    *value = num;
 
1795
    return NGX_OK;
 
1796
}
 
1797
#endif /* NGX_HTTP_LUA_NO_FFI_API */
 
1798
 
 
1799
 
1312
1800
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */