durable_rules 0.34.29 → 0.34.31
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/src/rules/events.c +69 -154
- data/src/rules/json.c +7 -3
- data/src/rules/json.h +3 -0
- data/src/rules/net.c +72 -55
- data/src/rules/net.h +3 -4
- data/src/rules/rete.c +29 -43
- data/src/rules/state.c +138 -80
- data/src/rules/state.h +29 -13
- metadata +2 -2
data/src/rules/json.c
CHANGED
@@ -395,7 +395,7 @@ static unsigned int getString(char *start, char **first, char **last) {
|
|
395
395
|
static unsigned int getStringAndHash(char *start, char **first, char **last, unsigned int *hash) {
|
396
396
|
unsigned char state = ST_STRING_SEEK;
|
397
397
|
char delimiter = '\0';
|
398
|
-
unsigned int currentHash =
|
398
|
+
unsigned int currentHash = FNV_32_OFFSET_BASIS;
|
399
399
|
while(start[0] != '\0') {
|
400
400
|
switch (state) {
|
401
401
|
case ST_STRING_SEEK:
|
@@ -417,11 +417,14 @@ static unsigned int getStringAndHash(char *start, char **first, char **last, uns
|
|
417
417
|
state = ST_STRING_ESC;
|
418
418
|
}
|
419
419
|
|
420
|
-
currentHash
|
420
|
+
currentHash ^= (*start);
|
421
|
+
currentHash *= FNV_32_PRIME;
|
421
422
|
break;
|
422
423
|
case ST_STRING_ESC:
|
423
424
|
state = ST_STRING_PARSE;
|
424
|
-
|
425
|
+
|
426
|
+
currentHash ^= (*start);
|
427
|
+
currentHash *= FNV_32_PRIME;
|
425
428
|
break;
|
426
429
|
}
|
427
430
|
|
@@ -430,3 +433,4 @@ static unsigned int getStringAndHash(char *start, char **first, char **last, uns
|
|
430
433
|
|
431
434
|
return ERR_PARSE_STRING;
|
432
435
|
}
|
436
|
+
|
data/src/rules/json.h
CHANGED
@@ -17,6 +17,9 @@
|
|
17
17
|
#define JSON_REGEX 0x0C
|
18
18
|
#define JSON_IREGEX 0x0D
|
19
19
|
|
20
|
+
#define FNV_32_OFFSET_BASIS 0x811c9dc5
|
21
|
+
#define FNV_32_PRIME 16777619
|
22
|
+
|
20
23
|
unsigned int readNextName(char *start, char **first, char **last, unsigned int *hash);
|
21
24
|
unsigned int readNextValue(char *start, char **first, char **last, unsigned char *type);
|
22
25
|
unsigned int readNextArrayValue(char *start, char **first, char **last, unsigned char *type);
|
data/src/rules/net.c
CHANGED
@@ -686,7 +686,12 @@ static unsigned int loadAddMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
686
686
|
if (asprintf(&lua,
|
687
687
|
"local sid = ARGV[1]\n"
|
688
688
|
"local assert_fact = tonumber(ARGV[2])\n"
|
689
|
-
|
689
|
+
// when mark visited is set to 0, it means eval will be called immedately
|
690
|
+
// with the same message. In that case, the function will avid setting
|
691
|
+
// the visited bit (for events), storing the message and increasing the
|
692
|
+
// mid count (for the case of auto generated mid)
|
693
|
+
"local mark_visited = tonumber(ARGV[3])\n"
|
694
|
+
"local keys_count = tonumber(ARGV[4])\n"
|
690
695
|
"local events_hashset = \"%s!e!\" .. sid\n"
|
691
696
|
"local facts_hashset = \"%s!f!\" .. sid\n"
|
692
697
|
"local visited_hashset = \"%s!v!\" .. sid\n"
|
@@ -694,12 +699,14 @@ static unsigned int loadAddMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
694
699
|
"local message = {}\n"
|
695
700
|
"local primary_message_keys = {}\n"
|
696
701
|
"local input_keys = {}\n"
|
697
|
-
"local save_message = function(current_key, message, events_key, messages_key)\n"
|
698
|
-
"
|
702
|
+
"local save_message = function(current_key, message, events_key, messages_key, save_hashset)\n"
|
703
|
+
" if save_hashset == 1 then\n"
|
704
|
+
" redis.call(\"hsetnx\", messages_key, message[\"id\"], cmsgpack.pack(message))\n"
|
705
|
+
" end\n"
|
699
706
|
" local primary_key = primary_message_keys[current_key](message)\n"
|
700
707
|
" redis.call(\"lpush\", events_key .. \"!m!\" .. primary_key, message[\"id\"])\n"
|
701
708
|
"end\n"
|
702
|
-
"for index =
|
709
|
+
"for index = 5 + keys_count, #ARGV, 3 do\n"
|
703
710
|
" if ARGV[index + 2] == \"1\" then\n"
|
704
711
|
" message[ARGV[index]] = ARGV[index + 1]\n"
|
705
712
|
" elseif ARGV[index + 2] == \"2\" or ARGV[index + 2] == \"3\" then\n"
|
@@ -717,35 +724,41 @@ static unsigned int loadAddMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
717
724
|
" end\n"
|
718
725
|
"end\n"
|
719
726
|
"local mid = message[\"id\"]\n"
|
720
|
-
"if
|
721
|
-
"
|
727
|
+
"if mid == \"\" then\n"
|
728
|
+
" if mark_visited == 0 then\n"
|
729
|
+
" mid = \"$m-\" .. redis.call(\"hget\", mid_count_hashset, sid) + 1\n"
|
730
|
+
" else\n"
|
731
|
+
" mid = \"$m-\" .. redis.call(\"hincrby\", mid_count_hashset, sid, 1)\n"
|
732
|
+
" end\n"
|
722
733
|
" message[\"id\"] = mid\n"
|
723
734
|
"else\n"
|
724
|
-
" if
|
725
|
-
" if
|
726
|
-
"
|
727
|
-
"
|
728
|
-
"
|
729
|
-
"
|
730
|
-
" if
|
735
|
+
" if assert_fact == 1 then\n"
|
736
|
+
" if redis.call(\"hexists\", facts_hashset, mid) == 1 then\n"
|
737
|
+
" return %d\n"
|
738
|
+
" end\n"
|
739
|
+
" else\n"
|
740
|
+
" if mark_visited == 1 then\n"
|
741
|
+
" if redis.call(\"hsetnx\", visited_hashset, mid, 1) == 0 then\n"
|
731
742
|
" return %d\n"
|
732
743
|
" end\n"
|
744
|
+
" elseif redis.call(\"hexists\", visited_hashset, mid) == 1 then \n"
|
745
|
+
" return %d\n"
|
733
746
|
" end\n"
|
734
747
|
" end\n"
|
735
748
|
"end\n"
|
736
|
-
"for index =
|
749
|
+
"for index = 5, 4 + keys_count, 1 do\n"
|
737
750
|
" input_keys[ARGV[index]] = true\n"
|
738
751
|
"end\n"
|
739
752
|
"%sif assert_fact == 1 then\n"
|
740
753
|
" message[\"$f\"] = 1\n"
|
741
|
-
" for index =
|
754
|
+
" for index = 5, 4 + keys_count, 1 do\n"
|
742
755
|
" local key = ARGV[index]\n"
|
743
|
-
" save_message(key, message, key .. \"!f!\" .. sid, facts_hashset)\n"
|
756
|
+
" save_message(key, message, key .. \"!f!\" .. sid, facts_hashset, mark_visited)\n"
|
744
757
|
" end\n"
|
745
758
|
"else\n"
|
746
|
-
" for index =
|
759
|
+
" for index = 5, 4 + keys_count, 1 do\n"
|
747
760
|
" local key = ARGV[index]\n"
|
748
|
-
" save_message(key, message, key .. \"!e!\" .. sid, events_hashset)\n"
|
761
|
+
" save_message(key, message, key .. \"!e!\" .. sid, events_hashset, mark_visited)\n"
|
749
762
|
" end\n"
|
750
763
|
"end\n",
|
751
764
|
name,
|
@@ -754,6 +767,7 @@ static unsigned int loadAddMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
754
767
|
name,
|
755
768
|
ERR_EVENT_OBSERVED,
|
756
769
|
ERR_EVENT_OBSERVED,
|
770
|
+
ERR_EVENT_OBSERVED,
|
757
771
|
addMessageLua) == -1) {
|
758
772
|
return ERR_OUT_OF_MEMORY;
|
759
773
|
}
|
@@ -947,6 +961,7 @@ static unsigned int loadPeekActionCommand(ruleset *tree, binding *rulesBinding)
|
|
947
961
|
if (asprintf(&lua,
|
948
962
|
"local facts_key = \"%s!f!\"\n"
|
949
963
|
"local events_key = \"%s!e!\"\n"
|
964
|
+
"local visited_key = \"%s!v!\"\n"
|
950
965
|
"local action_key = \"%s!a\"\n"
|
951
966
|
"local state_key = \"%s!s\"\n"
|
952
967
|
"local timers_key = \"%s!t\"\n"
|
@@ -1040,7 +1055,7 @@ static unsigned int loadPeekActionCommand(ruleset *tree, binding *rulesBinding)
|
|
1040
1055
|
" if cancel then\n"
|
1041
1056
|
" for i = 1, #frame, 1 do\n"
|
1042
1057
|
" if type(frame[i]) == \"table\" then\n"
|
1043
|
-
" redis.call(\"
|
1058
|
+
" redis.call(\"hdel\", visited_key .. sid, frame[i][\"id\"])\n"
|
1044
1059
|
" redis.call(\"zadd\", timers_key, max_score, \"p:\" .. cjson.encode(frame[i]))\n"
|
1045
1060
|
" end\n"
|
1046
1061
|
" end\n"
|
@@ -1211,6 +1226,7 @@ static unsigned int loadPeekActionCommand(ruleset *tree, binding *rulesBinding)
|
|
1211
1226
|
name,
|
1212
1227
|
name,
|
1213
1228
|
name,
|
1229
|
+
name,
|
1214
1230
|
peekActionLua) == -1) {
|
1215
1231
|
return ERR_OUT_OF_MEMORY;
|
1216
1232
|
}
|
@@ -2095,15 +2111,13 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
2095
2111
|
" message[\"id\"] = mid\n"
|
2096
2112
|
" end\n"
|
2097
2113
|
"else\n"
|
2098
|
-
" if
|
2099
|
-
" if
|
2100
|
-
"
|
2101
|
-
"
|
2102
|
-
"
|
2103
|
-
"
|
2104
|
-
"
|
2105
|
-
" return %d\n"
|
2106
|
-
" end\n"
|
2114
|
+
" if assert_fact == 1 then\n"
|
2115
|
+
" if message and redis.call(\"hexists\", facts_hashset, mid) == 1 then\n"
|
2116
|
+
" return %d\n"
|
2117
|
+
" end\n"
|
2118
|
+
" else\n"
|
2119
|
+
" if message and redis.call(\"hsetnx\", visited_hashset, mid, 1) == 0 then\n"
|
2120
|
+
" return %d\n"
|
2107
2121
|
" end\n"
|
2108
2122
|
" end\n"
|
2109
2123
|
"end\n"
|
@@ -2354,12 +2368,12 @@ unsigned int formatEvalMessage(void *rulesBinding,
|
|
2354
2368
|
char *sid,
|
2355
2369
|
char *mid,
|
2356
2370
|
char *message,
|
2357
|
-
|
2358
|
-
unsigned int propertiesLength,
|
2371
|
+
jsonObject *jo,
|
2359
2372
|
unsigned char actionType,
|
2360
2373
|
char **keys,
|
2361
2374
|
unsigned int keysLength,
|
2362
2375
|
char **command) {
|
2376
|
+
unsigned int propertiesLength = jo->propertiesLength;
|
2363
2377
|
if (actionType == ACTION_RETRACT_FACT || actionType == ACTION_RETRACT_EVENT) {
|
2364
2378
|
propertiesLength = 0;
|
2365
2379
|
}
|
@@ -2404,16 +2418,16 @@ unsigned int formatEvalMessage(void *rulesBinding,
|
|
2404
2418
|
|
2405
2419
|
unsigned int offset = 8 + keysLength;
|
2406
2420
|
for (unsigned int i = 0; i < propertiesLength; ++i) {
|
2407
|
-
argv[offset + i * 3] =
|
2408
|
-
argvl[offset + i * 3] =
|
2409
|
-
argv[offset + i * 3 + 1] =
|
2410
|
-
if (
|
2411
|
-
argvl[offset + i * 3 + 1] =
|
2421
|
+
argv[offset + i * 3] = jo->properties[i].name;
|
2422
|
+
argvl[offset + i * 3] = jo->properties[i].nameLength;
|
2423
|
+
argv[offset + i * 3 + 1] = jo->properties[i].valueString;
|
2424
|
+
if (jo->properties[i].type == JSON_STRING) {
|
2425
|
+
argvl[offset + i * 3 + 1] = jo->properties[i].valueLength;
|
2412
2426
|
} else {
|
2413
|
-
argvl[offset + i * 3 + 1] =
|
2427
|
+
argvl[offset + i * 3 + 1] = jo->properties[i].valueLength + 1;
|
2414
2428
|
}
|
2415
2429
|
|
2416
|
-
switch(
|
2430
|
+
switch(jo->properties[i].type) {
|
2417
2431
|
case JSON_STRING:
|
2418
2432
|
argv[offset + i * 3 + 2] = "1";
|
2419
2433
|
break;
|
@@ -2446,22 +2460,23 @@ unsigned int formatEvalMessage(void *rulesBinding,
|
|
2446
2460
|
unsigned int formatStoreMessage(void *rulesBinding,
|
2447
2461
|
char *sid,
|
2448
2462
|
char *message,
|
2449
|
-
|
2450
|
-
unsigned int propertiesLength,
|
2463
|
+
jsonObject *jo,
|
2451
2464
|
unsigned char storeFact,
|
2465
|
+
unsigned char markVisited,
|
2452
2466
|
char **keys,
|
2453
2467
|
unsigned int keysLength,
|
2454
2468
|
char **command) {
|
2469
|
+
unsigned int propertiesLength = jo->propertiesLength;
|
2455
2470
|
binding *bindingContext = (binding*)rulesBinding;
|
2456
2471
|
char keysLengthString[5];
|
2457
2472
|
#ifdef _WIN32
|
2458
2473
|
sprintf_s(keysLengthString, sizeof(char) * 5, "%d", keysLength);
|
2459
|
-
char **argv = (char **)_alloca(sizeof(char*)*(
|
2460
|
-
size_t *argvl = (size_t *)_alloca(sizeof(size_t)*(
|
2474
|
+
char **argv = (char **)_alloca(sizeof(char*)*(7 + keysLength + propertiesLength * 3));
|
2475
|
+
size_t *argvl = (size_t *)_alloca(sizeof(size_t)*(7 + keysLength + propertiesLength * 3));
|
2461
2476
|
#else
|
2462
2477
|
snprintf(keysLengthString, sizeof(char) * 5, "%d", keysLength);
|
2463
|
-
char *argv[
|
2464
|
-
size_t argvl[
|
2478
|
+
char *argv[7 + keysLength + propertiesLength * 3];
|
2479
|
+
size_t argvl[7 + keysLength + propertiesLength * 3];
|
2465
2480
|
#endif
|
2466
2481
|
|
2467
2482
|
argv[0] = "evalsha";
|
@@ -2474,26 +2489,28 @@ unsigned int formatStoreMessage(void *rulesBinding,
|
|
2474
2489
|
argvl[3] = strlen(sid);
|
2475
2490
|
argv[4] = storeFact ? "1" : "0";
|
2476
2491
|
argvl[4] = 1;
|
2477
|
-
argv[5] =
|
2478
|
-
argvl[5] =
|
2492
|
+
argv[5] = markVisited ? "1" : "0";
|
2493
|
+
argvl[5] = 1;
|
2494
|
+
argv[6] = keysLengthString;
|
2495
|
+
argvl[6] = strlen(keysLengthString);
|
2479
2496
|
|
2480
2497
|
for (unsigned int i = 0; i < keysLength; ++i) {
|
2481
|
-
argv[
|
2482
|
-
argvl[
|
2498
|
+
argv[7 + i] = keys[i];
|
2499
|
+
argvl[7 + i] = strlen(keys[i]);
|
2483
2500
|
}
|
2484
2501
|
|
2485
|
-
unsigned int offset =
|
2502
|
+
unsigned int offset = 7 + keysLength;
|
2486
2503
|
for (unsigned int i = 0; i < propertiesLength; ++i) {
|
2487
|
-
argv[offset + i * 3] =
|
2488
|
-
argvl[offset + i * 3] =
|
2489
|
-
argv[offset + i * 3 + 1] =
|
2490
|
-
if (
|
2491
|
-
argvl[offset + i * 3 + 1] =
|
2504
|
+
argv[offset + i * 3] = jo->properties[i].name;
|
2505
|
+
argvl[offset + i * 3] = jo->properties[i].nameLength;
|
2506
|
+
argv[offset + i * 3 + 1] = jo->properties[i].valueString;
|
2507
|
+
if (jo->properties[i].type == JSON_STRING) {
|
2508
|
+
argvl[offset + i * 3 + 1] = jo->properties[i].valueLength;
|
2492
2509
|
} else {
|
2493
|
-
argvl[offset + i * 3 + 1] =
|
2510
|
+
argvl[offset + i * 3 + 1] = jo->properties[i].valueLength + 1;
|
2494
2511
|
}
|
2495
2512
|
|
2496
|
-
switch(
|
2513
|
+
switch(jo->properties[i].type) {
|
2497
2514
|
case JSON_STRING:
|
2498
2515
|
argv[offset + i * 3 + 2] = "1";
|
2499
2516
|
break;
|
data/src/rules/net.h
CHANGED
@@ -54,8 +54,7 @@ unsigned int formatEvalMessage(void *rulesBinding,
|
|
54
54
|
char *sid,
|
55
55
|
char *mid,
|
56
56
|
char *message,
|
57
|
-
|
58
|
-
unsigned int propertiesLength,
|
57
|
+
jsonObject *jo,
|
59
58
|
unsigned char actionType,
|
60
59
|
char **keys,
|
61
60
|
unsigned int keysLength,
|
@@ -64,9 +63,9 @@ unsigned int formatEvalMessage(void *rulesBinding,
|
|
64
63
|
unsigned int formatStoreMessage(void *rulesBinding,
|
65
64
|
char *sid,
|
66
65
|
char *message,
|
67
|
-
|
68
|
-
unsigned int propertiesLength,
|
66
|
+
jsonObject *jo,
|
69
67
|
unsigned char storeFact,
|
68
|
+
unsigned char markVisited,
|
70
69
|
char **keys,
|
71
70
|
unsigned int keysLength,
|
72
71
|
char **command);
|
data/src/rules/rete.c
CHANGED
@@ -8,34 +8,32 @@
|
|
8
8
|
#include "json.h"
|
9
9
|
#include "regex.h"
|
10
10
|
|
11
|
-
#define HASH_ALL
|
12
|
-
#define HASH_ANY
|
13
|
-
#define HASH_PRI
|
14
|
-
#define HASH_COUNT
|
15
|
-
#define
|
16
|
-
#define
|
17
|
-
#define
|
18
|
-
#define
|
19
|
-
#define
|
20
|
-
#define
|
21
|
-
#define
|
22
|
-
#define
|
23
|
-
#define
|
24
|
-
#define
|
25
|
-
#define
|
26
|
-
#define
|
27
|
-
#define
|
28
|
-
#define
|
29
|
-
#define
|
30
|
-
#define
|
31
|
-
#define
|
32
|
-
#define
|
33
|
-
#define
|
34
|
-
#define
|
35
|
-
#define
|
36
|
-
#define
|
37
|
-
#define HASH_R 5861211 //$r
|
38
|
-
#define HASH_FORWARD 1810358942 // $forward
|
11
|
+
#define HASH_ALL 321211332 // all
|
12
|
+
#define HASH_ANY 740945997 // any
|
13
|
+
#define HASH_PRI 1450887882 // pri
|
14
|
+
#define HASH_COUNT 967958004 // count
|
15
|
+
#define HASH_CAP 41178555 // cap
|
16
|
+
#define HASH_LT 542787579 // $lt
|
17
|
+
#define HASH_LTE 2350824890 // $lte
|
18
|
+
#define HASH_GT 507407960 // $gt
|
19
|
+
#define HASH_GTE 3645344263 // $gte
|
20
|
+
#define HASH_EQ 256037865 // $eq
|
21
|
+
#define HASH_NEQ 2488026869 // $neq
|
22
|
+
#define HASH_MT 576092554 // $mt
|
23
|
+
#define HASH_IMT 1472564215 // $imt
|
24
|
+
#define HASH_EX 373481198 // $ex
|
25
|
+
#define HASH_NEX 2605470202 // $nex
|
26
|
+
#define HASH_OR 340911698 // $or
|
27
|
+
#define HASH_AND 3746487396 // $and
|
28
|
+
#define HASH_S 1186729920 // $s
|
29
|
+
#define HASH_NAME 2369371622 // name
|
30
|
+
#define HASH_ADD 4081054038 // $add
|
31
|
+
#define HASH_SUB 1040718071 // $sub
|
32
|
+
#define HASH_MUL 304370403 // $mul
|
33
|
+
#define HASH_DIV 130502 // $div
|
34
|
+
#define HASH_L 1706836109 // $l
|
35
|
+
#define HASH_R 1203507539 //$r
|
36
|
+
#define HASH_FORWARD 739185624 // $forward
|
39
37
|
|
40
38
|
typedef struct path {
|
41
39
|
unsigned char operator;
|
@@ -746,26 +744,15 @@ static unsigned int validateRuleset(char *rules) {
|
|
746
744
|
return countResult;
|
747
745
|
}
|
748
746
|
|
749
|
-
unsigned int spanResult = validateSetting(HASH_SPAN, first, JSON_INT);
|
750
|
-
if (spanResult != PARSE_OK && spanResult != ERR_SETTING_NOT_FOUND) {
|
751
|
-
return spanResult;
|
752
|
-
}
|
753
|
-
|
754
747
|
unsigned int capResult = validateSetting(HASH_CAP, first, JSON_INT);
|
755
748
|
if (capResult != PARSE_OK && capResult != ERR_SETTING_NOT_FOUND) {
|
756
749
|
return capResult;
|
757
750
|
}
|
758
751
|
|
759
|
-
if (
|
760
|
-
(countResult == PARSE_OK && capResult == PARSE_OK)) {
|
752
|
+
if (countResult == PARSE_OK && capResult == PARSE_OK) {
|
761
753
|
return ERR_UNEXPECTED_NAME;
|
762
754
|
}
|
763
755
|
|
764
|
-
result = validateSetting(HASH_BY, first, JSON_STRING);
|
765
|
-
if (result != PARSE_OK && result != ERR_SETTING_NOT_FOUND) {
|
766
|
-
return result;
|
767
|
-
}
|
768
|
-
|
769
756
|
result = validateSetting(HASH_PRI, first, JSON_INT);
|
770
757
|
if (result != PARSE_OK && result != ERR_SETTING_NOT_FOUND) {
|
771
758
|
return result;
|
@@ -783,7 +770,7 @@ static unsigned int validateRuleset(char *rules) {
|
|
783
770
|
if (result != RULES_OK && result != PARSE_END) {
|
784
771
|
return result;
|
785
772
|
}
|
786
|
-
} else if (hash != HASH_COUNT && hash != HASH_PRI && hash !=
|
773
|
+
} else if (hash != HASH_COUNT && hash != HASH_PRI && hash != HASH_CAP) {
|
787
774
|
return ERR_UNEXPECTED_NAME;
|
788
775
|
}
|
789
776
|
|
@@ -1289,7 +1276,7 @@ static unsigned int createBetaConnector(ruleset *tree,
|
|
1289
1276
|
|
1290
1277
|
if (operator == OP_ALL || operator == OP_ANY || operator == OP_NOT) {
|
1291
1278
|
nameLength = nameLength - 4;
|
1292
|
-
hash =
|
1279
|
+
hash = fnv1Hash32(first, nameLength);
|
1293
1280
|
}
|
1294
1281
|
}
|
1295
1282
|
|
@@ -1694,7 +1681,6 @@ static unsigned int createTree(ruleset *tree, char *rules) {
|
|
1694
1681
|
ruleAction->value.c.cap = 0;
|
1695
1682
|
getSetting(HASH_PRI, first, &ruleAction->value.c.priority);
|
1696
1683
|
getSetting(HASH_COUNT, first, &ruleAction->value.c.count);
|
1697
|
-
getSetting(HASH_SPAN, first, &ruleAction->value.c.span);
|
1698
1684
|
getSetting(HASH_CAP, first, &ruleAction->value.c.cap);
|
1699
1685
|
if (!ruleAction->value.c.count && !ruleAction->value.c.span && !ruleAction->value.c.cap) {
|
1700
1686
|
ruleAction->value.c.count = 1;
|
data/src/rules/state.c
CHANGED
@@ -6,15 +6,13 @@
|
|
6
6
|
#include "json.h"
|
7
7
|
#include "net.h"
|
8
8
|
|
9
|
-
unsigned int
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
return hash;
|
9
|
+
unsigned int fnv1Hash32(char *str, unsigned int len) {
|
10
|
+
unsigned int hash = FNV_32_OFFSET_BASIS;
|
11
|
+
for(unsigned int i = 0; i < len; str++, i++) {
|
12
|
+
hash ^= (*str);
|
13
|
+
hash *= FNV_32_PRIME;
|
14
|
+
}
|
15
|
+
return hash;
|
18
16
|
}
|
19
17
|
|
20
18
|
static unsigned int evictEntry(ruleset *tree) {
|
@@ -43,7 +41,7 @@ static unsigned int evictEntry(ruleset *tree) {
|
|
43
41
|
current->sidHash = 0;
|
44
42
|
current->bindingIndex = 0;
|
45
43
|
current->lastRefresh = 0;
|
46
|
-
current->propertiesLength = 0;
|
44
|
+
current->jo.propertiesLength = 0;
|
47
45
|
found = 1;
|
48
46
|
}
|
49
47
|
}
|
@@ -164,15 +162,70 @@ static stateEntry *getEntry(ruleset *tree, char *sid, unsigned int sidHash) {
|
|
164
162
|
return NULL;
|
165
163
|
}
|
166
164
|
|
165
|
+
static unsigned int fixupIds(jsonObject *jo) {
|
166
|
+
jsonProperty *property;
|
167
|
+
// id and sid are coerced to strings
|
168
|
+
// to avoid unnecessary conversions
|
169
|
+
if (jo->sidIndex != UNDEFINED_INDEX && jo->properties[jo->sidIndex].type != JSON_NIL) {
|
170
|
+
//coerce value to string
|
171
|
+
property = &jo->properties[jo->sidIndex];
|
172
|
+
if (property->type == JSON_DOUBLE || property->type == JSON_INT) {
|
173
|
+
++property->valueLength;
|
174
|
+
}
|
175
|
+
|
176
|
+
property->type = JSON_STRING;
|
177
|
+
} else {
|
178
|
+
property = &jo->properties[jo->propertiesLength];
|
179
|
+
jo->sidIndex = jo->propertiesLength;
|
180
|
+
++jo->propertiesLength;
|
181
|
+
if (jo->propertiesLength == MAX_OBJECT_PROPERTIES) {
|
182
|
+
return ERR_EVENT_MAX_PROPERTIES;
|
183
|
+
}
|
184
|
+
|
185
|
+
strncpy(jo->sidBuffer, "0", 1);
|
186
|
+
property->hash = HASH_SID;
|
187
|
+
property->isMaterial = 1;
|
188
|
+
property->valueString = jo->sidBuffer;
|
189
|
+
property->valueLength = 1;
|
190
|
+
strncpy(property->name, "sid", 3);
|
191
|
+
property->nameLength = 3;
|
192
|
+
property->type = JSON_STRING;
|
193
|
+
}
|
194
|
+
|
195
|
+
if (jo->idIndex != UNDEFINED_INDEX && jo->properties[jo->idIndex].type != JSON_NIL) {
|
196
|
+
//coerce value to string
|
197
|
+
property = &jo->properties[jo->idIndex];
|
198
|
+
if (property->type == JSON_DOUBLE || property->type == JSON_INT) {
|
199
|
+
++property->valueLength;
|
200
|
+
}
|
201
|
+
|
202
|
+
property->type = JSON_STRING;
|
203
|
+
} else {
|
204
|
+
property = &jo->properties[jo->propertiesLength];
|
205
|
+
jo->idIndex = jo->propertiesLength;
|
206
|
+
++jo->propertiesLength;
|
207
|
+
if (jo->propertiesLength == MAX_OBJECT_PROPERTIES) {
|
208
|
+
return ERR_EVENT_MAX_PROPERTIES;
|
209
|
+
}
|
210
|
+
|
211
|
+
jo->idBuffer[0] = 0;
|
212
|
+
property->hash = HASH_ID;
|
213
|
+
property->isMaterial = 1;
|
214
|
+
property->valueString = jo->idBuffer;
|
215
|
+
property->valueLength = 0;
|
216
|
+
strncpy(property->name, "id", 2);
|
217
|
+
property->nameLength = 2;
|
218
|
+
property->type = JSON_STRING;
|
219
|
+
}
|
220
|
+
|
221
|
+
return RULES_OK;
|
222
|
+
}
|
223
|
+
|
167
224
|
unsigned int constructObject(char *root,
|
168
225
|
char *parentName,
|
169
226
|
char *object,
|
170
|
-
char
|
171
|
-
|
172
|
-
jsonProperty *properties,
|
173
|
-
unsigned int *propertiesLength,
|
174
|
-
unsigned int *midIndex,
|
175
|
-
unsigned int *sidIndex,
|
227
|
+
char layout,
|
228
|
+
jsonObject *jo,
|
176
229
|
char **next) {
|
177
230
|
char *firstName;
|
178
231
|
char *lastName;
|
@@ -180,7 +233,16 @@ unsigned int constructObject(char *root,
|
|
180
233
|
char *last;
|
181
234
|
unsigned char type;
|
182
235
|
unsigned int hash;
|
183
|
-
int parentNameLength
|
236
|
+
int parentNameLength;
|
237
|
+
if (parentName) {
|
238
|
+
parentNameLength = strlen(parentName);
|
239
|
+
} else {
|
240
|
+
parentNameLength = 0;
|
241
|
+
jo->idIndex = UNDEFINED_INDEX;
|
242
|
+
jo->sidIndex = UNDEFINED_INDEX;
|
243
|
+
jo->propertiesLength = 0;
|
244
|
+
}
|
245
|
+
|
184
246
|
object = (object ? object : root);
|
185
247
|
unsigned int result = readNextName(object, &firstName, &lastName, &hash);
|
186
248
|
while (result == PARSE_OK) {
|
@@ -191,35 +253,40 @@ unsigned int constructObject(char *root,
|
|
191
253
|
|
192
254
|
jsonProperty *property = NULL;
|
193
255
|
if (type != JSON_OBJECT) {
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
256
|
+
switch (layout) {
|
257
|
+
case JSON_OBJECT_SEQUENCED:
|
258
|
+
property = &jo->properties[jo->propertiesLength];
|
259
|
+
if (hash == HASH_ID) {
|
260
|
+
jo->idIndex = jo->propertiesLength;
|
261
|
+
} else if (hash == HASH_SID) {
|
262
|
+
jo->sidIndex = jo->propertiesLength;
|
263
|
+
}
|
264
|
+
break;
|
265
|
+
case JSON_OBJECT_HASHED:
|
266
|
+
{
|
267
|
+
unsigned int candidate = hash % MAX_OBJECT_PROPERTIES;
|
268
|
+
while (jo->properties[candidate].type != 0) {
|
269
|
+
candidate = (candidate + 1) % MAX_OBJECT_PROPERTIES;
|
270
|
+
}
|
271
|
+
|
272
|
+
if (hash == HASH_ID) {
|
273
|
+
jo->idIndex = candidate;
|
274
|
+
} else if (hash == HASH_SID) {
|
275
|
+
jo->sidIndex = candidate;
|
276
|
+
}
|
277
|
+
|
278
|
+
property = &jo->properties[candidate];
|
211
279
|
}
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
if (*propertiesLength == maxProperties) {
|
280
|
+
break;
|
281
|
+
}
|
282
|
+
|
283
|
+
++jo->propertiesLength;
|
284
|
+
if (jo->propertiesLength == MAX_OBJECT_PROPERTIES) {
|
218
285
|
return ERR_EVENT_MAX_PROPERTIES;
|
219
286
|
}
|
220
287
|
|
221
288
|
property->isMaterial = 0;
|
222
|
-
property->
|
289
|
+
property->valueString = first;
|
223
290
|
property->valueLength = last - first;
|
224
291
|
property->type = type;
|
225
292
|
}
|
@@ -244,15 +311,11 @@ unsigned int constructObject(char *root,
|
|
244
311
|
strncpy(newParent, firstName, nameLength);
|
245
312
|
newParent[nameLength] = '\0';
|
246
313
|
result = constructObject(root,
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
propertiesLength,
|
253
|
-
midIndex,
|
254
|
-
sidIndex,
|
255
|
-
next);
|
314
|
+
newParent,
|
315
|
+
first,
|
316
|
+
layout,
|
317
|
+
jo,
|
318
|
+
next);
|
256
319
|
if (result != RULES_OK) {
|
257
320
|
return result;
|
258
321
|
}
|
@@ -269,7 +332,7 @@ unsigned int constructObject(char *root,
|
|
269
332
|
property->name[parentNameLength] = '.';
|
270
333
|
strncpy(&property->name[parentNameLength + 1], firstName, nameLength);
|
271
334
|
property->nameLength = fullNameLength;
|
272
|
-
property->hash =
|
335
|
+
property->hash = fnv1Hash32(property->name, fullNameLength);
|
273
336
|
} else {
|
274
337
|
#ifdef _WIN32
|
275
338
|
char *fullName = (char *)_alloca(sizeof(char)*(fullNameLength + 1));
|
@@ -281,15 +344,11 @@ unsigned int constructObject(char *root,
|
|
281
344
|
strncpy(&fullName[parentNameLength + 1], firstName, nameLength);
|
282
345
|
fullName[fullNameLength] = '\0';
|
283
346
|
result = constructObject(root,
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
propertiesLength,
|
290
|
-
midIndex,
|
291
|
-
sidIndex,
|
292
|
-
next);
|
347
|
+
fullName,
|
348
|
+
first,
|
349
|
+
layout,
|
350
|
+
jo,
|
351
|
+
next);
|
293
352
|
if (result != RULES_OK) {
|
294
353
|
return result;
|
295
354
|
}
|
@@ -300,15 +359,20 @@ unsigned int constructObject(char *root,
|
|
300
359
|
result = readNextName(last, &firstName, &lastName, &hash);
|
301
360
|
}
|
302
361
|
|
362
|
+
if (!parentName) {
|
363
|
+
int idResult = fixupIds(jo);
|
364
|
+
if (idResult != RULES_OK) {
|
365
|
+
return idResult;
|
366
|
+
}
|
367
|
+
}
|
368
|
+
|
303
369
|
return (result == PARSE_END ? RULES_OK: result);
|
304
370
|
}
|
305
371
|
|
306
372
|
void rehydrateProperty(jsonProperty *property, char *state) {
|
307
|
-
|
308
|
-
// to avoid unnecessary conversions
|
309
|
-
if (!property->isMaterial && property->hash != HASH_ID && property->hash != HASH_SID) {
|
373
|
+
if (!property->isMaterial) {
|
310
374
|
unsigned short propertyLength = property->valueLength + 1;
|
311
|
-
char *propertyFirst =
|
375
|
+
char *propertyFirst = property->valueString;
|
312
376
|
unsigned char propertyType = property->type;
|
313
377
|
unsigned char b = 0;
|
314
378
|
char temp;
|
@@ -343,7 +407,7 @@ static unsigned int resolveBindingAndEntry(ruleset *tree,
|
|
343
407
|
char *sid,
|
344
408
|
stateEntry **entry,
|
345
409
|
void **rulesBinding) {
|
346
|
-
unsigned int sidHash =
|
410
|
+
unsigned int sidHash = fnv1Hash32(sid, strlen(sid));
|
347
411
|
if (!ensureEntry(tree, sid, sidHash, entry)) {
|
348
412
|
unsigned int result = getBindingIndex(tree, sidHash, &(*entry)->bindingIndex);
|
349
413
|
if (result != RULES_OK) {
|
@@ -386,20 +450,14 @@ unsigned int refreshState(void *handle,
|
|
386
450
|
return result;
|
387
451
|
}
|
388
452
|
|
389
|
-
memset(entry->properties, 0,
|
390
|
-
entry->propertiesLength = 0;
|
453
|
+
memset(entry->jo.properties, 0, MAX_OBJECT_PROPERTIES * sizeof(jsonProperty));
|
454
|
+
entry->jo.propertiesLength = 0;
|
391
455
|
char *next;
|
392
|
-
unsigned int midIndex = UNDEFINED_INDEX;
|
393
|
-
unsigned int sidIndex = UNDEFINED_INDEX;
|
394
456
|
result = constructObject(entry->state,
|
395
457
|
NULL,
|
396
458
|
NULL,
|
397
|
-
|
398
|
-
|
399
|
-
entry->properties,
|
400
|
-
&entry->propertiesLength,
|
401
|
-
&midIndex,
|
402
|
-
&sidIndex,
|
459
|
+
JSON_OBJECT_HASHED,
|
460
|
+
&entry->jo,
|
403
461
|
&next);
|
404
462
|
if (result != RULES_OK) {
|
405
463
|
return result;
|
@@ -416,7 +474,7 @@ unsigned int fetchStateProperty(void *tree,
|
|
416
474
|
unsigned char ignoreStaleState,
|
417
475
|
char **state,
|
418
476
|
jsonProperty **property) {
|
419
|
-
unsigned int sidHash =
|
477
|
+
unsigned int sidHash = fnv1Hash32(sid, strlen(sid));
|
420
478
|
stateEntry *entry = getEntry(tree, sid, sidHash);
|
421
479
|
if (entry == NULL || entry->lastRefresh == 0) {
|
422
480
|
return ERR_STATE_NOT_LOADED;
|
@@ -426,11 +484,11 @@ unsigned int fetchStateProperty(void *tree,
|
|
426
484
|
return ERR_STALE_STATE;
|
427
485
|
}
|
428
486
|
|
429
|
-
unsigned int propertyIndex = propertyHash %
|
430
|
-
jsonProperty *result = &entry->properties[propertyIndex];
|
487
|
+
unsigned int propertyIndex = propertyHash % MAX_OBJECT_PROPERTIES;
|
488
|
+
jsonProperty *result = &entry->jo.properties[propertyIndex];
|
431
489
|
while (result->type != 0 && result->hash != propertyHash) {
|
432
|
-
propertyIndex = (propertyIndex + 1) %
|
433
|
-
result = &entry->properties[propertyIndex];
|
490
|
+
propertyIndex = (propertyIndex + 1) % MAX_OBJECT_PROPERTIES;
|
491
|
+
result = &entry->jo.properties[propertyIndex];
|
434
492
|
}
|
435
493
|
|
436
494
|
if (!result->type) {
|