durable_rules 0.34.57 → 2.00.001

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