durable_rules 0.34.01 → 0.34.02
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 +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
|