durable_rules 0.34.57 → 2.00.001
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 +46 -28
- data/librb/engine.rb +257 -548
- data/src/rules/Makefile +6 -7
- data/src/rules/events.c +1690 -1559
- data/src/rules/json.h +10 -6
- data/src/rules/rete.c +829 -1046
- data/src/rules/rete.h +66 -52
- data/src/rules/rules.h +67 -109
- data/src/rules/state.c +1245 -449
- data/src/rules/state.h +305 -31
- data/src/rulesrb/extconf.rb +1 -8
- data/src/rulesrb/rules.c +71 -369
- metadata +2 -36
- data/deps/hiredis/COPYING +0 -29
- data/deps/hiredis/Makefile +0 -217
- data/deps/hiredis/async.c +0 -687
- data/deps/hiredis/async.h +0 -129
- data/deps/hiredis/dict.c +0 -338
- data/deps/hiredis/dict.h +0 -126
- data/deps/hiredis/fmacros.h +0 -21
- data/deps/hiredis/hiredis.c +0 -1021
- data/deps/hiredis/hiredis.h +0 -223
- data/deps/hiredis/net.c +0 -458
- data/deps/hiredis/net.h +0 -53
- data/deps/hiredis/read.c +0 -525
- data/deps/hiredis/read.h +0 -116
- data/deps/hiredis/sds.c +0 -1095
- data/deps/hiredis/sds.h +0 -105
- data/deps/hiredis/test.c +0 -807
- data/deps/hiredis/win32.h +0 -42
- data/librb/interface.rb +0 -126
- data/src/rules/net.c +0 -3257
- data/src/rules/net.h +0 -165
data/src/rules/Makefile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
OBJ=events.o json.o
|
1
|
+
OBJ=events.o json.o rete.o state.o regex.o
|
2
2
|
LIBNAME=librules
|
3
3
|
|
4
4
|
# Fallback to gcc when $CC is not in $PATH.
|
@@ -6,21 +6,20 @@ CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
|
|
6
6
|
OPTIMIZATION?=-O3
|
7
7
|
WARNINGS=-Wall
|
8
8
|
DEBUG?= -g -ggdb
|
9
|
-
REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG) $(ARCH) -
|
9
|
+
REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG) $(ARCH) -D_GNU_SOURCE
|
10
10
|
|
11
11
|
STLIBSUFFIX=a
|
12
12
|
STLIBNAME=$(LIBNAME).$(STLIBSUFFIX)
|
13
|
-
STLIB_MAKE_CMD=ld $(ARCH) -o $(STLIBNAME) -
|
13
|
+
STLIB_MAKE_CMD=ld $(ARCH) -o $(STLIBNAME) -r
|
14
14
|
#STLIB_MAKE_CMD=ar rcs $(STLIBNAME)
|
15
15
|
|
16
16
|
all: $(STLIBNAME)
|
17
17
|
|
18
18
|
# Deps (use make dep to generate this)
|
19
|
-
events.o: events.c rules.h
|
19
|
+
events.o: events.c rules.h json.h regex.h
|
20
20
|
json.o: json.c json.h rules.h
|
21
|
-
|
22
|
-
|
23
|
-
state.o: state.c state.h json.h net.h
|
21
|
+
rete.o: rete.c rete.h json.h state.h regex.h
|
22
|
+
state.o: state.c state.h json.h
|
24
23
|
regex.o: regex.c regex.h rules.h
|
25
24
|
|
26
25
|
$(STLIBNAME): $(OBJ)
|
data/src/rules/events.c
CHANGED
@@ -3,11 +3,16 @@
|
|
3
3
|
#include <stdlib.h>
|
4
4
|
#include <string.h>
|
5
5
|
#include "rules.h"
|
6
|
-
#include "net.h"
|
7
6
|
#include "json.h"
|
8
7
|
#include "regex.h"
|
8
|
+
#include "rete.h"
|
9
|
+
|
10
|
+
#define ACTION_ASSERT_FACT 1
|
11
|
+
#define ACTION_ASSERT_EVENT 2
|
12
|
+
#define ACTION_RETRACT_FACT 3
|
13
|
+
#define ACTION_RETRACT_EVENT 4
|
14
|
+
#define ACTION_UPDATE_STATE 5
|
9
15
|
|
10
|
-
#include <time.h>
|
11
16
|
|
12
17
|
#define MAX_RESULT_NODES 32
|
13
18
|
#define MAX_NODE_RESULTS 16
|
@@ -16,6 +21,8 @@
|
|
16
21
|
#define MAX_COMMAND_COUNT 10000
|
17
22
|
#define MAX_ADD_COUNT 1000
|
18
23
|
#define MAX_EVAL_COUNT 1000
|
24
|
+
#define MAX_INT_LENGTH 256
|
25
|
+
#define MAX_DOUBLE_LENGTH 256
|
19
26
|
|
20
27
|
#define OP_BOOL_BOOL 0x0404
|
21
28
|
#define OP_BOOL_INT 0x0402
|
@@ -47,903 +54,1361 @@
|
|
47
54
|
|
48
55
|
#define HASH_I 1622948014 //$i
|
49
56
|
|
50
|
-
|
51
|
-
void *rulesBinding;
|
52
|
-
redisReply *reply;
|
53
|
-
} actionContext;
|
54
|
-
|
55
|
-
typedef struct jsonResult {
|
56
|
-
unsigned int hash;
|
57
|
-
char *firstName;
|
58
|
-
char *lastName;
|
59
|
-
char *messages[MAX_MESSAGE_BATCH];
|
60
|
-
unsigned short messagesLength;
|
61
|
-
unsigned char childrenCount;
|
62
|
-
unsigned char children[MAX_NODE_RESULTS];
|
63
|
-
} jsonResult;
|
57
|
+
#define ONE_HASH 873244444
|
64
58
|
|
65
59
|
static unsigned int handleMessage(ruleset *tree,
|
66
|
-
char *state,
|
67
60
|
char *message,
|
68
61
|
unsigned char actionType,
|
69
|
-
|
70
|
-
unsigned int *
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
unsigned char
|
84
|
-
|
62
|
+
unsigned int *messageOffset,
|
63
|
+
unsigned int *stateOffset);
|
64
|
+
|
65
|
+
static unsigned int reduceExpression(ruleset *tree,
|
66
|
+
stateNode *state,
|
67
|
+
expression *currentExpression,
|
68
|
+
jsonObject *messageObject,
|
69
|
+
leftFrameNode *context,
|
70
|
+
jsonProperty *targetProperty);
|
71
|
+
|
72
|
+
static unsigned int reduceString(char *left,
|
73
|
+
unsigned short leftLength,
|
74
|
+
char *right,
|
75
|
+
unsigned short rightLength,
|
76
|
+
unsigned char op,
|
77
|
+
jsonProperty *targetProperty) {
|
78
|
+
int length = (leftLength > rightLength ? leftLength: rightLength);
|
79
|
+
int result = strncmp(left, right, length);
|
85
80
|
switch(op) {
|
81
|
+
case OP_ADD:
|
82
|
+
case OP_SUB:
|
83
|
+
case OP_MUL:
|
84
|
+
case OP_DIV:
|
85
|
+
return ERR_OPERATION_NOT_SUPPORTED;
|
86
86
|
case OP_LT:
|
87
|
-
|
87
|
+
targetProperty->type = JSON_BOOL;
|
88
|
+
targetProperty->value.b = (result < 0);
|
89
|
+
break;
|
88
90
|
case OP_LTE:
|
89
|
-
|
91
|
+
targetProperty->type = JSON_BOOL;
|
92
|
+
targetProperty->value.b = (result <= 0);
|
93
|
+
break;
|
90
94
|
case OP_GT:
|
91
|
-
|
95
|
+
targetProperty->type = JSON_BOOL;
|
96
|
+
targetProperty->value.b = (result > 0);
|
97
|
+
break;
|
92
98
|
case OP_GTE:
|
93
|
-
|
99
|
+
targetProperty->type = JSON_BOOL;
|
100
|
+
targetProperty->value.b = (result >= 0);
|
101
|
+
break;
|
94
102
|
case OP_EQ:
|
95
|
-
|
103
|
+
targetProperty->type = JSON_BOOL;
|
104
|
+
targetProperty->value.b = (result == 0);
|
105
|
+
break;
|
96
106
|
case OP_NEQ:
|
97
|
-
|
107
|
+
targetProperty->type = JSON_BOOL;
|
108
|
+
targetProperty->value.b = (result != 0);
|
109
|
+
break;
|
98
110
|
}
|
99
111
|
|
100
|
-
return
|
112
|
+
return RULES_OK;
|
101
113
|
}
|
102
114
|
|
103
|
-
static unsigned
|
104
|
-
|
105
|
-
|
115
|
+
static unsigned int reduceBool(unsigned char left,
|
116
|
+
unsigned char right,
|
117
|
+
unsigned char op,
|
118
|
+
jsonProperty *targetProperty) {
|
106
119
|
switch(op) {
|
120
|
+
case OP_DIV:
|
121
|
+
case OP_SUB:
|
122
|
+
return ERR_OPERATION_NOT_SUPPORTED;
|
123
|
+
case OP_ADD:
|
124
|
+
targetProperty->type = JSON_BOOL;
|
125
|
+
targetProperty->value.b = left & right;
|
126
|
+
break;
|
127
|
+
case OP_MUL:
|
128
|
+
targetProperty->type = JSON_BOOL;
|
129
|
+
targetProperty->value.b = left ^ right;
|
130
|
+
break;
|
107
131
|
case OP_LT:
|
108
|
-
|
132
|
+
targetProperty->type = JSON_BOOL;
|
133
|
+
targetProperty->value.b = (left < right);
|
134
|
+
break;
|
109
135
|
case OP_LTE:
|
110
|
-
|
136
|
+
targetProperty->type = JSON_BOOL;
|
137
|
+
targetProperty->value.b = (left <= right);
|
138
|
+
break;
|
111
139
|
case OP_GT:
|
112
|
-
|
140
|
+
targetProperty->type = JSON_BOOL;
|
141
|
+
targetProperty->value.b = (left > right);
|
142
|
+
break;
|
113
143
|
case OP_GTE:
|
114
|
-
|
144
|
+
targetProperty->type = JSON_BOOL;
|
145
|
+
targetProperty->value.b = (left >= right);
|
146
|
+
break;
|
115
147
|
case OP_EQ:
|
116
|
-
|
148
|
+
targetProperty->type = JSON_BOOL;
|
149
|
+
targetProperty->value.b = (left == right);
|
150
|
+
break;
|
117
151
|
case OP_NEQ:
|
118
|
-
|
152
|
+
targetProperty->type = JSON_BOOL;
|
153
|
+
targetProperty->value.b = (left != right);
|
154
|
+
break;
|
119
155
|
}
|
120
156
|
|
121
|
-
return
|
157
|
+
return RULES_OK;
|
122
158
|
}
|
123
159
|
|
124
|
-
static unsigned
|
125
|
-
|
126
|
-
|
160
|
+
static unsigned int reduceInt(long left,
|
161
|
+
long right,
|
162
|
+
unsigned char op,
|
163
|
+
jsonProperty *targetProperty) {
|
127
164
|
switch(op) {
|
165
|
+
case OP_ADD:
|
166
|
+
targetProperty->type = JSON_INT;
|
167
|
+
targetProperty->value.i = left + right;
|
168
|
+
break;
|
169
|
+
case OP_SUB:
|
170
|
+
targetProperty->type = JSON_INT;
|
171
|
+
targetProperty->value.i = left - right;
|
172
|
+
break;
|
173
|
+
case OP_MUL:
|
174
|
+
targetProperty->type = JSON_INT;
|
175
|
+
targetProperty->value.i = left * right;
|
176
|
+
break;
|
177
|
+
case OP_DIV:
|
178
|
+
targetProperty->type = JSON_INT;
|
179
|
+
targetProperty->value.i = left / right;
|
180
|
+
break;
|
128
181
|
case OP_LT:
|
129
|
-
|
182
|
+
targetProperty->type = JSON_BOOL;
|
183
|
+
targetProperty->value.b = (left < right);
|
184
|
+
break;
|
130
185
|
case OP_LTE:
|
131
|
-
|
186
|
+
targetProperty->type = JSON_BOOL;
|
187
|
+
targetProperty->value.b = (left <= right);
|
188
|
+
break;
|
132
189
|
case OP_GT:
|
133
|
-
|
190
|
+
targetProperty->type = JSON_BOOL;
|
191
|
+
targetProperty->value.b = (left > right);
|
192
|
+
break;
|
134
193
|
case OP_GTE:
|
135
|
-
|
194
|
+
targetProperty->type = JSON_BOOL;
|
195
|
+
targetProperty->value.b = (left >= right);
|
196
|
+
break;
|
136
197
|
case OP_EQ:
|
137
|
-
|
198
|
+
targetProperty->type = JSON_BOOL;
|
199
|
+
targetProperty->value.b = (left == right);
|
200
|
+
break;
|
138
201
|
case OP_NEQ:
|
139
|
-
|
202
|
+
targetProperty->type = JSON_BOOL;
|
203
|
+
targetProperty->value.b = (left != right);
|
204
|
+
break;
|
140
205
|
}
|
141
206
|
|
142
|
-
return
|
207
|
+
return RULES_OK;
|
143
208
|
}
|
144
209
|
|
145
|
-
static unsigned
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
char temp = leftFirst[leftLength];
|
150
|
-
leftFirst[leftLength] = '\0';
|
151
|
-
int result = strcmp(leftFirst, right);
|
152
|
-
leftFirst[leftLength] = temp;
|
210
|
+
static unsigned int reduceDouble(double left,
|
211
|
+
double right,
|
212
|
+
unsigned char op,
|
213
|
+
jsonProperty *targetProperty) {
|
153
214
|
switch(op) {
|
215
|
+
case OP_ADD:
|
216
|
+
targetProperty->type = JSON_DOUBLE;
|
217
|
+
targetProperty->value.d = left + right;
|
218
|
+
break;
|
219
|
+
case OP_SUB:
|
220
|
+
targetProperty->type = JSON_DOUBLE;
|
221
|
+
targetProperty->value.d = left - right;
|
222
|
+
break;
|
223
|
+
case OP_MUL:
|
224
|
+
targetProperty->type = JSON_DOUBLE;
|
225
|
+
targetProperty->value.d = left * right;
|
226
|
+
break;
|
227
|
+
case OP_DIV:
|
228
|
+
targetProperty->type = JSON_DOUBLE;
|
229
|
+
targetProperty->value.d = left / right;
|
230
|
+
break;
|
154
231
|
case OP_LT:
|
155
|
-
|
232
|
+
targetProperty->type = JSON_BOOL;
|
233
|
+
targetProperty->value.b = (left < right);
|
234
|
+
break;
|
156
235
|
case OP_LTE:
|
157
|
-
|
236
|
+
targetProperty->type = JSON_BOOL;
|
237
|
+
targetProperty->value.b = (left <= right);
|
238
|
+
break;
|
158
239
|
case OP_GT:
|
159
|
-
|
240
|
+
targetProperty->type = JSON_BOOL;
|
241
|
+
targetProperty->value.b = (left > right);
|
242
|
+
break;
|
160
243
|
case OP_GTE:
|
161
|
-
|
244
|
+
targetProperty->type = JSON_BOOL;
|
245
|
+
targetProperty->value.b = (left >= right);
|
246
|
+
break;
|
162
247
|
case OP_EQ:
|
163
|
-
|
248
|
+
targetProperty->type = JSON_BOOL;
|
249
|
+
targetProperty->value.b = (left == right);
|
250
|
+
break;
|
164
251
|
case OP_NEQ:
|
165
|
-
|
252
|
+
targetProperty->type = JSON_BOOL;
|
253
|
+
targetProperty->value.b = (left != right);
|
254
|
+
break;
|
166
255
|
}
|
167
256
|
|
168
|
-
return
|
257
|
+
return RULES_OK;
|
169
258
|
}
|
170
259
|
|
171
|
-
static unsigned
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
case
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
case
|
191
|
-
|
260
|
+
static unsigned int reduceOperand(ruleset *tree,
|
261
|
+
stateNode *state,
|
262
|
+
operand *sourceOperand,
|
263
|
+
jsonObject *messageObject,
|
264
|
+
leftFrameNode *context,
|
265
|
+
jsonProperty **targetProperty) {
|
266
|
+
(*targetProperty)->type = sourceOperand->type;
|
267
|
+
switch(sourceOperand->type) {
|
268
|
+
case JSON_EXPRESSION:
|
269
|
+
case JSON_MESSAGE_EXPRESSION:
|
270
|
+
{
|
271
|
+
expression *currentExpression = &tree->expressionPool[sourceOperand->value.expressionOffset];
|
272
|
+
return reduceExpression(tree,
|
273
|
+
state,
|
274
|
+
currentExpression,
|
275
|
+
messageObject,
|
276
|
+
context,
|
277
|
+
*targetProperty);
|
278
|
+
}
|
279
|
+
case JSON_IDENTIFIER:
|
280
|
+
CHECK_RESULT(getMessageFromFrame(state,
|
281
|
+
context->messages,
|
282
|
+
sourceOperand->value.id.nameHash,
|
283
|
+
&messageObject));
|
284
|
+
// break omitted intentionally, continue to next case
|
285
|
+
case JSON_MESSAGE_IDENTIFIER:
|
286
|
+
CHECK_RESULT(getObjectProperty(messageObject,
|
287
|
+
sourceOperand->value.id.propertyNameHash,
|
288
|
+
targetProperty));
|
289
|
+
return RULES_OK;
|
290
|
+
case JSON_STRING:
|
291
|
+
{
|
292
|
+
char *stringValue = &tree->stringPool[sourceOperand->value.stringOffset];
|
293
|
+
(*targetProperty)->valueLength = strlen(stringValue);
|
294
|
+
(*targetProperty)->valueOffset = 0;
|
295
|
+
(*targetProperty)->value.s = stringValue;
|
296
|
+
return RULES_OK;
|
297
|
+
}
|
298
|
+
case JSON_INT:
|
299
|
+
(*targetProperty)->value.i = sourceOperand->value.i;
|
300
|
+
return RULES_OK;
|
301
|
+
case JSON_DOUBLE:
|
302
|
+
(*targetProperty)->value.d = sourceOperand->value.d;
|
303
|
+
return RULES_OK;
|
304
|
+
case JSON_BOOL:
|
305
|
+
(*targetProperty)->value.b = sourceOperand->value.b;
|
306
|
+
return RULES_OK;
|
192
307
|
}
|
193
308
|
|
194
|
-
return
|
309
|
+
return ERR_OPERATION_NOT_SUPPORTED;
|
195
310
|
}
|
196
311
|
|
197
|
-
static unsigned
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
312
|
+
static unsigned int reduceProperties(unsigned char operator,
|
313
|
+
jsonProperty *leftProperty,
|
314
|
+
jsonProperty *rightProperty,
|
315
|
+
jsonProperty *targetProperty) {
|
316
|
+
unsigned short type = leftProperty->type << 8;
|
317
|
+
type = type + rightProperty->type;
|
318
|
+
switch(type) {
|
319
|
+
case OP_BOOL_BOOL:
|
320
|
+
return reduceBool(leftProperty->value.b, rightProperty->value.b, operator, targetProperty);
|
321
|
+
case OP_BOOL_INT:
|
322
|
+
return reduceInt(leftProperty->value.b, rightProperty->value.i, operator, targetProperty);
|
323
|
+
case OP_BOOL_DOUBLE:
|
324
|
+
return reduceDouble(leftProperty->value.b, rightProperty->value.d, operator, targetProperty);
|
325
|
+
case OP_INT_BOOL:
|
326
|
+
return reduceInt(leftProperty->value.i, rightProperty->value.b, operator, targetProperty);
|
327
|
+
case OP_INT_INT:
|
328
|
+
return reduceInt(leftProperty->value.i, rightProperty->value.i, operator, targetProperty);
|
329
|
+
case OP_INT_DOUBLE:
|
330
|
+
return reduceDouble(leftProperty->value.i, rightProperty->value.d, operator, targetProperty);
|
331
|
+
case OP_DOUBLE_BOOL:
|
332
|
+
return reduceDouble(leftProperty->value.d, rightProperty->value.b, operator, targetProperty);
|
333
|
+
case OP_DOUBLE_INT:
|
334
|
+
return reduceDouble(leftProperty->value.d, rightProperty->value.i, operator, targetProperty);
|
335
|
+
case OP_DOUBLE_DOUBLE:
|
336
|
+
return reduceDouble(leftProperty->value.d, rightProperty->value.d, operator, targetProperty);
|
337
|
+
case OP_BOOL_STRING:
|
338
|
+
if (leftProperty->value.b) {
|
339
|
+
return reduceString("true ",
|
340
|
+
4,
|
341
|
+
rightProperty->value.s,
|
342
|
+
rightProperty->valueLength,
|
343
|
+
operator,
|
344
|
+
targetProperty);
|
345
|
+
}
|
346
|
+
else {
|
347
|
+
return reduceString("false ",
|
348
|
+
5,
|
349
|
+
rightProperty->value.s,
|
350
|
+
rightProperty->valueLength,
|
351
|
+
operator,
|
352
|
+
targetProperty);
|
353
|
+
}
|
354
|
+
case OP_INT_STRING:
|
355
|
+
{
|
356
|
+
#ifdef _WIN32
|
357
|
+
char *leftString = (char *)_alloca(sizeof(char)*(MAX_INT_LENGTH + 1));
|
358
|
+
sprintf_s(leftString, sizeof(char)*(MAX_INT_LENGTH + 1), "%ld", leftProperty->value.i);
|
359
|
+
#else
|
360
|
+
char leftString[MAX_INT_LENGTH + 1];
|
361
|
+
snprintf(leftString, sizeof(char)*(MAX_INT_LENGTH + 1), "%ld", leftProperty->value.i);
|
362
|
+
#endif
|
363
|
+
return reduceString(leftString,
|
364
|
+
leftProperty->valueLength,
|
365
|
+
rightProperty->value.s,
|
366
|
+
rightProperty->valueLength,
|
367
|
+
operator,
|
368
|
+
targetProperty);
|
369
|
+
}
|
370
|
+
case OP_DOUBLE_STRING:
|
371
|
+
{
|
372
|
+
#ifdef _WIN32
|
373
|
+
char *leftString = (char *)_alloca(sizeof(char)*(MAX_DOUBLE_LENGTH + 1));
|
374
|
+
sprintf_s(leftString, sizeof(char)*(MAX_DOUBLE_LENGTH + 1), "%f", leftProperty->value.d);
|
375
|
+
#else
|
376
|
+
char leftString[MAX_DOUBLE_LENGTH + 1];
|
377
|
+
snprintf(leftString, sizeof(char)*(MAX_DOUBLE_LENGTH + 1), "%f", leftProperty->value.d);
|
378
|
+
#endif
|
379
|
+
return reduceString(leftString,
|
380
|
+
leftProperty->valueLength,
|
381
|
+
rightProperty->value.s,
|
382
|
+
rightProperty->valueLength,
|
383
|
+
operator,
|
384
|
+
targetProperty);
|
385
|
+
}
|
386
|
+
case OP_STRING_BOOL:
|
387
|
+
if (rightProperty->value.b) {
|
388
|
+
return reduceString(leftProperty->value.s,
|
389
|
+
leftProperty->valueLength,
|
390
|
+
"true ",
|
391
|
+
4,
|
392
|
+
operator,
|
393
|
+
targetProperty);
|
394
|
+
}
|
395
|
+
else {
|
396
|
+
return reduceString(leftProperty->value.s,
|
397
|
+
leftProperty->valueLength,
|
398
|
+
"false ",
|
399
|
+
5,
|
400
|
+
operator,
|
401
|
+
targetProperty);
|
402
|
+
}
|
403
|
+
case OP_STRING_INT:
|
404
|
+
{
|
405
|
+
#ifdef _WIN32
|
406
|
+
char *rightString = (char *)_alloca(sizeof(char)*(MAX_INT_LENGTH + 1));
|
407
|
+
sprintf_s(rightString, sizeof(char)*(MAX_INT_LENGTH + 1), "%ld", rightProperty->value.i);
|
408
|
+
#else
|
409
|
+
char rightString[MAX_INT_LENGTH + 1];
|
410
|
+
snprintf(rightString, sizeof(char)*(MAX_INT_LENGTH + 1), "%ld", rightProperty->value.i);
|
411
|
+
#endif
|
412
|
+
return reduceString(leftProperty->value.s,
|
413
|
+
leftProperty->valueLength,
|
414
|
+
rightString,
|
415
|
+
rightProperty->valueLength,
|
416
|
+
operator,
|
417
|
+
targetProperty);
|
418
|
+
}
|
419
|
+
case OP_STRING_DOUBLE:
|
420
|
+
{
|
421
|
+
#ifdef _WIN32
|
422
|
+
char *rightString = (char *)_alloca(sizeof(char)*(MAX_DOUBLE_LENGTH + 1));
|
423
|
+
sprintf_s(rightString, sizeof(char)*(MAX_DOUBLE_LENGTH + 1), "%f", rightProperty->value.d);
|
424
|
+
#else
|
425
|
+
char rightString[MAX_DOUBLE_LENGTH + 1];
|
426
|
+
snprintf(rightString, sizeof(char)*(MAX_DOUBLE_LENGTH + 1), "%f", rightProperty->value.d);
|
427
|
+
#endif
|
428
|
+
return reduceString(leftProperty->value.s,
|
429
|
+
leftProperty->valueLength,
|
430
|
+
rightString,
|
431
|
+
rightProperty->valueLength,
|
432
|
+
operator,
|
433
|
+
targetProperty);
|
434
|
+
}
|
435
|
+
case OP_STRING_STRING:
|
436
|
+
return reduceString(leftProperty->value.s,
|
437
|
+
leftProperty->valueLength,
|
438
|
+
rightProperty->value.s,
|
439
|
+
rightProperty->valueLength,
|
440
|
+
operator,
|
441
|
+
targetProperty);
|
442
|
+
case OP_BOOL_NIL:
|
443
|
+
case OP_INT_NIL:
|
444
|
+
case OP_DOUBLE_NIL:
|
445
|
+
case OP_STRING_NIL:
|
446
|
+
targetProperty->type = JSON_BOOL;
|
447
|
+
if (operator == OP_NEQ) {
|
448
|
+
targetProperty->value.b = 1;
|
449
|
+
} else {
|
450
|
+
targetProperty->value.b = 0;
|
451
|
+
}
|
226
452
|
|
227
|
-
|
453
|
+
return RULES_OK;
|
454
|
+
case OP_NIL_NIL:
|
455
|
+
targetProperty->type = JSON_BOOL;
|
456
|
+
if (operator == OP_EQ) {
|
457
|
+
targetProperty->value.b = 1;
|
458
|
+
} else {
|
459
|
+
targetProperty->value.b = 0;
|
460
|
+
}
|
228
461
|
|
229
|
-
|
230
|
-
|
231
|
-
unsigned char op) {
|
232
|
-
switch(op) {
|
233
|
-
case OP_ADD:
|
234
|
-
return left + right;
|
235
|
-
case OP_SUB:
|
236
|
-
return left - right;
|
237
|
-
case OP_MUL:
|
238
|
-
return left * right;
|
239
|
-
case OP_DIV:
|
240
|
-
return left / right;
|
241
|
-
}
|
462
|
+
return RULES_OK;
|
463
|
+
}
|
242
464
|
|
243
|
-
return
|
465
|
+
return ERR_OPERATION_NOT_SUPPORTED;
|
244
466
|
}
|
245
467
|
|
246
|
-
static
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
468
|
+
static unsigned int reduceExpression(ruleset *tree,
|
469
|
+
stateNode *state,
|
470
|
+
expression *currentExpression,
|
471
|
+
jsonObject *messageObject,
|
472
|
+
leftFrameNode *context,
|
473
|
+
jsonProperty *targetProperty) {
|
474
|
+
jsonProperty leftValue;
|
475
|
+
jsonProperty *leftProperty = &leftValue;
|
476
|
+
CHECK_RESULT(reduceOperand(tree,
|
477
|
+
state,
|
478
|
+
¤tExpression->left,
|
479
|
+
messageObject,
|
480
|
+
context,
|
481
|
+
&leftProperty));
|
482
|
+
|
483
|
+
if (currentExpression->right.type == JSON_REGEX || currentExpression->right.type == JSON_IREGEX) {
|
484
|
+
targetProperty->type = JSON_BOOL;
|
485
|
+
targetProperty->value.b = evaluateRegex(tree,
|
486
|
+
leftProperty->value.s,
|
487
|
+
leftProperty->valueLength,
|
488
|
+
(currentExpression->right.type == JSON_REGEX) ? 0 : 1,
|
489
|
+
currentExpression->right.value.regex.vocabularyLength,
|
490
|
+
currentExpression->right.value.regex.statesLength,
|
491
|
+
currentExpression->right.value.regex.stateMachineOffset);
|
492
|
+
return RULES_OK;
|
258
493
|
}
|
259
494
|
|
260
|
-
|
495
|
+
jsonProperty rightValue;
|
496
|
+
jsonProperty *rightProperty = &rightValue;
|
497
|
+
CHECK_RESULT(reduceOperand(tree,
|
498
|
+
state,
|
499
|
+
¤tExpression->right,
|
500
|
+
messageObject,
|
501
|
+
context,
|
502
|
+
&rightProperty));
|
503
|
+
|
504
|
+
return reduceProperties(currentExpression->operator,
|
505
|
+
leftProperty,
|
506
|
+
rightProperty,
|
507
|
+
targetProperty);
|
261
508
|
}
|
262
509
|
|
263
|
-
static
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
510
|
+
static unsigned int reduceExpressionSequence(ruleset *tree,
|
511
|
+
stateNode *state,
|
512
|
+
expressionSequence *exprs,
|
513
|
+
unsigned short operator,
|
514
|
+
jsonObject *messageObject,
|
515
|
+
leftFrameNode *context,
|
516
|
+
unsigned short *i,
|
517
|
+
jsonProperty *targetProperty) {
|
518
|
+
targetProperty->type = JSON_BOOL;
|
519
|
+
targetProperty->value.b = 1;
|
520
|
+
while (*i < exprs->length) {
|
521
|
+
expression *currentExpression = &exprs->expressions[*i];
|
522
|
+
if (currentExpression->operator == OP_END) {
|
523
|
+
return RULES_OK;
|
524
|
+
}
|
269
525
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
void **rulesBinding) {
|
282
|
-
unsigned int result = ERR_UNEXPECTED_VALUE;
|
283
|
-
if (*rulesBinding == NULL) {
|
284
|
-
result = resolveBinding(tree,
|
285
|
-
sid,
|
286
|
-
rulesBinding);
|
287
|
-
if (result != RULES_OK) {
|
288
|
-
return result;
|
289
|
-
}
|
290
|
-
}
|
526
|
+
if ((operator != OP_NOP) &&
|
527
|
+
((operator == OP_OR && targetProperty->value.b) ||
|
528
|
+
(operator == OP_AND && !targetProperty->value.b))) {
|
529
|
+
if (currentExpression->operator == OP_AND || currentExpression->operator == OP_OR) {
|
530
|
+
jsonProperty dummyProperty;
|
531
|
+
dummyProperty.type = JSON_BOOL;
|
532
|
+
if (currentExpression->operator == OP_AND) {
|
533
|
+
dummyProperty.value.b = 0;
|
534
|
+
} else {
|
535
|
+
dummyProperty.value.b = 1;
|
536
|
+
}
|
291
537
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
538
|
+
++*i;
|
539
|
+
CHECK_RESULT(reduceExpressionSequence(tree,
|
540
|
+
state,
|
541
|
+
exprs,
|
542
|
+
currentExpression->operator,
|
543
|
+
messageObject,
|
544
|
+
context,
|
545
|
+
i,
|
546
|
+
&dummyProperty));
|
299
547
|
}
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
548
|
+
} else {
|
549
|
+
if (currentExpression->operator == OP_AND || currentExpression->operator == OP_OR) {
|
550
|
+
++*i;
|
551
|
+
CHECK_RESULT(reduceExpressionSequence(tree,
|
552
|
+
state,
|
553
|
+
exprs,
|
554
|
+
currentExpression->operator,
|
555
|
+
messageObject,
|
556
|
+
context,
|
557
|
+
i,
|
558
|
+
targetProperty));
|
559
|
+
} else if (currentExpression->operator == OP_IALL || currentExpression->operator == OP_IANY) {
|
560
|
+
|
561
|
+
} else {
|
562
|
+
CHECK_RESULT(reduceExpression(tree,
|
563
|
+
state,
|
564
|
+
currentExpression,
|
565
|
+
messageObject,
|
566
|
+
context,
|
567
|
+
targetProperty));
|
568
|
+
if (targetProperty->type != JSON_BOOL) {
|
569
|
+
return ERR_OPERATION_NOT_SUPPORTED;
|
570
|
+
}
|
304
571
|
}
|
572
|
+
}
|
305
573
|
|
306
|
-
|
307
|
-
|
308
|
-
++*evalCount;
|
309
|
-
break;
|
574
|
+
++*i;
|
575
|
+
}
|
310
576
|
|
311
|
-
|
312
|
-
|
313
|
-
if (*addCount == MAX_ADD_COUNT) {
|
314
|
-
return ERR_MAX_ADD_COUNT;
|
315
|
-
}
|
316
|
-
char *addKey = malloc((strlen(prefix) + 1) * sizeof(char));
|
317
|
-
if (addKey == NULL) {
|
318
|
-
return ERR_OUT_OF_MEMORY;
|
319
|
-
}
|
577
|
+
return RULES_OK;
|
578
|
+
}
|
320
579
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
580
|
+
static unsigned int getFrameHashForExpression(ruleset *tree,
|
581
|
+
stateNode *state,
|
582
|
+
expression *currentExpression,
|
583
|
+
jsonObject *messageObject,
|
584
|
+
leftFrameNode *context,
|
585
|
+
unsigned int *hash) {
|
586
|
+
jsonProperty value;
|
587
|
+
jsonProperty *property = &value;
|
588
|
+
*hash = ONE_HASH;
|
589
|
+
|
590
|
+
if (context) {
|
591
|
+
CHECK_RESULT(reduceOperand(tree,
|
592
|
+
state,
|
593
|
+
¤tExpression->right,
|
594
|
+
NULL,
|
595
|
+
context,
|
596
|
+
&property));
|
597
|
+
} else {
|
598
|
+
CHECK_RESULT(reduceOperand(tree,
|
599
|
+
state,
|
600
|
+
¤tExpression->left,
|
601
|
+
messageObject,
|
602
|
+
NULL,
|
603
|
+
&property));
|
604
|
+
}
|
325
605
|
|
326
|
-
|
327
|
-
case
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
if (result != RULES_OK) {
|
336
|
-
return result;
|
337
|
-
}
|
606
|
+
switch (property->type) {
|
607
|
+
case JSON_STRING:
|
608
|
+
*hash = fnv1Hash32(property->value.s, property->valueLength);
|
609
|
+
break;
|
610
|
+
case JSON_BOOL:
|
611
|
+
if (property->value.b) {
|
612
|
+
*hash = fnv1Hash32("true", 4);
|
613
|
+
} else {
|
614
|
+
*hash = fnv1Hash32("false", 5);
|
338
615
|
}
|
339
616
|
break;
|
617
|
+
case JSON_INT:
|
618
|
+
{
|
619
|
+
#ifdef _WIN32
|
620
|
+
char *string = (char *)_alloca(sizeof(char)*(MAX_INT_LENGTH + 1));
|
621
|
+
sprintf_s(string, sizeof(char)*(MAX_INT_LENGTH + 1), "%ld", property->value.i);
|
622
|
+
#else
|
623
|
+
char string[MAX_INT_LENGTH + 1];
|
624
|
+
snprintf(string, sizeof(char)*(MAX_INT_LENGTH + 1), "%ld", property->value.i);
|
625
|
+
#endif
|
626
|
+
*hash = fnv1Hash32(string, strlen(string));
|
627
|
+
break;
|
628
|
+
}
|
629
|
+
case JSON_DOUBLE:
|
630
|
+
{
|
631
|
+
#ifdef _WIN32
|
632
|
+
char *string = (char *)_alloca(sizeof(char)*(MAX_INT_LENGTH + 1));
|
633
|
+
sprintf_s(string, sizeof(char)*(MAX_INT_LENGTH + 1), "%f", property->value.d);
|
634
|
+
#else
|
635
|
+
char string[MAX_INT_LENGTH + 1];
|
636
|
+
snprintf(string, sizeof(char)*(MAX_INT_LENGTH + 1), "%f", property->value.d);
|
637
|
+
#endif
|
638
|
+
*hash = fnv1Hash32(string, strlen(string));
|
639
|
+
break;
|
640
|
+
}
|
340
641
|
}
|
642
|
+
|
341
643
|
return RULES_OK;
|
342
644
|
}
|
343
645
|
|
344
|
-
static unsigned int
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
646
|
+
static unsigned int getFrameHash(ruleset *tree,
|
647
|
+
stateNode *state,
|
648
|
+
beta *currentBeta,
|
649
|
+
jsonObject *messageObject,
|
650
|
+
leftFrameNode *context,
|
651
|
+
unsigned int *hash) {
|
652
|
+
expressionSequence *exprs = ¤tBeta->expressionSequence;
|
653
|
+
*hash = ONE_HASH;
|
654
|
+
if (exprs->length == 1) {
|
655
|
+
if (exprs->expressions[0].operator == OP_EQ) {
|
656
|
+
return getFrameHashForExpression(tree,
|
657
|
+
state,
|
658
|
+
&exprs->expressions[0],
|
659
|
+
messageObject,
|
660
|
+
context,
|
661
|
+
hash);
|
662
|
+
}
|
663
|
+
} else if (exprs->length > 0) {
|
664
|
+
if (exprs->expressions[0].operator == OP_AND) {
|
665
|
+
*hash = FNV_32_OFFSET_BASIS;
|
666
|
+
unsigned int result;
|
667
|
+
for (unsigned int i = 1; i < exprs->length; ++ i) {
|
668
|
+
|
669
|
+
if (exprs->expressions[i].operator == OP_EQ) {
|
670
|
+
unsigned int newHash;
|
671
|
+
result = getFrameHashForExpression(tree,
|
672
|
+
state,
|
673
|
+
&exprs->expressions[i],
|
674
|
+
messageObject,
|
675
|
+
context,
|
676
|
+
&newHash);
|
677
|
+
if (result == RULES_OK) {
|
678
|
+
*hash ^= newHash;
|
679
|
+
*hash *= FNV_32_PRIME;
|
680
|
+
}
|
378
681
|
}
|
379
682
|
}
|
380
|
-
currentNode = &tree->nodePool[currentNode->value.b.nextOffset];
|
381
|
-
}
|
382
|
-
}
|
383
|
-
|
384
|
-
node *actionNode = NULL;
|
385
|
-
#ifdef _WIN32
|
386
|
-
char *prefix = (char *)_alloca(sizeof(char)*(prefixLength));
|
387
|
-
#else
|
388
|
-
char prefix[prefixLength];
|
389
|
-
#endif
|
390
|
-
char *currentPrefix = prefix;
|
391
|
-
currentNode = betaNode;
|
392
|
-
while (currentNode != NULL) {
|
393
|
-
char *name = &tree->stringPool[currentNode->nameOffset];
|
394
|
-
int nameLength = strlen(&tree->stringPool[currentNode->nameOffset]);
|
395
|
-
strncpy(currentPrefix, name, nameLength);
|
396
|
-
|
397
|
-
if (currentNode->type == NODE_ACTION) {
|
398
|
-
currentPrefix[nameLength] = '\0';
|
399
|
-
actionNode = currentNode;
|
400
|
-
currentNode = NULL;
|
401
|
-
}
|
402
|
-
else {
|
403
|
-
currentPrefix[nameLength] = '!';
|
404
|
-
currentPrefix = ¤tPrefix[nameLength + 1];
|
405
|
-
currentNode = &tree->nodePool[currentNode->value.b.nextOffset];
|
406
683
|
}
|
407
684
|
}
|
408
|
-
|
409
|
-
|
410
|
-
mid,
|
411
|
-
prefix,
|
412
|
-
actionNode,
|
413
|
-
actionType,
|
414
|
-
evalKeys,
|
415
|
-
evalCount,
|
416
|
-
addKeys,
|
417
|
-
addCount,
|
418
|
-
removeCommand,
|
419
|
-
rulesBinding);
|
685
|
+
|
686
|
+
return RULES_OK;
|
420
687
|
}
|
421
688
|
|
689
|
+
static unsigned int isBetaMatch(ruleset *tree,
|
690
|
+
stateNode *state,
|
691
|
+
beta *currentBeta,
|
692
|
+
jsonObject *messageObject,
|
693
|
+
leftFrameNode *context,
|
694
|
+
unsigned char *propertyMatch) {
|
422
695
|
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
696
|
+
jsonProperty resultProperty;
|
697
|
+
unsigned short i = 0;
|
698
|
+
CHECK_RESULT(reduceExpressionSequence(tree,
|
699
|
+
state,
|
700
|
+
¤tBeta->expressionSequence,
|
701
|
+
OP_NOP,
|
702
|
+
messageObject,
|
703
|
+
context,
|
704
|
+
&i,
|
705
|
+
&resultProperty));
|
431
706
|
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
case JSON_EVENT_LOCAL_IDIOM:
|
436
|
-
case JSON_STATE_IDIOM:
|
437
|
-
result = reduceIdiom(tree,
|
438
|
-
sid,
|
439
|
-
message,
|
440
|
-
messageObject,
|
441
|
-
sourceValue->value.idiomOffset,
|
442
|
-
state,
|
443
|
-
releaseState,
|
444
|
-
targetProperty);
|
707
|
+
if (resultProperty.type != JSON_BOOL) {
|
708
|
+
return ERR_OPERATION_NOT_SUPPORTED;
|
709
|
+
}
|
445
710
|
|
446
|
-
|
447
|
-
case JSON_EVENT_LOCAL_PROPERTY:
|
448
|
-
for (unsigned short i = 0; i < messageObject->propertiesLength; ++i) {
|
449
|
-
if (sourceValue->value.property.nameHash == messageObject->properties[i].hash) {
|
450
|
-
*targetProperty = &messageObject->properties[i];
|
451
|
-
rehydrateProperty(*targetProperty, message);
|
452
|
-
return RULES_OK;
|
453
|
-
}
|
454
|
-
}
|
711
|
+
*propertyMatch = resultProperty.value.b;
|
455
712
|
|
456
|
-
|
457
|
-
|
458
|
-
if (sourceValue->value.property.idOffset) {
|
459
|
-
sid = &tree->stringPool[sourceValue->value.property.idOffset];
|
460
|
-
}
|
461
|
-
result = fetchStateProperty(tree,
|
462
|
-
sid,
|
463
|
-
sourceValue->value.property.nameHash,
|
464
|
-
MAX_STATE_PROPERTY_TIME,
|
465
|
-
0,
|
466
|
-
state,
|
467
|
-
targetProperty);
|
713
|
+
return RULES_OK;
|
714
|
+
}
|
468
715
|
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
}
|
716
|
+
static unsigned int isAlphaMatch(ruleset *tree,
|
717
|
+
alpha *currentAlpha,
|
718
|
+
jsonObject *messageObject,
|
719
|
+
unsigned char *propertyMatch) {
|
474
720
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
721
|
+
*propertyMatch = 0;
|
722
|
+
if (currentAlpha->expression.operator == OP_EX) {
|
723
|
+
*propertyMatch = 1;
|
724
|
+
} else {
|
725
|
+
jsonProperty resultProperty;
|
726
|
+
unsigned int result = reduceExpression(tree,
|
727
|
+
NULL,
|
728
|
+
¤tAlpha->expression,
|
729
|
+
messageObject,
|
730
|
+
NULL,
|
731
|
+
&resultProperty);
|
732
|
+
|
733
|
+
if (result == ERR_OPERATION_NOT_SUPPORTED || resultProperty.type != JSON_BOOL) {
|
734
|
+
*propertyMatch = 0;
|
735
|
+
} else {
|
736
|
+
*propertyMatch = resultProperty.value.b;
|
737
|
+
}
|
738
|
+
}
|
483
739
|
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
break;
|
493
|
-
case JSON_DOUBLE:
|
494
|
-
(*targetProperty)->value.d = sourceValue->value.d;
|
495
|
-
break;
|
496
|
-
case JSON_BOOL:
|
497
|
-
(*targetProperty)->value.b = sourceValue->value.b;
|
498
|
-
break;
|
740
|
+
return RULES_OK;
|
741
|
+
}
|
742
|
+
|
743
|
+
static unsigned char isDistinct(leftFrameNode *currentFrame, unsigned int currentMessageOffset) {
|
744
|
+
for (unsigned short i = 0; i < currentFrame->messageCount; ++i) {
|
745
|
+
if (currentFrame->messages[currentFrame->reverseIndex[i]].messageNodeOffset == currentMessageOffset) {
|
746
|
+
return 0;
|
747
|
+
}
|
499
748
|
}
|
500
749
|
|
501
|
-
|
502
|
-
(*targetProperty)->type = sourceValue->type;
|
503
|
-
return result;
|
750
|
+
return 1;
|
504
751
|
}
|
505
752
|
|
506
|
-
static unsigned int
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
if (operator != OP_ADD) {
|
520
|
-
*state = (char *)calloc(1, sizeof(char));
|
521
|
-
if (!*state) {
|
522
|
-
return ERR_OUT_OF_MEMORY;
|
523
|
-
}
|
524
|
-
return RULES_OK;
|
753
|
+
static unsigned int handleAction(ruleset *tree,
|
754
|
+
stateNode *state,
|
755
|
+
node *node,
|
756
|
+
frameLocation currentFrameLocation,
|
757
|
+
leftFrameNode *frame) {
|
758
|
+
#ifdef _PRINT
|
759
|
+
|
760
|
+
printf("handle action %s\n", &tree->stringPool[node->nameOffset]);
|
761
|
+
printf("frame %d, %d\n", currentFrameLocation.nodeIndex, currentFrameLocation.frameOffset);
|
762
|
+
for (int i = 0; i < MAX_MESSAGE_FRAMES; ++i) {
|
763
|
+
if (frame->messages[i].hash) {
|
764
|
+
messageNode *node = MESSAGE_NODE(state, frame->messages[i].messageNodeOffset);
|
765
|
+
printf(" %d -> %s\n", frame->messages[i].messageNodeOffset, node->jo.content);
|
525
766
|
}
|
767
|
+
}
|
526
768
|
|
527
|
-
|
528
|
-
leftTemp = *(leftProperty->valueString + leftProperty->valueLength);
|
529
|
-
*(leftProperty->valueString + leftProperty->valueLength) = '\0';
|
530
|
-
}
|
769
|
+
#endif
|
531
770
|
|
532
|
-
|
533
|
-
|
534
|
-
|
771
|
+
return RULES_OK;
|
772
|
+
}
|
773
|
+
|
774
|
+
static unsigned int handleBetaFrame(ruleset *tree,
|
775
|
+
stateNode *state,
|
776
|
+
unsigned int oldMessageOffset,
|
777
|
+
node *oldNode,
|
778
|
+
node *currentNode,
|
779
|
+
leftFrameNode *oldFrame,
|
780
|
+
leftFrameNode *currentFrame) {
|
781
|
+
frameLocation currentFrameLocation;
|
782
|
+
unsigned int frameType = LEFT_FRAME;
|
783
|
+
|
784
|
+
if (currentNode->type == NODE_ACTION) {
|
785
|
+
CHECK_RESULT(createActionFrame(state,
|
786
|
+
currentNode,
|
787
|
+
currentFrame,
|
788
|
+
¤tFrame,
|
789
|
+
¤tFrameLocation));
|
790
|
+
} else if (currentNode->type == NODE_BETA) {
|
791
|
+
CHECK_RESULT(createLeftFrame(state,
|
792
|
+
currentNode,
|
793
|
+
currentFrame,
|
794
|
+
¤tFrame,
|
795
|
+
¤tFrameLocation));
|
796
|
+
} else {
|
797
|
+
node *aNode = &tree->nodePool[currentNode->value.b.aOffset];
|
798
|
+
frameType = (aNode == oldNode) ? A_FRAME : B_FRAME;
|
799
|
+
CHECK_RESULT(createConnectorFrame(state,
|
800
|
+
frameType,
|
801
|
+
currentNode,
|
802
|
+
currentFrame,
|
803
|
+
¤tFrame,
|
804
|
+
¤tFrameLocation));
|
805
|
+
}
|
806
|
+
|
807
|
+
if (oldMessageOffset != UNDEFINED_HASH_OFFSET) {
|
808
|
+
CHECK_RESULT(setMessageInFrame(currentFrame,
|
809
|
+
oldNode->nameOffset,
|
810
|
+
oldNode->value.b.hash,
|
811
|
+
oldMessageOffset));
|
812
|
+
|
813
|
+
CHECK_RESULT(addFrameLocation(state,
|
814
|
+
currentFrameLocation,
|
815
|
+
oldMessageOffset));
|
816
|
+
}
|
817
|
+
|
818
|
+
if (oldFrame) {
|
819
|
+
for (int i = 0; i < oldFrame->messageCount; ++i) {
|
820
|
+
messageFrame *currentMessageFrame = &oldFrame->messages[oldFrame->reverseIndex[i]];
|
821
|
+
CHECK_RESULT(setMessageInFrame(currentFrame,
|
822
|
+
currentMessageFrame->nameOffset,
|
823
|
+
currentMessageFrame->hash,
|
824
|
+
currentMessageFrame->messageNodeOffset));
|
825
|
+
|
826
|
+
CHECK_RESULT(addFrameLocation(state,
|
827
|
+
currentFrameLocation,
|
828
|
+
currentMessageFrame->messageNodeOffset));
|
535
829
|
}
|
536
830
|
}
|
537
831
|
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
832
|
+
unsigned int frameHash = UNDEFINED_HASH_OFFSET;
|
833
|
+
if (currentNode->type == NODE_ACTION) {
|
834
|
+
CHECK_RESULT(setActionFrame(state,
|
835
|
+
currentFrameLocation));
|
836
|
+
|
837
|
+
return handleAction(tree,
|
838
|
+
state,
|
839
|
+
currentNode,
|
840
|
+
currentFrameLocation,
|
841
|
+
currentFrame);
|
842
|
+
} else if (currentNode->type == NODE_BETA) {
|
843
|
+
CHECK_RESULT(getFrameHash(tree,
|
844
|
+
state,
|
845
|
+
¤tNode->value.b,
|
846
|
+
NULL,
|
847
|
+
currentFrame,
|
848
|
+
&frameHash));
|
849
|
+
|
850
|
+
CHECK_RESULT(setLeftFrame(state,
|
851
|
+
frameHash,
|
852
|
+
currentFrameLocation));
|
853
|
+
} else {
|
854
|
+
CHECK_RESULT(setConnectorFrame(state,
|
855
|
+
frameType,
|
856
|
+
currentFrameLocation));
|
857
|
+
}
|
858
|
+
|
859
|
+
|
860
|
+
node *nextNode = &tree->nodePool[currentNode->value.b.nextOffset];
|
861
|
+
if (currentNode->value.b.not) {
|
862
|
+
// Apply filter to frame and clone old closure
|
863
|
+
rightFrameNode *rightFrame = NULL;
|
864
|
+
CHECK_RESULT(getLastRightFrame(state,
|
865
|
+
currentNode->value.b.index,
|
866
|
+
frameHash,
|
867
|
+
&rightFrame));
|
868
|
+
while (rightFrame) {
|
869
|
+
messageNode *rightMessage = MESSAGE_NODE(state, rightFrame->messageOffset);
|
870
|
+
unsigned char match = 0;
|
871
|
+
CHECK_RESULT(isBetaMatch(tree,
|
872
|
+
state,
|
873
|
+
¤tNode->value.b,
|
874
|
+
&rightMessage->jo,
|
875
|
+
currentFrame,
|
876
|
+
&match));
|
877
|
+
if (match) {
|
878
|
+
if (!currentNode->value.b.distinct || isDistinct(currentFrame, rightFrame->messageOffset)) {
|
879
|
+
return RULES_OK;
|
880
|
+
}
|
577
881
|
}
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
targetValue->type = JSON_DOUBLE;
|
590
|
-
break;
|
591
|
-
case OP_DOUBLE_STRING:
|
592
|
-
if (asprintf(state,
|
593
|
-
"%g%s",
|
594
|
-
leftProperty->value.d,
|
595
|
-
rightProperty->valueString) == -1) {
|
596
|
-
return ERR_OUT_OF_MEMORY;
|
882
|
+
|
883
|
+
unsigned int rightFrameOffset = rightFrame->prevOffset;
|
884
|
+
rightFrame = NULL;
|
885
|
+
while (rightFrameOffset != UNDEFINED_HASH_OFFSET && !rightFrame) {
|
886
|
+
rightFrame = RIGHT_FRAME_NODE(state,
|
887
|
+
currentNode->value.b.index,
|
888
|
+
rightFrameOffset);
|
889
|
+
if (rightFrame->hash != frameHash) {
|
890
|
+
rightFrameOffset = rightFrame->prevOffset;
|
891
|
+
rightFrame = NULL;
|
892
|
+
}
|
597
893
|
}
|
894
|
+
}
|
598
895
|
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
896
|
+
return handleBetaFrame(tree,
|
897
|
+
state,
|
898
|
+
UNDEFINED_HASH_OFFSET,
|
899
|
+
currentNode,
|
900
|
+
nextNode,
|
901
|
+
NULL,
|
902
|
+
currentFrame);
|
903
|
+
|
904
|
+
} else if (currentNode->type == NODE_BETA) {
|
905
|
+
// Find all messages for frame
|
906
|
+
rightFrameNode *rightFrame;
|
907
|
+
CHECK_RESULT(getLastRightFrame(state,
|
908
|
+
currentNode->value.b.index,
|
909
|
+
frameHash,
|
910
|
+
&rightFrame));
|
911
|
+
|
912
|
+
|
913
|
+
while (rightFrame) {
|
914
|
+
messageNode *rightMessage = MESSAGE_NODE(state, rightFrame->messageOffset);
|
915
|
+
unsigned char match = 0;
|
916
|
+
CHECK_RESULT(isBetaMatch(tree,
|
917
|
+
state,
|
918
|
+
¤tNode->value.b,
|
919
|
+
&rightMessage->jo,
|
920
|
+
currentFrame,
|
921
|
+
&match));
|
922
|
+
|
923
|
+
if (match && (!currentNode->value.b.distinct || isDistinct(currentFrame, rightFrame->messageOffset))) {
|
924
|
+
CHECK_RESULT(handleBetaFrame(tree,
|
925
|
+
state,
|
926
|
+
rightFrame->messageOffset,
|
927
|
+
currentNode,
|
928
|
+
nextNode,
|
929
|
+
NULL,
|
930
|
+
currentFrame));
|
614
931
|
}
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
932
|
+
|
933
|
+
unsigned int rightFrameOffset = rightFrame->prevOffset;
|
934
|
+
rightFrame = NULL;
|
935
|
+
while (rightFrameOffset != UNDEFINED_HASH_OFFSET && !rightFrame) {
|
936
|
+
rightFrame = RIGHT_FRAME_NODE(state,
|
937
|
+
currentNode->value.b.index,
|
938
|
+
rightFrameOffset);
|
939
|
+
if (rightFrame->hash != frameHash) {
|
940
|
+
rightFrameOffset = rightFrame->prevOffset;
|
941
|
+
rightFrame = NULL;
|
942
|
+
}
|
622
943
|
}
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
944
|
+
}
|
945
|
+
} else {
|
946
|
+
// Get all other frames
|
947
|
+
leftFrameNode *connectorFrame;
|
948
|
+
unsigned int connectorFrameOffset;
|
949
|
+
unsigned int otherFrameType = (frameType == B_FRAME) ? A_FRAME : B_FRAME;
|
950
|
+
CHECK_RESULT(getLastConnectorFrame(state,
|
951
|
+
otherFrameType,
|
952
|
+
currentNode->value.b.index,
|
953
|
+
&connectorFrameOffset,
|
954
|
+
&connectorFrame));
|
955
|
+
|
956
|
+
while (connectorFrame) {
|
957
|
+
CHECK_RESULT(handleBetaFrame(tree,
|
958
|
+
state,
|
959
|
+
UNDEFINED_HASH_OFFSET,
|
960
|
+
currentNode,
|
961
|
+
nextNode,
|
962
|
+
connectorFrame,
|
963
|
+
currentFrame));
|
964
|
+
|
965
|
+
connectorFrameOffset = connectorFrame->prevOffset;
|
966
|
+
if (connectorFrameOffset == UNDEFINED_HASH_OFFSET) {
|
967
|
+
connectorFrame = NULL;
|
968
|
+
} else if (otherFrameType == A_FRAME) {
|
969
|
+
connectorFrame = A_FRAME_NODE(state,
|
970
|
+
currentNode->value.b.index,
|
971
|
+
connectorFrameOffset);
|
972
|
+
} else {
|
973
|
+
connectorFrame = B_FRAME_NODE(state,
|
974
|
+
currentNode->value.b.index,
|
975
|
+
connectorFrameOffset);
|
630
976
|
}
|
631
|
-
break;
|
632
|
-
}
|
633
|
-
|
634
|
-
if (leftProperty->type == JSON_STRING || rightProperty->type == JSON_STRING) {
|
635
|
-
targetValue->type = JSON_STRING;
|
636
|
-
targetValue->valueString = *state;
|
637
|
-
targetValue->valueLength = strlen(*state);
|
638
|
-
|
639
|
-
if (leftTemp) {
|
640
|
-
*(leftProperty->valueString + leftProperty->valueLength) = leftTemp;
|
641
|
-
}
|
642
|
-
|
643
|
-
if (rightTemp) {
|
644
|
-
*(rightProperty->valueString + rightProperty->valueLength) = rightTemp;
|
645
977
|
}
|
646
978
|
}
|
647
979
|
|
980
|
+
if (currentNode->value.b.gateType == GATE_OR || currentNode->value.b.isFirst) {
|
981
|
+
CHECK_RESULT(handleBetaFrame(tree,
|
982
|
+
state,
|
983
|
+
UNDEFINED_HASH_OFFSET,
|
984
|
+
currentNode,
|
985
|
+
nextNode,
|
986
|
+
NULL,
|
987
|
+
currentFrame));
|
988
|
+
}
|
989
|
+
|
648
990
|
return RULES_OK;
|
649
991
|
}
|
650
992
|
|
651
|
-
static unsigned int
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
*releaseState = 0;
|
661
|
-
idiom *currentIdiom = &tree->idiomPool[idiomOffset];
|
662
|
-
jsonProperty leftValue;
|
663
|
-
jsonProperty *leftProperty = &leftValue;
|
664
|
-
unsigned char releaseLeftState = 0;
|
665
|
-
char *leftState = NULL;
|
666
|
-
result = valueToProperty(tree,
|
667
|
-
sid,
|
668
|
-
message,
|
669
|
-
messageObject,
|
670
|
-
¤tIdiom->left,
|
671
|
-
&leftState,
|
672
|
-
&releaseLeftState,
|
673
|
-
&leftProperty);
|
674
|
-
if (result != RULES_OK) {
|
675
|
-
return result;
|
993
|
+
static unsigned int handleDeleteMessage(ruleset *tree,
|
994
|
+
stateNode *state,
|
995
|
+
unsigned int messageOffset) {
|
996
|
+
unsigned int result;
|
997
|
+
unsigned int count = 0;
|
998
|
+
unsigned int i = 1;
|
999
|
+
messageNode *message = MESSAGE_NODE(state, messageOffset);
|
1000
|
+
if (!message->isActive) {
|
1001
|
+
return RULES_OK;
|
676
1002
|
}
|
677
1003
|
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
1004
|
+
while (count < message->locationPool.count) {
|
1005
|
+
locationNode *currentLocationNode = LOCATION_NODE(message, i++);
|
1006
|
+
if (currentLocationNode->isActive) {
|
1007
|
+
++count;
|
1008
|
+
leftFrameNode *frame = NULL;
|
1009
|
+
switch(currentLocationNode->location.frameType) {
|
1010
|
+
case A_FRAME:
|
1011
|
+
frame = A_FRAME_NODE(state,
|
1012
|
+
currentLocationNode->location.nodeIndex,
|
1013
|
+
currentLocationNode->location.frameOffset);
|
1014
|
+
|
1015
|
+
result = deleteConnectorFrame(state,
|
1016
|
+
currentLocationNode->location.frameType,
|
1017
|
+
currentLocationNode->location);
|
1018
|
+
break;
|
1019
|
+
case B_FRAME:
|
1020
|
+
frame = B_FRAME_NODE(state,
|
1021
|
+
currentLocationNode->location.nodeIndex,
|
1022
|
+
currentLocationNode->location.frameOffset);
|
1023
|
+
|
1024
|
+
result = deleteConnectorFrame(state,
|
1025
|
+
currentLocationNode->location.frameType,
|
1026
|
+
currentLocationNode->location);
|
1027
|
+
break;
|
1028
|
+
case LEFT_FRAME:
|
1029
|
+
frame = LEFT_FRAME_NODE(state,
|
1030
|
+
currentLocationNode->location.nodeIndex,
|
1031
|
+
currentLocationNode->location.frameOffset);
|
1032
|
+
|
1033
|
+
result = deleteLeftFrame(state,
|
1034
|
+
currentLocationNode->location);
|
1035
|
+
break;
|
1036
|
+
case ACTION_FRAME:
|
1037
|
+
frame = ACTION_FRAME_NODE(state,
|
1038
|
+
currentLocationNode->location.nodeIndex,
|
1039
|
+
currentLocationNode->location.frameOffset);
|
1040
|
+
|
1041
|
+
result = deleteActionFrame(state,
|
1042
|
+
currentLocationNode->location);
|
1043
|
+
break;
|
1044
|
+
case RIGHT_FRAME:
|
1045
|
+
result = deleteRightFrame(state,
|
1046
|
+
currentLocationNode->location);
|
1047
|
+
break;
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
if (result != RULES_OK && result != ERR_NODE_DISPATCHING && result != ERR_NODE_DELETED) {
|
1051
|
+
return result;
|
1052
|
+
} else if (result == ERR_NODE_DISPATCHING) {
|
1053
|
+
CHECK_RESULT(deleteMessageFromFrame(messageOffset, frame));
|
1054
|
+
} else if (result == RULES_OK) {
|
1055
|
+
if (currentLocationNode->location.frameType != RIGHT_FRAME) {
|
1056
|
+
for (unsigned int ii = 0; ii < frame->messageCount; ++ii) {
|
1057
|
+
messageFrame *currentFrame = &frame->messages[frame->reverseIndex[ii]];
|
1058
|
+
if (currentFrame->messageNodeOffset != messageOffset) {
|
1059
|
+
CHECK_RESULT(deleteFrameLocation(state,
|
1060
|
+
currentFrame->messageNodeOffset,
|
1061
|
+
currentLocationNode->location));
|
1062
|
+
}
|
1063
|
+
}
|
1064
|
+
} else {
|
1065
|
+
node *currentNode = state->betaState[currentLocationNode->location.nodeIndex].reteNode;
|
1066
|
+
if (currentNode->value.b.not) {
|
1067
|
+
if (currentNode->value.b.isFirst) {
|
1068
|
+
if (!state->betaState[currentLocationNode->location.nodeIndex].rightFramePool.count) {
|
1069
|
+
node *nextNode = &tree->nodePool[currentNode->value.b.nextOffset];
|
1070
|
+
CHECK_RESULT(handleBetaFrame(tree,
|
1071
|
+
state,
|
1072
|
+
UNDEFINED_HASH_OFFSET,
|
1073
|
+
currentNode,
|
1074
|
+
nextNode,
|
1075
|
+
NULL,
|
1076
|
+
NULL));
|
1077
|
+
}
|
1078
|
+
} else {
|
1079
|
+
unsigned int messageHash;
|
1080
|
+
CHECK_RESULT(getFrameHash(tree,
|
1081
|
+
state,
|
1082
|
+
¤tNode->value.b,
|
1083
|
+
&message->jo,
|
1084
|
+
NULL,
|
1085
|
+
&messageHash));
|
1086
|
+
|
1087
|
+
node *nextNode = &tree->nodePool[currentNode->value.b.nextOffset];
|
1088
|
+
|
1089
|
+
// Find all frames for message
|
1090
|
+
leftFrameNode *currentFrame = NULL;
|
1091
|
+
CHECK_RESULT(getLastLeftFrame(state,
|
1092
|
+
currentNode->value.b.index,
|
1093
|
+
messageHash,
|
1094
|
+
NULL,
|
1095
|
+
¤tFrame));
|
1096
|
+
while (currentFrame) {
|
1097
|
+
unsigned char match = 0;
|
1098
|
+
CHECK_RESULT(isBetaMatch(tree,
|
1099
|
+
state,
|
1100
|
+
¤tNode->value.b,
|
1101
|
+
&message->jo,
|
1102
|
+
currentFrame,
|
1103
|
+
&match));
|
1104
|
+
|
1105
|
+
if (match && (!currentNode->value.b.distinct || isDistinct(currentFrame, messageOffset))) {
|
1106
|
+
CHECK_RESULT(handleBetaFrame(tree,
|
1107
|
+
state,
|
1108
|
+
UNDEFINED_HASH_OFFSET,
|
1109
|
+
currentNode,
|
1110
|
+
nextNode,
|
1111
|
+
NULL,
|
1112
|
+
currentFrame));
|
1113
|
+
}
|
1114
|
+
|
1115
|
+
unsigned int currentFrameOffset = currentFrame->prevOffset;
|
1116
|
+
currentFrame = NULL;
|
1117
|
+
while (currentFrameOffset != UNDEFINED_HASH_OFFSET) {
|
1118
|
+
currentFrame = LEFT_FRAME_NODE(state,
|
1119
|
+
currentNode->value.b.index,
|
1120
|
+
currentFrameOffset);
|
1121
|
+
if (currentFrame->hash != messageHash) {
|
1122
|
+
currentFrameOffset = currentFrame->prevOffset;
|
1123
|
+
currentFrame = NULL;
|
1124
|
+
} else {
|
1125
|
+
currentFrameOffset = UNDEFINED_HASH_OFFSET;
|
1126
|
+
}
|
1127
|
+
}
|
1128
|
+
}
|
1129
|
+
}
|
1130
|
+
}
|
1131
|
+
}
|
1132
|
+
}
|
693
1133
|
}
|
1134
|
+
}
|
694
1135
|
|
1136
|
+
result = deleteMessage(state, messageOffset);
|
1137
|
+
if (result == ERR_NODE_DELETED) {
|
1138
|
+
return RULES_OK;
|
1139
|
+
} else if (result != RULES_OK) {
|
695
1140
|
return result;
|
696
1141
|
}
|
697
1142
|
|
698
|
-
|
699
|
-
|
700
|
-
leftState,
|
701
|
-
rightProperty,
|
702
|
-
rightState,
|
703
|
-
*targetValue,
|
704
|
-
state);
|
1143
|
+
return RULES_OK;
|
1144
|
+
}
|
705
1145
|
|
706
|
-
|
707
|
-
|
708
|
-
}
|
1146
|
+
static unsigned char isSubset(leftFrameNode *currentFrame,
|
1147
|
+
leftFrameNode *targetFrame) {
|
709
1148
|
|
710
|
-
|
711
|
-
|
712
|
-
|
1149
|
+
for (unsigned int i = 0; i < currentFrame->messageCount; ++i) {
|
1150
|
+
unsigned char found = 0;
|
1151
|
+
for (unsigned int ii = 0; ii < targetFrame->messageCount; ++ii) {
|
1152
|
+
if (currentFrame->messages[currentFrame->reverseIndex[i]].messageNodeOffset ==
|
1153
|
+
targetFrame->messages[targetFrame->reverseIndex[ii]].messageNodeOffset) {
|
1154
|
+
found = 1;
|
1155
|
+
break;
|
1156
|
+
}
|
1157
|
+
}
|
713
1158
|
|
714
|
-
|
715
|
-
|
1159
|
+
if (!found) {
|
1160
|
+
return 0;
|
1161
|
+
}
|
716
1162
|
}
|
717
1163
|
|
718
|
-
return
|
1164
|
+
return 1;
|
719
1165
|
}
|
720
1166
|
|
721
|
-
static unsigned int
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
jsonProperty *currentProperty,
|
726
|
-
alpha *currentAlpha,
|
727
|
-
unsigned char *propertyMatch,
|
728
|
-
void **rulesBinding) {
|
729
|
-
unsigned char alphaOp = currentAlpha->operator;
|
730
|
-
unsigned char propertyType = currentProperty->type;
|
731
|
-
unsigned int result = RULES_OK;
|
732
|
-
*propertyMatch = 0;
|
733
|
-
if (alphaOp == OP_EX) {
|
734
|
-
*propertyMatch = 1;
|
735
|
-
return RULES_OK;
|
736
|
-
}
|
1167
|
+
static unsigned int deleteDownstreamFrames(ruleset *tree,
|
1168
|
+
stateNode *state,
|
1169
|
+
node *currentNode,
|
1170
|
+
leftFrameNode *currentFrame) {
|
737
1171
|
|
738
|
-
|
739
|
-
jsonProperty rightValue;
|
740
|
-
jsonProperty *rightProperty = &rightValue;
|
741
|
-
unsigned char releaseRightState = 0;
|
742
|
-
char *rightState = NULL;
|
743
|
-
result = valueToProperty(tree,
|
744
|
-
sid,
|
745
|
-
message,
|
746
|
-
messageObject,
|
747
|
-
¤tAlpha->right,
|
748
|
-
&rightState,
|
749
|
-
&releaseRightState,
|
750
|
-
&rightProperty);
|
751
|
-
if (result != RULES_OK) {
|
752
|
-
if (releaseRightState) {
|
753
|
-
free(rightState);
|
754
|
-
}
|
1172
|
+
messageNode *currentMessage = NULL;
|
755
1173
|
|
756
|
-
|
757
|
-
|
1174
|
+
// Find message with the smallest location count
|
1175
|
+
for (unsigned int i = 0; i < currentFrame->messageCount; ++i) {
|
1176
|
+
if (currentFrame->messages[i].messageNodeOffset != UNDEFINED_HASH_OFFSET) {
|
1177
|
+
messageNode *message = MESSAGE_NODE(state, currentFrame->messages[i].messageNodeOffset);
|
1178
|
+
if (!currentMessage ||
|
1179
|
+
message->locationPool.count < currentMessage->locationPool.count) {
|
1180
|
+
currentMessage = message;
|
1181
|
+
}
|
758
1182
|
}
|
759
|
-
|
760
|
-
return RULES_OK;
|
761
1183
|
}
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
1184
|
+
|
1185
|
+
if (currentMessage) {
|
1186
|
+
unsigned int i = 1;
|
1187
|
+
unsigned int count = 0;
|
1188
|
+
while (count < currentMessage->locationPool.count) {
|
1189
|
+
locationNode *candidateLocationNode = LOCATION_NODE(currentMessage, i++);
|
1190
|
+
if (candidateLocationNode->isActive) {
|
1191
|
+
++count;
|
1192
|
+
|
1193
|
+
leftFrameNode *candidateFrame = NULL;
|
1194
|
+
if (candidateLocationNode->location.frameType == LEFT_FRAME &&
|
1195
|
+
candidateLocationNode->location.nodeIndex > currentNode->value.b.index) {
|
1196
|
+
candidateFrame = LEFT_FRAME_NODE(state,
|
1197
|
+
candidateLocationNode->location.nodeIndex,
|
1198
|
+
candidateLocationNode->location.frameOffset);
|
1199
|
+
} else if (candidateLocationNode->location.frameType == ACTION_FRAME) {
|
1200
|
+
candidateFrame = ACTION_FRAME_NODE(state,
|
1201
|
+
candidateLocationNode->location.nodeIndex,
|
1202
|
+
candidateLocationNode->location.frameOffset);
|
1203
|
+
}
|
1204
|
+
|
1205
|
+
if (candidateFrame && isSubset(currentFrame, candidateFrame)) {
|
1206
|
+
|
1207
|
+
unsigned int result;
|
1208
|
+
if (candidateLocationNode->location.frameType == LEFT_FRAME) {
|
1209
|
+
result = deleteLeftFrame(state,
|
1210
|
+
candidateLocationNode->location);
|
1211
|
+
} else {
|
1212
|
+
result = deleteActionFrame(state,
|
1213
|
+
candidateLocationNode->location);
|
1214
|
+
}
|
1215
|
+
|
1216
|
+
if (result != ERR_NODE_DELETED && result != ERR_NODE_DISPATCHING && result != RULES_OK) {
|
1217
|
+
return result;
|
1218
|
+
}
|
1219
|
+
}
|
783
1220
|
}
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
1221
|
+
}
|
1222
|
+
}
|
1223
|
+
|
1224
|
+
return RULES_OK;
|
1225
|
+
}
|
1226
|
+
|
1227
|
+
static unsigned int handleFilterFrames(ruleset *tree,
|
1228
|
+
stateNode *state,
|
1229
|
+
node *currentNode,
|
1230
|
+
jsonObject *messageObject,
|
1231
|
+
unsigned int currentMessageOffset,
|
1232
|
+
unsigned int messageHash) {
|
1233
|
+
|
1234
|
+
leftFrameNode *currentFrame = NULL;
|
1235
|
+
frameLocation location;
|
1236
|
+
CHECK_RESULT(getLastLeftFrame(state,
|
1237
|
+
currentNode->value.b.index,
|
1238
|
+
messageHash,
|
1239
|
+
&location,
|
1240
|
+
¤tFrame));
|
1241
|
+
|
1242
|
+
while (currentFrame) {
|
1243
|
+
|
1244
|
+
unsigned char match = 0;
|
1245
|
+
CHECK_RESULT(isBetaMatch(tree,
|
1246
|
+
state,
|
1247
|
+
¤tNode->value.b,
|
1248
|
+
messageObject,
|
1249
|
+
currentFrame,
|
1250
|
+
&match));
|
1251
|
+
|
1252
|
+
if (match) {
|
1253
|
+
if (!currentNode->value.b.distinct || isDistinct(currentFrame, currentMessageOffset)) {
|
1254
|
+
CHECK_RESULT(deleteDownstreamFrames(tree,
|
1255
|
+
state,
|
1256
|
+
currentNode,
|
1257
|
+
currentFrame));
|
789
1258
|
}
|
1259
|
+
}
|
1260
|
+
|
1261
|
+
location.frameOffset = currentFrame->prevOffset;
|
1262
|
+
currentFrame = NULL;
|
1263
|
+
while (location.frameOffset != UNDEFINED_HASH_OFFSET) {
|
1264
|
+
currentFrame = LEFT_FRAME_NODE(state,
|
1265
|
+
location.nodeIndex,
|
1266
|
+
location.frameOffset);
|
790
1267
|
|
791
|
-
|
792
|
-
|
793
|
-
*propertyMatch = compareInt(currentProperty->value.i, rightProperty->value.b, alphaOp);
|
794
|
-
break;
|
795
|
-
case OP_INT_INT:
|
796
|
-
*propertyMatch = compareInt(currentProperty->value.i, rightProperty->value.i, alphaOp);
|
797
|
-
break;
|
798
|
-
case OP_INT_DOUBLE:
|
799
|
-
*propertyMatch = compareDouble(currentProperty->value.i, rightProperty->value.d, alphaOp);
|
800
|
-
break;
|
801
|
-
case OP_INT_STRING:
|
802
|
-
{
|
803
|
-
rightLength = rightProperty->valueLength + 1;
|
804
|
-
#ifdef _WIN32
|
805
|
-
char *leftStringInt = (char *)_alloca(sizeof(char)*(rightLength));
|
806
|
-
sprintf_s(leftStringInt, sizeof(char)*(rightLength), "%ld", currentProperty->value.i);
|
807
|
-
#else
|
808
|
-
char leftStringInt[rightLength];
|
809
|
-
snprintf(leftStringInt, sizeof(char)*(rightLength), "%ld", currentProperty->value.i);
|
810
|
-
#endif
|
811
|
-
*propertyMatch = compareStringProperty(leftStringInt,
|
812
|
-
rightProperty->valueString,
|
813
|
-
rightProperty->valueLength,
|
814
|
-
alphaOp);
|
815
|
-
}
|
816
|
-
break;
|
817
|
-
case OP_DOUBLE_BOOL:
|
818
|
-
*propertyMatch = compareDouble(currentProperty->value.d, rightProperty->value.b, alphaOp);
|
819
|
-
break;
|
820
|
-
case OP_DOUBLE_INT:
|
821
|
-
*propertyMatch = compareDouble(currentProperty->value.d, rightProperty->value.i, alphaOp);
|
822
|
-
break;
|
823
|
-
case OP_DOUBLE_DOUBLE:
|
824
|
-
*propertyMatch = compareDouble(currentProperty->value.d, rightProperty->value.d, alphaOp);
|
825
|
-
break;
|
826
|
-
case OP_DOUBLE_STRING:
|
827
|
-
{
|
828
|
-
rightLength = rightProperty->valueLength + 1;
|
829
|
-
#ifdef _WIN32
|
830
|
-
char *leftStringDouble = (char *)_alloca(sizeof(char)*(rightLength));
|
831
|
-
sprintf_s(leftStringDouble, sizeof(char)*(rightLength), "%f", currentProperty->value.d);
|
832
|
-
#else
|
833
|
-
char leftStringDouble[rightLength];
|
834
|
-
snprintf(leftStringDouble, sizeof(char)*(rightLength), "%f", currentProperty->value.d);
|
835
|
-
#endif
|
836
|
-
*propertyMatch = compareStringProperty(leftStringDouble,
|
837
|
-
rightProperty->valueString,
|
838
|
-
rightProperty->valueLength,
|
839
|
-
alphaOp);
|
840
|
-
}
|
841
|
-
break;
|
842
|
-
case OP_STRING_BOOL:
|
843
|
-
if (rightProperty->value.b) {
|
844
|
-
*propertyMatch = compareString(currentProperty->valueString,
|
845
|
-
currentProperty->valueLength,
|
846
|
-
"true",
|
847
|
-
alphaOp);
|
848
|
-
}
|
849
|
-
else {
|
850
|
-
*propertyMatch = compareString(currentProperty->valueString,
|
851
|
-
currentProperty->valueLength,
|
852
|
-
"false",
|
853
|
-
alphaOp);
|
854
|
-
}
|
855
|
-
break;
|
856
|
-
case OP_STRING_INT:
|
857
|
-
{
|
858
|
-
leftLength = currentProperty->valueLength + 1;
|
859
|
-
#ifdef _WIN32
|
860
|
-
char *rightStringInt = (char *)_alloca(sizeof(char)*(leftLength));
|
861
|
-
sprintf_s(rightStringInt, sizeof(char)*(leftLength), "%ld", rightProperty->value.i);
|
862
|
-
#else
|
863
|
-
char rightStringInt[leftLength];
|
864
|
-
snprintf(rightStringInt, sizeof(char)*(leftLength), "%ld", rightProperty->value.i);
|
865
|
-
#endif
|
866
|
-
*propertyMatch = compareString(currentProperty->valueString,
|
867
|
-
currentProperty->valueLength,
|
868
|
-
rightStringInt,
|
869
|
-
alphaOp);
|
870
|
-
}
|
871
|
-
break;
|
872
|
-
case OP_STRING_DOUBLE:
|
873
|
-
{
|
874
|
-
leftLength = currentProperty->valueLength + 1;
|
875
|
-
#ifdef _WIN32
|
876
|
-
char *rightStringDouble = (char *)_alloca(sizeof(char)*(leftLength));
|
877
|
-
sprintf_s(rightStringDouble, sizeof(char)*(leftLength), "%f", rightProperty->value.d);
|
878
|
-
#else
|
879
|
-
char rightStringDouble[leftLength];
|
880
|
-
snprintf(rightStringDouble, sizeof(char)*(leftLength), "%f", rightProperty->value.d);
|
881
|
-
#endif
|
882
|
-
*propertyMatch = compareString(currentProperty->valueString,
|
883
|
-
currentProperty->valueLength,
|
884
|
-
rightStringDouble,
|
885
|
-
alphaOp);
|
886
|
-
}
|
887
|
-
break;
|
888
|
-
case OP_STRING_STRING:
|
889
|
-
*propertyMatch = compareStringAndStringProperty(currentProperty->valueString,
|
890
|
-
currentProperty->valueLength,
|
891
|
-
rightProperty->valueString,
|
892
|
-
rightProperty->valueLength,
|
893
|
-
alphaOp);
|
894
|
-
break;
|
895
|
-
case OP_BOOL_NIL:
|
896
|
-
case OP_INT_NIL:
|
897
|
-
case OP_DOUBLE_NIL:
|
898
|
-
case OP_STRING_NIL:
|
899
|
-
if (alphaOp == OP_NEQ) {
|
900
|
-
*propertyMatch = 1;
|
1268
|
+
if (currentFrame->hash == messageHash) {
|
1269
|
+
break;
|
901
1270
|
} else {
|
902
|
-
|
903
|
-
|
1271
|
+
location.frameOffset = currentFrame->prevOffset;
|
1272
|
+
currentFrame = NULL;
|
1273
|
+
}
|
1274
|
+
}
|
1275
|
+
}
|
904
1276
|
|
905
|
-
|
906
|
-
|
907
|
-
if (alphaOp == OP_EQ) {
|
908
|
-
*propertyMatch = 1;
|
909
|
-
} else {
|
910
|
-
*propertyMatch = 0;
|
911
|
-
}
|
1277
|
+
return RULES_OK;
|
1278
|
+
}
|
912
1279
|
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
1280
|
+
static unsigned int handleMatchFrames(ruleset *tree,
|
1281
|
+
stateNode *state,
|
1282
|
+
node *currentNode,
|
1283
|
+
jsonObject *messageObject,
|
1284
|
+
unsigned int currentMessageOffset,
|
1285
|
+
unsigned int messageHash) {
|
1286
|
+
// Find frames for message
|
1287
|
+
leftFrameNode *currentFrame = NULL;
|
1288
|
+
node *nextNode = &tree->nodePool[currentNode->value.b.nextOffset];
|
1289
|
+
CHECK_RESULT(getLastLeftFrame(state,
|
1290
|
+
currentNode->value.b.index,
|
1291
|
+
messageHash,
|
1292
|
+
NULL,
|
1293
|
+
¤tFrame));
|
1294
|
+
|
1295
|
+
while (currentFrame) {
|
1296
|
+
unsigned char match = 0;
|
1297
|
+
CHECK_RESULT(isBetaMatch(tree,
|
1298
|
+
state,
|
1299
|
+
¤tNode->value.b,
|
1300
|
+
messageObject,
|
1301
|
+
currentFrame,
|
1302
|
+
&match));
|
1303
|
+
|
1304
|
+
if (match && (!currentNode->value.b.distinct || isDistinct(currentFrame, currentMessageOffset))) {
|
1305
|
+
CHECK_RESULT(handleBetaFrame(tree,
|
1306
|
+
state,
|
1307
|
+
currentMessageOffset,
|
1308
|
+
currentNode,
|
1309
|
+
nextNode,
|
1310
|
+
NULL,
|
1311
|
+
currentFrame));
|
1312
|
+
}
|
924
1313
|
|
1314
|
+
unsigned int currentFrameOffset = currentFrame->prevOffset;
|
1315
|
+
currentFrame = NULL;
|
1316
|
+
while (currentFrameOffset != UNDEFINED_HASH_OFFSET) {
|
1317
|
+
currentFrame = LEFT_FRAME_NODE(state,
|
1318
|
+
currentNode->value.b.index,
|
1319
|
+
currentFrameOffset);
|
1320
|
+
if (currentFrame->hash == messageHash) {
|
1321
|
+
break;
|
1322
|
+
} else {
|
1323
|
+
currentFrameOffset = currentFrame->prevOffset;
|
1324
|
+
currentFrame = NULL;
|
1325
|
+
}
|
1326
|
+
}
|
925
1327
|
}
|
926
|
-
|
927
|
-
if
|
928
|
-
|
1328
|
+
|
1329
|
+
if(currentNode->value.b.gateType == GATE_OR && !currentNode->value.b.expressionSequence.length) {
|
1330
|
+
return handleBetaFrame(tree,
|
1331
|
+
state,
|
1332
|
+
currentMessageOffset,
|
1333
|
+
currentNode,
|
1334
|
+
nextNode,
|
1335
|
+
NULL,
|
1336
|
+
NULL);
|
929
1337
|
}
|
930
|
-
|
1338
|
+
|
1339
|
+
return RULES_OK;
|
931
1340
|
}
|
932
1341
|
|
933
|
-
static unsigned int
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
1342
|
+
static unsigned int handleBetaMessage(ruleset *tree,
|
1343
|
+
stateNode *state,
|
1344
|
+
node *betaNode,
|
1345
|
+
jsonObject *messageObject,
|
1346
|
+
unsigned int currentMessageOffset) {
|
1347
|
+
if (betaNode->value.b.isFirst && !betaNode->value.b.not) {
|
1348
|
+
node *nextNode = &tree->nodePool[betaNode->value.b.nextOffset];
|
1349
|
+
return handleBetaFrame(tree,
|
1350
|
+
state,
|
1351
|
+
currentMessageOffset,
|
1352
|
+
betaNode,
|
1353
|
+
nextNode,
|
1354
|
+
NULL,
|
1355
|
+
NULL);
|
1356
|
+
}
|
1357
|
+
|
1358
|
+
frameLocation rightFrameLocation;
|
1359
|
+
rightFrameNode *rightFrame;
|
1360
|
+
|
1361
|
+
CHECK_RESULT(createRightFrame(state,
|
1362
|
+
betaNode,
|
1363
|
+
&rightFrame,
|
1364
|
+
&rightFrameLocation));
|
1365
|
+
|
1366
|
+
unsigned int messageHash;
|
1367
|
+
CHECK_RESULT(getFrameHash(tree,
|
1368
|
+
state,
|
1369
|
+
&betaNode->value.b,
|
1370
|
+
messageObject,
|
1371
|
+
NULL,
|
1372
|
+
&messageHash));
|
1373
|
+
|
1374
|
+
rightFrame->messageOffset = currentMessageOffset;
|
1375
|
+
CHECK_RESULT(addFrameLocation(state,
|
1376
|
+
rightFrameLocation,
|
1377
|
+
currentMessageOffset));
|
1378
|
+
|
1379
|
+
CHECK_RESULT(setRightFrame(state,
|
1380
|
+
messageHash,
|
1381
|
+
rightFrameLocation));
|
1382
|
+
|
1383
|
+
if (betaNode->value.b.not) {
|
1384
|
+
return handleFilterFrames(tree,
|
1385
|
+
state,
|
1386
|
+
betaNode,
|
1387
|
+
messageObject,
|
1388
|
+
currentMessageOffset,
|
1389
|
+
messageHash);
|
1390
|
+
}
|
1391
|
+
|
1392
|
+
return handleMatchFrames(tree,
|
1393
|
+
state,
|
1394
|
+
betaNode,
|
1395
|
+
messageObject,
|
1396
|
+
currentMessageOffset,
|
1397
|
+
messageHash);
|
1398
|
+
}
|
1399
|
+
|
1400
|
+
|
1401
|
+
static unsigned int handleAplhaArray(ruleset *tree,
|
1402
|
+
jsonObject *messageObject,
|
1403
|
+
jsonProperty *currentProperty,
|
1404
|
+
alpha *arrayAlpha,
|
1405
|
+
unsigned char *propertyMatch) {
|
941
1406
|
unsigned int result = RULES_OK;
|
942
1407
|
if (currentProperty->type != JSON_ARRAY) {
|
943
1408
|
return RULES_OK;
|
944
1409
|
}
|
945
1410
|
|
946
|
-
char *first = currentProperty->
|
1411
|
+
char *first = messageObject->content + currentProperty->valueOffset;
|
947
1412
|
char *last;
|
948
1413
|
unsigned char type;
|
949
1414
|
jsonObject jo;
|
@@ -957,25 +1422,26 @@ static unsigned int isArrayMatch(ruleset *tree,
|
|
957
1422
|
if (type == JSON_OBJECT) {
|
958
1423
|
char *next;
|
959
1424
|
jo.propertiesLength = 0;
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
1425
|
+
jo.content = first;
|
1426
|
+
jo.idIndex = UNDEFINED_INDEX;
|
1427
|
+
jo.sidIndex = UNDEFINED_INDEX;
|
1428
|
+
memset(jo.propertyIndex, 0, MAX_OBJECT_PROPERTIES * sizeof(unsigned short));
|
1429
|
+
|
1430
|
+
CHECK_RESULT(constructObject(first,
|
1431
|
+
"$i",
|
1432
|
+
NULL,
|
1433
|
+
0,
|
1434
|
+
&jo,
|
1435
|
+
&next));
|
970
1436
|
} else {
|
971
|
-
jo.
|
972
|
-
jo.
|
973
|
-
jo.
|
974
|
-
jo
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
1437
|
+
memset(jo.propertyIndex, 0, MAX_OBJECT_PROPERTIES * sizeof(unsigned short));
|
1438
|
+
jo.propertiesLength = 0;
|
1439
|
+
jo.content = first;
|
1440
|
+
CHECK_RESULT(setObjectProperty(&jo,
|
1441
|
+
HASH_I,
|
1442
|
+
type,
|
1443
|
+
0,
|
1444
|
+
last - first + 1));
|
979
1445
|
}
|
980
1446
|
|
981
1447
|
while (top) {
|
@@ -988,7 +1454,7 @@ static unsigned int isArrayMatch(ruleset *tree,
|
|
988
1454
|
node *listNode = &tree->nodePool[nextList[entry]];
|
989
1455
|
char exists = 0;
|
990
1456
|
for(unsigned int propertyIndex = 0; propertyIndex < jo.propertiesLength; ++propertyIndex) {
|
991
|
-
if (listNode->value.a.
|
1457
|
+
if (listNode->value.a.expression.left.value.id.propertyNameHash == jo.properties[propertyIndex].hash) {
|
992
1458
|
// filter out not exists (OP_NEX)
|
993
1459
|
exists = 1;
|
994
1460
|
break;
|
@@ -1013,27 +1479,20 @@ static unsigned int isArrayMatch(ruleset *tree,
|
|
1013
1479
|
jsonProperty *currentProperty = &jo.properties[propertyIndex];
|
1014
1480
|
for (unsigned int entry = currentProperty->hash & HASH_MASK; nextHashset[entry] != 0; entry = (entry + 1) % NEXT_BUCKET_LENGTH) {
|
1015
1481
|
node *hashNode = &tree->nodePool[nextHashset[entry]];
|
1016
|
-
if (currentProperty->hash == hashNode->value.a.
|
1482
|
+
if (currentProperty->hash == hashNode->value.a.expression.left.value.id.propertyNameHash) {
|
1017
1483
|
unsigned char match = 0;
|
1018
|
-
if (hashNode->value.a.operator == OP_IALL || hashNode->value.a.operator == OP_IANY) {
|
1019
|
-
//
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
&hashNode->value.a,
|
1026
|
-
propertyMatch,
|
1027
|
-
rulesBinding);
|
1484
|
+
if (hashNode->value.a.expression.operator == OP_IALL || hashNode->value.a.expression.operator == OP_IANY) {
|
1485
|
+
// handleAplhaArray finds a valid path, thus use propertyMatch
|
1486
|
+
CHECK_RESULT(handleAplhaArray(tree,
|
1487
|
+
&jo,
|
1488
|
+
currentProperty,
|
1489
|
+
&hashNode->value.a,
|
1490
|
+
propertyMatch));
|
1028
1491
|
} else {
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
currentProperty,
|
1034
|
-
&hashNode->value.a,
|
1035
|
-
&match,
|
1036
|
-
rulesBinding);
|
1492
|
+
CHECK_RESULT(isAlphaMatch(tree,
|
1493
|
+
&hashNode->value.a,
|
1494
|
+
&jo,
|
1495
|
+
&match));
|
1037
1496
|
|
1038
1497
|
if (match) {
|
1039
1498
|
if (top == MAX_STACK_SIZE) {
|
@@ -1044,10 +1503,6 @@ static unsigned int isArrayMatch(ruleset *tree,
|
|
1044
1503
|
++top;
|
1045
1504
|
}
|
1046
1505
|
}
|
1047
|
-
|
1048
|
-
if (result != RULES_OK) {
|
1049
|
-
return result;
|
1050
|
-
}
|
1051
1506
|
}
|
1052
1507
|
}
|
1053
1508
|
}
|
@@ -1062,8 +1517,8 @@ static unsigned int isArrayMatch(ruleset *tree,
|
|
1062
1517
|
|
1063
1518
|
// OP_IANY, one element led a a valid path
|
1064
1519
|
// OP_IALL, all elements led to a valid path
|
1065
|
-
if ((arrayAlpha->operator == OP_IALL && !*propertyMatch) ||
|
1066
|
-
(arrayAlpha->operator == OP_IANY && *propertyMatch)) {
|
1520
|
+
if ((arrayAlpha->expression.operator == OP_IALL && !*propertyMatch) ||
|
1521
|
+
(arrayAlpha->expression.operator == OP_IANY && *propertyMatch)) {
|
1067
1522
|
break;
|
1068
1523
|
}
|
1069
1524
|
|
@@ -1073,25 +1528,19 @@ static unsigned int isArrayMatch(ruleset *tree,
|
|
1073
1528
|
return (result == PARSE_END ? RULES_OK: result);
|
1074
1529
|
}
|
1075
1530
|
|
1076
|
-
static unsigned int handleAlpha(ruleset *tree,
|
1077
|
-
|
1531
|
+
static unsigned int handleAlpha(ruleset *tree,
|
1532
|
+
stateNode *state,
|
1078
1533
|
char *mid,
|
1079
|
-
char *message,
|
1080
1534
|
jsonObject *jo,
|
1081
|
-
|
1082
|
-
|
1083
|
-
char **evalKeys,
|
1084
|
-
unsigned int *evalCount,
|
1085
|
-
char **addKeys,
|
1086
|
-
unsigned int *addCount,
|
1087
|
-
char **removeCommand,
|
1088
|
-
void **rulesBinding) {
|
1089
|
-
unsigned int result = ERR_EVENT_NOT_HANDLED;
|
1535
|
+
unsigned int currentMessageOffset,
|
1536
|
+
alpha *alphaNode) {
|
1090
1537
|
unsigned short top = 1;
|
1091
1538
|
unsigned int entry;
|
1092
1539
|
alpha *stack[MAX_STACK_SIZE];
|
1093
1540
|
stack[0] = alphaNode;
|
1094
1541
|
alpha *currentAlpha;
|
1542
|
+
unsigned int result = ERR_EVENT_NOT_HANDLED;
|
1543
|
+
|
1095
1544
|
while (top) {
|
1096
1545
|
--top;
|
1097
1546
|
currentAlpha = stack[top];
|
@@ -1100,16 +1549,10 @@ static unsigned int handleAlpha(ruleset *tree,
|
|
1100
1549
|
unsigned int *nextList = &tree->nextPool[currentAlpha->nextListOffset];
|
1101
1550
|
for (entry = 0; nextList[entry] != 0; ++entry) {
|
1102
1551
|
node *listNode = &tree->nodePool[nextList[entry]];
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
exists = 1;
|
1108
|
-
break;
|
1109
|
-
}
|
1110
|
-
}
|
1111
|
-
|
1112
|
-
if (!exists) {
|
1552
|
+
jsonProperty *property;
|
1553
|
+
unsigned int aresult = getObjectProperty(jo, listNode->value.a.expression.left.value.id.propertyNameHash, &property);
|
1554
|
+
if (aresult == ERR_PROPERTY_NOT_FOUND) {
|
1555
|
+
// filter out not exists (OP_NEX)
|
1113
1556
|
if (top == MAX_STACK_SIZE) {
|
1114
1557
|
return ERR_MAX_STACK_SIZE;
|
1115
1558
|
}
|
@@ -1127,8 +1570,8 @@ static unsigned int handleAlpha(ruleset *tree,
|
|
1127
1570
|
jsonProperty *currentProperty = &jo->properties[propertyIndex];
|
1128
1571
|
for (entry = currentProperty->hash & HASH_MASK; nextHashset[entry] != 0; entry = (entry + 1) % NEXT_BUCKET_LENGTH) {
|
1129
1572
|
node *hashNode = &tree->nodePool[nextHashset[entry]];
|
1130
|
-
if (currentProperty->hash == hashNode->value.a.
|
1131
|
-
if (hashNode->value.a.right.type ==
|
1573
|
+
if (currentProperty->hash == hashNode->value.a.expression.left.value.id.propertyNameHash) {
|
1574
|
+
if (hashNode->value.a.expression.right.type == JSON_IDENTIFIER || hashNode->value.a.expression.right.type == JSON_EXPRESSION) {
|
1132
1575
|
if (top == MAX_STACK_SIZE) {
|
1133
1576
|
return ERR_MAX_STACK_SIZE;
|
1134
1577
|
}
|
@@ -1136,29 +1579,17 @@ static unsigned int handleAlpha(ruleset *tree,
|
|
1136
1579
|
++top;
|
1137
1580
|
} else {
|
1138
1581
|
unsigned char match = 0;
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
currentProperty,
|
1146
|
-
&hashNode->value.a,
|
1147
|
-
&match,
|
1148
|
-
rulesBinding);
|
1582
|
+
if (hashNode->value.a.expression.operator == OP_IALL || hashNode->value.a.expression.operator == OP_IANY) {
|
1583
|
+
CHECK_RESULT(handleAplhaArray(tree,
|
1584
|
+
jo,
|
1585
|
+
currentProperty,
|
1586
|
+
&hashNode->value.a,
|
1587
|
+
&match));
|
1149
1588
|
} else {
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
currentProperty,
|
1155
|
-
&hashNode->value.a,
|
1156
|
-
&match,
|
1157
|
-
rulesBinding);
|
1158
|
-
}
|
1159
|
-
|
1160
|
-
if (mresult != RULES_OK){
|
1161
|
-
return mresult;
|
1589
|
+
CHECK_RESULT(isAlphaMatch(tree,
|
1590
|
+
&hashNode->value.a,
|
1591
|
+
jo,
|
1592
|
+
&match));
|
1162
1593
|
}
|
1163
1594
|
|
1164
1595
|
if (match) {
|
@@ -1176,26 +1607,14 @@ static unsigned int handleAlpha(ruleset *tree,
|
|
1176
1607
|
}
|
1177
1608
|
|
1178
1609
|
if (currentAlpha->betaListOffset) {
|
1610
|
+
result = RULES_OK;
|
1179
1611
|
unsigned int *betaList = &tree->nextPool[currentAlpha->betaListOffset];
|
1180
1612
|
for (unsigned int entry = 0; betaList[entry] != 0; ++entry) {
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
evalKeys,
|
1187
|
-
evalCount,
|
1188
|
-
addKeys,
|
1189
|
-
addCount,
|
1190
|
-
removeCommand,
|
1191
|
-
rulesBinding);
|
1192
|
-
if (bresult != RULES_OK && bresult != ERR_NEW_SESSION) {
|
1193
|
-
return result;
|
1194
|
-
}
|
1195
|
-
|
1196
|
-
if (result != ERR_NEW_SESSION) {
|
1197
|
-
result = bresult;
|
1198
|
-
}
|
1613
|
+
CHECK_RESULT(handleBetaMessage(tree,
|
1614
|
+
state,
|
1615
|
+
&tree->nodePool[betaList[entry]],
|
1616
|
+
jo,
|
1617
|
+
currentMessageOffset));
|
1199
1618
|
}
|
1200
1619
|
}
|
1201
1620
|
}
|
@@ -1204,256 +1623,158 @@ static unsigned int handleAlpha(ruleset *tree,
|
|
1204
1623
|
}
|
1205
1624
|
|
1206
1625
|
static unsigned int handleMessageCore(ruleset *tree,
|
1207
|
-
char *state,
|
1208
|
-
char *message,
|
1209
1626
|
jsonObject *jo,
|
1210
1627
|
unsigned char actionType,
|
1211
|
-
|
1212
|
-
unsigned int *
|
1213
|
-
|
1214
|
-
unsigned int result;
|
1215
|
-
char *storeCommand;
|
1628
|
+
unsigned int *messageOffset,
|
1629
|
+
unsigned int *stateOffset) {
|
1630
|
+
stateNode *sidState;
|
1216
1631
|
jsonProperty *sidProperty = &jo->properties[jo->sidIndex];
|
1217
1632
|
jsonProperty *midProperty = &jo->properties[jo->idIndex];
|
1218
|
-
|
1633
|
+
|
1219
1634
|
#ifdef _WIN32
|
1220
1635
|
char *sid = (char *)_alloca(sizeof(char)*(sidProperty->valueLength + 1));
|
1221
1636
|
#else
|
1222
1637
|
char sid[sidProperty->valueLength + 1];
|
1223
1638
|
#endif
|
1224
|
-
|
1639
|
+
if (sidProperty->valueOffset) {
|
1640
|
+
strncpy(sid, jo->content + sidProperty->valueOffset, sidProperty->valueLength);
|
1641
|
+
} else {
|
1642
|
+
strncpy(sid, jo->sidBuffer, sidProperty->valueLength);
|
1643
|
+
}
|
1644
|
+
|
1225
1645
|
sid[sidProperty->valueLength] = '\0';
|
1226
|
-
|
1227
|
-
#ifdef _WIN32
|
1646
|
+
|
1647
|
+
#ifdef _WIN32
|
1228
1648
|
char *mid = (char *)_alloca(sizeof(char)*(midProperty->valueLength + 1));
|
1229
1649
|
#else
|
1230
1650
|
char mid[midProperty->valueLength + 1];
|
1231
1651
|
#endif
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
return ERR_MAX_COMMAND_COUNT;
|
1237
|
-
}
|
1238
|
-
|
1239
|
-
if (state) {
|
1240
|
-
if (!*rulesBinding) {
|
1241
|
-
result = resolveBinding(tree, sid, rulesBinding);
|
1242
|
-
if (result != RULES_OK) {
|
1243
|
-
return result;
|
1244
|
-
}
|
1245
|
-
}
|
1246
|
-
|
1247
|
-
result = formatStoreSession(*rulesBinding, sid, state, 0, &storeCommand);
|
1248
|
-
if (result != RULES_OK) {
|
1249
|
-
return result;
|
1250
|
-
}
|
1251
|
-
|
1252
|
-
commands[*commandCount] = storeCommand;
|
1253
|
-
++*commandCount;
|
1652
|
+
if (midProperty->valueOffset) {
|
1653
|
+
strncpy(mid, jo->content + midProperty->valueOffset, midProperty->valueLength);
|
1654
|
+
} else {
|
1655
|
+
strncpy(mid, jo->idBuffer, midProperty->valueLength);
|
1254
1656
|
}
|
1255
|
-
char *removeCommand = NULL;
|
1256
|
-
char *addKeys[MAX_ADD_COUNT];
|
1257
|
-
unsigned int addCount = 0;
|
1258
|
-
char *evalKeys[MAX_EVAL_COUNT];
|
1259
|
-
unsigned int evalCount = 0;
|
1260
|
-
result = handleAlpha(tree,
|
1261
|
-
sid,
|
1262
|
-
mid,
|
1263
|
-
message,
|
1264
|
-
jo,
|
1265
|
-
&tree->nodePool[NODE_M_OFFSET].value.a,
|
1266
|
-
actionType,
|
1267
|
-
evalKeys,
|
1268
|
-
&evalCount,
|
1269
|
-
addKeys,
|
1270
|
-
&addCount,
|
1271
|
-
&removeCommand,
|
1272
|
-
rulesBinding);
|
1273
|
-
if (result == RULES_OK) {
|
1274
|
-
if (*commandCount == MAX_COMMAND_COUNT - 3) {
|
1275
|
-
for (unsigned int i = 0; i < addCount; ++i) {
|
1276
|
-
free(addKeys[i]);
|
1277
|
-
}
|
1278
|
-
|
1279
|
-
for (unsigned int i = 0; i < evalCount; ++i) {
|
1280
|
-
free(evalKeys[i]);
|
1281
|
-
}
|
1282
|
-
|
1283
|
-
return ERR_MAX_COMMAND_COUNT;
|
1284
|
-
}
|
1285
|
-
|
1286
|
-
if (removeCommand) {
|
1287
|
-
commands[*commandCount] = removeCommand;
|
1288
|
-
++*commandCount;
|
1289
|
-
}
|
1290
|
-
|
1291
|
-
if (addCount > 0) {
|
1292
|
-
char *addCommand = NULL;
|
1293
|
-
result = formatStoreMessage(*rulesBinding,
|
1294
|
-
sid,
|
1295
|
-
message,
|
1296
|
-
jo,
|
1297
|
-
actionType == ACTION_ASSERT_FACT ? 1 : 0,
|
1298
|
-
evalCount == 0 ? 1 : 0,
|
1299
|
-
addKeys,
|
1300
|
-
addCount,
|
1301
|
-
&addCommand);
|
1302
|
-
for (unsigned int i = 0; i < addCount; ++i) {
|
1303
|
-
free(addKeys[i]);
|
1304
|
-
}
|
1305
|
-
|
1306
|
-
if (result != RULES_OK) {
|
1307
|
-
for (unsigned int i = 0; i < evalCount; ++i) {
|
1308
|
-
free(evalKeys[i]);
|
1309
|
-
}
|
1310
|
-
|
1311
|
-
return result;
|
1312
|
-
}
|
1313
|
-
|
1314
|
-
commands[*commandCount] = addCommand;
|
1315
|
-
++*commandCount;
|
1316
|
-
}
|
1317
|
-
|
1318
|
-
if (evalCount > 0) {
|
1319
|
-
char *evalCommand = NULL;
|
1320
|
-
result = formatEvalMessage(*rulesBinding,
|
1321
|
-
sid,
|
1322
|
-
mid,
|
1323
|
-
message,
|
1324
|
-
jo,
|
1325
|
-
actionType == ACTION_REMOVE_FACT ? ACTION_RETRACT_FACT : actionType,
|
1326
|
-
evalKeys,
|
1327
|
-
evalCount,
|
1328
|
-
&evalCommand);
|
1329
|
-
|
1330
|
-
for (unsigned int i = 0; i < evalCount; ++i) {
|
1331
|
-
free(evalKeys[i]);
|
1332
|
-
}
|
1333
1657
|
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1658
|
+
mid[midProperty->valueLength] = '\0';
|
1659
|
+
unsigned char isNewState;
|
1660
|
+
CHECK_RESULT(ensureStateNode(tree,
|
1661
|
+
sid,
|
1662
|
+
&isNewState,
|
1663
|
+
&sidState));
|
1664
|
+
|
1665
|
+
*stateOffset = sidState->offset;
|
1666
|
+
if (actionType == ACTION_UPDATE_STATE) {
|
1667
|
+
if (sidState->factOffset != UNDEFINED_HASH_OFFSET) {
|
1668
|
+
CHECK_RESULT(handleDeleteMessage(tree,
|
1669
|
+
sidState,
|
1670
|
+
sidState->factOffset));
|
1337
1671
|
|
1338
|
-
commands[*commandCount] = evalCommand;
|
1339
|
-
++*commandCount;
|
1340
1672
|
}
|
1341
1673
|
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1674
|
+
CHECK_RESULT(storeMessage(sidState,
|
1675
|
+
mid,
|
1676
|
+
jo,
|
1677
|
+
MESSAGE_TYPE_FACT,
|
1678
|
+
messageOffset));
|
1679
|
+
|
1680
|
+
|
1681
|
+
sidState->factOffset = *messageOffset;
|
1682
|
+
CHECK_RESULT(handleAlpha(tree,
|
1683
|
+
sidState,
|
1684
|
+
mid,
|
1685
|
+
jo,
|
1686
|
+
sidState->factOffset,
|
1687
|
+
&tree->nodePool[NODE_M_OFFSET].value.a));
|
1688
|
+
|
1689
|
+
} else if (actionType == ACTION_RETRACT_FACT || actionType == ACTION_RETRACT_EVENT) {
|
1690
|
+
CHECK_RESULT(getMessage(sidState,
|
1691
|
+
mid,
|
1692
|
+
messageOffset));
|
1693
|
+
|
1694
|
+
if (*messageOffset != UNDEFINED_HASH_OFFSET) {
|
1695
|
+
CHECK_RESULT(handleDeleteMessage(tree,
|
1696
|
+
sidState,
|
1697
|
+
*messageOffset));
|
1698
|
+
}
|
1699
|
+
} else {
|
1700
|
+
CHECK_RESULT(storeMessage(sidState,
|
1701
|
+
mid,
|
1702
|
+
jo,
|
1703
|
+
(actionType == ACTION_ASSERT_FACT ? MESSAGE_TYPE_FACT : MESSAGE_TYPE_EVENT),
|
1704
|
+
messageOffset));
|
1705
|
+
|
1706
|
+
unsigned int result = handleAlpha(tree,
|
1707
|
+
sidState,
|
1708
|
+
mid,
|
1709
|
+
jo,
|
1710
|
+
*messageOffset,
|
1711
|
+
&tree->nodePool[NODE_M_OFFSET].value.a);
|
1712
|
+
|
1713
|
+
if (result == RULES_OK || result == ERR_EVENT_NOT_HANDLED) {
|
1714
|
+
if (isNewState) {
|
1366
1715
|
#ifdef _WIN32
|
1367
|
-
|
1368
|
-
|
1369
|
-
sprintf_s(stateMessage, sizeof(char)*(26 + sidProperty->valueLength), "{\"sid\":\"%s\", \"$s\":1}", sid);
|
1370
|
-
sprintf_s(newState, sizeof(char)*(12 + sidProperty->valueLength), "{\"sid\":\"%s\"}", sid);
|
1716
|
+
char *stateMessage = (char *)_alloca(sizeof(char)*(50 + sidProperty->valueLength * 2));
|
1717
|
+
sprintf_s(stateMessage, sizeof(char)*(50 + sidProperty->valueLength * 2), "{ \"sid\":\"%s\", \"id\":\"sid-%s\", \"$s\":1}", sid, sid);
|
1371
1718
|
#else
|
1372
|
-
|
1373
|
-
|
1374
|
-
snprintf(stateMessage, sizeof(char)*(26 + sidProperty->valueLength), "{\"sid\":\"%s\", \"$s\":1}", sid);
|
1375
|
-
snprintf(newState, sizeof(char)*(12 + sidProperty->valueLength), "{\"sid\":\"%s\"}", sid);
|
1719
|
+
char stateMessage[50 + sidProperty->valueLength * 2];
|
1720
|
+
snprintf(stateMessage, sizeof(char)*(50 + sidProperty->valueLength * 2), "{ \"sid\":\"%s\", \"id\":\"sid-%s\", \"$s\":1}", sid, sid);
|
1376
1721
|
#endif
|
1722
|
+
|
1723
|
+
unsigned int stateMessageOffset;
|
1724
|
+
unsigned int stateResult = handleMessage(tree,
|
1725
|
+
stateMessage,
|
1726
|
+
ACTION_ASSERT_FACT,
|
1727
|
+
&stateMessageOffset,
|
1728
|
+
stateOffset);
|
1729
|
+
if (stateResult != RULES_OK && stateResult != ERR_EVENT_NOT_HANDLED) {
|
1730
|
+
return stateResult;
|
1731
|
+
}
|
1377
1732
|
|
1378
|
-
|
1379
|
-
return ERR_MAX_COMMAND_COUNT;
|
1380
|
-
}
|
1381
|
-
|
1382
|
-
result = formatStoreSession(*rulesBinding, sid, newState, 1, &storeCommand);
|
1383
|
-
if (result != RULES_OK) {
|
1384
|
-
return result;
|
1385
|
-
}
|
1386
|
-
|
1387
|
-
commands[*commandCount] = storeCommand;
|
1388
|
-
++*commandCount;
|
1389
|
-
result = handleMessage(tree,
|
1390
|
-
NULL,
|
1391
|
-
stateMessage,
|
1392
|
-
ACTION_ASSERT_EVENT,
|
1393
|
-
commands,
|
1394
|
-
commandCount,
|
1395
|
-
rulesBinding);
|
1396
|
-
if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
|
1397
|
-
return result;
|
1398
|
-
}
|
1733
|
+
sidState->factOffset = stateMessageOffset;
|
1399
1734
|
|
1400
|
-
if (result == ERR_EVENT_NOT_HANDLED) {
|
1401
|
-
return RULES_OK;
|
1402
1735
|
}
|
1403
1736
|
}
|
1404
1737
|
|
1405
|
-
return
|
1738
|
+
return result;
|
1406
1739
|
}
|
1407
1740
|
|
1408
|
-
return
|
1741
|
+
return RULES_OK;
|
1742
|
+
|
1409
1743
|
}
|
1410
1744
|
|
1411
1745
|
static unsigned int handleMessage(ruleset *tree,
|
1412
|
-
char *state,
|
1413
1746
|
char *message,
|
1414
1747
|
unsigned char actionType,
|
1415
|
-
|
1416
|
-
unsigned int *
|
1417
|
-
void **rulesBinding) {
|
1748
|
+
unsigned int *messageOffset,
|
1749
|
+
unsigned int *stateOffset) {
|
1418
1750
|
char *next;
|
1419
1751
|
jsonObject jo;
|
1420
|
-
|
1752
|
+
CHECK_RESULT(constructObject(message,
|
1421
1753
|
NULL,
|
1422
1754
|
NULL,
|
1423
|
-
|
1424
|
-
actionType == ACTION_ASSERT_FACT ||
|
1425
|
-
actionType == ACTION_RETRACT_FACT ||
|
1426
|
-
actionType == ACTION_REMOVE_FACT,
|
1755
|
+
1,
|
1427
1756
|
&jo,
|
1428
|
-
&next);
|
1429
|
-
if (result != RULES_OK) {
|
1430
|
-
return result;
|
1431
|
-
}
|
1757
|
+
&next));
|
1432
1758
|
|
1433
|
-
return handleMessageCore(tree,
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
commands,
|
1439
|
-
commandCount,
|
1440
|
-
rulesBinding);
|
1759
|
+
return handleMessageCore(tree,
|
1760
|
+
&jo,
|
1761
|
+
actionType,
|
1762
|
+
messageOffset,
|
1763
|
+
stateOffset);
|
1441
1764
|
}
|
1442
1765
|
|
1443
1766
|
static unsigned int handleMessages(ruleset *tree,
|
1444
1767
|
unsigned char actionType,
|
1445
1768
|
char *messages,
|
1446
|
-
|
1447
|
-
unsigned int *commandCount,
|
1448
|
-
void **rulesBinding) {
|
1769
|
+
unsigned int *stateOffset) {
|
1449
1770
|
unsigned int result;
|
1450
1771
|
unsigned int returnResult = RULES_OK;
|
1772
|
+
unsigned int messageOffset;
|
1451
1773
|
jsonObject jo;
|
1452
1774
|
|
1453
1775
|
char *first = messages;
|
1454
1776
|
char *last = NULL;
|
1455
1777
|
char lastTemp;
|
1456
|
-
|
1457
1778
|
while (*first != '{' && *first != '\0' ) {
|
1458
1779
|
++first;
|
1459
1780
|
}
|
@@ -1461,10 +1782,7 @@ static unsigned int handleMessages(ruleset *tree,
|
|
1461
1782
|
while (constructObject(first,
|
1462
1783
|
NULL,
|
1463
1784
|
NULL,
|
1464
|
-
|
1465
|
-
actionType == ACTION_ASSERT_FACT ||
|
1466
|
-
actionType == ACTION_RETRACT_FACT ||
|
1467
|
-
actionType == ACTION_REMOVE_FACT,
|
1785
|
+
1,
|
1468
1786
|
&jo,
|
1469
1787
|
&last) == RULES_OK) {
|
1470
1788
|
|
@@ -1479,13 +1797,10 @@ static unsigned int handleMessages(ruleset *tree,
|
|
1479
1797
|
lastTemp = *last;
|
1480
1798
|
*last = '\0';
|
1481
1799
|
result = handleMessageCore(tree,
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
commands,
|
1487
|
-
commandCount,
|
1488
|
-
rulesBinding);
|
1800
|
+
&jo,
|
1801
|
+
actionType,
|
1802
|
+
&messageOffset,
|
1803
|
+
stateOffset);
|
1489
1804
|
|
1490
1805
|
*last = lastTemp;
|
1491
1806
|
if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
|
@@ -1505,599 +1820,415 @@ static unsigned int handleMessages(ruleset *tree,
|
|
1505
1820
|
return returnResult;
|
1506
1821
|
}
|
1507
1822
|
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
unsigned int *commandCount,
|
1512
|
-
void **rulesBinding) {
|
1513
|
-
int stateLength = strlen(state);
|
1514
|
-
if (stateLength < 2) {
|
1515
|
-
return ERR_PARSE_OBJECT;
|
1516
|
-
}
|
1517
|
-
|
1518
|
-
if (state[0] != '{') {
|
1519
|
-
return ERR_PARSE_OBJECT;
|
1520
|
-
}
|
1521
|
-
|
1522
|
-
char *stateMessagePostfix = state + 1;
|
1523
|
-
#ifdef _WIN32
|
1524
|
-
char *stateMessage = (char *)_alloca(sizeof(char)*(24 + stateLength - 1));
|
1525
|
-
#else
|
1526
|
-
char stateMessage[24 + stateLength - 1];
|
1527
|
-
#endif
|
1528
|
-
|
1529
|
-
#ifdef _WIN32
|
1530
|
-
sprintf_s(stateMessage, sizeof(char)*(24 + stateLength - 1), "{\"$s\":1, %s", stateMessagePostfix);
|
1531
|
-
#else
|
1532
|
-
snprintf(stateMessage, sizeof(char)*(24 + stateLength - 1), "{\"$s\":1, %s", stateMessagePostfix);
|
1533
|
-
#endif
|
1534
|
-
unsigned int result = handleMessage(tree,
|
1535
|
-
state,
|
1536
|
-
stateMessage,
|
1537
|
-
ACTION_ASSERT_EVENT,
|
1538
|
-
commands,
|
1539
|
-
commandCount,
|
1540
|
-
rulesBinding);
|
1541
|
-
|
1542
|
-
return result;
|
1543
|
-
}
|
1544
|
-
|
1545
|
-
static unsigned int handleTimers(ruleset *tree,
|
1546
|
-
char **commands,
|
1547
|
-
unsigned int *commandCount,
|
1548
|
-
void **rulesBinding) {
|
1549
|
-
redisReply *reply;
|
1550
|
-
unsigned int result = peekTimers(tree, rulesBinding, &reply);
|
1551
|
-
if (result != RULES_OK) {
|
1552
|
-
return result;
|
1553
|
-
}
|
1554
|
-
|
1555
|
-
for (unsigned long i = 0; i < reply->elements; ++i) {
|
1556
|
-
if (*commandCount == MAX_COMMAND_COUNT) {
|
1557
|
-
return ERR_MAX_COMMAND_COUNT;
|
1558
|
-
}
|
1559
|
-
|
1560
|
-
char *command;
|
1561
|
-
result = formatRemoveTimer(*rulesBinding, reply->element[i]->str, &command);
|
1562
|
-
if (result != RULES_OK) {
|
1563
|
-
freeReplyObject(reply);
|
1564
|
-
return result;
|
1565
|
-
}
|
1566
|
-
|
1567
|
-
unsigned int action;
|
1568
|
-
switch (reply->element[i]->str[0]) {
|
1569
|
-
case 'p':
|
1570
|
-
action = ACTION_ASSERT_EVENT;
|
1571
|
-
break;
|
1572
|
-
case 'a':
|
1573
|
-
action = ACTION_ASSERT_FACT;
|
1574
|
-
break;
|
1575
|
-
case 'r':
|
1576
|
-
action = ACTION_RETRACT_FACT;
|
1577
|
-
break;
|
1578
|
-
}
|
1579
|
-
|
1580
|
-
commands[*commandCount] = command;
|
1581
|
-
++*commandCount;
|
1582
|
-
result = handleMessage(tree,
|
1583
|
-
NULL,
|
1584
|
-
reply->element[i]->str + 2,
|
1585
|
-
action,
|
1586
|
-
commands,
|
1587
|
-
commandCount,
|
1588
|
-
rulesBinding);
|
1589
|
-
if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
|
1590
|
-
freeReplyObject(reply);
|
1591
|
-
return result;
|
1592
|
-
}
|
1593
|
-
}
|
1594
|
-
|
1595
|
-
freeReplyObject(reply);
|
1596
|
-
return RULES_OK;
|
1597
|
-
}
|
1598
|
-
|
1599
|
-
static unsigned int startHandleMessage(ruleset *tree,
|
1600
|
-
char *message,
|
1601
|
-
unsigned char actionType,
|
1602
|
-
void **rulesBinding,
|
1603
|
-
unsigned int *replyCount) {
|
1604
|
-
char *commands[MAX_COMMAND_COUNT];
|
1605
|
-
unsigned int commandCount = 0;
|
1606
|
-
unsigned int result = handleMessage(tree,
|
1607
|
-
NULL,
|
1608
|
-
message,
|
1609
|
-
actionType,
|
1610
|
-
commands,
|
1611
|
-
&commandCount,
|
1612
|
-
rulesBinding);
|
1613
|
-
if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
|
1614
|
-
freeCommands(commands, commandCount);
|
1615
|
-
return result;
|
1616
|
-
}
|
1617
|
-
|
1618
|
-
unsigned int batchResult = startNonBlockingBatch(*rulesBinding, commands, commandCount, replyCount);
|
1619
|
-
if (batchResult != RULES_OK) {
|
1620
|
-
return batchResult;
|
1621
|
-
}
|
1622
|
-
|
1623
|
-
return result;
|
1624
|
-
}
|
1625
|
-
|
1626
|
-
static unsigned int executeHandleMessage(ruleset *tree,
|
1627
|
-
char *message,
|
1628
|
-
unsigned char actionType) {
|
1629
|
-
char *commands[MAX_COMMAND_COUNT];
|
1630
|
-
unsigned int commandCount = 0;
|
1631
|
-
void *rulesBinding = NULL;
|
1632
|
-
unsigned int result = handleMessage(tree,
|
1633
|
-
NULL,
|
1634
|
-
message,
|
1635
|
-
actionType,
|
1636
|
-
commands,
|
1637
|
-
&commandCount,
|
1638
|
-
&rulesBinding);
|
1639
|
-
if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
|
1640
|
-
freeCommands(commands, commandCount);
|
1641
|
-
return result;
|
1642
|
-
}
|
1643
|
-
|
1644
|
-
unsigned int batchResult = executeBatch(rulesBinding, commands, commandCount);
|
1645
|
-
if (batchResult != RULES_OK) {
|
1646
|
-
return batchResult;
|
1647
|
-
}
|
1648
|
-
|
1649
|
-
return result;
|
1650
|
-
}
|
1651
|
-
|
1652
|
-
static unsigned int startHandleMessages(ruleset *tree,
|
1653
|
-
char *messages,
|
1654
|
-
unsigned char actionType,
|
1655
|
-
void **rulesBinding,
|
1656
|
-
unsigned int *replyCount) {
|
1657
|
-
char *commands[MAX_COMMAND_COUNT];
|
1658
|
-
unsigned int commandCount = 0;
|
1659
|
-
unsigned int result = handleMessages(tree,
|
1660
|
-
actionType,
|
1661
|
-
messages,
|
1662
|
-
commands,
|
1663
|
-
&commandCount,
|
1664
|
-
rulesBinding);
|
1665
|
-
if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
|
1666
|
-
freeCommands(commands, commandCount);
|
1667
|
-
return result;
|
1668
|
-
}
|
1669
|
-
|
1670
|
-
unsigned int batchResult = startNonBlockingBatch(*rulesBinding, commands, commandCount, replyCount);
|
1671
|
-
if (batchResult != RULES_OK) {
|
1672
|
-
return batchResult;
|
1673
|
-
}
|
1674
|
-
|
1675
|
-
return result;
|
1676
|
-
}
|
1677
|
-
|
1678
|
-
static unsigned int executeHandleMessages(ruleset *tree,
|
1679
|
-
char *messages,
|
1680
|
-
unsigned char actionType) {
|
1681
|
-
char *commands[MAX_COMMAND_COUNT];
|
1682
|
-
unsigned int commandCount = 0;
|
1683
|
-
void *rulesBinding = NULL;
|
1684
|
-
unsigned int result = handleMessages(tree,
|
1685
|
-
actionType,
|
1686
|
-
messages,
|
1687
|
-
commands,
|
1688
|
-
&commandCount,
|
1689
|
-
&rulesBinding);
|
1690
|
-
if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
|
1691
|
-
freeCommands(commands, commandCount);
|
1692
|
-
return result;
|
1693
|
-
}
|
1694
|
-
|
1695
|
-
unsigned int batchResult = executeBatch(rulesBinding, commands, commandCount);
|
1696
|
-
if (batchResult != RULES_OK) {
|
1697
|
-
return batchResult;
|
1698
|
-
}
|
1699
|
-
|
1700
|
-
return result;
|
1701
|
-
}
|
1702
|
-
|
1703
|
-
unsigned int complete(void *rulesBinding, unsigned int replyCount) {
|
1704
|
-
unsigned int result = completeNonBlockingBatch(rulesBinding, replyCount);
|
1705
|
-
if (result != RULES_OK && result != ERR_EVENT_OBSERVED) {
|
1706
|
-
return result;
|
1707
|
-
}
|
1708
|
-
|
1709
|
-
return RULES_OK;
|
1710
|
-
}
|
1711
|
-
|
1712
|
-
unsigned int assertEvent(unsigned int handle, char *message) {
|
1713
|
-
ruleset *tree;
|
1714
|
-
RESOLVE_HANDLE(handle, &tree);
|
1715
|
-
|
1716
|
-
return executeHandleMessage(tree, message, ACTION_ASSERT_EVENT);
|
1717
|
-
}
|
1718
|
-
|
1719
|
-
unsigned int startAssertEvent(unsigned int handle,
|
1720
|
-
char *message,
|
1721
|
-
void **rulesBinding,
|
1722
|
-
unsigned int *replyCount) {
|
1823
|
+
unsigned int assertEvent(unsigned int handle,
|
1824
|
+
char *message,
|
1825
|
+
unsigned int *stateOffset) {
|
1723
1826
|
ruleset *tree;
|
1827
|
+
unsigned int messageOffset;
|
1724
1828
|
RESOLVE_HANDLE(handle, &tree);
|
1725
1829
|
|
1726
|
-
return
|
1830
|
+
return handleMessage(tree, message, ACTION_ASSERT_EVENT, &messageOffset, stateOffset);
|
1727
1831
|
}
|
1728
1832
|
|
1729
1833
|
unsigned int assertEvents(unsigned int handle,
|
1730
|
-
char *messages
|
1731
|
-
|
1732
|
-
RESOLVE_HANDLE(handle, &tree);
|
1733
|
-
|
1734
|
-
return executeHandleMessages(tree, messages, ACTION_ASSERT_EVENT);
|
1735
|
-
}
|
1736
|
-
|
1737
|
-
unsigned int startAssertEvents(unsigned int handle,
|
1738
|
-
char *messages,
|
1739
|
-
void **rulesBinding,
|
1740
|
-
unsigned int *replyCount) {
|
1741
|
-
ruleset *tree;
|
1742
|
-
RESOLVE_HANDLE(handle, &tree);
|
1743
|
-
|
1744
|
-
return startHandleMessages(tree, messages, ACTION_ASSERT_EVENT, rulesBinding, replyCount);
|
1745
|
-
}
|
1746
|
-
|
1747
|
-
unsigned int retractEvent(unsigned int handle, char *message) {
|
1748
|
-
ruleset *tree;
|
1749
|
-
RESOLVE_HANDLE(handle, &tree);
|
1750
|
-
|
1751
|
-
return executeHandleMessage(tree, message, ACTION_REMOVE_EVENT);
|
1752
|
-
}
|
1753
|
-
|
1754
|
-
unsigned int startAssertFact(unsigned int handle,
|
1755
|
-
char *message,
|
1756
|
-
void **rulesBinding,
|
1757
|
-
unsigned int *replyCount) {
|
1758
|
-
ruleset *tree;
|
1759
|
-
RESOLVE_HANDLE(handle, &tree);
|
1760
|
-
|
1761
|
-
return startHandleMessage(tree, message, ACTION_ASSERT_FACT, rulesBinding, replyCount);
|
1762
|
-
}
|
1763
|
-
|
1764
|
-
unsigned int assertFact(unsigned int handle, char *message) {
|
1834
|
+
char *messages,
|
1835
|
+
unsigned int *stateOffset) {
|
1765
1836
|
ruleset *tree;
|
1766
1837
|
RESOLVE_HANDLE(handle, &tree);
|
1767
1838
|
|
1768
|
-
return
|
1839
|
+
return handleMessages(tree, ACTION_ASSERT_EVENT, messages, stateOffset);
|
1769
1840
|
}
|
1770
1841
|
|
1771
|
-
unsigned int
|
1772
|
-
|
1773
|
-
|
1774
|
-
unsigned int *replyCount) {
|
1842
|
+
unsigned int assertFact(unsigned int handle,
|
1843
|
+
char *message,
|
1844
|
+
unsigned int *stateOffset) {
|
1775
1845
|
ruleset *tree;
|
1846
|
+
unsigned int messageOffset;
|
1776
1847
|
RESOLVE_HANDLE(handle, &tree);
|
1777
1848
|
|
1778
|
-
return
|
1849
|
+
return handleMessage(tree, message, ACTION_ASSERT_FACT, &messageOffset, stateOffset);
|
1779
1850
|
}
|
1780
1851
|
|
1781
1852
|
unsigned int assertFacts(unsigned int handle,
|
1782
|
-
char *messages
|
1853
|
+
char *messages,
|
1854
|
+
unsigned int *stateOffset) {
|
1783
1855
|
ruleset *tree;
|
1784
1856
|
RESOLVE_HANDLE(handle, &tree);
|
1785
1857
|
|
1786
|
-
return
|
1858
|
+
return handleMessages(tree, ACTION_ASSERT_EVENT, messages, stateOffset);
|
1787
1859
|
}
|
1788
1860
|
|
1789
|
-
unsigned int retractFact(unsigned int handle,
|
1861
|
+
unsigned int retractFact(unsigned int handle,
|
1862
|
+
char *message,
|
1863
|
+
unsigned int *stateOffset) {
|
1790
1864
|
ruleset *tree;
|
1865
|
+
unsigned int messageOffset;
|
1791
1866
|
RESOLVE_HANDLE(handle, &tree);
|
1792
1867
|
|
1793
|
-
return
|
1794
|
-
}
|
1795
|
-
|
1796
|
-
unsigned int startRetractFact(unsigned int handle,
|
1797
|
-
char *message,
|
1798
|
-
void **rulesBinding,
|
1799
|
-
unsigned int *replyCount) {
|
1800
|
-
ruleset *tree;
|
1801
|
-
RESOLVE_HANDLE(handle, &tree);
|
1802
|
-
|
1803
|
-
return startHandleMessage(tree, message, ACTION_REMOVE_FACT, rulesBinding, replyCount);
|
1868
|
+
return handleMessage(tree, message, ACTION_RETRACT_FACT, &messageOffset, stateOffset);
|
1804
1869
|
}
|
1805
1870
|
|
1806
1871
|
unsigned int retractFacts(unsigned int handle,
|
1807
|
-
char *messages
|
1808
|
-
|
1809
|
-
RESOLVE_HANDLE(handle, &tree);
|
1810
|
-
|
1811
|
-
return executeHandleMessages(tree, messages, ACTION_REMOVE_FACT);
|
1812
|
-
}
|
1813
|
-
|
1814
|
-
unsigned int startRetractFacts(unsigned int handle,
|
1815
|
-
char *messages,
|
1816
|
-
void **rulesBinding,
|
1817
|
-
unsigned int *replyCount) {
|
1872
|
+
char *messages,
|
1873
|
+
unsigned int *stateOffset) {
|
1818
1874
|
ruleset *tree;
|
1819
1875
|
RESOLVE_HANDLE(handle, &tree);
|
1820
1876
|
|
1821
|
-
return
|
1877
|
+
return handleMessages(tree, ACTION_ASSERT_EVENT, messages, stateOffset);
|
1822
1878
|
}
|
1823
1879
|
|
1824
|
-
unsigned int
|
1880
|
+
unsigned int updateState(unsigned int handle,
|
1881
|
+
char *state,
|
1882
|
+
unsigned int *stateOffset) {
|
1825
1883
|
ruleset *tree;
|
1826
1884
|
RESOLVE_HANDLE(handle, &tree);
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
unsigned int result = handleState(tree,
|
1833
|
-
state,
|
1834
|
-
commands,
|
1835
|
-
&commandCount,
|
1836
|
-
&rulesBinding);
|
1837
|
-
if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
|
1838
|
-
freeCommands(commands, commandCount);
|
1839
|
-
return result;
|
1840
|
-
}
|
1841
|
-
|
1842
|
-
unsigned int batchResult = executeBatch(rulesBinding, commands, commandCount);
|
1843
|
-
if (batchResult != RULES_OK) {
|
1844
|
-
return batchResult;
|
1885
|
+
unsigned int messageOffset;
|
1886
|
+
unsigned int result = handleMessage(tree, state, ACTION_UPDATE_STATE, &messageOffset, stateOffset);
|
1887
|
+
if (result == ERR_EVENT_NOT_HANDLED || result == ERR_EVENT_OBSERVED) {
|
1888
|
+
return RULES_OK;
|
1845
1889
|
}
|
1846
1890
|
|
1847
1891
|
return result;
|
1848
1892
|
}
|
1849
1893
|
|
1850
|
-
unsigned int assertTimers(unsigned int handle) {
|
1851
|
-
ruleset *tree;
|
1852
|
-
RESOLVE_HANDLE(handle, &tree);
|
1853
|
-
|
1854
|
-
char *commands[MAX_COMMAND_COUNT];
|
1855
|
-
unsigned int commandCount = 0;
|
1856
|
-
void *rulesBinding = NULL;
|
1857
|
-
unsigned int result = handleTimers(tree,
|
1858
|
-
commands,
|
1859
|
-
&commandCount,
|
1860
|
-
&rulesBinding);
|
1861
|
-
if (result != RULES_OK) {
|
1862
|
-
freeCommands(commands, commandCount);
|
1863
|
-
return result;
|
1864
|
-
}
|
1865
|
-
|
1866
|
-
result = executeBatch(rulesBinding, commands, commandCount);
|
1867
|
-
if (result != RULES_OK && result != ERR_EVENT_OBSERVED) {
|
1868
|
-
return result;
|
1869
|
-
}
|
1870
|
-
|
1871
|
-
return RULES_OK;
|
1872
|
-
}
|
1873
|
-
|
1874
1894
|
unsigned int startAction(unsigned int handle,
|
1875
|
-
char **
|
1895
|
+
char **stateFact,
|
1876
1896
|
char **messages,
|
1877
|
-
|
1878
|
-
void **actionBinding) {
|
1897
|
+
unsigned int *stateOffset) {
|
1879
1898
|
ruleset *tree;
|
1880
1899
|
RESOLVE_HANDLE(handle, &tree);
|
1881
|
-
|
1882
|
-
|
1883
|
-
|
1884
|
-
unsigned int
|
1885
|
-
|
1886
|
-
|
1887
|
-
|
1888
|
-
|
1889
|
-
|
1890
|
-
|
1891
|
-
|
1892
|
-
|
1893
|
-
|
1894
|
-
|
1900
|
+
stateNode *resultState;
|
1901
|
+
actionStateNode *resultAction;
|
1902
|
+
unsigned int actionStateIndex;
|
1903
|
+
unsigned int resultCount;
|
1904
|
+
unsigned int resultFrameOffset;
|
1905
|
+
time_t currentTime = time(NULL);
|
1906
|
+
|
1907
|
+
CHECK_RESULT(getNextResult(tree,
|
1908
|
+
currentTime,
|
1909
|
+
&resultState,
|
1910
|
+
&actionStateIndex,
|
1911
|
+
&resultCount,
|
1912
|
+
&resultFrameOffset,
|
1913
|
+
&resultAction));
|
1914
|
+
|
1915
|
+
CHECK_RESULT(serializeResult(tree,
|
1916
|
+
resultState,
|
1917
|
+
resultAction,
|
1918
|
+
resultCount,
|
1919
|
+
&resultState->context.messages));
|
1920
|
+
|
1921
|
+
CHECK_RESULT(serializeState(resultState,
|
1922
|
+
&resultState->context.stateFact));
|
1923
|
+
|
1924
|
+
|
1925
|
+
resultState->context.actionStateIndex = actionStateIndex;
|
1926
|
+
resultState->context.resultCount = resultCount;
|
1927
|
+
resultState->context.resultFrameOffset = resultFrameOffset;
|
1928
|
+
resultState->lockExpireTime = currentTime + STATE_LEASE_TIME;
|
1929
|
+
*stateOffset = resultState->offset;
|
1930
|
+
*messages = resultState->context.messages;
|
1931
|
+
*stateFact = resultState->context.stateFact;
|
1895
1932
|
|
1896
|
-
context->reply = reply;
|
1897
|
-
context->rulesBinding = rulesBinding;
|
1898
|
-
*actionHandle = context;
|
1899
|
-
*actionBinding = rulesBinding;
|
1900
1933
|
return RULES_OK;
|
1901
1934
|
}
|
1902
1935
|
|
1903
|
-
unsigned int
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1907
|
-
unsigned int *replyCount) {
|
1936
|
+
unsigned int startActionForState(unsigned int handle,
|
1937
|
+
unsigned int stateOffset,
|
1938
|
+
char **stateFact,
|
1939
|
+
char **messages) {
|
1908
1940
|
ruleset *tree;
|
1909
1941
|
RESOLVE_HANDLE(handle, &tree);
|
1942
|
+
stateNode *resultState = STATE_NODE(tree, stateOffset);
|
1910
1943
|
|
1911
|
-
|
1912
|
-
unsigned int
|
1913
|
-
unsigned int
|
1914
|
-
|
1915
|
-
|
1916
|
-
|
1917
|
-
|
1918
|
-
|
1919
|
-
|
1920
|
-
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
|
1944
|
+
actionStateNode *resultAction;
|
1945
|
+
unsigned int actionStateIndex;
|
1946
|
+
unsigned int resultCount;
|
1947
|
+
unsigned int resultFrameOffset;
|
1948
|
+
|
1949
|
+
CHECK_RESULT(getNextResultInState(tree,
|
1950
|
+
resultState,
|
1951
|
+
&actionStateIndex,
|
1952
|
+
&resultCount,
|
1953
|
+
&resultFrameOffset,
|
1954
|
+
&resultAction));
|
1955
|
+
|
1956
|
+
CHECK_RESULT(serializeResult(tree,
|
1957
|
+
resultState,
|
1958
|
+
resultAction,
|
1959
|
+
resultCount,
|
1960
|
+
&resultState->context.messages));
|
1961
|
+
|
1962
|
+
CHECK_RESULT(serializeState(resultState,
|
1963
|
+
&resultState->context.stateFact));
|
1964
|
+
|
1965
|
+
resultState->context.actionStateIndex = actionStateIndex;
|
1966
|
+
resultState->context.resultCount = resultCount;
|
1967
|
+
resultState->context.resultFrameOffset = resultFrameOffset;
|
1968
|
+
resultState->lockExpireTime = time(NULL) + STATE_LEASE_TIME;
|
1969
|
+
*messages = resultState->context.messages;
|
1970
|
+
*stateFact = resultState->context.stateFact;
|
1971
|
+
|
1972
|
+
return RULES_OK;
|
1928
1973
|
}
|
1929
1974
|
|
1930
|
-
unsigned int
|
1931
|
-
|
1932
|
-
|
1933
|
-
|
1934
|
-
|
1975
|
+
static unsigned int deleteCurrentAction(ruleset *tree,
|
1976
|
+
stateNode *state,
|
1977
|
+
unsigned int actionStateIndex,
|
1978
|
+
unsigned int resultCount,
|
1979
|
+
unsigned int resultFrameOffset) {
|
1980
|
+
|
1981
|
+
for (unsigned int currentCount = 0; currentCount < resultCount; ++currentCount) {
|
1982
|
+
leftFrameNode *resultFrame;
|
1983
|
+
frameLocation resultLocation;
|
1984
|
+
resultLocation.frameType = ACTION_FRAME;
|
1985
|
+
resultLocation.nodeIndex = actionStateIndex;
|
1986
|
+
resultLocation.frameOffset = resultFrameOffset;
|
1987
|
+
CHECK_RESULT(getActionFrame(state,
|
1988
|
+
resultLocation,
|
1989
|
+
&resultFrame));
|
1990
|
+
|
1991
|
+
for (int i = 0; i < resultFrame->messageCount; ++i) {
|
1992
|
+
messageFrame *currentMessageFrame = &resultFrame->messages[resultFrame->reverseIndex[i]];
|
1993
|
+
if (currentMessageFrame->messageNodeOffset != UNDEFINED_HASH_OFFSET) {
|
1994
|
+
messageNode *currentMessageNode = MESSAGE_NODE(state,
|
1995
|
+
currentMessageFrame->messageNodeOffset);
|
1935
1996
|
|
1936
|
-
char *commands[MAX_COMMAND_COUNT];
|
1937
|
-
unsigned int commandCount = 0;
|
1938
|
-
actionContext *context = (actionContext*)actionHandle;
|
1939
|
-
redisReply *reply = context->reply;
|
1940
|
-
void *rulesBinding = context->rulesBinding;
|
1941
|
-
|
1942
|
-
unsigned int result = formatRemoveAction(rulesBinding,
|
1943
|
-
reply->element[0]->str,
|
1944
|
-
&commands[commandCount]);
|
1945
|
-
if (result != RULES_OK) {
|
1946
|
-
//reply object should be freed by the app during abandonAction
|
1947
|
-
return result;
|
1948
|
-
}
|
1949
1997
|
|
1950
|
-
|
1951
|
-
|
1952
|
-
|
1953
|
-
|
1954
|
-
|
1955
|
-
|
1956
|
-
|
1957
|
-
//reply object should be freed by the app during abandonAction
|
1958
|
-
freeCommands(commands, commandCount);
|
1959
|
-
return result;
|
1960
|
-
}
|
1998
|
+
if (currentMessageNode->messageType == MESSAGE_TYPE_EVENT) {
|
1999
|
+
CHECK_RESULT(handleDeleteMessage(tree,
|
2000
|
+
state,
|
2001
|
+
currentMessageFrame->messageNodeOffset));
|
2002
|
+
}
|
2003
|
+
}
|
2004
|
+
}
|
1961
2005
|
|
1962
|
-
|
1963
|
-
|
1964
|
-
|
1965
|
-
|
2006
|
+
resultFrameOffset = resultFrame->nextOffset;
|
2007
|
+
unsigned int result = deleteDispatchingActionFrame(state, resultLocation);
|
2008
|
+
if (result != RULES_OK) {
|
2009
|
+
return result;
|
2010
|
+
}
|
1966
2011
|
}
|
1967
2012
|
|
1968
|
-
freeReplyObject(reply);
|
1969
|
-
free(actionHandle);
|
1970
2013
|
return RULES_OK;
|
1971
2014
|
}
|
1972
2015
|
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
char *commands[MAX_COMMAND_COUNT];
|
1978
|
-
unsigned int commandCount = 0;
|
1979
|
-
actionContext *context = (actionContext*)actionHandle;
|
1980
|
-
redisReply *reply = context->reply;
|
1981
|
-
void *rulesBinding = context->rulesBinding;
|
1982
|
-
|
1983
|
-
unsigned int result = formatRemoveAction(rulesBinding,
|
1984
|
-
reply->element[0]->str,
|
1985
|
-
&commands[commandCount]);
|
1986
|
-
if (result != RULES_OK) {
|
1987
|
-
//reply object should be freed by the app during abandonAction
|
1988
|
-
return result;
|
2016
|
+
static void freeActionContext(stateNode *resultState) {
|
2017
|
+
if (resultState->context.messages) {
|
2018
|
+
free(resultState->context.messages);
|
2019
|
+
resultState->context.messages = NULL;
|
1989
2020
|
}
|
1990
2021
|
|
1991
|
-
|
1992
|
-
|
1993
|
-
|
1994
|
-
freeCommands(commands, commandCount);
|
1995
|
-
return ERR_MAX_COMMAND_COUNT;
|
2022
|
+
if (resultState->context.stateFact) {
|
2023
|
+
free(resultState->context.stateFact);
|
2024
|
+
resultState->context.stateFact = NULL;
|
1996
2025
|
}
|
1997
2026
|
|
1998
|
-
|
1999
|
-
|
2000
|
-
&commands[commandCount]);
|
2001
|
-
if (result != RULES_OK) {
|
2002
|
-
//reply object should be freed by the app during abandonAction
|
2003
|
-
freeCommands(commands, commandCount);
|
2004
|
-
return result;
|
2005
|
-
}
|
2027
|
+
resultState->lockExpireTime = 0;
|
2028
|
+
}
|
2006
2029
|
|
2007
|
-
|
2008
|
-
|
2009
|
-
|
2010
|
-
|
2011
|
-
|
2012
|
-
|
2013
|
-
&newReply);
|
2014
|
-
if (result != RULES_OK && result != ERR_EVENT_OBSERVED) {
|
2015
|
-
//reply object should be freed by the app during abandonAction
|
2016
|
-
return result;
|
2017
|
-
}
|
2030
|
+
unsigned int completeAndStartAction(unsigned int handle,
|
2031
|
+
unsigned int stateOffset,
|
2032
|
+
char **messages) {
|
2033
|
+
ruleset *tree;
|
2034
|
+
RESOLVE_HANDLE(handle, &tree);
|
2035
|
+
stateNode *resultState = STATE_NODE(tree, stateOffset);
|
2018
2036
|
|
2019
|
-
|
2020
|
-
|
2021
|
-
|
2022
|
-
|
2023
|
-
|
2037
|
+
CHECK_RESULT(deleteCurrentAction(tree,
|
2038
|
+
resultState,
|
2039
|
+
resultState->context.actionStateIndex,
|
2040
|
+
resultState->context.resultCount,
|
2041
|
+
resultState->context.resultFrameOffset));
|
2024
2042
|
|
2025
|
-
|
2026
|
-
|
2043
|
+
|
2044
|
+
freeActionContext(resultState);
|
2045
|
+
|
2046
|
+
actionStateNode *resultAction;
|
2047
|
+
unsigned int actionStateIndex;
|
2048
|
+
unsigned int resultCount;
|
2049
|
+
unsigned int resultFrameOffset;
|
2050
|
+
|
2051
|
+
CHECK_RESULT(getNextResultInState(tree,
|
2052
|
+
resultState,
|
2053
|
+
&actionStateIndex,
|
2054
|
+
&resultCount,
|
2055
|
+
&resultFrameOffset,
|
2056
|
+
&resultAction));
|
2057
|
+
|
2058
|
+
CHECK_RESULT(serializeResult(tree,
|
2059
|
+
resultState,
|
2060
|
+
resultAction,
|
2061
|
+
resultCount,
|
2062
|
+
&resultState->context.messages));
|
2063
|
+
|
2064
|
+
resultState->context.actionStateIndex = actionStateIndex;
|
2065
|
+
resultState->context.resultCount = resultCount;
|
2066
|
+
resultState->context.resultFrameOffset = resultFrameOffset;
|
2067
|
+
resultState->lockExpireTime = time(NULL) + STATE_LEASE_TIME;
|
2068
|
+
*messages = resultState->context.messages;
|
2027
2069
|
return RULES_OK;
|
2028
2070
|
}
|
2029
2071
|
|
2030
|
-
unsigned int abandonAction(unsigned int handle,
|
2031
|
-
|
2032
|
-
|
2072
|
+
unsigned int abandonAction(unsigned int handle, unsigned int stateOffset) {
|
2073
|
+
ruleset *tree;
|
2074
|
+
RESOLVE_HANDLE(handle, &tree);
|
2075
|
+
stateNode *resultState = STATE_NODE(tree, stateOffset);
|
2076
|
+
|
2077
|
+
freeActionContext(resultState);
|
2033
2078
|
return RULES_OK;
|
2034
2079
|
}
|
2035
2080
|
|
2036
|
-
unsigned int
|
2081
|
+
unsigned int renewActionLease(unsigned int handle, char *sid) {
|
2037
2082
|
ruleset *tree;
|
2038
|
-
|
2083
|
+
unsigned char isNewState;
|
2084
|
+
stateNode *state = NULL;
|
2039
2085
|
|
2040
|
-
|
2086
|
+
RESOLVE_HANDLE(handle, &tree);
|
2041
2087
|
if (!sid) {
|
2042
2088
|
sid = "0";
|
2043
2089
|
}
|
2044
2090
|
|
2045
|
-
|
2046
|
-
|
2047
|
-
|
2048
|
-
|
2091
|
+
CHECK_RESULT(ensureStateNode(tree,
|
2092
|
+
sid,
|
2093
|
+
&isNewState,
|
2094
|
+
&state));
|
2049
2095
|
|
2050
|
-
|
2096
|
+
state->lockExpireTime = time(NULL) + STATE_LEASE_TIME;
|
2097
|
+
return RULES_OK;
|
2051
2098
|
}
|
2052
2099
|
|
2053
|
-
unsigned int
|
2100
|
+
unsigned int assertTimers(unsigned int handle) {
|
2054
2101
|
ruleset *tree;
|
2102
|
+
unsigned int result;
|
2055
2103
|
RESOLVE_HANDLE(handle, &tree);
|
2056
2104
|
|
2057
|
-
|
2058
|
-
|
2059
|
-
|
2060
|
-
|
2061
|
-
|
2062
|
-
|
2063
|
-
|
2064
|
-
|
2105
|
+
time_t pulseTime = time(NULL);
|
2106
|
+
for (unsigned int i = 0; i < tree->statePool.count; ++i) {
|
2107
|
+
stateNode *state = STATE_NODE(tree, tree->reverseStateIndex[i]);
|
2108
|
+
unsigned int stateOffset;
|
2109
|
+
unsigned int messageOffset;
|
2110
|
+
CHECK_RESULT(getMessage(state,
|
2111
|
+
"$pulse",
|
2112
|
+
&messageOffset));
|
2113
|
+
|
2114
|
+
if (messageOffset != UNDEFINED_HASH_OFFSET) {
|
2115
|
+
messageNode *message = MESSAGE_NODE(state, messageOffset);
|
2116
|
+
CHECK_RESULT(handleMessage(tree,
|
2117
|
+
message->jo.content,
|
2118
|
+
ACTION_RETRACT_FACT,
|
2119
|
+
&messageOffset,
|
2120
|
+
&stateOffset));
|
2121
|
+
}
|
2122
|
+
|
2123
|
+
int messageSize = sizeof(char) * (100 + strlen(state->sid));
|
2124
|
+
#ifdef _WIN32
|
2125
|
+
char *pulseMessage = (char *)_alloca(messageSize);
|
2126
|
+
sprintf_s(pulseMessage,
|
2127
|
+
messageSize,
|
2128
|
+
"{ \"sid\":\"%s\", \"id\":\"$pulse\", \"$time\":%ld }",
|
2129
|
+
state->sid,
|
2130
|
+
pulseTime);
|
2131
|
+
#else
|
2132
|
+
char pulseMessage[messageSize];
|
2133
|
+
snprintf(pulseMessage,
|
2134
|
+
messageSize,
|
2135
|
+
"{ \"sid\":\"%s\", \"id\":\"$pulse\", \"$time\":%ld }",
|
2136
|
+
state->sid,
|
2137
|
+
pulseTime);
|
2138
|
+
#endif
|
2139
|
+
result = handleMessage(tree,
|
2140
|
+
pulseMessage,
|
2141
|
+
ACTION_ASSERT_EVENT,
|
2142
|
+
&messageOffset,
|
2143
|
+
&stateOffset);
|
2144
|
+
if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
|
2145
|
+
return result;
|
2146
|
+
}
|
2065
2147
|
}
|
2066
2148
|
|
2067
|
-
return
|
2149
|
+
return RULES_OK;
|
2068
2150
|
}
|
2069
2151
|
|
2070
2152
|
unsigned int cancelTimer(unsigned int handle, char *sid, char *timerName) {
|
2071
2153
|
ruleset *tree;
|
2072
|
-
|
2154
|
+
unsigned char isNewState;
|
2155
|
+
unsigned int messageOffset;
|
2156
|
+
unsigned int stateOffset;
|
2157
|
+
stateNode *state = NULL;
|
2073
2158
|
|
2074
|
-
|
2159
|
+
RESOLVE_HANDLE(handle, &tree);
|
2075
2160
|
if (!sid) {
|
2076
2161
|
sid = "0";
|
2077
2162
|
}
|
2078
2163
|
|
2079
|
-
|
2080
|
-
|
2081
|
-
|
2082
|
-
|
2164
|
+
CHECK_RESULT(ensureStateNode(tree,
|
2165
|
+
sid,
|
2166
|
+
&isNewState,
|
2167
|
+
&state));
|
2083
2168
|
|
2084
|
-
|
2169
|
+
CHECK_RESULT(getMessage(state,
|
2170
|
+
timerName,
|
2171
|
+
&messageOffset));
|
2172
|
+
|
2173
|
+
if (messageOffset != UNDEFINED_HASH_OFFSET) {
|
2174
|
+
messageNode *message = MESSAGE_NODE(state, messageOffset);
|
2175
|
+
CHECK_RESULT(handleMessage(tree,
|
2176
|
+
message->jo.content,
|
2177
|
+
ACTION_RETRACT_FACT,
|
2178
|
+
&messageOffset,
|
2179
|
+
&stateOffset));
|
2180
|
+
}
|
2181
|
+
|
2182
|
+
return RULES_OK;
|
2085
2183
|
}
|
2086
2184
|
|
2087
|
-
unsigned int
|
2185
|
+
unsigned int startTimer(unsigned int handle,
|
2186
|
+
char *sid,
|
2187
|
+
unsigned int duration,
|
2188
|
+
char manualReset,
|
2189
|
+
char *timer) {
|
2088
2190
|
ruleset *tree;
|
2089
2191
|
RESOLVE_HANDLE(handle, &tree);
|
2192
|
+
unsigned int result = cancelTimer(handle, sid, timer);
|
2193
|
+
if (result != RULES_OK && result != ERR_MESSAGE_NOT_FOUND) {
|
2194
|
+
return result;
|
2195
|
+
}
|
2090
2196
|
|
2091
|
-
|
2197
|
+
time_t baseTime = time(NULL);
|
2198
|
+
baseTime += duration;
|
2092
2199
|
if (!sid) {
|
2093
2200
|
sid = "0";
|
2094
2201
|
}
|
2202
|
+
|
2203
|
+
int messageSize = sizeof(char) * (100 + strlen(sid) + strlen(timer) * 2);
|
2095
2204
|
|
2096
|
-
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
2100
|
-
|
2101
|
-
|
2205
|
+
#ifdef _WIN32
|
2206
|
+
char *baseMessage = (char *)_alloca(messageSize);
|
2207
|
+
sprintf_s(baseMessage,
|
2208
|
+
messageSize,
|
2209
|
+
"{ \"sid\":\"%s\", \"id\":\"%s\", \"$timerName\":\"%s\", \"$baseTime\":%ld }",
|
2210
|
+
sid,
|
2211
|
+
timer,
|
2212
|
+
timer,
|
2213
|
+
baseTime);
|
2214
|
+
#else
|
2215
|
+
char baseMessage[messageSize];
|
2216
|
+
snprintf(baseMessage,
|
2217
|
+
messageSize,
|
2218
|
+
"{ \"sid\":\"%s\", \"id\":\"%s\", \"$timerName\":\"%s\", \"$baseTime\":%ld }",
|
2219
|
+
sid,
|
2220
|
+
timer,
|
2221
|
+
timer,
|
2222
|
+
baseTime);
|
2223
|
+
#endif
|
2224
|
+
unsigned int messageOffset;
|
2225
|
+
unsigned int stateOffset;
|
2226
|
+
|
2227
|
+
return handleMessage(tree,
|
2228
|
+
baseMessage,
|
2229
|
+
manualReset ? ACTION_ASSERT_FACT : ACTION_ASSERT_EVENT,
|
2230
|
+
&messageOffset,
|
2231
|
+
&stateOffset);
|
2102
2232
|
}
|
2103
2233
|
|
2234
|
+
|