durable_rules 0.34.57 → 2.00.001

Sign up to get free protection for your applications and to get access to all the features.
data/src/rules/Makefile CHANGED
@@ -1,4 +1,4 @@
1
- OBJ=events.o json.o net.o rete.o state.o regex.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) -I../../deps/hiredis -D_GNU_SOURCE
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) -L../../deps/hiredis/ -lhiredis -r
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 net.h json.h regex.h
19
+ events.o: events.c rules.h json.h regex.h
20
20
  json.o: json.c json.h rules.h
21
- net.o: net.c net.h rules.h json.h rete.h
22
- rete.o: rete.c rete.h net.h json.h state.h regex.h
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
- typedef struct actionContext {
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
- char **commands,
70
- unsigned int *commandCount,
71
- void **rulesBinding);
72
-
73
- static unsigned int reduceIdiom(ruleset *tree,
74
- char *sid,
75
- char *message,
76
- jsonObject *messageObject,
77
- unsigned int idiomOffset,
78
- char **state,
79
- unsigned char *releaseState,
80
- jsonProperty **targetValue);
81
-
82
- static unsigned char compareBool(unsigned char left,
83
- unsigned char right,
84
- unsigned char op) {
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
- return (left < right);
87
+ targetProperty->type = JSON_BOOL;
88
+ targetProperty->value.b = (result < 0);
89
+ break;
88
90
  case OP_LTE:
89
- return 1;
91
+ targetProperty->type = JSON_BOOL;
92
+ targetProperty->value.b = (result <= 0);
93
+ break;
90
94
  case OP_GT:
91
- return (left > right);
95
+ targetProperty->type = JSON_BOOL;
96
+ targetProperty->value.b = (result > 0);
97
+ break;
92
98
  case OP_GTE:
93
- return 1;
99
+ targetProperty->type = JSON_BOOL;
100
+ targetProperty->value.b = (result >= 0);
101
+ break;
94
102
  case OP_EQ:
95
- return (left == right);
103
+ targetProperty->type = JSON_BOOL;
104
+ targetProperty->value.b = (result == 0);
105
+ break;
96
106
  case OP_NEQ:
97
- return (left != right);
107
+ targetProperty->type = JSON_BOOL;
108
+ targetProperty->value.b = (result != 0);
109
+ break;
98
110
  }
99
111
 
100
- return 0;
112
+ return RULES_OK;
101
113
  }
102
114
 
103
- static unsigned char compareInt(long left,
104
- long right,
105
- unsigned char op) {
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
- return (left < right);
132
+ targetProperty->type = JSON_BOOL;
133
+ targetProperty->value.b = (left < right);
134
+ break;
109
135
  case OP_LTE:
110
- return (left <= right);
136
+ targetProperty->type = JSON_BOOL;
137
+ targetProperty->value.b = (left <= right);
138
+ break;
111
139
  case OP_GT:
112
- return (left > right);
140
+ targetProperty->type = JSON_BOOL;
141
+ targetProperty->value.b = (left > right);
142
+ break;
113
143
  case OP_GTE:
114
- return (left >= right);
144
+ targetProperty->type = JSON_BOOL;
145
+ targetProperty->value.b = (left >= right);
146
+ break;
115
147
  case OP_EQ:
116
- return (left == right);
148
+ targetProperty->type = JSON_BOOL;
149
+ targetProperty->value.b = (left == right);
150
+ break;
117
151
  case OP_NEQ:
118
- return (left != right);
152
+ targetProperty->type = JSON_BOOL;
153
+ targetProperty->value.b = (left != right);
154
+ break;
119
155
  }
120
156
 
121
- return 0;
157
+ return RULES_OK;
122
158
  }
123
159
 
124
- static unsigned char compareDouble(double left,
125
- double right,
126
- unsigned char op) {
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
- return (left < right);
182
+ targetProperty->type = JSON_BOOL;
183
+ targetProperty->value.b = (left < right);
184
+ break;
130
185
  case OP_LTE:
131
- return (left <= right);
186
+ targetProperty->type = JSON_BOOL;
187
+ targetProperty->value.b = (left <= right);
188
+ break;
132
189
  case OP_GT:
133
- return (left > right);
190
+ targetProperty->type = JSON_BOOL;
191
+ targetProperty->value.b = (left > right);
192
+ break;
134
193
  case OP_GTE:
135
- return (left >= right);
194
+ targetProperty->type = JSON_BOOL;
195
+ targetProperty->value.b = (left >= right);
196
+ break;
136
197
  case OP_EQ:
137
- return (left == right);
198
+ targetProperty->type = JSON_BOOL;
199
+ targetProperty->value.b = (left == right);
200
+ break;
138
201
  case OP_NEQ:
139
- return (left != right);
202
+ targetProperty->type = JSON_BOOL;
203
+ targetProperty->value.b = (left != right);
204
+ break;
140
205
  }
141
206
 
142
- return 0;
207
+ return RULES_OK;
143
208
  }
144
209
 
145
- static unsigned char compareString(char *leftFirst,
146
- unsigned short leftLength,
147
- char *right,
148
- unsigned char op) {
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
- return (result < 0);
232
+ targetProperty->type = JSON_BOOL;
233
+ targetProperty->value.b = (left < right);
234
+ break;
156
235
  case OP_LTE:
157
- return (result <= 0);
236
+ targetProperty->type = JSON_BOOL;
237
+ targetProperty->value.b = (left <= right);
238
+ break;
158
239
  case OP_GT:
159
- return (result > 0);
240
+ targetProperty->type = JSON_BOOL;
241
+ targetProperty->value.b = (left > right);
242
+ break;
160
243
  case OP_GTE:
161
- return (result >= 0);
244
+ targetProperty->type = JSON_BOOL;
245
+ targetProperty->value.b = (left >= right);
246
+ break;
162
247
  case OP_EQ:
163
- return (result == 0);
248
+ targetProperty->type = JSON_BOOL;
249
+ targetProperty->value.b = (left == right);
250
+ break;
164
251
  case OP_NEQ:
165
- return (result != 0);
252
+ targetProperty->type = JSON_BOOL;
253
+ targetProperty->value.b = (left != right);
254
+ break;
166
255
  }
167
256
 
168
- return 0;
257
+ return RULES_OK;
169
258
  }
170
259
 
171
- static unsigned char compareStringProperty(char *left,
172
- char *rightFirst,
173
- unsigned short rightLength,
174
- unsigned char op) {
175
- char temp = rightFirst[rightLength];
176
- rightFirst[rightLength] = '\0';
177
- int result = strcmp(left, rightFirst);
178
- rightFirst[rightLength] = temp;
179
- switch(op) {
180
- case OP_LT:
181
- return (result < 0);
182
- case OP_LTE:
183
- return (result <= 0);
184
- case OP_GT:
185
- return (result > 0);
186
- case OP_GTE:
187
- return (result >= 0);
188
- case OP_EQ:
189
- return (result == 0);
190
- case OP_NEQ:
191
- return (result != 0);
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 0;
309
+ return ERR_OPERATION_NOT_SUPPORTED;
195
310
  }
196
311
 
197
- static unsigned char compareStringAndStringProperty(char *leftFirst,
198
- unsigned short leftLength,
199
- char *rightFirst,
200
- unsigned short rightLength,
201
- unsigned char op) {
202
-
203
- char rightTemp = rightFirst[rightLength];
204
- rightFirst[rightLength] = '\0';
205
- char leftTemp = leftFirst[leftLength];
206
- leftFirst[leftLength] = '\0';
207
- int result = strcmp(leftFirst, rightFirst);
208
- rightFirst[rightLength] = rightTemp;
209
- leftFirst[leftLength] = leftTemp;
210
- switch(op) {
211
- case OP_LT:
212
- return (result < 0);
213
- case OP_LTE:
214
- return (result <= 0);
215
- case OP_GT:
216
- return (result > 0);
217
- case OP_GTE:
218
- return (result >= 0);
219
- case OP_EQ:
220
- return (result == 0);
221
- case OP_NEQ:
222
- return (result != 0);
223
- }
224
-
225
- return 0;
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
- static long reduceInt(long left,
230
- long right,
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 0;
465
+ return ERR_OPERATION_NOT_SUPPORTED;
244
466
  }
245
467
 
246
- static double reduceDouble(double left,
247
- double right,
248
- unsigned char op) {
249
- switch(op) {
250
- case OP_ADD:
251
- return left + right;
252
- case OP_SUB:
253
- return left - right;
254
- case OP_MUL:
255
- return left * right;
256
- case OP_DIV:
257
- return left / right;
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
+ &currentExpression->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
- return 0;
495
+ jsonProperty rightValue;
496
+ jsonProperty *rightProperty = &rightValue;
497
+ CHECK_RESULT(reduceOperand(tree,
498
+ state,
499
+ &currentExpression->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 void freeCommands(char **commands,
264
- unsigned int commandCount) {
265
- for (unsigned int i = 0; i < commandCount; ++i) {
266
- free(commands[i]);
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
- static unsigned int handleAction(ruleset *tree,
271
- char *sid,
272
- char *mid,
273
- char *prefix,
274
- node *node,
275
- unsigned char actionType,
276
- char **evalKeys,
277
- unsigned int *evalCount,
278
- char **addKeys,
279
- unsigned int *addCount,
280
- char **removeCommand,
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
- switch (actionType) {
293
- case ACTION_ASSERT_EVENT:
294
- case ACTION_ASSERT_FACT:
295
- case ACTION_RETRACT_EVENT:
296
- case ACTION_RETRACT_FACT:
297
- if (*evalCount == MAX_EVAL_COUNT) {
298
- return ERR_MAX_EVAL_COUNT;
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
- char *evalKey = malloc((strlen(prefix) + 1) * sizeof(char));
302
- if (evalKey == NULL) {
303
- return ERR_OUT_OF_MEMORY;
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
- strcpy(evalKey, prefix);
307
- evalKeys[*evalCount] = evalKey;
308
- ++*evalCount;
309
- break;
574
+ ++*i;
575
+ }
310
576
 
311
- case ACTION_ADD_EVENT:
312
- case ACTION_ADD_FACT:
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
- strcpy(addKey, prefix);
322
- addKeys[*addCount] = addKey;
323
- *addCount = *addCount + 1;
324
- break;
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
+ &currentExpression->right,
594
+ NULL,
595
+ context,
596
+ &property));
597
+ } else {
598
+ CHECK_RESULT(reduceOperand(tree,
599
+ state,
600
+ &currentExpression->left,
601
+ messageObject,
602
+ NULL,
603
+ &property));
604
+ }
325
605
 
326
- case ACTION_REMOVE_EVENT:
327
- case ACTION_REMOVE_FACT:
328
- if (*removeCommand == NULL) {
329
- result = formatRemoveMessage(*rulesBinding,
330
- sid,
331
- mid,
332
- actionType == ACTION_REMOVE_FACT ? 1 : 0,
333
- removeCommand);
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 handleBeta(ruleset *tree,
345
- char *sid,
346
- char *mid,
347
- node *betaNode,
348
- unsigned short actionType,
349
- char **evalKeys,
350
- unsigned int *evalCount,
351
- char **addKeys,
352
- unsigned int *addCount,
353
- char **removeCommand,
354
- void **rulesBinding) {
355
- int prefixLength = 0;
356
- node *currentNode = betaNode;
357
- while (currentNode != NULL) {
358
- int nameLength = strlen(&tree->stringPool[currentNode->nameOffset]);
359
- prefixLength += nameLength + 1;
360
-
361
- if (currentNode->type == NODE_ACTION) {
362
- currentNode = NULL;
363
- } else {
364
- if (currentNode->value.b.not) {
365
- switch (actionType) {
366
- case ACTION_ASSERT_FACT:
367
- actionType = ACTION_ADD_FACT;
368
- break;
369
- case ACTION_ASSERT_EVENT:
370
- actionType = ACTION_ADD_EVENT;
371
- break;
372
- case ACTION_REMOVE_FACT:
373
- actionType = ACTION_RETRACT_FACT;
374
- break;
375
- case ACTION_REMOVE_EVENT:
376
- actionType = ACTION_RETRACT_EVENT;
377
- break;
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 = &currentBeta->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 = &currentPrefix[nameLength + 1];
405
- currentNode = &tree->nodePool[currentNode->value.b.nextOffset];
406
683
  }
407
684
  }
408
- return handleAction(tree,
409
- sid,
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
- static unsigned int valueToProperty(ruleset *tree,
424
- char *sid,
425
- char *message,
426
- jsonObject *messageObject,
427
- jsonValue *sourceValue,
428
- char **state,
429
- unsigned char *releaseState,
430
- jsonProperty **targetProperty) {
696
+ jsonProperty resultProperty;
697
+ unsigned short i = 0;
698
+ CHECK_RESULT(reduceExpressionSequence(tree,
699
+ state,
700
+ &currentBeta->expressionSequence,
701
+ OP_NOP,
702
+ messageObject,
703
+ context,
704
+ &i,
705
+ &resultProperty));
431
706
 
432
- unsigned int result = RULES_OK;
433
- *releaseState = 0;
434
- switch(sourceValue->type) {
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
- return result;
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
- return ERR_PROPERTY_NOT_FOUND;
457
- case JSON_STATE_PROPERTY:
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
- if (result == ERR_STATE_NOT_LOADED || result == ERR_STALE_STATE) {
470
- result = refreshState(tree,sid);
471
- if (result != RULES_OK) {
472
- return result;
473
- }
716
+ static unsigned int isAlphaMatch(ruleset *tree,
717
+ alpha *currentAlpha,
718
+ jsonObject *messageObject,
719
+ unsigned char *propertyMatch) {
474
720
 
475
- result = fetchStateProperty(tree,
476
- sid,
477
- sourceValue->value.property.nameHash,
478
- MAX_STATE_PROPERTY_TIME,
479
- 0,
480
- state,
481
- targetProperty);
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
+ &currentAlpha->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
- return result;
485
- case JSON_STRING:
486
- *state = &tree->stringPool[sourceValue->value.stringOffset];
487
- (*targetProperty)->valueLength = strlen(*state);
488
- (*targetProperty)->valueString = *state;
489
- break;
490
- case JSON_INT:
491
- (*targetProperty)->value.i = sourceValue->value.i;
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
- (*targetProperty)->isMaterial = 1;
502
- (*targetProperty)->type = sourceValue->type;
503
- return result;
750
+ return 1;
504
751
  }
505
752
 
506
- static unsigned int reduceProperties(unsigned char operator,
507
- jsonProperty *leftProperty,
508
- char *leftState,
509
- jsonProperty *rightProperty,
510
- char *rightState,
511
- jsonProperty *targetValue,
512
- char **state) {
513
- *state = NULL;
514
- unsigned short type = leftProperty->type << 8;
515
- type = type + rightProperty->type;
516
- char leftTemp = 0;
517
- char rightTemp = 0;
518
- if (leftProperty->type == JSON_STRING || rightProperty->type == JSON_STRING) {
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
- if (leftProperty->type == JSON_STRING) {
528
- leftTemp = *(leftProperty->valueString + leftProperty->valueLength);
529
- *(leftProperty->valueString + leftProperty->valueLength) = '\0';
530
- }
769
+ #endif
531
770
 
532
- if (rightProperty->type == JSON_STRING) {
533
- rightTemp = *(rightProperty->valueString + rightProperty->valueLength);
534
- *(rightProperty->valueString + rightProperty->valueLength) = '\0';
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
+ &currentFrame,
789
+ &currentFrameLocation));
790
+ } else if (currentNode->type == NODE_BETA) {
791
+ CHECK_RESULT(createLeftFrame(state,
792
+ currentNode,
793
+ currentFrame,
794
+ &currentFrame,
795
+ &currentFrameLocation));
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
+ &currentFrame,
804
+ &currentFrameLocation));
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
- switch(type) {
539
- case OP_BOOL_BOOL:
540
- targetValue->value.i = reduceInt(leftProperty->value.b, rightProperty->value.b, operator);
541
- targetValue->type = JSON_INT;
542
- break;
543
- case OP_BOOL_INT:
544
- targetValue->value.i = reduceInt(leftProperty->value.b, rightProperty->value.i, operator);
545
- targetValue->type = JSON_INT;
546
- break;
547
- case OP_BOOL_DOUBLE:
548
- targetValue->value.d = reduceDouble(leftProperty->value.b, rightProperty->value.d, operator);
549
- targetValue->type = JSON_DOUBLE;
550
- break;
551
- case OP_BOOL_STRING:
552
- if (asprintf(state,
553
- "%s%s",
554
- leftProperty->value.b ? "true" : "false",
555
- rightProperty->valueString) == -1) {
556
- return ERR_OUT_OF_MEMORY;
557
- }
558
- break;
559
- case OP_INT_BOOL:
560
- targetValue->value.i = reduceInt(leftProperty->value.i, rightProperty->value.b, operator);
561
- targetValue->type = JSON_INT;
562
- break;
563
- case OP_INT_INT:
564
- targetValue->value.i = reduceInt(leftProperty->value.i, rightProperty->value.i, operator);
565
- targetValue->type = JSON_INT;
566
- break;
567
- case OP_INT_DOUBLE:
568
- targetValue->value.d = reduceDouble(leftProperty->value.i, rightProperty->value.d, operator);
569
- targetValue->type = JSON_DOUBLE;
570
- break;
571
- case OP_INT_STRING:
572
- if (asprintf(state,
573
- "%ld%s",
574
- leftProperty->value.i,
575
- rightProperty->valueString) == -1) {
576
- return ERR_OUT_OF_MEMORY;
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
+ &currentNode->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
+ &currentNode->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
- break;
579
- case OP_DOUBLE_BOOL:
580
- targetValue->value.d = reduceDouble(leftProperty->value.d, rightProperty->value.b, operator);
581
- targetValue->type = JSON_DOUBLE;
582
- break;
583
- case OP_DOUBLE_INT:
584
- targetValue->value.d = reduceDouble(leftProperty->value.d, rightProperty->value.i, operator);
585
- targetValue->type = JSON_DOUBLE;
586
- break;
587
- case OP_DOUBLE_DOUBLE:
588
- targetValue->value.d = reduceDouble(leftProperty->value.d, rightProperty->value.d, operator);
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
- break;
600
- case OP_STRING_BOOL:
601
- if (asprintf(state,
602
- "%s%s",
603
- leftProperty->valueString,
604
- rightProperty->value.b ? "true" : "false") == -1) {
605
- return ERR_OUT_OF_MEMORY;
606
- }
607
- break;
608
- case OP_STRING_INT:
609
- if (asprintf(state,
610
- "%s%ld",
611
- leftProperty->valueString,
612
- rightProperty->value.i) == -1) {
613
- return ERR_OUT_OF_MEMORY;
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
+ &currentNode->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
- break;
616
- case OP_STRING_DOUBLE:
617
- if (asprintf(state,
618
- "%s%ld",
619
- leftProperty->valueString,
620
- rightProperty->value.i) == -1) {
621
- return ERR_OUT_OF_MEMORY;
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
- break;
624
- case OP_STRING_STRING:
625
- if (asprintf(state,
626
- "%s%s",
627
- leftProperty->valueString,
628
- rightProperty->valueString) == -1) {
629
- return ERR_OUT_OF_MEMORY;
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 reduceIdiom(ruleset *tree,
652
- char *sid,
653
- char *message,
654
- jsonObject *messageObject,
655
- unsigned int idiomOffset,
656
- char **state,
657
- unsigned char *releaseState,
658
- jsonProperty **targetValue) {
659
- unsigned int result = RULES_OK;
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
- &currentIdiom->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
- jsonProperty rightValue;
679
- jsonProperty *rightProperty = &rightValue;
680
- unsigned char releaseRightState = 0;
681
- char *rightState = NULL;
682
- result = valueToProperty(tree,
683
- sid,
684
- message,
685
- messageObject,
686
- &currentIdiom->right,
687
- &rightState,
688
- &releaseRightState,
689
- &rightProperty);
690
- if (result != RULES_OK) {
691
- if (releaseLeftState) {
692
- free(leftState);
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
+ &currentNode->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
+ &currentFrame));
1096
+ while (currentFrame) {
1097
+ unsigned char match = 0;
1098
+ CHECK_RESULT(isBetaMatch(tree,
1099
+ state,
1100
+ &currentNode->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
- result = reduceProperties(currentIdiom->operator,
699
- leftProperty,
700
- leftState,
701
- rightProperty,
702
- rightState,
703
- *targetValue,
704
- state);
1143
+ return RULES_OK;
1144
+ }
705
1145
 
706
- if (releaseLeftState) {
707
- free(leftState);
708
- }
1146
+ static unsigned char isSubset(leftFrameNode *currentFrame,
1147
+ leftFrameNode *targetFrame) {
709
1148
 
710
- if (releaseRightState) {
711
- free(rightState);
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
- if (state) {
715
- *releaseState = 1;
1159
+ if (!found) {
1160
+ return 0;
1161
+ }
716
1162
  }
717
1163
 
718
- return result;
1164
+ return 1;
719
1165
  }
720
1166
 
721
- static unsigned int isMatch(ruleset *tree,
722
- char *sid,
723
- char *message,
724
- jsonObject *messageObject,
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
- rehydrateProperty(currentProperty, message);
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
- &currentAlpha->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
- if (result != ERR_NEW_SESSION && result != ERR_PROPERTY_NOT_FOUND) {
757
- return result;
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
- int leftLength;
764
- int rightLength;
765
- unsigned short type = propertyType << 8;
766
- type = type + rightProperty->type;
767
- switch(type) {
768
- case OP_BOOL_BOOL:
769
- *propertyMatch = compareBool(currentProperty->value.b, rightProperty->value.b, alphaOp);
770
- break;
771
- case OP_BOOL_INT:
772
- *propertyMatch = compareInt(currentProperty->value.b, rightProperty->value.i, alphaOp);
773
- break;
774
- case OP_BOOL_DOUBLE:
775
- *propertyMatch = compareDouble(currentProperty->value.b, rightProperty->value.d, alphaOp);
776
- break;
777
- case OP_BOOL_STRING:
778
- if (currentProperty->value.b) {
779
- *propertyMatch = compareStringProperty("true",
780
- rightProperty->valueString,
781
- rightProperty->valueLength,
782
- alphaOp);
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
- else {
785
- *propertyMatch = compareStringProperty("false",
786
- rightProperty->valueString,
787
- rightProperty->valueLength,
788
- alphaOp);
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
+ &currentFrame));
1241
+
1242
+ while (currentFrame) {
1243
+
1244
+ unsigned char match = 0;
1245
+ CHECK_RESULT(isBetaMatch(tree,
1246
+ state,
1247
+ &currentNode->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
- break;
792
- case OP_INT_BOOL:
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
- *propertyMatch = 0;
903
- }
1271
+ location.frameOffset = currentFrame->prevOffset;
1272
+ currentFrame = NULL;
1273
+ }
1274
+ }
1275
+ }
904
1276
 
905
- break;
906
- case OP_NIL_NIL:
907
- if (alphaOp == OP_EQ) {
908
- *propertyMatch = 1;
909
- } else {
910
- *propertyMatch = 0;
911
- }
1277
+ return RULES_OK;
1278
+ }
912
1279
 
913
- break;
914
- case OP_STRING_REGEX:
915
- case OP_STRING_IREGEX:
916
- *propertyMatch = evaluateRegex(tree,
917
- currentProperty->valueString,
918
- currentProperty->valueLength,
919
- (type == OP_STRING_REGEX) ? 0 : 1,
920
- currentAlpha->right.value.regex.vocabularyLength,
921
- currentAlpha->right.value.regex.statesLength,
922
- currentAlpha->right.value.regex.stateMachineOffset);
923
- break;
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
+ &currentFrame));
1294
+
1295
+ while (currentFrame) {
1296
+ unsigned char match = 0;
1297
+ CHECK_RESULT(isBetaMatch(tree,
1298
+ state,
1299
+ &currentNode->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 (releaseRightState) {
928
- free(rightState);
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
- return result;
1338
+
1339
+ return RULES_OK;
931
1340
  }
932
1341
 
933
- static unsigned int isArrayMatch(ruleset *tree,
934
- char *sid,
935
- char *message,
936
- jsonObject *messageObject,
937
- jsonProperty *currentProperty,
938
- alpha *arrayAlpha,
939
- unsigned char *propertyMatch,
940
- void **rulesBinding) {
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->valueString;
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
- result = constructObject(first,
961
- "$i",
962
- NULL,
963
- JSON_OBJECT_SEQUENCED,
964
- 0,
965
- &jo,
966
- &next);
967
- if (result != RULES_OK) {
968
- return result;
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.propertiesLength = 1;
972
- jo.properties[0].hash = HASH_I;
973
- jo.properties[0].type = type;
974
- jo.properties[0].isMaterial = 0;
975
- jo.properties[0].valueString = first;
976
- jo.properties[0].valueLength = last - first;
977
- jo.properties[0].nameLength = 2;
978
- strcpy(jo.properties[0].name, "$i");
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.hash == jo.properties[propertyIndex].hash) {
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.hash) {
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
- // isArrayMatch finds a valid path, thus use propertyMatch
1020
- result = isArrayMatch(tree,
1021
- sid,
1022
- message,
1023
- messageObject,
1024
- currentProperty,
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
- result = isMatch(tree,
1030
- sid,
1031
- message,
1032
- messageObject,
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
- char *sid,
1531
+ static unsigned int handleAlpha(ruleset *tree,
1532
+ stateNode *state,
1078
1533
  char *mid,
1079
- char *message,
1080
1534
  jsonObject *jo,
1081
- alpha *alphaNode,
1082
- unsigned char actionType,
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
- char exists = 0;
1104
- for(unsigned int propertyIndex = 0; propertyIndex < jo->propertiesLength; ++propertyIndex) {
1105
- if (listNode->value.a.hash == jo->properties[propertyIndex].hash) {
1106
- // filter out not exists (OP_NEX)
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.hash) {
1131
- if (hashNode->value.a.right.type == JSON_EVENT_PROPERTY || hashNode->value.a.right.type == JSON_EVENT_IDIOM) {
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
- unsigned int mresult = RULES_OK;
1140
- if (hashNode->value.a.operator == OP_IALL || hashNode->value.a.operator == OP_IANY) {
1141
- mresult = isArrayMatch(tree,
1142
- sid,
1143
- message,
1144
- jo,
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
- mresult = isMatch(tree,
1151
- sid,
1152
- message,
1153
- jo,
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
- unsigned int bresult = handleBeta(tree,
1182
- sid,
1183
- mid,
1184
- &tree->nodePool[betaList[entry]],
1185
- actionType,
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
- char **commands,
1212
- unsigned int *commandCount,
1213
- void **rulesBinding) {
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
- strncpy(sid, sidProperty->valueString, sidProperty->valueLength);
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
- strncpy(mid, midProperty->valueString, midProperty->valueLength);
1233
- mid[midProperty->valueLength] = '\0';
1234
-
1235
- if (*commandCount == MAX_COMMAND_COUNT) {
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
- if (result != RULES_OK) {
1335
- return result;
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
- if (!state) {
1343
- // try creating state if doesn't exist
1344
- jsonProperty *targetProperty;
1345
- char *targetState;
1346
- result = fetchStateProperty(tree,
1347
- sid,
1348
- HASH_SID,
1349
- MAX_STATE_PROPERTY_TIME,
1350
- 1,
1351
- &targetState,
1352
- &targetProperty);
1353
- if (result != ERR_STATE_NOT_LOADED && result != ERR_PROPERTY_NOT_FOUND) {
1354
- return result;
1355
- }
1356
-
1357
- // this sid has been tried by this process already
1358
- if (result == ERR_PROPERTY_NOT_FOUND) {
1359
- return RULES_OK;
1360
- }
1361
-
1362
- result = refreshState(tree, sid);
1363
- if (result != ERR_NEW_SESSION) {
1364
- return result;
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
- char *stateMessage = (char *)_alloca(sizeof(char)*(36 + sidProperty->valueLength));
1368
- char *newState = (char *)_alloca(sizeof(char)*(12 + sidProperty->valueLength));
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
- char stateMessage[36 + sidProperty->valueLength];
1373
- char newState[12 + sidProperty->valueLength];
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
- if (*commandCount == MAX_COMMAND_COUNT) {
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 RULES_OK;
1738
+ return result;
1406
1739
  }
1407
1740
 
1408
- return result;
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
- char **commands,
1416
- unsigned int *commandCount,
1417
- void **rulesBinding) {
1748
+ unsigned int *messageOffset,
1749
+ unsigned int *stateOffset) {
1418
1750
  char *next;
1419
1751
  jsonObject jo;
1420
- int result = constructObject(message,
1752
+ CHECK_RESULT(constructObject(message,
1421
1753
  NULL,
1422
1754
  NULL,
1423
- JSON_OBJECT_SEQUENCED,
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
- state,
1435
- message,
1436
- &jo,
1437
- actionType,
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
- char **commands,
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
- JSON_OBJECT_SEQUENCED,
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
- NULL,
1483
- first,
1484
- &jo,
1485
- actionType,
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
- static unsigned int handleState(ruleset *tree,
1509
- char *state,
1510
- char **commands,
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 startHandleMessage(tree, message, ACTION_ASSERT_EVENT, rulesBinding, replyCount);
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
- ruleset *tree;
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 executeHandleMessage(tree, message, ACTION_ASSERT_FACT);
1839
+ return handleMessages(tree, ACTION_ASSERT_EVENT, messages, stateOffset);
1769
1840
  }
1770
1841
 
1771
- unsigned int startAssertFacts(unsigned int handle,
1772
- char *messages,
1773
- void **rulesBinding,
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 startHandleMessages(tree, messages, ACTION_ASSERT_FACT, rulesBinding, replyCount);
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 executeHandleMessages(tree, messages, ACTION_ASSERT_FACT);
1858
+ return handleMessages(tree, ACTION_ASSERT_EVENT, messages, stateOffset);
1787
1859
  }
1788
1860
 
1789
- unsigned int retractFact(unsigned int handle, char *message) {
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 executeHandleMessage(tree, message, ACTION_REMOVE_FACT);
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
- ruleset *tree;
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 startHandleMessages(tree, messages, ACTION_REMOVE_FACT, rulesBinding, replyCount);
1877
+ return handleMessages(tree, ACTION_ASSERT_EVENT, messages, stateOffset);
1822
1878
  }
1823
1879
 
1824
- unsigned int assertState(unsigned int handle, char *sid, char *state) {
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
- char *commands[MAX_COMMAND_COUNT];
1829
- unsigned int commandCount = 0;
1830
- void *rulesBinding = NULL;
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 **state,
1895
+ char **stateFact,
1876
1896
  char **messages,
1877
- void **actionHandle,
1878
- void **actionBinding) {
1897
+ unsigned int *stateOffset) {
1879
1898
  ruleset *tree;
1880
1899
  RESOLVE_HANDLE(handle, &tree);
1881
-
1882
- redisReply *reply;
1883
- void *rulesBinding;
1884
- unsigned int result = peekAction(tree, &rulesBinding, &reply);
1885
- if (result != RULES_OK) {
1886
- return result;
1887
- }
1888
-
1889
- *state = reply->element[1]->str;
1890
- *messages = reply->element[2]->str;
1891
- actionContext *context = malloc(sizeof(actionContext));
1892
- if (!context) {
1893
- return ERR_OUT_OF_MEMORY;
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 startUpdateState(unsigned int handle,
1904
- void *actionHandle,
1905
- char *state,
1906
- void **rulesBinding,
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
- char *commands[MAX_COMMAND_COUNT];
1912
- unsigned int result = RULES_OK;
1913
- unsigned int commandCount = 0;
1914
- result = handleState(tree,
1915
- state,
1916
- commands,
1917
- &commandCount,
1918
- rulesBinding);
1919
- if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
1920
- //reply object should be freed by the app during abandonAction
1921
- freeCommands(commands, commandCount);
1922
- return result;
1923
- }
1924
-
1925
- result = startNonBlockingBatch(*rulesBinding, commands, commandCount, replyCount);
1926
- return result;
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 completeAction(unsigned int handle,
1931
- void *actionHandle,
1932
- char *state) {
1933
- ruleset *tree;
1934
- RESOLVE_HANDLE(handle, &tree);
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
- ++commandCount;
1951
- result = handleState(tree,
1952
- state,
1953
- commands,
1954
- &commandCount,
1955
- &rulesBinding);
1956
- if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
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
- result = executeBatch(rulesBinding, commands, commandCount);
1963
- if (result != RULES_OK && result != ERR_EVENT_OBSERVED) {
1964
- //reply object should be freed by the app during abandonAction
1965
- return result;
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
- unsigned int completeAndStartAction(unsigned int handle,
1974
- unsigned int expectedReplies,
1975
- void *actionHandle,
1976
- char **messages) {
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
- ++commandCount;
1992
- if (commandCount == MAX_COMMAND_COUNT) {
1993
- //reply object should be freed by the app during abandonAction
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
- result = formatPeekAction(rulesBinding,
1999
- reply->element[0]->str,
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
- ++commandCount;
2008
- redisReply *newReply;
2009
- result = executeBatchWithReply(rulesBinding,
2010
- expectedReplies,
2011
- commands,
2012
- commandCount,
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
- freeReplyObject(reply);
2020
- if (newReply == NULL) {
2021
- free(actionHandle);
2022
- return ERR_NO_ACTION_AVAILABLE;
2023
- }
2037
+ CHECK_RESULT(deleteCurrentAction(tree,
2038
+ resultState,
2039
+ resultState->context.actionStateIndex,
2040
+ resultState->context.resultCount,
2041
+ resultState->context.resultFrameOffset));
2024
2042
 
2025
- *messages = newReply->element[1]->str;
2026
- context->reply = newReply;
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, void *actionHandle) {
2031
- freeReplyObject(((actionContext*)actionHandle)->reply);
2032
- free(actionHandle);
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 queueMessage(unsigned int handle, unsigned int queueAction, char *sid, char *destination, char *message) {
2081
+ unsigned int renewActionLease(unsigned int handle, char *sid) {
2037
2082
  ruleset *tree;
2038
- RESOLVE_HANDLE(handle, &tree);
2083
+ unsigned char isNewState;
2084
+ stateNode *state = NULL;
2039
2085
 
2040
- void *rulesBinding;
2086
+ RESOLVE_HANDLE(handle, &tree);
2041
2087
  if (!sid) {
2042
2088
  sid = "0";
2043
2089
  }
2044
2090
 
2045
- unsigned int result = resolveBinding(tree, sid, &rulesBinding);
2046
- if (result != RULES_OK) {
2047
- return result;
2048
- }
2091
+ CHECK_RESULT(ensureStateNode(tree,
2092
+ sid,
2093
+ &isNewState,
2094
+ &state));
2049
2095
 
2050
- return registerMessage(rulesBinding, queueAction, destination, message);
2096
+ state->lockExpireTime = time(NULL) + STATE_LEASE_TIME;
2097
+ return RULES_OK;
2051
2098
  }
2052
2099
 
2053
- unsigned int startTimer(unsigned int handle, char *sid, unsigned int duration, char manualReset, char *timer) {
2100
+ unsigned int assertTimers(unsigned int handle) {
2054
2101
  ruleset *tree;
2102
+ unsigned int result;
2055
2103
  RESOLVE_HANDLE(handle, &tree);
2056
2104
 
2057
- void *rulesBinding;
2058
- if (!sid) {
2059
- sid = "0";
2060
- }
2061
-
2062
- unsigned int result = resolveBinding(tree, sid, &rulesBinding);
2063
- if (result != RULES_OK) {
2064
- return result;
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 registerTimer(rulesBinding, duration, manualReset, timer);
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
- RESOLVE_HANDLE(handle, &tree);
2154
+ unsigned char isNewState;
2155
+ unsigned int messageOffset;
2156
+ unsigned int stateOffset;
2157
+ stateNode *state = NULL;
2073
2158
 
2074
- void *rulesBinding;
2159
+ RESOLVE_HANDLE(handle, &tree);
2075
2160
  if (!sid) {
2076
2161
  sid = "0";
2077
2162
  }
2078
2163
 
2079
- unsigned int result = resolveBinding(tree, sid, &rulesBinding);
2080
- if (result != RULES_OK) {
2081
- return result;
2082
- }
2164
+ CHECK_RESULT(ensureStateNode(tree,
2165
+ sid,
2166
+ &isNewState,
2167
+ &state));
2083
2168
 
2084
- return removeTimer(rulesBinding, sid, timerName);
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 renewActionLease(unsigned int handle, char *sid) {
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
- void *rulesBinding;
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
- unsigned int result = resolveBinding(tree, sid, &rulesBinding);
2097
- if (result != RULES_OK) {
2098
- return result;
2099
- }
2100
-
2101
- return updateAction(rulesBinding, sid);
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
+