durable_rules 0.34.01 → 0.34.02
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 +14 -9
- data/librb/engine.rb +99 -27
- data/src/rules/events.c +17 -4
- data/src/rules/net.c +263 -176
- data/src/rules/net.h +1 -0
- data/src/rules/rete.c +57 -0
- data/src/rules/rules.h +12 -1
- data/src/rulesrb/rules.c +76 -4
- 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: d6180a0278ca667dd708b04c45359d7d205bb5ee
|
4
|
+
data.tar.gz: 77f98579d75d5a6ede0cf04de0cb030eb75227cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83a19d52b25b82a7369a679d5223b8e3dc2eb848b0c3a9cc4a75882f327f55434fc7a822bc9f2f91387977f8372daebbb19303cc6223516b67011229aebb172a
|
7
|
+
data.tar.gz: 0ec42e6ec72b8e569f632bcdb487787eb9692401c556071393ed2b62cccc46d4064f89d76b72f36c9567c2413eeb796fa03ecfc1cf9506493a5224c20d75bd09
|
data/librb/durable.rb
CHANGED
@@ -5,22 +5,27 @@ module Durable
|
|
5
5
|
@@rulesets = {}
|
6
6
|
@@start_blocks = []
|
7
7
|
|
8
|
-
def self.
|
9
|
-
|
10
|
-
start.call main_host if start
|
11
|
-
main_host.start!
|
12
|
-
Interface::Application.set_host main_host
|
13
|
-
Interface::Application.run!
|
8
|
+
def self.create_queue(ruleset_name, database = {:host => 'localhost', :port => 6379, :password => nil}, state_cache_size = 1024)
|
9
|
+
Engine::Queue.new ruleset_name, database, state_cache_size
|
14
10
|
end
|
15
11
|
|
16
|
-
def self.
|
17
|
-
main_host = Engine::Host.new @@rulesets, databases
|
12
|
+
def self.create_host(databases = [{:host => 'localhost', :port => 6379, :password => nil}], state_cache_size = 1024)
|
13
|
+
main_host = Engine::Host.new @@rulesets, databases, state_cache_size
|
18
14
|
for block in @@start_blocks
|
19
15
|
main_host.instance_exec main_host, &block
|
20
16
|
end
|
21
17
|
main_host.start!
|
18
|
+
main_host
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.run_all(databases = [{:host => 'localhost', :port => 6379, :password => nil}], host_name = nil, port = nil, run = nil, state_cache_size = 1024)
|
22
|
+
main_host = self.create_host databases, state_cache_size
|
22
23
|
Interface::Application.set_host main_host
|
23
|
-
|
24
|
+
if run
|
25
|
+
run(main_host, Interface::Application)
|
26
|
+
else
|
27
|
+
Interface::Application.run!
|
28
|
+
end
|
24
29
|
end
|
25
30
|
|
26
31
|
def self.ruleset(name, &block)
|
data/librb/engine.rb
CHANGED
@@ -4,8 +4,43 @@ require_relative "../src/rulesrb/rules"
|
|
4
4
|
|
5
5
|
module Engine
|
6
6
|
@@timers = nil
|
7
|
+
|
8
|
+
class Closure_Queue
|
9
|
+
attr_reader :_queued_posts, :_queued_asserts, :_queued_retracts
|
10
|
+
|
11
|
+
def initialize()
|
12
|
+
@_queued_posts = []
|
13
|
+
@_queued_asserts = []
|
14
|
+
@_queued_retracts = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def post(message)
|
18
|
+
if message.kind_of? Content
|
19
|
+
message = message._d
|
20
|
+
end
|
21
|
+
|
22
|
+
@_queued_posts << message
|
23
|
+
end
|
24
|
+
|
25
|
+
def assert(message)
|
26
|
+
if message.kind_of? Content
|
27
|
+
message = message._d
|
28
|
+
end
|
29
|
+
|
30
|
+
@_queued_asserts << message
|
31
|
+
end
|
32
|
+
|
33
|
+
def retract(message)
|
34
|
+
if message.kind_of? Content
|
35
|
+
message = message._d
|
36
|
+
end
|
37
|
+
|
38
|
+
@_queued_retracts << message
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
7
42
|
class Closure
|
8
|
-
attr_reader :host, :handle, :ruleset_name, :_timers, :_cancelled_timers, :_branches, :_messages, :
|
43
|
+
attr_reader :host, :handle, :ruleset_name, :_timers, :_cancelled_timers, :_branches, :_messages, :_queues, :_facts, :_retract
|
9
44
|
attr_accessor :s
|
10
45
|
|
11
46
|
def initialize(host, state, message, handle, ruleset_name)
|
@@ -16,7 +51,7 @@ module Engine
|
|
16
51
|
@_timers = {}
|
17
52
|
@_cancelled_timers = {}
|
18
53
|
@_messages = {}
|
19
|
-
@
|
54
|
+
@_queues = {}
|
20
55
|
@_branches = {}
|
21
56
|
@_facts = {}
|
22
57
|
@_retract = {}
|
@@ -58,22 +93,12 @@ module Engine
|
|
58
93
|
message_list << message
|
59
94
|
end
|
60
95
|
|
61
|
-
def
|
62
|
-
if
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
if !(message.key? :sid) && !(message.key? "sid")
|
67
|
-
message[:sid] = @s.sid
|
96
|
+
def get_queue(ruleset_name)
|
97
|
+
if !@_queues.key? ruleset_name
|
98
|
+
@_queues[ruleset_name] = Closure_Queue.new
|
68
99
|
end
|
69
100
|
|
70
|
-
|
71
|
-
if @_queued_messages.key? ruleset_name
|
72
|
-
message_list = @_queued_messages[ruleset_name]
|
73
|
-
else
|
74
|
-
@_queued_messages[ruleset_name] = message_list
|
75
|
-
end
|
76
|
-
message_list << message
|
101
|
+
@_queues[ruleset_name]
|
77
102
|
end
|
78
103
|
|
79
104
|
def start_timer(timer_name, duration, timer_id = nil)
|
@@ -151,7 +176,7 @@ module Engine
|
|
151
176
|
def renew_action_lease()
|
152
177
|
if Time.now - @_start_time < 10000
|
153
178
|
@_start_time = Time.now
|
154
|
-
@host.renew_action_lease
|
179
|
+
@host.renew_action_lease @ruleset_name, @s.sid
|
155
180
|
end
|
156
181
|
end
|
157
182
|
|
@@ -289,7 +314,7 @@ module Engine
|
|
289
314
|
c.s.exception = "timeout expired"
|
290
315
|
complete.call nil
|
291
316
|
else
|
292
|
-
c.renew_action_lease
|
317
|
+
c.renew_action_lease
|
293
318
|
end
|
294
319
|
}
|
295
320
|
Thread.new do
|
@@ -382,8 +407,8 @@ module Engine
|
|
382
407
|
Rules.assert_event @handle, JSON.generate(message)
|
383
408
|
end
|
384
409
|
|
385
|
-
def
|
386
|
-
Rules.
|
410
|
+
def queue_assert_event(sid, ruleset_name, message)
|
411
|
+
Rules.queue_assert_event @handle, sid.to_s, ruleset_name.to_s, JSON.generate(message)
|
387
412
|
end
|
388
413
|
|
389
414
|
def start_assert_event(message)
|
@@ -410,6 +435,10 @@ module Engine
|
|
410
435
|
Rules.assert_fact @handle, JSON.generate(fact)
|
411
436
|
end
|
412
437
|
|
438
|
+
def queue_assert_fact(sid, ruleset_name, message)
|
439
|
+
Rules.queue_assert_fact @handle, sid.to_s, ruleset_name.to_s, JSON.generate(message)
|
440
|
+
end
|
441
|
+
|
413
442
|
def start_assert_fact(fact)
|
414
443
|
return Rules.start_assert_fact @handle, JSON.generate(fact)
|
415
444
|
end
|
@@ -426,6 +455,10 @@ module Engine
|
|
426
455
|
Rules.retract_fact @handle, JSON.generate(fact)
|
427
456
|
end
|
428
457
|
|
458
|
+
def queue_retract_fact(sid, ruleset_name, message)
|
459
|
+
Rules.queue_retract_fact @handle, sid.to_s, ruleset_name.to_s, JSON.generate(message)
|
460
|
+
end
|
461
|
+
|
429
462
|
def start_retract_fact(fact)
|
430
463
|
return Rules.start_retract_fact @handle, JSON.generate(fact)
|
431
464
|
end
|
@@ -538,9 +571,20 @@ module Engine
|
|
538
571
|
start_timer c.s.sid, timer_duration[0], timer_duration[1]
|
539
572
|
end
|
540
573
|
|
541
|
-
for ruleset_name,
|
542
|
-
for message in
|
543
|
-
|
574
|
+
for ruleset_name, q in c._queues do
|
575
|
+
for message in q._queued_posts do
|
576
|
+
sid = (message.key? :sid) ? message[:sid]: message['sid']
|
577
|
+
queue_assert_event sid.to_s, ruleset_name, message
|
578
|
+
end
|
579
|
+
|
580
|
+
for message in q._queued_asserts do
|
581
|
+
sid = (message.key? :sid) ? message[:sid]: message['sid']
|
582
|
+
queue_assert_fact sid.to_s, ruleset_name, message
|
583
|
+
end
|
584
|
+
|
585
|
+
for message in q._queued_retracts do
|
586
|
+
sid = (message.key? :sid) ? message[:sid]: message['sid']
|
587
|
+
queue_retract_fact sid.to_s, ruleset_name, message
|
544
588
|
end
|
545
589
|
end
|
546
590
|
|
@@ -1077,10 +1121,6 @@ module Engine
|
|
1077
1121
|
return get_ruleset(ruleset_name).start_retract_facts facts
|
1078
1122
|
end
|
1079
1123
|
|
1080
|
-
def start_timer(ruleset_name, sid, timer_name, timer_duration)
|
1081
|
-
get_ruleset(ruleset_name).start_timer sid, timer_name, timer_duration
|
1082
|
-
end
|
1083
|
-
|
1084
1124
|
def patch_state(ruleset_name, state)
|
1085
1125
|
get_ruleset(ruleset_name).assert_state state
|
1086
1126
|
end
|
@@ -1145,4 +1185,36 @@ module Engine
|
|
1145
1185
|
|
1146
1186
|
end
|
1147
1187
|
|
1188
|
+
class Queue
|
1189
|
+
|
1190
|
+
def initialize(ruleset_name, database = {:host => 'localhost', :port => 6379, :password => nil}, state_cache_size = 1024)
|
1191
|
+
@_ruleset_name = ruleset_name.to_s
|
1192
|
+
@handle = Rules.create_client @_ruleset_name, state_cache_size
|
1193
|
+
if database.kind_of? String
|
1194
|
+
Rules.bind_ruleset @handle, database, 0, nil
|
1195
|
+
else
|
1196
|
+
Rules.bind_ruleset @handle, database[:host], database[:port], database[:password]
|
1197
|
+
end
|
1198
|
+
end
|
1199
|
+
|
1200
|
+
def post(message)
|
1201
|
+
sid = (message.key? :sid) ? message[:sid]: message['sid']
|
1202
|
+
Rules.queue_assert_event @handle, sid.to_s, @_ruleset_name, JSON.generate(message)
|
1203
|
+
end
|
1204
|
+
|
1205
|
+
def assert(message)
|
1206
|
+
sid = (message.key? :sid) ? message[:sid]: message['sid']
|
1207
|
+
Rules.queue_assert_fact @handle, sid.to_s, @_ruleset_name, JSON.generate(message)
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
def retract(message)
|
1211
|
+
sid = (message.key? :sid) ? message[:sid]: message['sid']
|
1212
|
+
Rules.queue_retract_fact @handle, sid.to_s, @_ruleset_name, JSON.generate(message)
|
1213
|
+
end
|
1214
|
+
|
1215
|
+
def close()
|
1216
|
+
Rules.delete_client @handle
|
1217
|
+
end
|
1218
|
+
end
|
1219
|
+
|
1148
1220
|
end
|
data/src/rules/events.c
CHANGED
@@ -1436,12 +1436,25 @@ static unsigned int handleTimers(void *handle,
|
|
1436
1436
|
return result;
|
1437
1437
|
}
|
1438
1438
|
|
1439
|
+
unsigned int action;
|
1440
|
+
switch (reply->element[i]->str[0]) {
|
1441
|
+
case 'p':
|
1442
|
+
action = ACTION_ASSERT_EVENT;
|
1443
|
+
break;
|
1444
|
+
case 'a':
|
1445
|
+
action = ACTION_ASSERT_FACT;
|
1446
|
+
break;
|
1447
|
+
case 'r':
|
1448
|
+
action = ACTION_RETRACT_FACT;
|
1449
|
+
break;
|
1450
|
+
}
|
1451
|
+
|
1439
1452
|
commands[*commandCount] = command;
|
1440
1453
|
++*commandCount;
|
1441
1454
|
result = handleMessage(handle,
|
1442
1455
|
NULL,
|
1443
|
-
reply->element[i]->str,
|
1444
|
-
|
1456
|
+
reply->element[i]->str + 2,
|
1457
|
+
action,
|
1445
1458
|
commands,
|
1446
1459
|
commandCount,
|
1447
1460
|
rulesBinding);
|
@@ -1847,14 +1860,14 @@ unsigned int abandonAction(void *handle, void *actionHandle) {
|
|
1847
1860
|
return RULES_OK;
|
1848
1861
|
}
|
1849
1862
|
|
1850
|
-
unsigned int queueMessage(void *handle, char *sid, char *destination, char *message) {
|
1863
|
+
unsigned int queueMessage(void *handle, unsigned int queueAction, char *sid, char *destination, char *message) {
|
1851
1864
|
void *rulesBinding;
|
1852
1865
|
unsigned int result = resolveBinding(handle, sid, &rulesBinding);
|
1853
1866
|
if (result != RULES_OK) {
|
1854
1867
|
return result;
|
1855
1868
|
}
|
1856
1869
|
|
1857
|
-
return registerMessage(rulesBinding, destination, message);
|
1870
|
+
return registerMessage(rulesBinding, queueAction, destination, message);
|
1858
1871
|
}
|
1859
1872
|
|
1860
1873
|
unsigned int startTimer(void *handle, char *sid, unsigned int duration, char *timer) {
|
data/src/rules/net.c
CHANGED
@@ -1,12 +1,17 @@
|
|
1
1
|
#include <stdio.h>
|
2
2
|
#include <stdlib.h>
|
3
3
|
#include <string.h>
|
4
|
-
#include <time.h>
|
5
4
|
#include <errno.h>
|
5
|
+
#ifndef _WIN32
|
6
|
+
#include <time.h> /* for struct timeval */
|
7
|
+
#else
|
8
|
+
#include <WinSock2.h>
|
9
|
+
#endif
|
6
10
|
#include "net.h"
|
7
11
|
#include "rules.h"
|
8
12
|
#include "json.h"
|
9
13
|
|
14
|
+
|
10
15
|
#ifdef _WIN32
|
11
16
|
int asprintf(char** ret, char* format, ...){
|
12
17
|
va_list args;
|
@@ -299,11 +304,233 @@ static unsigned int createTest(ruleset *tree, expression *expr, char **test, cha
|
|
299
304
|
return RULES_OK;
|
300
305
|
}
|
301
306
|
|
302
|
-
static unsigned int
|
307
|
+
static unsigned int loadPartitionCommand(ruleset *tree, binding *rulesBinding, char *name) {
|
308
|
+
redisContext *reContext = rulesBinding->reContext;
|
309
|
+
redisReply *reply;
|
310
|
+
char *lua = NULL;
|
311
|
+
if (asprintf(&lua,
|
312
|
+
"local partition_key = \"%s!p\"\n"
|
313
|
+
"local res = redis.call(\"hget\", partition_key, ARGV[1])\n"
|
314
|
+
"if (not res) then\n"
|
315
|
+
" res = redis.call(\"hincrby\", partition_key, \"index\", 1)\n"
|
316
|
+
" res = res %% tonumber(ARGV[2])\n"
|
317
|
+
" redis.call(\"hset\", partition_key, ARGV[1], res)\n"
|
318
|
+
"end\n"
|
319
|
+
"return tonumber(res)\n", name) == -1) {
|
320
|
+
return ERR_OUT_OF_MEMORY;
|
321
|
+
}
|
322
|
+
|
323
|
+
redisAppendCommand(reContext, "SCRIPT LOAD %s", lua);
|
324
|
+
redisGetReply(reContext, (void**)&reply);
|
325
|
+
if (reply->type == REDIS_REPLY_ERROR) {
|
326
|
+
printf("%s\n", reply->str);
|
327
|
+
freeReplyObject(reply);
|
328
|
+
return ERR_REDIS_ERROR;
|
329
|
+
}
|
330
|
+
|
331
|
+
strncpy(rulesBinding->partitionHash, reply->str, 40);
|
332
|
+
rulesBinding->partitionHash[40] = '\0';
|
333
|
+
freeReplyObject(reply);
|
334
|
+
free(lua);
|
335
|
+
return RULES_OK;
|
336
|
+
}
|
337
|
+
|
338
|
+
static unsigned int loadRemoveActionCommand(ruleset *tree, binding *rulesBinding, char *name) {
|
339
|
+
redisContext *reContext = rulesBinding->reContext;
|
340
|
+
redisReply *reply;
|
341
|
+
char *lua = NULL;
|
342
|
+
if (asprintf(&lua,
|
343
|
+
"local delete_frame = function(key, action_key)\n"
|
344
|
+
" local rule_action_key = redis.call(\"lpop\", key)\n"
|
345
|
+
" local raw_count = redis.call(\"lpop\", key)\n"
|
346
|
+
" local count = 1\n"
|
347
|
+
" if raw_count ~= \"single\" then\n"
|
348
|
+
" count = tonumber(raw_count)\n"
|
349
|
+
" end\n"
|
350
|
+
" if count == 0 then\n"
|
351
|
+
" local packed_frame = redis.call(\"lpop\", rule_action_key)\n"
|
352
|
+
" while packed_frame ~= \"0\" do\n"
|
353
|
+
" packed_frame = redis.call(\"lpop\", rule_action_key)\n"
|
354
|
+
" end\n"
|
355
|
+
" else\n"
|
356
|
+
" for i = 0, count - 1, 1 do\n"
|
357
|
+
" local packed_frame = redis.call(\"rpop\", rule_action_key)\n"
|
358
|
+
" end\n"
|
359
|
+
" end\n"
|
360
|
+
" return (redis.call(\"llen\", key) > 0)\n"
|
361
|
+
"end\n"
|
362
|
+
"local sid = ARGV[1]\n"
|
363
|
+
"local max_score = tonumber(ARGV[2])\n"
|
364
|
+
"local action_key = \"%s!a\"\n"
|
365
|
+
"if delete_frame(action_key .. \"!\" .. sid, action_key) then\n"
|
366
|
+
" redis.call(\"zadd\", action_key , max_score, sid)\n"
|
367
|
+
"else\n"
|
368
|
+
" redis.call(\"zrem\", action_key, sid)\n"
|
369
|
+
"end\n", name) == -1) {
|
370
|
+
return ERR_OUT_OF_MEMORY;
|
371
|
+
}
|
372
|
+
|
373
|
+
redisAppendCommand(reContext, "SCRIPT LOAD %s", lua);
|
374
|
+
redisGetReply(reContext, (void**)&reply);
|
375
|
+
if (reply->type == REDIS_REPLY_ERROR) {
|
376
|
+
printf("%s\n", reply->str);
|
377
|
+
freeReplyObject(reply);
|
378
|
+
free(lua);
|
379
|
+
return ERR_REDIS_ERROR;
|
380
|
+
}
|
381
|
+
|
382
|
+
strncpy(rulesBinding->removeActionHash, reply->str, 40);
|
383
|
+
rulesBinding->removeActionHash[40] = '\0';
|
384
|
+
freeReplyObject(reply);
|
385
|
+
free(lua);
|
386
|
+
return RULES_OK;
|
387
|
+
}
|
388
|
+
|
389
|
+
static unsigned int loadTimerCommand(ruleset *tree, binding *rulesBinding, char *name) {
|
303
390
|
redisContext *reContext = rulesBinding->reContext;
|
304
391
|
redisReply *reply;
|
392
|
+
char *lua = NULL;
|
393
|
+
if (asprintf(&lua,
|
394
|
+
"local timer_key = \"%s!t\"\n"
|
395
|
+
"local timestamp = tonumber(ARGV[1])\n"
|
396
|
+
"local res = redis.call(\"zrangebyscore\", timer_key, 0, timestamp, \"limit\", 0, 10)\n"
|
397
|
+
"if #res > 0 then\n"
|
398
|
+
" for i = 0, #res, 1 do\n"
|
399
|
+
" redis.call(\"zincrby\", timer_key, 10, res[i])\n"
|
400
|
+
" end\n"
|
401
|
+
" return res\n"
|
402
|
+
"end\n"
|
403
|
+
"return 0\n", name) == -1) {
|
404
|
+
return ERR_OUT_OF_MEMORY;
|
405
|
+
}
|
406
|
+
|
407
|
+
redisAppendCommand(reContext, "SCRIPT LOAD %s", lua);
|
408
|
+
redisGetReply(reContext, (void**)&reply);
|
409
|
+
if (reply->type == REDIS_REPLY_ERROR) {
|
410
|
+
printf("%s\n", reply->str);
|
411
|
+
freeReplyObject(reply);
|
412
|
+
return ERR_REDIS_ERROR;
|
413
|
+
}
|
414
|
+
|
415
|
+
strncpy(rulesBinding->timersHash, reply->str, 40);
|
416
|
+
rulesBinding->timersHash[40] = '\0';
|
417
|
+
freeReplyObject(reply);
|
418
|
+
free(lua);
|
419
|
+
return RULES_OK;
|
420
|
+
}
|
421
|
+
|
422
|
+
static unsigned int loadUpdateActionCommand(ruleset *tree, binding *rulesBinding, char *name) {
|
423
|
+
redisContext *reContext = rulesBinding->reContext;
|
424
|
+
redisReply *reply;
|
425
|
+
char *lua = NULL;
|
426
|
+
if (asprintf(&lua,
|
427
|
+
"local actions_key = \"%s!a\"\n"
|
428
|
+
"local score = tonumber(ARGV[2])\n"
|
429
|
+
"local sid = ARGV[1]\n"
|
430
|
+
"if redis.call(\"zscore\", actions_key, sid) then\n"
|
431
|
+
" redis.call(\"zadd\", actions_key , score, sid)\n"
|
432
|
+
"end\n", name) == -1) {
|
433
|
+
return ERR_OUT_OF_MEMORY;
|
434
|
+
}
|
435
|
+
|
436
|
+
redisAppendCommand(reContext, "SCRIPT LOAD %s", lua);
|
437
|
+
redisGetReply(reContext, (void**)&reply);
|
438
|
+
if (reply->type == REDIS_REPLY_ERROR) {
|
439
|
+
printf("%s\n", reply->str);
|
440
|
+
freeReplyObject(reply);
|
441
|
+
return ERR_REDIS_ERROR;
|
442
|
+
}
|
443
|
+
|
444
|
+
strncpy(rulesBinding->updateActionHash, reply->str, 40);
|
445
|
+
rulesBinding->updateActionHash[40] = '\0';
|
446
|
+
freeReplyObject(reply);
|
447
|
+
free(lua);
|
448
|
+
return RULES_OK;
|
449
|
+
}
|
450
|
+
|
451
|
+
static unsigned int setNames(ruleset *tree, binding *rulesBinding, char *name) {
|
452
|
+
int nameLength = strlen(name);
|
453
|
+
char *sessionHashset = malloc((nameLength + 3) * sizeof(char));
|
454
|
+
if (!sessionHashset) {
|
455
|
+
return ERR_OUT_OF_MEMORY;
|
456
|
+
}
|
457
|
+
|
458
|
+
strncpy(sessionHashset, name, nameLength);
|
459
|
+
sessionHashset[nameLength] = '!';
|
460
|
+
sessionHashset[nameLength + 1] = 's';
|
461
|
+
sessionHashset[nameLength + 2] = '\0';
|
462
|
+
rulesBinding->sessionHashset = sessionHashset;
|
463
|
+
|
464
|
+
char *factsHashset = malloc((nameLength + 3) * sizeof(char));
|
465
|
+
if (!factsHashset) {
|
466
|
+
return ERR_OUT_OF_MEMORY;
|
467
|
+
}
|
468
|
+
|
469
|
+
strncpy(factsHashset, name, nameLength);
|
470
|
+
factsHashset[nameLength] = '!';
|
471
|
+
factsHashset[nameLength + 1] = 'f';
|
472
|
+
factsHashset[nameLength + 2] = '\0';
|
473
|
+
rulesBinding->factsHashset = factsHashset;
|
474
|
+
|
475
|
+
char *eventsHashset = malloc((nameLength + 3) * sizeof(char));
|
476
|
+
if (!eventsHashset) {
|
477
|
+
return ERR_OUT_OF_MEMORY;
|
478
|
+
}
|
479
|
+
|
480
|
+
strncpy(eventsHashset, name, nameLength);
|
481
|
+
eventsHashset[nameLength] = '!';
|
482
|
+
eventsHashset[nameLength + 1] = 'e';
|
483
|
+
eventsHashset[nameLength + 2] = '\0';
|
484
|
+
rulesBinding->eventsHashset = eventsHashset;
|
485
|
+
|
486
|
+
char *timersSortedset = malloc((nameLength + 3) * sizeof(char));
|
487
|
+
if (!timersSortedset) {
|
488
|
+
return ERR_OUT_OF_MEMORY;
|
489
|
+
}
|
490
|
+
|
491
|
+
strncpy(timersSortedset, name, nameLength);
|
492
|
+
timersSortedset[nameLength] = '!';
|
493
|
+
timersSortedset[nameLength + 1] = 't';
|
494
|
+
timersSortedset[nameLength + 2] = '\0';
|
495
|
+
rulesBinding->timersSortedset = timersSortedset;
|
496
|
+
return RULES_OK;
|
497
|
+
}
|
498
|
+
|
499
|
+
static unsigned int loadCommands(ruleset *tree, binding *rulesBinding) {
|
305
500
|
char *name = &tree->stringPool[tree->nameOffset];
|
306
501
|
int nameLength = strlen(name);
|
502
|
+
unsigned int result = loadPartitionCommand(tree, rulesBinding, name);
|
503
|
+
if (result != RULES_OK) {
|
504
|
+
return result;
|
505
|
+
}
|
506
|
+
|
507
|
+
// client queues have no commands to load,
|
508
|
+
if (!tree->stringPool) {
|
509
|
+
return RULES_OK;
|
510
|
+
}
|
511
|
+
|
512
|
+
result = loadRemoveActionCommand(tree, rulesBinding, name);
|
513
|
+
if (result != RULES_OK) {
|
514
|
+
return result;
|
515
|
+
}
|
516
|
+
|
517
|
+
result = loadTimerCommand(tree, rulesBinding, name);
|
518
|
+
if (result != RULES_OK) {
|
519
|
+
return result;
|
520
|
+
}
|
521
|
+
|
522
|
+
result = loadUpdateActionCommand(tree, rulesBinding, name);
|
523
|
+
if (result != RULES_OK) {
|
524
|
+
return result;
|
525
|
+
}
|
526
|
+
|
527
|
+
result = setNames(tree, rulesBinding, name);
|
528
|
+
if (result != RULES_OK) {
|
529
|
+
return result;
|
530
|
+
}
|
531
|
+
|
532
|
+
redisContext *reContext = rulesBinding->reContext;
|
533
|
+
redisReply *reply;
|
307
534
|
#ifdef _WIN32
|
308
535
|
char *actionKey = (char *)_alloca(sizeof(char)*(nameLength + 3));
|
309
536
|
sprintf_s(actionKey, nameLength + 3, "%s!a", name);
|
@@ -1444,7 +1671,7 @@ static unsigned int loadCommands(ruleset *tree, binding *rulesBinding) {
|
|
1444
1671
|
" for i = 1, #frame, 1 do\n"
|
1445
1672
|
" if type(frame[i]) == \"table\" then\n"
|
1446
1673
|
" redis.call(\"hsetnx\", events_hashset, frame[i][\"id\"], cmsgpack.pack(frame[i]))\n"
|
1447
|
-
" redis.call(\"zadd\", timers_key, max_score, cjson.encode(frame[i]))\n"
|
1674
|
+
" redis.call(\"zadd\", timers_key, max_score, \"p:\" .. cjson.encode(frame[i]))\n"
|
1448
1675
|
" end\n"
|
1449
1676
|
" end\n"
|
1450
1677
|
" full_frame = nil\n"
|
@@ -1661,170 +1888,6 @@ static unsigned int loadCommands(ruleset *tree, binding *rulesBinding) {
|
|
1661
1888
|
freeReplyObject(reply);
|
1662
1889
|
free(lua);
|
1663
1890
|
|
1664
|
-
if (asprintf(&lua,
|
1665
|
-
"local delete_frame = function(key, action_key)\n"
|
1666
|
-
" local rule_action_key = redis.call(\"lpop\", key)\n"
|
1667
|
-
" local raw_count = redis.call(\"lpop\", key)\n"
|
1668
|
-
" local count = 1\n"
|
1669
|
-
" if raw_count ~= \"single\" then\n"
|
1670
|
-
" count = tonumber(raw_count)\n"
|
1671
|
-
" end\n"
|
1672
|
-
" if count == 0 then\n"
|
1673
|
-
" local packed_frame = redis.call(\"lpop\", rule_action_key)\n"
|
1674
|
-
" while packed_frame ~= \"0\" do\n"
|
1675
|
-
" packed_frame = redis.call(\"lpop\", rule_action_key)\n"
|
1676
|
-
" end\n"
|
1677
|
-
" else\n"
|
1678
|
-
" for i = 0, count - 1, 1 do\n"
|
1679
|
-
" local packed_frame = redis.call(\"rpop\", rule_action_key)\n"
|
1680
|
-
" end\n"
|
1681
|
-
" end\n"
|
1682
|
-
" return (redis.call(\"llen\", key) > 0)\n"
|
1683
|
-
"end\n"
|
1684
|
-
"local sid = ARGV[1]\n"
|
1685
|
-
"local max_score = tonumber(ARGV[2])\n"
|
1686
|
-
"local action_key = \"%s!a\"\n"
|
1687
|
-
"if delete_frame(action_key .. \"!\" .. sid, action_key) then\n"
|
1688
|
-
" redis.call(\"zadd\", action_key , max_score, sid)\n"
|
1689
|
-
"else\n"
|
1690
|
-
" redis.call(\"zrem\", action_key, sid)\n"
|
1691
|
-
"end\n", name) == -1) {
|
1692
|
-
return ERR_OUT_OF_MEMORY;
|
1693
|
-
}
|
1694
|
-
|
1695
|
-
redisAppendCommand(reContext, "SCRIPT LOAD %s", lua);
|
1696
|
-
redisGetReply(reContext, (void**)&reply);
|
1697
|
-
if (reply->type == REDIS_REPLY_ERROR) {
|
1698
|
-
printf("%s\n", reply->str);
|
1699
|
-
freeReplyObject(reply);
|
1700
|
-
free(lua);
|
1701
|
-
return ERR_REDIS_ERROR;
|
1702
|
-
}
|
1703
|
-
|
1704
|
-
strncpy(rulesBinding->removeActionHash, reply->str, 40);
|
1705
|
-
rulesBinding->removeActionHash[40] = '\0';
|
1706
|
-
freeReplyObject(reply);
|
1707
|
-
free(lua);
|
1708
|
-
|
1709
|
-
if (asprintf(&lua,
|
1710
|
-
"local partition_key = \"%s!p\"\n"
|
1711
|
-
"local res = redis.call(\"hget\", partition_key, ARGV[1])\n"
|
1712
|
-
"if (not res) then\n"
|
1713
|
-
" res = redis.call(\"hincrby\", partition_key, \"index\", 1)\n"
|
1714
|
-
" res = res %% tonumber(ARGV[2])\n"
|
1715
|
-
" redis.call(\"hset\", partition_key, ARGV[1], res)\n"
|
1716
|
-
"end\n"
|
1717
|
-
"return tonumber(res)\n", name) == -1) {
|
1718
|
-
return ERR_OUT_OF_MEMORY;
|
1719
|
-
}
|
1720
|
-
|
1721
|
-
redisAppendCommand(reContext, "SCRIPT LOAD %s", lua);
|
1722
|
-
redisGetReply(reContext, (void**)&reply);
|
1723
|
-
if (reply->type == REDIS_REPLY_ERROR) {
|
1724
|
-
printf("%s\n", reply->str);
|
1725
|
-
freeReplyObject(reply);
|
1726
|
-
return ERR_REDIS_ERROR;
|
1727
|
-
}
|
1728
|
-
|
1729
|
-
strncpy(rulesBinding->partitionHash, reply->str, 40);
|
1730
|
-
rulesBinding->partitionHash[40] = '\0';
|
1731
|
-
freeReplyObject(reply);
|
1732
|
-
free(lua);
|
1733
|
-
|
1734
|
-
if (asprintf(&lua,
|
1735
|
-
"local timer_key = \"%s!t\"\n"
|
1736
|
-
"local timestamp = tonumber(ARGV[1])\n"
|
1737
|
-
"local res = redis.call(\"zrangebyscore\", timer_key, 0, timestamp, \"limit\", 0, 10)\n"
|
1738
|
-
"if #res > 0 then\n"
|
1739
|
-
" for i = 0, #res, 1 do\n"
|
1740
|
-
" redis.call(\"zincrby\", timer_key, 10, res[i])\n"
|
1741
|
-
" end\n"
|
1742
|
-
" return res\n"
|
1743
|
-
"end\n"
|
1744
|
-
"return 0\n", name) == -1) {
|
1745
|
-
return ERR_OUT_OF_MEMORY;
|
1746
|
-
}
|
1747
|
-
|
1748
|
-
redisAppendCommand(reContext, "SCRIPT LOAD %s", lua);
|
1749
|
-
redisGetReply(reContext, (void**)&reply);
|
1750
|
-
if (reply->type == REDIS_REPLY_ERROR) {
|
1751
|
-
printf("%s\n", reply->str);
|
1752
|
-
freeReplyObject(reply);
|
1753
|
-
return ERR_REDIS_ERROR;
|
1754
|
-
}
|
1755
|
-
|
1756
|
-
strncpy(rulesBinding->timersHash, reply->str, 40);
|
1757
|
-
rulesBinding->timersHash[40] = '\0';
|
1758
|
-
freeReplyObject(reply);
|
1759
|
-
free(lua);
|
1760
|
-
|
1761
|
-
if (asprintf(&lua,
|
1762
|
-
"local actions_key = \"%s!a\"\n"
|
1763
|
-
"local score = tonumber(ARGV[2])\n"
|
1764
|
-
"local sid = ARGV[1]\n"
|
1765
|
-
"if redis.call(\"zscore\", actions_key, sid) then\n"
|
1766
|
-
" redis.call(\"zadd\", actions_key , score, sid)\n"
|
1767
|
-
"end\n", name) == -1) {
|
1768
|
-
return ERR_OUT_OF_MEMORY;
|
1769
|
-
}
|
1770
|
-
|
1771
|
-
redisAppendCommand(reContext, "SCRIPT LOAD %s", lua);
|
1772
|
-
redisGetReply(reContext, (void**)&reply);
|
1773
|
-
if (reply->type == REDIS_REPLY_ERROR) {
|
1774
|
-
printf("%s\n", reply->str);
|
1775
|
-
freeReplyObject(reply);
|
1776
|
-
return ERR_REDIS_ERROR;
|
1777
|
-
}
|
1778
|
-
|
1779
|
-
strncpy(rulesBinding->updateActionHash, reply->str, 40);
|
1780
|
-
rulesBinding->updateActionHash[40] = '\0';
|
1781
|
-
freeReplyObject(reply);
|
1782
|
-
free(lua);
|
1783
|
-
|
1784
|
-
char *sessionHashset = malloc((nameLength + 3) * sizeof(char));
|
1785
|
-
if (!sessionHashset) {
|
1786
|
-
return ERR_OUT_OF_MEMORY;
|
1787
|
-
}
|
1788
|
-
|
1789
|
-
strncpy(sessionHashset, name, nameLength);
|
1790
|
-
sessionHashset[nameLength] = '!';
|
1791
|
-
sessionHashset[nameLength + 1] = 's';
|
1792
|
-
sessionHashset[nameLength + 2] = '\0';
|
1793
|
-
rulesBinding->sessionHashset = sessionHashset;
|
1794
|
-
|
1795
|
-
char *factsHashset = malloc((nameLength + 3) * sizeof(char));
|
1796
|
-
if (!factsHashset) {
|
1797
|
-
return ERR_OUT_OF_MEMORY;
|
1798
|
-
}
|
1799
|
-
|
1800
|
-
strncpy(factsHashset, name, nameLength);
|
1801
|
-
factsHashset[nameLength] = '!';
|
1802
|
-
factsHashset[nameLength + 1] = 'f';
|
1803
|
-
factsHashset[nameLength + 2] = '\0';
|
1804
|
-
rulesBinding->factsHashset = factsHashset;
|
1805
|
-
|
1806
|
-
char *eventsHashset = malloc((nameLength + 3) * sizeof(char));
|
1807
|
-
if (!eventsHashset) {
|
1808
|
-
return ERR_OUT_OF_MEMORY;
|
1809
|
-
}
|
1810
|
-
|
1811
|
-
strncpy(eventsHashset, name, nameLength);
|
1812
|
-
eventsHashset[nameLength] = '!';
|
1813
|
-
eventsHashset[nameLength + 1] = 'e';
|
1814
|
-
eventsHashset[nameLength + 2] = '\0';
|
1815
|
-
rulesBinding->eventsHashset = eventsHashset;
|
1816
|
-
|
1817
|
-
char *timersSortedset = malloc((nameLength + 3) * sizeof(char));
|
1818
|
-
if (!timersSortedset) {
|
1819
|
-
return ERR_OUT_OF_MEMORY;
|
1820
|
-
}
|
1821
|
-
|
1822
|
-
strncpy(timersSortedset, name, nameLength);
|
1823
|
-
timersSortedset[nameLength] = '!';
|
1824
|
-
timersSortedset[nameLength + 1] = 't';
|
1825
|
-
timersSortedset[nameLength + 2] = '\0';
|
1826
|
-
rulesBinding->timersSortedset = timersSortedset;
|
1827
|
-
|
1828
1891
|
return RULES_OK;
|
1829
1892
|
}
|
1830
1893
|
|
@@ -2302,12 +2365,15 @@ static unsigned int tryGetReply(redisContext *reContext,
|
|
2302
2365
|
|
2303
2366
|
if (redisGetReply(reContext, (void**)reply) != REDIS_OK) {
|
2304
2367
|
printf("getReply err %d, %d, %s\n", reContext->err, errno, reContext->errstr);
|
2368
|
+
#ifndef _WIN32
|
2305
2369
|
if (redisReconnect(reContext) != REDIS_OK) {
|
2306
2370
|
printf("reconnect err %d, %d, %s\n", reContext->err, errno, reContext->errstr);
|
2307
2371
|
return ERR_REDIS_ERROR;
|
2308
2372
|
}
|
2309
|
-
|
2310
2373
|
return ERR_TRY_AGAIN;
|
2374
|
+
#else
|
2375
|
+
return ERR_REDIS_ERROR;
|
2376
|
+
#endif
|
2311
2377
|
}
|
2312
2378
|
|
2313
2379
|
return RULES_OK;
|
@@ -2514,7 +2580,7 @@ unsigned int registerTimer(void *rulesBinding, unsigned int duration, char *time
|
|
2514
2580
|
time_t currentTime = time(NULL);
|
2515
2581
|
|
2516
2582
|
int result = redisAppendCommand(reContext,
|
2517
|
-
"zadd %s %ld
|
2583
|
+
"zadd %s %ld p:%s",
|
2518
2584
|
currentBinding->timersSortedset,
|
2519
2585
|
currentTime + duration,
|
2520
2586
|
timer);
|
@@ -2543,7 +2609,7 @@ unsigned int removeTimer(void *rulesBinding, char *timer) {
|
|
2543
2609
|
redisContext *reContext = currentBinding->reContext;
|
2544
2610
|
|
2545
2611
|
int result = redisAppendCommand(reContext,
|
2546
|
-
"zrem %s
|
2612
|
+
"zrem %s p:%s",
|
2547
2613
|
currentBinding->timersSortedset,
|
2548
2614
|
timer);
|
2549
2615
|
if (result != REDIS_OK) {
|
@@ -2566,16 +2632,37 @@ unsigned int removeTimer(void *rulesBinding, char *timer) {
|
|
2566
2632
|
return RULES_OK;
|
2567
2633
|
}
|
2568
2634
|
|
2569
|
-
unsigned int registerMessage(void *rulesBinding, char *destination, char *message) {
|
2635
|
+
unsigned int registerMessage(void *rulesBinding, unsigned int queueAction, char *destination, char *message) {
|
2570
2636
|
binding *currentBinding = (binding*)rulesBinding;
|
2571
2637
|
redisContext *reContext = currentBinding->reContext;
|
2572
2638
|
time_t currentTime = time(NULL);
|
2573
2639
|
|
2574
|
-
int result =
|
2575
|
-
|
2576
|
-
|
2577
|
-
|
2578
|
-
|
2640
|
+
int result = REDIS_OK;
|
2641
|
+
|
2642
|
+
switch (queueAction) {
|
2643
|
+
case QUEUE_ASSERT_FACT:
|
2644
|
+
result = redisAppendCommand(reContext,
|
2645
|
+
"zadd %s!t %ld a:%s",
|
2646
|
+
destination,
|
2647
|
+
currentTime,
|
2648
|
+
message);
|
2649
|
+
break;
|
2650
|
+
case QUEUE_ASSERT_EVENT:
|
2651
|
+
result = redisAppendCommand(reContext,
|
2652
|
+
"zadd %s!t %ld p:%s",
|
2653
|
+
destination,
|
2654
|
+
currentTime,
|
2655
|
+
message);
|
2656
|
+
break;
|
2657
|
+
case QUEUE_RETRACT_FACT:
|
2658
|
+
result = redisAppendCommand(reContext,
|
2659
|
+
"zadd %s!t %ld r:%s",
|
2660
|
+
destination,
|
2661
|
+
currentTime,
|
2662
|
+
message);
|
2663
|
+
break;
|
2664
|
+
}
|
2665
|
+
|
2579
2666
|
if (result != REDIS_OK) {
|
2580
2667
|
return ERR_REDIS_ERROR;
|
2581
2668
|
}
|
data/src/rules/net.h
CHANGED
data/src/rules/rete.c
CHANGED
@@ -1722,5 +1722,62 @@ unsigned int deleteRuleset(void *handle) {
|
|
1722
1722
|
return RULES_OK;
|
1723
1723
|
}
|
1724
1724
|
|
1725
|
+
unsigned int createClient(void **handle, char *name, unsigned int stateCaheSize) {
|
1726
|
+
ruleset *tree = malloc(sizeof(ruleset));
|
1727
|
+
if (!tree) {
|
1728
|
+
return ERR_OUT_OF_MEMORY;
|
1729
|
+
}
|
1730
|
+
|
1731
|
+
tree->stringPool = NULL;
|
1732
|
+
tree->stringPoolLength = 0;
|
1733
|
+
tree->nodePool = NULL;
|
1734
|
+
tree->nodeOffset = 0;
|
1735
|
+
tree->nextPool = NULL;
|
1736
|
+
tree->nextOffset = 0;
|
1737
|
+
tree->expressionPool = NULL;
|
1738
|
+
tree->expressionOffset = 0;
|
1739
|
+
tree->idiomPool = NULL;
|
1740
|
+
tree->idiomOffset = 0;
|
1741
|
+
tree->joinPool = NULL;
|
1742
|
+
tree->joinOffset = 0;
|
1743
|
+
tree->actionCount = 0;
|
1744
|
+
tree->bindingsList = NULL;
|
1745
|
+
tree->stateLength = 0;
|
1746
|
+
tree->state = calloc(stateCaheSize, sizeof(stateEntry));
|
1747
|
+
tree->maxStateLength = stateCaheSize;
|
1748
|
+
tree->stateBucketsLength = stateCaheSize / 4;
|
1749
|
+
tree->stateBuckets = malloc(tree->stateBucketsLength * sizeof(unsigned int));
|
1750
|
+
memset(tree->stateBuckets, 0xFF, tree->stateBucketsLength * sizeof(unsigned int));
|
1751
|
+
tree->lruStateOffset = UNDEFINED_HASH_OFFSET;
|
1752
|
+
tree->mruStateOffset = UNDEFINED_HASH_OFFSET;
|
1753
|
+
|
1754
|
+
unsigned int result = storeString(tree, name, &tree->nameOffset, strlen(name));
|
1755
|
+
if (result != RULES_OK) {
|
1756
|
+
return result;
|
1757
|
+
}
|
1758
|
+
|
1759
|
+
*handle = tree;
|
1760
|
+
return RULES_OK;
|
1761
|
+
}
|
1762
|
+
|
1763
|
+
unsigned int deleteClient(void *handle) {
|
1764
|
+
ruleset *tree = (ruleset*)(handle);
|
1765
|
+
deleteBindingsList(tree);
|
1766
|
+
free(tree->stringPool);
|
1767
|
+
free(tree->stateBuckets);
|
1768
|
+
for (unsigned int i = 0; i < tree->stateLength; ++i) {
|
1769
|
+
stateEntry *entry = &tree->state[i];
|
1770
|
+
if (entry->state) {
|
1771
|
+
free(entry->state);
|
1772
|
+
}
|
1773
|
+
|
1774
|
+
if (entry->sid) {
|
1775
|
+
free(entry->sid);
|
1776
|
+
}
|
1777
|
+
}
|
1778
|
+
|
1779
|
+
free(tree);
|
1780
|
+
return RULES_OK;
|
1781
|
+
}
|
1725
1782
|
|
1726
1783
|
|
data/src/rules/rules.h
CHANGED
@@ -43,6 +43,10 @@
|
|
43
43
|
#define BETA_LIST_LENGTH 16
|
44
44
|
#define HASH_MASK 0x1F
|
45
45
|
|
46
|
+
#define QUEUE_ASSERT_FACT 1
|
47
|
+
#define QUEUE_ASSERT_EVENT 2
|
48
|
+
#define QUEUE_RETRACT_FACT 3
|
49
|
+
|
46
50
|
#ifdef __cplusplus
|
47
51
|
extern "C" {
|
48
52
|
#endif
|
@@ -54,6 +58,12 @@ unsigned int createRuleset(void **handle,
|
|
54
58
|
|
55
59
|
unsigned int deleteRuleset(void *handle);
|
56
60
|
|
61
|
+
unsigned int createClient(void **handle,
|
62
|
+
char *name,
|
63
|
+
unsigned int stateCaheSize);
|
64
|
+
|
65
|
+
unsigned int deleteClient(void *handle);
|
66
|
+
|
57
67
|
unsigned int bindRuleset(void *handle,
|
58
68
|
char *host,
|
59
69
|
unsigned int port,
|
@@ -161,7 +171,8 @@ unsigned int cancelTimer(void *handle,
|
|
161
171
|
char *sid,
|
162
172
|
char *timer);
|
163
173
|
|
164
|
-
unsigned int queueMessage(void *handle,
|
174
|
+
unsigned int queueMessage(void *handle,
|
175
|
+
unsigned int queueAction,
|
165
176
|
char *sid,
|
166
177
|
char *destination,
|
167
178
|
char *message);
|
data/src/rulesrb/rules.c
CHANGED
@@ -35,6 +35,38 @@ static VALUE rbDeleteRuleset(VALUE self, VALUE handle) {
|
|
35
35
|
return Qnil;
|
36
36
|
}
|
37
37
|
|
38
|
+
static VALUE rbCreateClient(VALUE self, VALUE name, VALUE stateCacheSize) {
|
39
|
+
Check_Type(name, T_STRING);
|
40
|
+
Check_Type(stateCacheSize, T_FIXNUM);
|
41
|
+
|
42
|
+
void *output = NULL;
|
43
|
+
unsigned int result = createClient(&output, RSTRING_PTR(name), FIX2INT(stateCacheSize));
|
44
|
+
if (result != RULES_OK) {
|
45
|
+
if (result == ERR_OUT_OF_MEMORY) {
|
46
|
+
rb_raise(rb_eNoMemError, "Out of memory");
|
47
|
+
} else {
|
48
|
+
rb_raise(rb_eException, "Could not create client, error code: %d", result);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
return INT2FIX(output);
|
53
|
+
}
|
54
|
+
|
55
|
+
static VALUE rbDeleteClient(VALUE self, VALUE handle) {
|
56
|
+
Check_Type(handle, T_FIXNUM);
|
57
|
+
|
58
|
+
unsigned int result = deleteClient((void *)FIX2LONG(handle));
|
59
|
+
if (result != RULES_OK) {
|
60
|
+
if (result == ERR_OUT_OF_MEMORY) {
|
61
|
+
rb_raise(rb_eNoMemError, "Out of memory");
|
62
|
+
} else {
|
63
|
+
rb_raise(rb_eException, "Could not delete client, error code: %d", result);
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
return Qnil;
|
68
|
+
}
|
69
|
+
|
38
70
|
static VALUE rbBindRuleset(VALUE self, VALUE handle, VALUE host, VALUE port, VALUE password) {
|
39
71
|
Check_Type(handle, T_FIXNUM);
|
40
72
|
Check_Type(host, T_STRING);
|
@@ -124,18 +156,18 @@ static VALUE rbAssertEvent(VALUE self, VALUE handle, VALUE event) {
|
|
124
156
|
return Qnil;
|
125
157
|
}
|
126
158
|
|
127
|
-
static VALUE
|
159
|
+
static VALUE rbQueueAssertEvent(VALUE self, VALUE handle, VALUE sid, VALUE destination, VALUE event) {
|
128
160
|
Check_Type(handle, T_FIXNUM);
|
129
161
|
Check_Type(sid, T_STRING);
|
130
162
|
Check_Type(destination, T_STRING);
|
131
163
|
Check_Type(event, T_STRING);
|
132
164
|
|
133
|
-
unsigned int result = queueMessage((void *)FIX2LONG(handle), RSTRING_PTR(sid), RSTRING_PTR(destination), RSTRING_PTR(event));
|
165
|
+
unsigned int result = queueMessage((void *)FIX2LONG(handle), QUEUE_ASSERT_EVENT, RSTRING_PTR(sid), RSTRING_PTR(destination), RSTRING_PTR(event));
|
134
166
|
if (result != RULES_OK) {
|
135
167
|
if (result == ERR_OUT_OF_MEMORY) {
|
136
168
|
rb_raise(rb_eNoMemError, "Out of memory");
|
137
169
|
} else {
|
138
|
-
rb_raise(rb_eException, "Could not queue event, error code: %d", result);
|
170
|
+
rb_raise(rb_eException, "Could not queue assert event, error code: %d", result);
|
139
171
|
}
|
140
172
|
}
|
141
173
|
|
@@ -272,6 +304,24 @@ static VALUE rbAssertFact(VALUE self, VALUE handle, VALUE fact) {
|
|
272
304
|
return Qnil;
|
273
305
|
}
|
274
306
|
|
307
|
+
static VALUE rbQueueAssertFact(VALUE self, VALUE handle, VALUE sid, VALUE destination, VALUE event) {
|
308
|
+
Check_Type(handle, T_FIXNUM);
|
309
|
+
Check_Type(sid, T_STRING);
|
310
|
+
Check_Type(destination, T_STRING);
|
311
|
+
Check_Type(event, T_STRING);
|
312
|
+
|
313
|
+
unsigned int result = queueMessage((void *)FIX2LONG(handle), QUEUE_ASSERT_FACT, RSTRING_PTR(sid), RSTRING_PTR(destination), RSTRING_PTR(event));
|
314
|
+
if (result != RULES_OK) {
|
315
|
+
if (result == ERR_OUT_OF_MEMORY) {
|
316
|
+
rb_raise(rb_eNoMemError, "Out of memory");
|
317
|
+
} else {
|
318
|
+
rb_raise(rb_eException, "Could not queue assert fact, error code: %d", result);
|
319
|
+
}
|
320
|
+
}
|
321
|
+
|
322
|
+
return Qnil;
|
323
|
+
}
|
324
|
+
|
275
325
|
static VALUE rbStartAssertFacts(VALUE self, VALUE handle, VALUE facts) {
|
276
326
|
Check_Type(handle, T_FIXNUM);
|
277
327
|
Check_Type(facts, T_STRING);
|
@@ -382,6 +432,24 @@ static VALUE rbRetractFact(VALUE self, VALUE handle, VALUE fact) {
|
|
382
432
|
return Qnil;
|
383
433
|
}
|
384
434
|
|
435
|
+
static VALUE rbQueueRetractFact(VALUE self, VALUE handle, VALUE sid, VALUE destination, VALUE event) {
|
436
|
+
Check_Type(handle, T_FIXNUM);
|
437
|
+
Check_Type(sid, T_STRING);
|
438
|
+
Check_Type(destination, T_STRING);
|
439
|
+
Check_Type(event, T_STRING);
|
440
|
+
|
441
|
+
unsigned int result = queueMessage((void *)FIX2LONG(handle), QUEUE_RETRACT_FACT, RSTRING_PTR(sid), RSTRING_PTR(destination), RSTRING_PTR(event));
|
442
|
+
if (result != RULES_OK) {
|
443
|
+
if (result == ERR_OUT_OF_MEMORY) {
|
444
|
+
rb_raise(rb_eNoMemError, "Out of memory");
|
445
|
+
} else {
|
446
|
+
rb_raise(rb_eException, "Could not queue retract fact, error code: %d", result);
|
447
|
+
}
|
448
|
+
}
|
449
|
+
|
450
|
+
return Qnil;
|
451
|
+
}
|
452
|
+
|
385
453
|
static VALUE rbStartRetractFacts(VALUE self, VALUE handle, VALUE facts) {
|
386
454
|
Check_Type(handle, T_FIXNUM);
|
387
455
|
Check_Type(facts, T_STRING);
|
@@ -667,20 +735,24 @@ void Init_rules() {
|
|
667
735
|
rulesModule = rb_define_module("Rules");
|
668
736
|
rb_define_singleton_method(rulesModule, "create_ruleset", rbCreateRuleset, 3);
|
669
737
|
rb_define_singleton_method(rulesModule, "delete_ruleset", rbDeleteRuleset, 1);
|
738
|
+
rb_define_singleton_method(rulesModule, "create_client", rbCreateClient, 2);
|
739
|
+
rb_define_singleton_method(rulesModule, "delete_client", rbDeleteClient, 1);
|
670
740
|
rb_define_singleton_method(rulesModule, "bind_ruleset", rbBindRuleset, 4);
|
671
741
|
rb_define_singleton_method(rulesModule, "complete", rbComplete, 2);
|
672
742
|
rb_define_singleton_method(rulesModule, "assert_event", rbAssertEvent, 2);
|
673
|
-
rb_define_singleton_method(rulesModule, "
|
743
|
+
rb_define_singleton_method(rulesModule, "queue_assert_event", rbQueueAssertEvent, 4);
|
674
744
|
rb_define_singleton_method(rulesModule, "start_assert_event", rbStartAssertEvent, 2);
|
675
745
|
rb_define_singleton_method(rulesModule, "assert_events", rbAssertEvents, 2);
|
676
746
|
rb_define_singleton_method(rulesModule, "start_assert_events", rbStartAssertEvents, 2);
|
677
747
|
rb_define_singleton_method(rulesModule, "retract_event", rbRetractEvent, 2);
|
678
748
|
rb_define_singleton_method(rulesModule, "start_assert_fact", rbStartAssertFact, 2);
|
679
749
|
rb_define_singleton_method(rulesModule, "assert_fact", rbAssertFact, 2);
|
750
|
+
rb_define_singleton_method(rulesModule, "queue_assert_fact", rbQueueAssertFact, 4);
|
680
751
|
rb_define_singleton_method(rulesModule, "start_assert_facts", rbStartAssertFacts, 2);
|
681
752
|
rb_define_singleton_method(rulesModule, "assert_facts", rbAssertFacts, 2);
|
682
753
|
rb_define_singleton_method(rulesModule, "start_retract_fact", rbStartRetractFact, 2);
|
683
754
|
rb_define_singleton_method(rulesModule, "retract_fact", rbRetractFact, 2);
|
755
|
+
rb_define_singleton_method(rulesModule, "queue_retract_fact", rbQueueRetractFact, 4);
|
684
756
|
rb_define_singleton_method(rulesModule, "start_retract_facts", rbStartRetractFacts, 2);
|
685
757
|
rb_define_singleton_method(rulesModule, "retract_facts", rbRetractFacts, 2);
|
686
758
|
rb_define_singleton_method(rulesModule, "assert_state", rbAssertState, 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.02
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jesus Ruiz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|