durable_rules 0.34.27 → 0.34.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|