durable_rules 0.34.27 → 0.34.28
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/librb/durable.rb +10 -8
- data/librb/engine.rb +51 -41
- data/librb/interface.rb +1 -1
- data/src/rules/events.c +7 -4
- data/src/rules/json.h +1 -0
- data/src/rules/net.c +90 -143
- data/src/rules/net.h +3 -1
- data/src/rules/regex.c +47 -6
- data/src/rules/regex.h +3 -1
- data/src/rules/rete.c +15 -2
- data/src/rules/rete.h +1 -0
- data/src/rules/rules.h +2 -1
- data/src/rulesrb/rules.c +7 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 444692ec85550db95da9c6f15a8a4a28a5595327
|
4
|
+
data.tar.gz: f5613ee7347ce15f9f155a0819ff78463a842d06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00fb2a9657488183693516eae86078b46c22c1639c9c684c605e44a9c73b6a04d09581f116f637a9d8ce8b21c5931f4fbd20df0f40f90c1bf46a8280521e5362
|
7
|
+
data.tar.gz: 2032f03a299f12291099f33f1adec895ed3f67aec3a0b0e14ec1bf90b8f9bc32ad2b340ca140ce403e3b4f5d3fdf66002efc57e128af7a43c8a620a8dcd91739
|
data/librb/durable.rb
CHANGED
@@ -141,6 +141,10 @@ module Durable
|
|
141
141
|
return Expression.new(@name, @left).matches(other)
|
142
142
|
end
|
143
143
|
|
144
|
+
def imatches(other)
|
145
|
+
return Expression.new(@name, @left).imatches(other)
|
146
|
+
end
|
147
|
+
|
144
148
|
def ref_id(sid)
|
145
149
|
Arithmetic.new @name, @left, sid
|
146
150
|
end
|
@@ -251,6 +255,12 @@ module Durable
|
|
251
255
|
self
|
252
256
|
end
|
253
257
|
|
258
|
+
def imatches(other)
|
259
|
+
@__op = :$imt
|
260
|
+
@right = other
|
261
|
+
self
|
262
|
+
end
|
263
|
+
|
254
264
|
def -@
|
255
265
|
@__op = :$nex
|
256
266
|
@right = 1
|
@@ -424,10 +434,6 @@ module Durable
|
|
424
434
|
{:pri => value}
|
425
435
|
end
|
426
436
|
|
427
|
-
def span(value)
|
428
|
-
{:span => value}
|
429
|
-
end
|
430
|
-
|
431
437
|
def cap(value)
|
432
438
|
{:cap => value}
|
433
439
|
end
|
@@ -482,10 +488,6 @@ module Durable
|
|
482
488
|
rule["pri"] = options[:pri]
|
483
489
|
end
|
484
490
|
|
485
|
-
if options.key? :span
|
486
|
-
rule["span"] = options[:span]
|
487
|
-
end
|
488
|
-
|
489
491
|
if options.key? :cap
|
490
492
|
rule["cap"] = options[:cap]
|
491
493
|
end
|
data/librb/engine.rb
CHANGED
@@ -124,29 +124,38 @@ module Engine
|
|
124
124
|
@_queues[ruleset_name]
|
125
125
|
end
|
126
126
|
|
127
|
-
def start_timer(timer_name, duration,
|
128
|
-
if
|
129
|
-
|
127
|
+
def start_timer(timer_name, duration, manual_reset = false)
|
128
|
+
if manual_reset
|
129
|
+
manual_reset = 1
|
130
|
+
else
|
131
|
+
manual_reset = 0
|
130
132
|
end
|
131
133
|
|
132
|
-
if @_timers.key?
|
133
|
-
raise ArgumentError, "Timer with
|
134
|
+
if @_timers.key? timer_name
|
135
|
+
raise ArgumentError, "Timer with name #{timer_name} already added"
|
134
136
|
else
|
135
|
-
timer = {:sid => @s.sid,
|
136
|
-
@_timers[timer_id] = [timer, duration]
|
137
|
+
timer = {:sid => @s.sid, :$t => timer_name}
|
138
|
+
@_timers[timer_id] = [timer, duration, manual_reset]
|
137
139
|
end
|
138
140
|
end
|
139
141
|
|
140
|
-
def cancel_timer(timer_name
|
141
|
-
if
|
142
|
-
|
142
|
+
def cancel_timer(timer_name)
|
143
|
+
if @_cancelled_timers.key? timer_name
|
144
|
+
raise ArgumentError, "Timer with id #{timer_name} already cancelled"
|
145
|
+
else
|
146
|
+
@_cancelled_timers[timer_name] = true
|
143
147
|
end
|
148
|
+
end
|
144
149
|
|
145
|
-
|
146
|
-
|
150
|
+
def reset_timer(timer_name)
|
151
|
+
if @m.kind_of? Hash
|
152
|
+
retract_timer timer_name, @m
|
147
153
|
else
|
148
|
-
|
149
|
-
|
154
|
+
for m in @m do
|
155
|
+
return true if retract_timer(timer_name, m)
|
156
|
+
end
|
157
|
+
|
158
|
+
return false
|
150
159
|
end
|
151
160
|
end
|
152
161
|
|
@@ -214,6 +223,22 @@ module Engine
|
|
214
223
|
|
215
224
|
private
|
216
225
|
|
226
|
+
def retract_timer(timer_name, message)
|
227
|
+
if ((message.key? :$t) && (message[:$t] == timer_name)) ||
|
228
|
+
((message.key? '$t') && (message['$t'] == timer_name))
|
229
|
+
retract(message)
|
230
|
+
return true
|
231
|
+
end
|
232
|
+
|
233
|
+
for property_name, property_value in message do
|
234
|
+
if (property_value.kind_of? Hash) && retract_timer(timer_name, property_value)
|
235
|
+
return true
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
return false
|
240
|
+
end
|
241
|
+
|
217
242
|
def handle_property(name, value=nil)
|
218
243
|
name = name.to_s
|
219
244
|
if name.end_with? '?'
|
@@ -369,11 +394,10 @@ module Engine
|
|
369
394
|
end
|
370
395
|
end
|
371
396
|
|
372
|
-
id = rand(1000000000)
|
373
397
|
if assert_state
|
374
|
-
c.assert(:label => to_state, :chart => 1
|
398
|
+
c.assert(:label => to_state, :chart => 1)
|
375
399
|
else
|
376
|
-
c.post(:label => to_state, :chart => 1
|
400
|
+
c.post(:label => to_state, :chart => 1)
|
377
401
|
end
|
378
402
|
end
|
379
403
|
}
|
@@ -453,12 +477,12 @@ module Engine
|
|
453
477
|
Rules.start_assert_events @handle, JSON.generate(messages)
|
454
478
|
end
|
455
479
|
|
456
|
-
def start_timer(sid, timer, timer_duration)
|
457
|
-
Rules.start_timer @handle, sid.to_s, timer_duration, JSON.generate(timer)
|
480
|
+
def start_timer(sid, timer, timer_duration, manual_reset)
|
481
|
+
Rules.start_timer @handle, sid.to_s, timer_duration, manual_reset, JSON.generate(timer)
|
458
482
|
end
|
459
483
|
|
460
|
-
def cancel_timer(sid,
|
461
|
-
Rules.cancel_timer @handle, sid.to_s,
|
484
|
+
def cancel_timer(sid, timer_name)
|
485
|
+
Rules.cancel_timer @handle, sid.to_s, timer_name.to_s
|
462
486
|
end
|
463
487
|
|
464
488
|
def assert_fact(fact)
|
@@ -608,12 +632,12 @@ module Engine
|
|
608
632
|
complete.call e, true
|
609
633
|
else
|
610
634
|
begin
|
611
|
-
for
|
612
|
-
cancel_timer c.s.sid,
|
635
|
+
for timer_name, timer_value in c._cancelled_timers do
|
636
|
+
cancel_timer c.s.sid, timer_name
|
613
637
|
end
|
614
638
|
|
615
|
-
for timer_id,
|
616
|
-
start_timer c.s.sid,
|
639
|
+
for timer_id, timer_tuple in c._timers do
|
640
|
+
start_timer c.s.sid, timer_tuple[0], timer_tuple[1], timer_tuple[2]
|
617
641
|
end
|
618
642
|
|
619
643
|
for ruleset_name, q in c._queues do
|
@@ -752,8 +776,7 @@ module Engine
|
|
752
776
|
if ((trigger.key? :to) && (trigger[:to] == state_name)) ||
|
753
777
|
((trigger.key? "to") && (trigger["to"] == state_name)) ||
|
754
778
|
(trigger.key? :count) || (trigger.key? "count") ||
|
755
|
-
(trigger.key? :cap) || (trigger.key? "cap")
|
756
|
-
(trigger.key? :span) || (trigger.key? "span")
|
779
|
+
(trigger.key? :cap) || (trigger.key? "cap")
|
757
780
|
reflexive_states[qualified_name] = true
|
758
781
|
end
|
759
782
|
end
|
@@ -807,12 +830,6 @@ module Engine
|
|
807
830
|
rule[:count] = trigger["count"]
|
808
831
|
end
|
809
832
|
|
810
|
-
if trigger.key? :span
|
811
|
-
rule[:span] = trigger[:span]
|
812
|
-
elsif trigger.key? "span"
|
813
|
-
rule[:span] = trigger["span"]
|
814
|
-
end
|
815
|
-
|
816
833
|
if trigger.key? :cap
|
817
834
|
rule[:cap] = trigger[:cap]
|
818
835
|
elsif trigger.key? "cap"
|
@@ -936,8 +953,7 @@ module Engine
|
|
936
953
|
for transition_name, transition in stage_to do
|
937
954
|
if (transition_name == stage_name) ||
|
938
955
|
(transition.key? :count) || (transition.key? "count") ||
|
939
|
-
(transition.key? :cap) || (transition.key? "cap")
|
940
|
-
(transition.key? :span) || (transition.key? "span")
|
956
|
+
(transition.key? :cap) || (transition.key? "cap")
|
941
957
|
reflexive_stages[stage_name] = true
|
942
958
|
end
|
943
959
|
end
|
@@ -1002,12 +1018,6 @@ module Engine
|
|
1002
1018
|
rule[:count] = transition["count"]
|
1003
1019
|
end
|
1004
1020
|
|
1005
|
-
if transition.key? :span
|
1006
|
-
rule[:span] = transition[:span]
|
1007
|
-
elsif transition.key? "span"
|
1008
|
-
rule[:span] = transition["span"]
|
1009
|
-
end
|
1010
|
-
|
1011
1021
|
if transition.key? :cap
|
1012
1022
|
rule[:cap] = transition[:cap]
|
1013
1023
|
elsif transition.key? "cap"
|
data/librb/interface.rb
CHANGED
data/src/rules/events.c
CHANGED
@@ -39,6 +39,7 @@
|
|
39
39
|
#define OP_STRING_STRING 0x0101
|
40
40
|
#define OP_STRING_NIL 0x0107
|
41
41
|
#define OP_STRING_REGEX 0x010C
|
42
|
+
#define OP_STRING_IREGEX 0x010D
|
42
43
|
#define OP_NIL_BOOL 0x0704
|
43
44
|
#define OP_NIL_INT 0x0702
|
44
45
|
#define OP_NIL_DOUBLE 0x0703
|
@@ -885,9 +886,11 @@ static unsigned int isMatch(ruleset *tree,
|
|
885
886
|
|
886
887
|
break;
|
887
888
|
case OP_STRING_REGEX:
|
889
|
+
case OP_STRING_IREGEX:
|
888
890
|
*propertyMatch = evaluateRegex(tree,
|
889
891
|
message + currentProperty->valueOffset,
|
890
892
|
currentProperty->valueLength,
|
893
|
+
(type == OP_STRING_REGEX) ? 0 : 1,
|
891
894
|
currentAlpha->right.value.regex.vocabularyLength,
|
892
895
|
currentAlpha->right.value.regex.statesLength,
|
893
896
|
currentAlpha->right.value.regex.stateMachineOffset);
|
@@ -1878,7 +1881,7 @@ unsigned int queueMessage(void *handle, unsigned int queueAction, char *sid, cha
|
|
1878
1881
|
return registerMessage(rulesBinding, queueAction, destination, message);
|
1879
1882
|
}
|
1880
1883
|
|
1881
|
-
unsigned int startTimer(void *handle, char *sid, unsigned int duration, char *timer) {
|
1884
|
+
unsigned int startTimer(void *handle, char *sid, unsigned int duration, char manualReset, char *timer) {
|
1882
1885
|
void *rulesBinding;
|
1883
1886
|
if (!sid) {
|
1884
1887
|
sid = "0";
|
@@ -1889,10 +1892,10 @@ unsigned int startTimer(void *handle, char *sid, unsigned int duration, char *ti
|
|
1889
1892
|
return result;
|
1890
1893
|
}
|
1891
1894
|
|
1892
|
-
return registerTimer(rulesBinding, duration, timer);
|
1895
|
+
return registerTimer(rulesBinding, duration, manualReset, timer);
|
1893
1896
|
}
|
1894
1897
|
|
1895
|
-
unsigned int cancelTimer(void *handle, char *sid, char *
|
1898
|
+
unsigned int cancelTimer(void *handle, char *sid, char *timerName) {
|
1896
1899
|
void *rulesBinding;
|
1897
1900
|
if (!sid) {
|
1898
1901
|
sid = "0";
|
@@ -1903,7 +1906,7 @@ unsigned int cancelTimer(void *handle, char *sid, char *timer) {
|
|
1903
1906
|
return result;
|
1904
1907
|
}
|
1905
1908
|
|
1906
|
-
return removeTimer(rulesBinding,
|
1909
|
+
return removeTimer(rulesBinding, timerName);
|
1907
1910
|
}
|
1908
1911
|
|
1909
1912
|
unsigned int renewActionLease(void *handle, char *sid) {
|
data/src/rules/json.h
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
#define JSON_STATE_IDIOM 0x0A
|
16
16
|
#define JSON_EVENT_IDIOM 0x0B
|
17
17
|
#define JSON_REGEX 0x0C
|
18
|
+
#define JSON_IREGEX 0x0D
|
18
19
|
|
19
20
|
unsigned int readNextName(char *start, char **first, char **last, unsigned int *hash);
|
20
21
|
unsigned int readNextValue(char *start, char **first, char **last, unsigned char *type);
|
data/src/rules/net.c
CHANGED
@@ -393,16 +393,8 @@ static unsigned int loadRemoveActionCommand(ruleset *tree, binding *rulesBinding
|
|
393
393
|
"local delete_frame = function(key, action_key)\n"
|
394
394
|
" local rule_action_key = redis.call(\"lpop\", key)\n"
|
395
395
|
" local raw_count = redis.call(\"lpop\", key)\n"
|
396
|
-
"
|
397
|
-
"
|
398
|
-
" count = tonumber(raw_count)\n"
|
399
|
-
" end\n"
|
400
|
-
" if count == 0 then\n"
|
401
|
-
" local packed_frame = redis.call(\"lpop\", rule_action_key)\n"
|
402
|
-
" while packed_frame ~= \"0\" do\n"
|
403
|
-
" packed_frame = redis.call(\"lpop\", rule_action_key)\n"
|
404
|
-
" end\n"
|
405
|
-
" else\n"
|
396
|
+
" if raw_count then"
|
397
|
+
" local count = tonumber(string.sub(raw_count, 3))\n"
|
406
398
|
" for i = 0, count - 1, 1 do\n"
|
407
399
|
" local packed_frame = redis.call(\"rpop\", rule_action_key)\n"
|
408
400
|
" end\n"
|
@@ -439,12 +431,10 @@ static unsigned int loadTimerCommand(ruleset *tree, binding *rulesBinding) {
|
|
439
431
|
"local timestamp = tonumber(ARGV[1])\n"
|
440
432
|
"local res = redis.call(\"zrangebyscore\", timer_key, 0, timestamp, \"limit\", 0, 50)\n"
|
441
433
|
"if #res > 0 then\n"
|
442
|
-
"
|
443
|
-
"
|
444
|
-
" redis.call(\"zincrby\", timer_key, 10, tostring(res[i]))\n"
|
434
|
+
" for i = 1, #res, 1 do\n"
|
435
|
+
" redis.call(\"zincrby\", timer_key, 10, tostring(res[i]))\n"
|
445
436
|
" end\n"
|
446
|
-
"
|
447
|
-
" return res\n"
|
437
|
+
" return res\n"
|
448
438
|
"end\n"
|
449
439
|
"return 0\n", name) == -1) {
|
450
440
|
return ERR_OUT_OF_MEMORY;
|
@@ -460,6 +450,34 @@ static unsigned int loadTimerCommand(ruleset *tree, binding *rulesBinding) {
|
|
460
450
|
return RULES_OK;
|
461
451
|
}
|
462
452
|
|
453
|
+
static unsigned int loadRemoveTimerCommand(ruleset *tree, binding *rulesBinding) {
|
454
|
+
char *name = &tree->stringPool[tree->nameOffset];
|
455
|
+
redisContext *reContext = rulesBinding->reContext;
|
456
|
+
redisReply *reply;
|
457
|
+
char *lua = NULL;
|
458
|
+
if (asprintf(&lua,
|
459
|
+
"local timer_key = \"%s!t\"\n"
|
460
|
+
"local timer_name = ARGV[1]\n"
|
461
|
+
"local res = redis.call(\"zrange\", timer_key, 0, -1)\n"
|
462
|
+
"for i = 1, #res, 1 do\n"
|
463
|
+
" if string.find(res[i], \"\\\"%%$t\\\"%%s*:%%s*\\\"\" .. timer_name .. \"\\\"\") then\n"
|
464
|
+
" redis.call(\"zrem\", timer_key, res[i])\n"
|
465
|
+
" end\n"
|
466
|
+
"end\n"
|
467
|
+
"return 0\n", name) == -1) {
|
468
|
+
return ERR_OUT_OF_MEMORY;
|
469
|
+
}
|
470
|
+
|
471
|
+
unsigned int result = redisAppendCommand(reContext, "SCRIPT LOAD %s", lua);
|
472
|
+
GET_REPLY(result, "loadRemoveTimerCommand", reply);
|
473
|
+
|
474
|
+
strncpy(rulesBinding->removeTimerHash, reply->str, 40);
|
475
|
+
rulesBinding->removeTimerHash[40] = '\0';
|
476
|
+
freeReplyObject(reply);
|
477
|
+
free(lua);
|
478
|
+
return RULES_OK;
|
479
|
+
}
|
480
|
+
|
463
481
|
static unsigned int loadUpdateActionCommand(ruleset *tree, binding *rulesBinding) {
|
464
482
|
char *name = &tree->stringPool[tree->nameOffset];
|
465
483
|
redisContext *reContext = rulesBinding->reContext;
|
@@ -559,6 +577,7 @@ static unsigned int loadDeleteSessionCommand(ruleset *tree, binding *rulesBindin
|
|
559
577
|
" redis.call(\"del\", all_keys[i])\n"
|
560
578
|
" end\n"
|
561
579
|
"end\n"
|
580
|
+
"redis.call(\"hdel\", \"%s!c\", sid)\n"
|
562
581
|
"redis.call(\"hdel\", \"%s!s\", sid)\n"
|
563
582
|
"redis.call(\"hdel\", \"%s!s!v\", sid)\n"
|
564
583
|
"redis.call(\"zrem\", \"%s!a\", sid)\n"
|
@@ -569,6 +588,7 @@ static unsigned int loadDeleteSessionCommand(ruleset *tree, binding *rulesBindin
|
|
569
588
|
name,
|
570
589
|
name,
|
571
590
|
name,
|
591
|
+
name,
|
572
592
|
name,
|
573
593
|
name,
|
574
594
|
name,
|
@@ -1031,54 +1051,31 @@ static unsigned int loadPeekActionCommand(ruleset *tree, binding *rulesBinding)
|
|
1031
1051
|
"local load_frame_from_rule = function(rule_action_key, raw_count, sid, max_score)\n"
|
1032
1052
|
" local frames = {}\n"
|
1033
1053
|
" local packed_frames = {}\n"
|
1034
|
-
" local
|
1035
|
-
" local
|
1036
|
-
"
|
1037
|
-
"
|
1038
|
-
"
|
1039
|
-
"
|
1040
|
-
"
|
1041
|
-
"
|
1042
|
-
"
|
1043
|
-
"
|
1044
|
-
" while packed_frame ~= \"0\" do\n"
|
1054
|
+
" local count = tonumber(string.sub(raw_count, 3))\n"
|
1055
|
+
" local window = false\n"
|
1056
|
+
" if string.find(raw_count, \"$w\") == 1 then\n"
|
1057
|
+
" window = true\n"
|
1058
|
+
" end\n"
|
1059
|
+
" for i = 0, count - 1, 1 do\n"
|
1060
|
+
" local packed_frame = redis.call(\"rpop\", rule_action_key)\n"
|
1061
|
+
" if not packed_frame then\n"
|
1062
|
+
" break\n"
|
1063
|
+
" else\n"
|
1045
1064
|
" local frame = review_frame(cmsgpack.unpack(packed_frame), rule_action_key, sid, max_score)\n"
|
1046
1065
|
" if frame then\n"
|
1047
1066
|
" table.insert(frames, frame)\n"
|
1048
1067
|
" table.insert(packed_frames, packed_frame)\n"
|
1049
1068
|
" end\n"
|
1050
|
-
" packed_frame = redis.call(\"lpop\", rule_action_key)\n"
|
1051
|
-
" end\n"
|
1052
|
-
" if #packed_frames > 0 then\n"
|
1053
|
-
" redis.call(\"lpush\", rule_action_key, 0)\n"
|
1054
|
-
" end\n"
|
1055
|
-
" else\n"
|
1056
|
-
" while count > 0 do\n"
|
1057
|
-
" local packed_frame = redis.call(\"rpop\", rule_action_key)\n"
|
1058
|
-
" if not packed_frame then\n"
|
1059
|
-
" break\n"
|
1060
|
-
" else\n"
|
1061
|
-
" local frame = review_frame(cmsgpack.unpack(packed_frame), rule_action_key, sid, max_score)\n"
|
1062
|
-
" if frame then\n"
|
1063
|
-
" table.insert(frames, frame)\n"
|
1064
|
-
" table.insert(packed_frames, packed_frame)\n"
|
1065
|
-
" count = count - 1\n"
|
1066
|
-
" end\n"
|
1067
|
-
" end\n"
|
1068
1069
|
" end\n"
|
1069
1070
|
" end\n"
|
1070
1071
|
" for i = #packed_frames, 1, -1 do\n"
|
1071
|
-
"
|
1072
|
-
" redis.call(\"lpush\", rule_action_key, packed_frames[i])\n"
|
1073
|
-
" else\n"
|
1074
|
-
" redis.call(\"rpush\", rule_action_key, packed_frames[i])\n"
|
1075
|
-
" end\n"
|
1072
|
+
" redis.call(\"rpush\", rule_action_key, packed_frames[i])\n"
|
1076
1073
|
" end\n"
|
1077
|
-
" if #packed_frames == 0 then\n"
|
1074
|
+
" if #packed_frames == 0 or (window and (#packed_frames ~= count)) then\n"
|
1078
1075
|
" return nil, nil\n"
|
1079
1076
|
" end\n"
|
1080
1077
|
" local last_name = string.find(rule_action_key, \"!\") - 1\n"
|
1081
|
-
" if
|
1078
|
+
" if window and count == 1 then\n"
|
1082
1079
|
" return string.sub(rule_action_key, 1, last_name), frames[1]\n"
|
1083
1080
|
" else\n"
|
1084
1081
|
" return string.sub(rule_action_key, 1, last_name), frames\n"
|
@@ -1653,23 +1650,7 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
1653
1650
|
}
|
1654
1651
|
}
|
1655
1652
|
|
1656
|
-
if (currentNode->value.c.
|
1657
|
-
oldLua = lua;
|
1658
|
-
if (asprintf(&lua,
|
1659
|
-
"%sif toggle then\n"
|
1660
|
-
" context[\"process_key\"] = process_key_with_span\n"
|
1661
|
-
" context[\"process_key_count\"] = %d\n"
|
1662
|
-
" if not process_message(message) then\n"
|
1663
|
-
" return\n"
|
1664
|
-
" end\n"
|
1665
|
-
"end\n",
|
1666
|
-
lua,
|
1667
|
-
currentNode->value.c.span) == -1) {
|
1668
|
-
return ERR_OUT_OF_MEMORY;
|
1669
|
-
}
|
1670
|
-
free(oldLua);
|
1671
|
-
|
1672
|
-
} else if (currentNode->value.c.cap > 0) {
|
1653
|
+
if (currentNode->value.c.cap > 0) {
|
1673
1654
|
oldLua = lua;
|
1674
1655
|
if (asprintf(&lua,
|
1675
1656
|
"%sif toggle then\n"
|
@@ -1720,7 +1701,6 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
1720
1701
|
"local actions_key = \"%s!a\"\n"
|
1721
1702
|
"local state_key = \"%s!s\"\n"
|
1722
1703
|
"local mid_count_hashset = \"%s!c\"\n"
|
1723
|
-
"local queue_action = false\n"
|
1724
1704
|
"local facts_message_cache = {}\n"
|
1725
1705
|
"local events_message_cache = {}\n"
|
1726
1706
|
"local facts_mids_cache = {}\n"
|
@@ -1972,50 +1952,9 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
1972
1952
|
" end\n"
|
1973
1953
|
" return result\n"
|
1974
1954
|
"end\n"
|
1975
|
-
"local process_key_with_span = function(message, span)\n"
|
1976
|
-
" local index = directory[key]\n"
|
1977
|
-
" local queue_lock = false\n"
|
1978
|
-
" if index then\n"
|
1979
|
-
" local last_score = redis.call(\"get\", results_key .. \"!d\")\n"
|
1980
|
-
" if not last_score then\n"
|
1981
|
-
" redis.call(\"set\", results_key .. \"!d\", score)\n"
|
1982
|
-
" else\n"
|
1983
|
-
" local new_score = last_score + span\n"
|
1984
|
-
" if score > new_score then\n"
|
1985
|
-
" redis.call(\"rpush\", results_key, 0)\n"
|
1986
|
-
" redis.call(\"rpush\", actions_key .. \"!\" .. sid, results_key)\n"
|
1987
|
-
" redis.call(\"rpush\", actions_key .. \"!\" .. sid, 0)\n"
|
1988
|
-
" local span_count, span_remain = math.modf((score - new_score) / span)\n"
|
1989
|
-
" last_score = new_score + span_count * span\n"
|
1990
|
-
" redis.call(\"set\", results_key .. \"!d\", last_score)\n"
|
1991
|
-
" queue_lock = true\n"
|
1992
|
-
" end\n"
|
1993
|
-
" end\n"
|
1994
|
-
" local count = 0\n"
|
1995
|
-
" if not message then\n"
|
1996
|
-
" if assert_fact == 0 then\n"
|
1997
|
-
" count = process_inverse_event(message, index, keys[index] .. \"!e!\" .. sid, false)\n"
|
1998
|
-
" else\n"
|
1999
|
-
" count = process_inverse_event(message, index, keys[index] .. \"!f!\" .. sid, true)\n"
|
2000
|
-
" end\n"
|
2001
|
-
" else\n"
|
2002
|
-
" if assert_fact == 0 then\n"
|
2003
|
-
" count = process_event(message, index, keys[index] .. \"!e!\" .. sid, false)\n"
|
2004
|
-
" else\n"
|
2005
|
-
" count = process_event(message, index, keys[index] .. \"!f!\" .. sid, true)\n"
|
2006
|
-
" end\n"
|
2007
|
-
" end\n"
|
2008
|
-
" if (count > 0) then\n"
|
2009
|
-
" for i = 1, #results, 1 do\n"
|
2010
|
-
" redis.call(\"rpush\", results_key, results[i])\n"
|
2011
|
-
" end\n"
|
2012
|
-
" end\n"
|
2013
|
-
" end\n"
|
2014
|
-
" return queue_lock\n"
|
2015
|
-
"end\n"
|
2016
1955
|
"local process_key_with_cap = function(message, cap)\n"
|
2017
1956
|
" local index = directory[key]\n"
|
2018
|
-
" local
|
1957
|
+
" local result_recorded = false\n"
|
2019
1958
|
" if index then\n"
|
2020
1959
|
" local count = 0\n"
|
2021
1960
|
" if not message then\n"
|
@@ -2032,6 +1971,7 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
2032
1971
|
" end\n"
|
2033
1972
|
" end\n"
|
2034
1973
|
" if (count > 0) then\n"
|
1974
|
+
" result_recorded = true\n"
|
2035
1975
|
" for i = #results, 1, -1 do\n"
|
2036
1976
|
" redis.call(\"lpush\", results_key, results[i])\n"
|
2037
1977
|
" end\n"
|
@@ -2041,23 +1981,25 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
2041
1981
|
" if new_count > 0 then\n"
|
2042
1982
|
" for i = 1, new_count, 1 do\n"
|
2043
1983
|
" redis.call(\"rpush\", actions_key .. \"!\" .. sid, results_key)\n"
|
2044
|
-
" redis.call(\"rpush\", actions_key .. \"!\" .. sid, cap)\n"
|
1984
|
+
" redis.call(\"rpush\", actions_key .. \"!\" .. sid, \"$c\" .. cap)\n"
|
2045
1985
|
" end\n"
|
2046
1986
|
" end\n"
|
2047
1987
|
" if new_remain > 0 then\n"
|
2048
1988
|
" redis.call(\"rpush\", actions_key .. \"!\" .. sid, results_key)\n"
|
2049
|
-
" redis.call(\"rpush\", actions_key .. \"!\" .. sid, new_remain)\n"
|
1989
|
+
" redis.call(\"rpush\", actions_key .. \"!\" .. sid, \"$c\" .. new_remain)\n"
|
2050
1990
|
" end\n"
|
2051
|
-
" if
|
2052
|
-
"
|
1991
|
+
" if new_remain > 0 or new_count > 0 then\n"
|
1992
|
+
" if not redis.call(\"zscore\", actions_key, sid) then\n"
|
1993
|
+
" redis.call(\"zadd\", actions_key , score, sid)\n"
|
1994
|
+
" end\n"
|
2053
1995
|
" end\n"
|
2054
1996
|
" end\n"
|
2055
1997
|
" end\n"
|
2056
|
-
" return
|
1998
|
+
" return result_recorded\n"
|
2057
1999
|
"end\n"
|
2058
2000
|
"local process_key_with_window = function(message, window)\n"
|
2059
2001
|
" local index = directory[key]\n"
|
2060
|
-
" local
|
2002
|
+
" local result_recorded = false\n"
|
2061
2003
|
" if index then\n"
|
2062
2004
|
" local count = 0\n"
|
2063
2005
|
" if not message then\n"
|
@@ -2074,6 +2016,7 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
2074
2016
|
" end\n"
|
2075
2017
|
" end\n"
|
2076
2018
|
" if (count > 0) then\n"
|
2019
|
+
" result_recorded = true\n"
|
2077
2020
|
" for i = #results, 1, -1 do\n"
|
2078
2021
|
" redis.call(\"lpush\", results_key, results[i])\n"
|
2079
2022
|
" end\n"
|
@@ -2085,17 +2028,15 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
2085
2028
|
" if diff > 0 then\n"
|
2086
2029
|
" for i = 0, diff - 1, 1 do\n"
|
2087
2030
|
" redis.call(\"rpush\", actions_key .. \"!\" .. sid, results_key)\n"
|
2088
|
-
"
|
2089
|
-
"
|
2090
|
-
"
|
2091
|
-
"
|
2092
|
-
" end\n"
|
2031
|
+
" redis.call(\"rpush\", actions_key .. \"!\" .. sid, \"$w\" .. window)\n"
|
2032
|
+
" end\n"
|
2033
|
+
" if not redis.call(\"zscore\", actions_key, sid) then\n"
|
2034
|
+
" redis.call(\"zadd\", actions_key , score, sid)\n"
|
2093
2035
|
" end\n"
|
2094
|
-
" queue_lock = true\n"
|
2095
2036
|
" end\n"
|
2096
2037
|
" end\n"
|
2097
2038
|
" end\n"
|
2098
|
-
" return
|
2039
|
+
" return result_recorded\n"
|
2099
2040
|
"end\n"
|
2100
2041
|
"local process_message = function(message)\n"
|
2101
2042
|
" for index = 6, 5 + keys_count, 1 do\n"
|
@@ -2116,20 +2057,12 @@ static unsigned int loadEvalMessageCommand(ruleset *tree, binding *rulesBinding)
|
|
2116
2057
|
" expressions_count = context[\"expressions_count\"]\n"
|
2117
2058
|
" local process_key = context[\"process_key\"]\n"
|
2118
2059
|
" local process_key_count = context[\"process_key_count\"]\n"
|
2119
|
-
"
|
2120
|
-
" if assert_fact == 0 and
|
2121
|
-
"
|
2060
|
+
" local result_recorded = process_key(message, process_key_count)\n"
|
2061
|
+
" if assert_fact == 0 and result_recorded then\n"
|
2062
|
+
" return false\n"
|
2122
2063
|
" end\n"
|
2123
2064
|
" end\n"
|
2124
2065
|
" end\n"
|
2125
|
-
" if queue_action then\n"
|
2126
|
-
" if not redis.call(\"zscore\", actions_key, sid) then\n"
|
2127
|
-
" redis.call(\"zadd\", actions_key , score, sid)\n"
|
2128
|
-
" end\n"
|
2129
|
-
" if assert_fact == 0 then\n"
|
2130
|
-
" return false\n"
|
2131
|
-
" end\n"
|
2132
|
-
" end\n"
|
2133
2066
|
" return true\n"
|
2134
2067
|
"end\n"
|
2135
2068
|
"local message = nil\n"
|
@@ -2265,6 +2198,11 @@ static unsigned int loadCommands(ruleset *tree, binding *rulesBinding) {
|
|
2265
2198
|
return result;
|
2266
2199
|
}
|
2267
2200
|
|
2201
|
+
result = loadRemoveTimerCommand(tree, rulesBinding);
|
2202
|
+
if (result != RULES_OK) {
|
2203
|
+
return result;
|
2204
|
+
}
|
2205
|
+
|
2268
2206
|
result = loadEvalMessageCommand(tree, rulesBinding);
|
2269
2207
|
if (result != RULES_OK) {
|
2270
2208
|
return result;
|
@@ -2949,28 +2887,37 @@ unsigned int peekTimers(ruleset *tree, void **bindingContext, redisReply **reply
|
|
2949
2887
|
return ERR_NO_TIMERS_AVAILABLE;
|
2950
2888
|
}
|
2951
2889
|
|
2952
|
-
unsigned int registerTimer(void *rulesBinding, unsigned int duration, char *timer) {
|
2890
|
+
unsigned int registerTimer(void *rulesBinding, unsigned int duration, char assert, char *timer) {
|
2953
2891
|
binding *currentBinding = (binding*)rulesBinding;
|
2954
2892
|
redisContext *reContext = currentBinding->reContext;
|
2955
2893
|
time_t currentTime = time(NULL);
|
2956
2894
|
|
2957
|
-
int result =
|
2895
|
+
int result = RULES_OK;
|
2896
|
+
if (assert) {
|
2897
|
+
result = redisAppendCommand(reContext,
|
2898
|
+
"zadd %s %ld a:%s",
|
2899
|
+
currentBinding->timersSortedset,
|
2900
|
+
currentTime + duration,
|
2901
|
+
timer);
|
2902
|
+
} else {
|
2903
|
+
result = redisAppendCommand(reContext,
|
2958
2904
|
"zadd %s %ld p:%s",
|
2959
2905
|
currentBinding->timersSortedset,
|
2960
2906
|
currentTime + duration,
|
2961
2907
|
timer);
|
2908
|
+
}
|
2909
|
+
|
2962
2910
|
VERIFY(result, "registerTimer");
|
2963
2911
|
return RULES_OK;
|
2964
2912
|
}
|
2965
2913
|
|
2966
|
-
unsigned int removeTimer(void *rulesBinding, char *
|
2914
|
+
unsigned int removeTimer(void *rulesBinding, char *timerName) {
|
2967
2915
|
binding *currentBinding = (binding*)rulesBinding;
|
2968
2916
|
redisContext *reContext = currentBinding->reContext;
|
2969
|
-
|
2970
2917
|
int result = redisAppendCommand(reContext,
|
2971
|
-
"
|
2972
|
-
currentBinding->
|
2973
|
-
|
2918
|
+
"evalsha %s 0 %s",
|
2919
|
+
currentBinding->removeTimerHash,
|
2920
|
+
timerName);
|
2974
2921
|
VERIFY(result, "removeTimer");
|
2975
2922
|
return RULES_OK;
|
2976
2923
|
}
|
@@ -2980,7 +2927,7 @@ unsigned int registerMessage(void *rulesBinding, unsigned int queueAction, char
|
|
2980
2927
|
redisContext *reContext = currentBinding->reContext;
|
2981
2928
|
time_t currentTime = time(NULL);
|
2982
2929
|
|
2983
|
-
int result =
|
2930
|
+
int result = RULES_OK;
|
2984
2931
|
|
2985
2932
|
switch (queueAction) {
|
2986
2933
|
case QUEUE_ASSERT_FACT:
|
data/src/rules/net.h
CHANGED
@@ -30,6 +30,7 @@ typedef struct binding {
|
|
30
30
|
functionHash removeActionHash;
|
31
31
|
functionHash partitionHash;
|
32
32
|
functionHash timersHash;
|
33
|
+
functionHash removeTimerHash;
|
33
34
|
functionHash updateActionHash;
|
34
35
|
functionHash deleteSessionHash;
|
35
36
|
char *sessionHashset;
|
@@ -132,10 +133,11 @@ unsigned int peekTimers(ruleset *tree,
|
|
132
133
|
|
133
134
|
unsigned int registerTimer(void *rulesBinding,
|
134
135
|
unsigned int duration,
|
136
|
+
char assert,
|
135
137
|
char *timer);
|
136
138
|
|
137
139
|
unsigned int removeTimer(void *rulesBinding,
|
138
|
-
char *
|
140
|
+
char *timerName);
|
139
141
|
|
140
142
|
unsigned int registerMessage(void *rulesBinding,
|
141
143
|
unsigned int queueAction,
|
data/src/rules/regex.c
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
#include <stdio.h>
|
3
3
|
#include <stdlib.h>
|
4
4
|
#include <string.h>
|
5
|
+
#include <ctype.h>
|
5
6
|
#include "rules.h"
|
6
7
|
#include "rete.h"
|
7
8
|
#include "regex.h"
|
@@ -899,6 +900,7 @@ static unsigned int ensureState(unsigned short *id,
|
|
899
900
|
unsigned short stateListLength,
|
900
901
|
state **newState) {
|
901
902
|
CREATE_STATE(id, newState);
|
903
|
+
unsigned short dotTransitions = 0;
|
902
904
|
for (unsigned short i = 0; i < stateListLength; ++i) {
|
903
905
|
state *targetState = list[i];
|
904
906
|
for (unsigned short ii = 0; ii < targetState->transitionsLength; ++ii) {
|
@@ -907,6 +909,10 @@ static unsigned int ensureState(unsigned short *id,
|
|
907
909
|
if (result != RULES_OK) {
|
908
910
|
return result;
|
909
911
|
}
|
912
|
+
|
913
|
+
if (targetTransition->symbol == REGEX_DOT) {
|
914
|
+
++dotTransitions;
|
915
|
+
}
|
910
916
|
}
|
911
917
|
|
912
918
|
if (targetState->isAccept) {
|
@@ -921,6 +927,19 @@ static unsigned int ensureState(unsigned short *id,
|
|
921
927
|
return ERR_REGEX_CONFLICT;
|
922
928
|
}
|
923
929
|
}
|
930
|
+
|
931
|
+
// when merging two states results in two or more dot transitions
|
932
|
+
// all specific transitions are cancelled, this allows for the
|
933
|
+
// first match to succeed.
|
934
|
+
if (dotTransitions > 1) {
|
935
|
+
for (unsigned short i = 0; i < (*newState)->transitionsLength; ++i) {
|
936
|
+
transition *currentTransition = &(*newState)->transitions[i];
|
937
|
+
if (currentTransition->symbol != REGEX_DOT) {
|
938
|
+
unlinkStates(*newState, currentTransition->next, currentTransition->symbol);
|
939
|
+
}
|
940
|
+
}
|
941
|
+
}
|
942
|
+
|
924
943
|
return RULES_OK;
|
925
944
|
}
|
926
945
|
|
@@ -1130,7 +1149,7 @@ static unsigned int transformToDFA(state *nfa,
|
|
1130
1149
|
}
|
1131
1150
|
|
1132
1151
|
static unsigned int expandDot(state *nfa,
|
1133
|
-
|
1152
|
+
unsigned short *id) {
|
1134
1153
|
|
1135
1154
|
CREATE_HASHSET(state*);
|
1136
1155
|
CREATE_QUEUE(state*);
|
@@ -1216,7 +1235,8 @@ static unsigned short getIndex(symbolEntry *symbolHashSet, unsigned short vocabu
|
|
1216
1235
|
static unsigned int packGraph(state *start,
|
1217
1236
|
void *stateMachine,
|
1218
1237
|
unsigned short vocabularyLength,
|
1219
|
-
unsigned short statesLength
|
1238
|
+
unsigned short statesLength,
|
1239
|
+
char caseInsensitive) {
|
1220
1240
|
CREATE_QUEUE(state*);
|
1221
1241
|
unsigned short visited[MAX_STATES] = {0};
|
1222
1242
|
symbolEntry *symbolHashSet = (symbolEntry *)stateMachine;
|
@@ -1235,9 +1255,13 @@ static unsigned int packGraph(state *start,
|
|
1235
1255
|
|
1236
1256
|
for (int i = 0; i < currentState->transitionsLength; ++ i) {
|
1237
1257
|
transition *currentTransition = ¤tState->transitions[i];
|
1258
|
+
unsigned int currentTransitionSymbol = currentTransition->symbol;
|
1259
|
+
if (caseInsensitive) {
|
1260
|
+
currentTransitionSymbol = tolower(currentTransitionSymbol);
|
1261
|
+
}
|
1238
1262
|
|
1239
|
-
if (!getIndex(symbolHashSet, vocabularyLength,
|
1240
|
-
setIndex(symbolHashSet, vocabularyLength,
|
1263
|
+
if (!getIndex(symbolHashSet, vocabularyLength, currentTransitionSymbol)) {
|
1264
|
+
setIndex(symbolHashSet, vocabularyLength, currentTransitionSymbol, vocabularyNumber);
|
1241
1265
|
++vocabularyNumber;
|
1242
1266
|
}
|
1243
1267
|
|
@@ -1247,7 +1271,7 @@ static unsigned int packGraph(state *start,
|
|
1247
1271
|
ENQUEUE(currentTransition->next);
|
1248
1272
|
}
|
1249
1273
|
|
1250
|
-
unsigned short targetSymbolNumber = getIndex(symbolHashSet, vocabularyLength,
|
1274
|
+
unsigned short targetSymbolNumber = getIndex(symbolHashSet, vocabularyLength, currentTransitionSymbol);
|
1251
1275
|
stateTable[statesLength * (targetSymbolNumber - 1) + (targetStateNumber - 1)] = visited[currentTransition->next->id];
|
1252
1276
|
}
|
1253
1277
|
|
@@ -1265,6 +1289,7 @@ unsigned int validateRegex(char *first,
|
|
1265
1289
|
unsigned int compileRegex(void *tree,
|
1266
1290
|
char *first,
|
1267
1291
|
char *last,
|
1292
|
+
char caseInsensitive,
|
1268
1293
|
unsigned short *vocabularyLength,
|
1269
1294
|
unsigned short *statesLength,
|
1270
1295
|
unsigned int *regexStateMachineOffset) {
|
@@ -1288,11 +1313,21 @@ unsigned int compileRegex(void *tree,
|
|
1288
1313
|
return result;
|
1289
1314
|
}
|
1290
1315
|
|
1316
|
+
#ifdef _PRINT
|
1317
|
+
printf("*** DFA 1 ***\n");
|
1318
|
+
printGraph(start);
|
1319
|
+
#endif
|
1320
|
+
|
1291
1321
|
result = expandDot(start, &id);
|
1292
1322
|
if (result != RULES_OK) {
|
1293
1323
|
return result;
|
1294
1324
|
}
|
1295
1325
|
|
1326
|
+
#ifdef _PRINT
|
1327
|
+
printf("*** DOT 1 ***\n");
|
1328
|
+
printGraph(start);
|
1329
|
+
#endif
|
1330
|
+
|
1296
1331
|
result = transformToDFA(start, &id);
|
1297
1332
|
if (result != RULES_OK) {
|
1298
1333
|
return result;
|
@@ -1321,12 +1356,14 @@ unsigned int compileRegex(void *tree,
|
|
1321
1356
|
return packGraph(start,
|
1322
1357
|
newStateMachine,
|
1323
1358
|
*vocabularyLength,
|
1324
|
-
*statesLength
|
1359
|
+
*statesLength,
|
1360
|
+
caseInsensitive);
|
1325
1361
|
}
|
1326
1362
|
|
1327
1363
|
unsigned char evaluateRegex(void *tree,
|
1328
1364
|
char *first,
|
1329
1365
|
unsigned short length,
|
1366
|
+
char caseInsensitive,
|
1330
1367
|
unsigned short vocabularyLength,
|
1331
1368
|
unsigned short statesLength,
|
1332
1369
|
unsigned int regexStateMachineOffset) {
|
@@ -1340,6 +1377,10 @@ unsigned char evaluateRegex(void *tree,
|
|
1340
1377
|
if (utf8ToUnicode(&first, last, &unicodeSymbol) != REGEX_PARSE_OK) {
|
1341
1378
|
return 0;
|
1342
1379
|
} else {
|
1380
|
+
if (caseInsensitive) {
|
1381
|
+
unicodeSymbol = tolower(unicodeSymbol);
|
1382
|
+
}
|
1383
|
+
|
1343
1384
|
unsigned short currentSymbol = getIndex(symbolHashSet, vocabularyLength, unicodeSymbol);
|
1344
1385
|
if (!currentSymbol) {
|
1345
1386
|
currentSymbol = getIndex(symbolHashSet, vocabularyLength, REGEX_DOT);
|
data/src/rules/regex.h
CHANGED
@@ -8,13 +8,15 @@ unsigned int validateRegex(char *first,
|
|
8
8
|
unsigned int compileRegex(void *tree,
|
9
9
|
char *first,
|
10
10
|
char *last,
|
11
|
+
char caseInsensitive,
|
11
12
|
unsigned short *vocabularyLength,
|
12
13
|
unsigned short *statesLength,
|
13
14
|
unsigned int *regexStateMachineOffset);
|
14
15
|
|
15
16
|
unsigned char evaluateRegex(void *tree,
|
16
17
|
char *first,
|
17
|
-
unsigned short length,
|
18
|
+
unsigned short length,
|
19
|
+
char caseInsensitive,
|
18
20
|
unsigned short vocabularyLength,
|
19
21
|
unsigned short statesLength,
|
20
22
|
unsigned int regexStateMachineOffset);
|
data/src/rules/rete.c
CHANGED
@@ -22,6 +22,7 @@
|
|
22
22
|
#define HASH_EQ 193419647 // $eq
|
23
23
|
#define HASH_NEQ 2087890573 // $neq
|
24
24
|
#define HASH_MT 193419914 // $mt
|
25
|
+
#define HASH_IMT 2087885395 // $imt
|
25
26
|
#define HASH_EX 193419654 // $ex
|
26
27
|
#define HASH_NEX 2087890580 // $nex
|
27
28
|
#define HASH_OR 193419978 // $or
|
@@ -339,6 +340,7 @@ static unsigned int copyValue(ruleset *tree,
|
|
339
340
|
right->value.b = leftb;
|
340
341
|
break;
|
341
342
|
case JSON_REGEX:
|
343
|
+
case JSON_IREGEX:
|
342
344
|
leftLength = last - first;
|
343
345
|
result = storeString(tree, first, &right->value.regex.stringOffset, leftLength);
|
344
346
|
if (result != RULES_OK) {
|
@@ -348,6 +350,7 @@ static unsigned int copyValue(ruleset *tree,
|
|
348
350
|
result = compileRegex(tree,
|
349
351
|
first,
|
350
352
|
last,
|
353
|
+
(type == JSON_REGEX) ? 0 : 1,
|
351
354
|
&right->value.regex.vocabularyLength,
|
352
355
|
&right->value.regex.statesLength,
|
353
356
|
&right->value.regex.stateMachineOffset);
|
@@ -385,7 +388,7 @@ static unsigned char compareValue(ruleset *tree,
|
|
385
388
|
case JSON_STRING:
|
386
389
|
{
|
387
390
|
char *rightString;
|
388
|
-
if (right->type == JSON_REGEX) {
|
391
|
+
if (right->type == JSON_REGEX || right->type == JSON_IREGEX) {
|
389
392
|
rightString = &tree->stringPool[right->value.regex.stringOffset];
|
390
393
|
} else {
|
391
394
|
rightString = &tree->stringPool[right->value.stringOffset];
|
@@ -590,6 +593,9 @@ static unsigned int validateExpression(char *rule) {
|
|
590
593
|
case HASH_MT:
|
591
594
|
operator = OP_MT;
|
592
595
|
break;
|
596
|
+
case HASH_IMT:
|
597
|
+
operator = OP_IMT;
|
598
|
+
break;
|
593
599
|
case HASH_LT:
|
594
600
|
operator = OP_LT;
|
595
601
|
break;
|
@@ -640,7 +646,7 @@ static unsigned int validateExpression(char *rule) {
|
|
640
646
|
return result;
|
641
647
|
}
|
642
648
|
|
643
|
-
if (operator == OP_MT) {
|
649
|
+
if (operator == OP_MT || operator == OP_IMT) {
|
644
650
|
if (type != JSON_STRING) {
|
645
651
|
return ERR_UNEXPECTED_TYPE;
|
646
652
|
}
|
@@ -1069,6 +1075,10 @@ static unsigned int findAlpha(ruleset *tree,
|
|
1069
1075
|
type = JSON_REGEX;
|
1070
1076
|
}
|
1071
1077
|
|
1078
|
+
if (operator == OP_IMT) {
|
1079
|
+
type = JSON_IREGEX;
|
1080
|
+
}
|
1081
|
+
|
1072
1082
|
result = copyValue(tree, &newAlpha->value.a.right, first, last, idiomOffset, &ref, type);
|
1073
1083
|
if (result != RULES_OK) {
|
1074
1084
|
return result;
|
@@ -1155,6 +1165,9 @@ static unsigned int createAlpha(ruleset *tree,
|
|
1155
1165
|
case HASH_MT:
|
1156
1166
|
operator = OP_MT;
|
1157
1167
|
break;
|
1168
|
+
case HASH_IMT:
|
1169
|
+
operator = OP_IMT;
|
1170
|
+
break;
|
1158
1171
|
case HASH_LT:
|
1159
1172
|
operator = OP_LT;
|
1160
1173
|
break;
|
data/src/rules/rete.h
CHANGED
data/src/rules/rules.h
CHANGED
@@ -164,11 +164,12 @@ unsigned int abandonAction(void *handle,
|
|
164
164
|
unsigned int startTimer(void *handle,
|
165
165
|
char *sid,
|
166
166
|
unsigned int duration,
|
167
|
+
char manualReset,
|
167
168
|
char *timer);
|
168
169
|
|
169
170
|
unsigned int cancelTimer(void *handle,
|
170
171
|
char *sid,
|
171
|
-
char *
|
172
|
+
char *timerName);
|
172
173
|
|
173
174
|
unsigned int queueMessage(void *handle,
|
174
175
|
unsigned int queueAction,
|
data/src/rulesrb/rules.c
CHANGED
@@ -544,13 +544,14 @@ static VALUE rbAbandonAction(VALUE self, VALUE handle, VALUE actionHandle) {
|
|
544
544
|
return Qnil;
|
545
545
|
}
|
546
546
|
|
547
|
-
static VALUE rbStartTimer(VALUE self, VALUE handle, VALUE sid, VALUE duration, VALUE timer) {
|
547
|
+
static VALUE rbStartTimer(VALUE self, VALUE handle, VALUE sid, VALUE duration, VALUE manualReset, VALUE timer) {
|
548
548
|
Check_Type(handle, T_FIXNUM);
|
549
549
|
Check_Type(sid, T_STRING);
|
550
550
|
Check_Type(duration, T_FIXNUM);
|
551
|
+
Check_Type(manualReset, T_FIXNUM);
|
551
552
|
Check_Type(timer, T_STRING);
|
552
553
|
|
553
|
-
unsigned int result = startTimer((void *)FIX2LONG(handle), RSTRING_PTR(sid), FIX2UINT(duration), RSTRING_PTR(timer));
|
554
|
+
unsigned int result = startTimer((void *)FIX2LONG(handle), RSTRING_PTR(sid), FIX2UINT(duration), FIX2SHORT(manualReset), RSTRING_PTR(timer));
|
554
555
|
if (result != RULES_OK) {
|
555
556
|
if (result == ERR_OUT_OF_MEMORY) {
|
556
557
|
rb_raise(rb_eNoMemError, "Out of memory");
|
@@ -562,12 +563,12 @@ static VALUE rbStartTimer(VALUE self, VALUE handle, VALUE sid, VALUE duration, V
|
|
562
563
|
return Qnil;
|
563
564
|
}
|
564
565
|
|
565
|
-
static VALUE rbCancelTimer(VALUE self, VALUE handle, VALUE sid, VALUE
|
566
|
+
static VALUE rbCancelTimer(VALUE self, VALUE handle, VALUE sid, VALUE timerName) {
|
566
567
|
Check_Type(handle, T_FIXNUM);
|
567
568
|
Check_Type(sid, T_STRING);
|
568
|
-
Check_Type(
|
569
|
+
Check_Type(timerName, T_STRING);
|
569
570
|
|
570
|
-
unsigned int result = cancelTimer((void *)FIX2LONG(handle), RSTRING_PTR(sid), RSTRING_PTR(
|
571
|
+
unsigned int result = cancelTimer((void *)FIX2LONG(handle), RSTRING_PTR(sid), RSTRING_PTR(timerName));
|
571
572
|
if (result != RULES_OK) {
|
572
573
|
if (result == ERR_OUT_OF_MEMORY) {
|
573
574
|
rb_raise(rb_eNoMemError, "Out of memory");
|
@@ -679,7 +680,7 @@ void Init_rules() {
|
|
679
680
|
rb_define_singleton_method(rulesModule, "complete_action", rbCompleteAction, 3);
|
680
681
|
rb_define_singleton_method(rulesModule, "complete_and_start_action", rbCompleteAndStartAction, 3);
|
681
682
|
rb_define_singleton_method(rulesModule, "abandon_action", rbAbandonAction, 2);
|
682
|
-
rb_define_singleton_method(rulesModule, "start_timer", rbStartTimer,
|
683
|
+
rb_define_singleton_method(rulesModule, "start_timer", rbStartTimer, 5);
|
683
684
|
rb_define_singleton_method(rulesModule, "cancel_timer", rbCancelTimer, 3);
|
684
685
|
rb_define_singleton_method(rulesModule, "assert_timers", rbAssertTimers, 1);
|
685
686
|
rb_define_singleton_method(rulesModule, "get_state", rbGetState, 2);
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: durable_rules
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.34.
|
4
|
+
version: 0.34.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jesus Ruiz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|