durable_rules 0.34.57 → 2.00.001

Sign up to get free protection for your applications and to get access to all the features.
data/src/rules/rete.h CHANGED
@@ -1,5 +1,7 @@
1
1
  #include "state.h"
2
2
 
3
+ //#define _PRINT 1
4
+
3
5
  #define OP_NOP 0
4
6
  #define OP_LT 0x01
5
7
  #define OP_LTE 0x02
@@ -26,15 +28,24 @@
26
28
  #define OP_IANY 0x17
27
29
 
28
30
  #define NODE_ALPHA 0
29
- #define NODE_BETA_CONNECTOR 1
30
- #define NODE_ACTION 2
31
+ #define NODE_BETA 1
32
+ #define NODE_CONNECTOR 2
33
+ #define NODE_ACTION 3
34
+
35
+ #define GATE_AND 0
36
+ #define GATE_OR 1
37
+
31
38
  #define NODE_M_OFFSET 0
32
39
 
33
- typedef struct reference {
34
- unsigned int nameHash;
40
+ #define MAX_STATE_INDEX_LENGTH 1024
41
+ #define MAX_SEQUENCE_EXPRESSIONS 32
42
+
43
+ typedef struct identifier {
44
+ unsigned int propertyNameHash;
45
+ unsigned int propertyNameOffset;
35
46
  unsigned int nameOffset;
36
- unsigned int idOffset;
37
- } reference;
47
+ unsigned int nameHash;
48
+ } identifier;
38
49
 
39
50
  typedef struct regexReference {
40
51
  unsigned int stringOffset;
@@ -43,64 +54,58 @@ typedef struct regexReference {
43
54
  unsigned short vocabularyLength;
44
55
  } regexReference;
45
56
 
46
- typedef struct jsonValue {
57
+ typedef struct operand {
47
58
  unsigned char type;
48
59
  union {
49
60
  long i;
50
61
  double d;
51
62
  unsigned char b;
52
63
  unsigned int stringOffset;
53
- unsigned int idiomOffset;
64
+ unsigned int expressionOffset;
54
65
  regexReference regex;
55
- reference property;
66
+ identifier id;
56
67
  } value;
57
- } jsonValue;
68
+ } operand;
58
69
 
59
- typedef struct idiom {
70
+ typedef struct expression {
60
71
  unsigned char operator;
61
- jsonValue left;
62
- jsonValue right;
63
- } idiom;
72
+ operand left;
73
+ operand right;
74
+ } expression;
64
75
 
65
- typedef struct expression {
76
+ typedef struct expressionSequence {
66
77
  unsigned int nameOffset;
67
78
  unsigned int aliasOffset;
68
- unsigned short termsLength;
69
- unsigned char distinct;
79
+ unsigned short length;
70
80
  unsigned char not;
71
- union {
72
- unsigned int termsOffset;
73
- unsigned int *termsPointer;
74
- } t;
75
- } expression;
76
-
77
- typedef struct join {
78
- unsigned int expressionsOffset;
79
- unsigned short expressionsLength;
80
- } join;
81
+ expression expressions[MAX_SEQUENCE_EXPRESSIONS];
82
+ } expressionSequence;
81
83
 
82
84
  typedef struct alpha {
83
- unsigned int hash;
84
- unsigned char operator;
85
+ expression expression;
85
86
  unsigned int betaListOffset;
86
87
  unsigned int nextListOffset;
87
88
  unsigned int nextOffset;
88
- jsonValue right;
89
89
  } alpha;
90
90
 
91
- typedef struct betaConnector {
91
+ typedef struct beta {
92
+ unsigned int index;
93
+ expressionSequence expressionSequence;
92
94
  unsigned int hash;
93
95
  unsigned int nextOffset;
96
+ unsigned int aOffset;
97
+ unsigned int bOffset;
98
+ unsigned char distinct;
94
99
  unsigned char not;
95
- } betaConnector;
100
+ unsigned char gateType;
101
+ unsigned char isFirst;
102
+ } beta;
96
103
 
97
104
  typedef struct action {
98
105
  unsigned int index;
99
106
  unsigned short count;
100
107
  unsigned short cap;
101
108
  unsigned short priority;
102
- unsigned int joinsOffset;
103
- unsigned short joinsLength;
104
109
  } action;
105
110
 
106
111
  typedef struct node {
@@ -108,40 +113,49 @@ typedef struct node {
108
113
  unsigned char type;
109
114
  union {
110
115
  alpha a;
111
- betaConnector b;
116
+ beta b;
112
117
  action c;
113
118
  } value;
114
119
  } node;
115
120
 
116
-
117
121
  typedef struct ruleset {
118
122
  unsigned int nameOffset;
123
+ unsigned int actionCount;
124
+ unsigned int betaCount;
125
+ unsigned int connectorCount;
126
+ void *bindingsList;
127
+
119
128
  node *nodePool;
120
129
  unsigned int nodeOffset;
130
+
121
131
  unsigned int *nextPool;
122
132
  unsigned int nextOffset;
133
+
123
134
  char *stringPool;
124
135
  unsigned int stringPoolLength;
136
+
125
137
  expression *expressionPool;
126
138
  unsigned int expressionOffset;
127
- idiom *idiomPool;
128
- unsigned int idiomOffset;
129
- join *joinPool;
130
- unsigned int joinOffset;
139
+
131
140
  char *regexStateMachinePool;
132
141
  unsigned int regexStateMachineOffset;
133
- unsigned int actionCount;
134
- void *bindingsList;
135
- unsigned int *stateBuckets;
136
- unsigned int stateBucketsLength;
137
- stateEntry *state;
138
- unsigned int maxStateLength;
139
- unsigned int stateLength;
140
- unsigned int lruStateOffset;
141
- unsigned int mruStateOffset;
142
- unsigned int orNodeOffset;
143
- unsigned int andNodeOffset;
144
- unsigned int endNodeOffset;
142
+
143
+ pool statePool;
144
+ unsigned int stateIndex[MAX_STATE_INDEX_LENGTH];
145
+ unsigned int reverseStateIndex[MAX_STATE_INDEX_LENGTH];
146
+ unsigned int currentStateIndex;
145
147
  } ruleset;
146
148
 
149
+ #ifdef _PRINT
150
+
151
+ void printSimpleExpression(ruleset *tree,
152
+ expression *currentExpression,
153
+ unsigned char first,
154
+ char *comp);
155
+
156
+ void printExpressionSequence(ruleset *tree,
157
+ expressionSequence *exprs,
158
+ int level);
159
+
147
160
 
161
+ #endif
data/src/rules/rules.h CHANGED
@@ -1,46 +1,37 @@
1
1
 
2
2
  #define RULES_OK 0
3
- #define ERR_OUT_OF_MEMORY 1
4
- #define ERR_UNEXPECTED_TYPE 2
5
- #define ERR_IDENTIFIER_LENGTH 3
6
- #define ERR_UNEXPECTED_VALUE 4
7
- #define ERR_UNEXPECTED_NAME 5
8
- #define ERR_RULE_LIMIT_EXCEEDED 6
9
- #define ERR_RULE_EXISTS_LIMIT_EXCEEDED 7
10
- #define ERR_RULE_BETA_LIMIT_EXCEEDED 8
11
- #define ERR_RULE_WITHOUT_QUALIFIER 9
12
- #define ERR_SETTING_NOT_FOUND 10
13
- #define ERR_INVALID_HANDLE 11
14
- #define ERR_HANDLE_LIMIT_EXCEEDED 12
15
- #define ERR_PARSE_VALUE 101
16
- #define ERR_PARSE_STRING 102
17
- #define ERR_PARSE_NUMBER 103
18
- #define ERR_PARSE_OBJECT 104
19
- #define ERR_PARSE_ARRAY 105
20
- #define ERR_EVENT_NOT_HANDLED 201
21
- #define ERR_EVENT_MAX_PROPERTIES 202
22
- #define ERR_MAX_STACK_SIZE 203
23
- #define ERR_NO_ID_DEFINED 204
24
- #define ERR_INVALID_ID 205
25
- #define ERR_PARSE_PATH 206
26
- #define ERR_MAX_NODE_RESULTS 207
27
- #define ERR_MAX_RESULT_NODES 208
28
- #define ERR_MAX_COMMAND_COUNT 209
29
- #define ERR_MAX_ADD_COUNT 210
30
- #define ERR_MAX_EVAL_COUNT 211
31
- #define ERR_EVENT_OBSERVED 212
32
- #define ERR_CONNECT_REDIS 301
33
- #define ERR_REDIS_ERROR 302
34
- #define ERR_NO_ACTION_AVAILABLE 303
35
- #define ERR_NO_TIMERS_AVAILABLE 304
36
- #define ERR_NEW_SESSION 305
37
- #define ERR_TRY_AGAIN 306
38
- #define ERR_STATE_CACHE_FULL 401
39
- #define ERR_BINDING_NOT_MAPPED 402
40
- #define ERR_STATE_NOT_LOADED 403
41
- #define ERR_STALE_STATE 404
42
- #define ERR_PROPERTY_NOT_FOUND 405
43
- #define ERR_MAX_PROPERTY_NAME_LENGTH 406
3
+ #define ERR_EVENT_NOT_HANDLED 1
4
+ #define ERR_EVENT_OBSERVED 2
5
+
6
+ #define ERR_OUT_OF_MEMORY 101
7
+ #define ERR_UNEXPECTED_TYPE 102
8
+ #define ERR_IDENTIFIER_LENGTH 103
9
+ #define ERR_UNEXPECTED_VALUE 104
10
+ #define ERR_UNEXPECTED_NAME 105
11
+ #define ERR_RULE_LIMIT_EXCEEDED 106
12
+ #define ERR_RULE_EXISTS_LIMIT_EXCEEDED 107
13
+ #define ERR_RULE_BETA_LIMIT_EXCEEDED 108
14
+ #define ERR_RULE_WITHOUT_QUALIFIER 109
15
+ #define ERR_SETTING_NOT_FOUND 110
16
+ #define ERR_INVALID_HANDLE 111
17
+ #define ERR_HANDLE_LIMIT_EXCEEDED 112
18
+ #define ERR_EXPRESSION_LIMIT_EXCEEDED 113
19
+ #define ERR_PARSE_VALUE 201
20
+ #define ERR_PARSE_STRING 202
21
+ #define ERR_PARSE_NUMBER 203
22
+ #define ERR_PARSE_OBJECT 204
23
+ #define ERR_PARSE_ARRAY 205
24
+ #define ERR_EVENT_MAX_PROPERTIES 302
25
+ #define ERR_MAX_STACK_SIZE 303
26
+ #define ERR_MAX_MESSAGES_IN_FRAME 304
27
+ #define ERR_MESSAGE_NOT_FOUND 305
28
+ #define ERR_LOCATION_NOT_FOUND 306
29
+ #define ERR_NODE_DELETED 307
30
+ #define ERR_NODE_DISPATCHING 308
31
+ #define ERR_SID_NOT_FOUND 309
32
+ #define ERR_NO_ACTION_AVAILABLE 310
33
+ #define ERR_PROPERTY_NOT_FOUND 311
34
+ #define ERR_OPERATION_NOT_SUPPORTED 312
44
35
  #define ERR_PARSE_REGEX 501
45
36
  #define ERR_REGEX_MAX_TRANSITIONS 502
46
37
  #define ERR_REGEX_MAX_STATES 503
@@ -60,6 +51,7 @@
60
51
 
61
52
  #define MAX_HANDLES 131072
62
53
 
54
+
63
55
  #ifdef __cplusplus
64
56
  extern "C" {
65
57
  #endif
@@ -75,6 +67,13 @@ extern unsigned int firstEmptyEntry;
75
67
  extern unsigned int lastEmptyEntry;
76
68
  extern char entriesInitialized;
77
69
 
70
+ #define CHECK_RESULT(func) do { \
71
+ unsigned int result = func; \
72
+ if (result != RULES_OK) { \
73
+ return result; \
74
+ } \
75
+ } while(0)
76
+
78
77
  #define INITIALIZE_ENTRIES do { \
79
78
  if (!entriesInitialized) { \
80
79
  for (unsigned int i = 0; i < lastEmptyEntry; ++i) { \
@@ -111,14 +110,12 @@ extern char entriesInitialized;
111
110
 
112
111
  unsigned int createRuleset(unsigned int *handle,
113
112
  char *name,
114
- char *rules,
115
- unsigned int stateCaheSize);
113
+ char *rules);
116
114
 
117
115
  unsigned int deleteRuleset(unsigned int handle);
118
116
 
119
117
  unsigned int createClient(unsigned int *handle,
120
- char *name,
121
- unsigned int stateCaheSize);
118
+ char *name);
122
119
 
123
120
  unsigned int deleteClient(unsigned int handle);
124
121
 
@@ -128,87 +125,54 @@ unsigned int bindRuleset(unsigned int handle,
128
125
  char *password,
129
126
  unsigned char db);
130
127
 
131
- unsigned int complete(void *rulesBinding,
132
- unsigned int replyCount);
133
-
134
128
  unsigned int assertEvent(unsigned int handle,
135
- char *message);
136
-
137
- unsigned int startAssertEvent(unsigned int handle,
138
- char *message,
139
- void **rulesBinding,
140
- unsigned int *replyCount);
129
+ char *message,
130
+ unsigned int *stateOffset);
141
131
 
142
132
  unsigned int assertEvents(unsigned int handle,
143
- char *messages);
144
-
145
- unsigned int startAssertEvents(unsigned int handle,
146
- char *messages,
147
- void **rulesBinding,
148
- unsigned int *replyCount);
133
+ char *messages,
134
+ unsigned int *stateOffset);
149
135
 
150
136
  unsigned int retractEvent(unsigned int handle,
151
- char *message);
152
-
153
- unsigned int startAssertFact(unsigned int handle,
154
- char *message,
155
- void **rulesBinding,
156
- unsigned int *replyCount);
137
+ char *message,
138
+ unsigned int *stateOffset);
157
139
 
158
140
  unsigned int assertFact(unsigned int handle,
159
- char *message);
160
-
161
- unsigned int startAssertFacts(unsigned int handle,
162
- char *messages,
163
- void **rulesBinding,
164
- unsigned int *replyCount);
141
+ char *message,
142
+ unsigned int *stateOffset);
165
143
 
166
144
  unsigned int assertFacts(unsigned int handle,
167
- char *messages);
145
+ char *messages,
146
+ unsigned int *stateOffset);
168
147
 
169
148
  unsigned int retractFact(unsigned int handle,
170
- char *message);
171
-
172
- unsigned int startRetractFact(unsigned int handle,
173
- char *message,
174
- void **rulesBinding,
175
- unsigned int *replyCount);
149
+ char *message,
150
+ unsigned int *stateOffset);
176
151
 
177
152
  unsigned int retractFacts(unsigned int handle,
178
- char *messages);
179
-
180
- unsigned int startRetractFacts(unsigned int handle,
181
- char *messages,
182
- void **rulesBinding,
183
- unsigned int *replyCount);
153
+ char *messages,
154
+ unsigned int *stateOffset);
184
155
 
185
- unsigned int startUpdateState(unsigned int handle,
186
- void *actionHandle,
187
- char *state,
188
- void **rulesBinding,
189
- unsigned int *replyCount);
190
-
191
- unsigned int assertState(unsigned int handle,
192
- char *sid,
193
- char *state);
156
+ unsigned int updateState(unsigned int handle,
157
+ char *state,
158
+ unsigned int *stateOffset);
194
159
 
195
160
  unsigned int startAction(unsigned int handle,
196
- char **state,
161
+ char **stateFact,
197
162
  char **messages,
198
- void **actionHandle,
199
- void **actionBinding);
163
+ unsigned int *stateOffset);
200
164
 
201
- unsigned int completeAction(unsigned int handle,
202
- void *actionHandle,
203
- char *state);
165
+ unsigned int startActionForState(unsigned int handle,
166
+ unsigned int stateOffset,
167
+ char **stateFact,
168
+ char **messages);
204
169
 
205
170
  unsigned int completeAndStartAction(unsigned int handle,
206
- unsigned int expectedReplies,
207
- void *actionHandle,
171
+ unsigned int stateOffset,
208
172
  char **messages);
209
173
 
210
174
  unsigned int abandonAction(unsigned int handle,
211
- void *actionHandle);
175
+ unsigned int stateOffset);
212
176
 
213
177
  unsigned int startTimer(unsigned int handle,
214
178
  char *sid,
@@ -220,12 +184,6 @@ unsigned int cancelTimer(unsigned int handle,
220
184
  char *sid,
221
185
  char *timerName);
222
186
 
223
- unsigned int queueMessage(unsigned int handle,
224
- unsigned int queueAction,
225
- char *sid,
226
- char *destination,
227
- char *message);
228
-
229
187
  unsigned int assertTimers(unsigned int handle);
230
188
 
231
189
  unsigned int getState(unsigned int handle,
data/src/rules/state.c CHANGED
@@ -4,213 +4,1083 @@
4
4
  #include <time.h>
5
5
  #include "rules.h"
6
6
  #include "json.h"
7
- #include "net.h"
8
-
9
- unsigned int fnv1Hash32(char *str, unsigned int len) {
7
+ #include "rete.h"
8
+
9
+ #define MAX_STATE_NODES 8
10
+ #define MAX_MESSAGE_NODES 16
11
+ #define MAX_LEFT_FRAME_NODES 8
12
+ #define MAX_RIGHT_FRAME_NODES 8
13
+ #define MAX_LOCATION_NODES 16
14
+
15
+ // The first node is never used as it corresponds to UNDEFINED_HASH_OFFSET
16
+ #define INIT(type, pool, length) do { \
17
+ pool.content = malloc(length * sizeof(type)); \
18
+ if (!pool.content) { \
19
+ return ERR_OUT_OF_MEMORY; \
20
+ } \
21
+ pool.contentLength = length; \
22
+ for (unsigned int i = 0; i < length; ++ i) { \
23
+ ((type *)pool.content)[i].isActive = 0; \
24
+ ((type *)pool.content)[i].nextOffset = i + 1; \
25
+ ((type *)pool.content)[i].prevOffset = i - 1; \
26
+ } \
27
+ ((type *)pool.content)[length - 1].nextOffset = UNDEFINED_HASH_OFFSET; \
28
+ ((type *)pool.content)[0].prevOffset = UNDEFINED_HASH_OFFSET; \
29
+ pool.freeOffset = 1; \
30
+ pool.count = 0; \
31
+ } while(0)
32
+
33
+ #define GET_FIRST(type, index, max, pool, nodeHash, valueOffset) do { \
34
+ valueOffset = index[(nodeHash % max) * 2]; \
35
+ while (valueOffset != UNDEFINED_HASH_OFFSET) { \
36
+ type *value = &((type *)pool.content)[valueOffset]; \
37
+ if (value->hash != nodeHash) { \
38
+ valueOffset = value->nextOffset; \
39
+ } else { \
40
+ break; \
41
+ } \
42
+ } \
43
+ } while(0)
44
+
45
+ #define GET_LAST(type, index, max, pool, nodeHash, valueOffset) do { \
46
+ valueOffset = index[(nodeHash % max) * 2 + 1]; \
47
+ while (valueOffset != UNDEFINED_HASH_OFFSET) { \
48
+ type *value = &((type *)pool.content)[valueOffset]; \
49
+ if (value->hash != nodeHash) { \
50
+ valueOffset = value->prevOffset; \
51
+ } else { \
52
+ break; \
53
+ } \
54
+ } \
55
+ } while(0)
56
+
57
+ #define NEW(type, pool, valueOffset) do { \
58
+ valueOffset = pool.freeOffset; \
59
+ type *value = &((type *)pool.content)[valueOffset]; \
60
+ if (value->nextOffset == UNDEFINED_HASH_OFFSET) { \
61
+ pool.content = realloc(pool.content, (pool.contentLength * 1.5) * sizeof(type)); \
62
+ if (!pool.content) { \
63
+ return ERR_OUT_OF_MEMORY; \
64
+ } \
65
+ for (unsigned int i = pool.contentLength; i < pool.contentLength * 1.5; ++ i) { \
66
+ ((type *)pool.content)[i].isActive = 0; \
67
+ ((type *)pool.content)[i].nextOffset = i + 1; \
68
+ ((type *)pool.content)[i].prevOffset = i - 1; \
69
+ } \
70
+ value = &((type *)pool.content)[valueOffset]; \
71
+ value->nextOffset = pool.contentLength; \
72
+ ((type *)pool.content)[pool.contentLength].prevOffset = valueOffset; \
73
+ pool.contentLength *= 1.5; \
74
+ ((type *)pool.content)[pool.contentLength - 1].nextOffset = UNDEFINED_HASH_OFFSET; \
75
+ } \
76
+ ((type *)pool.content)[value->nextOffset].prevOffset = UNDEFINED_HASH_OFFSET; \
77
+ pool.freeOffset = value->nextOffset; \
78
+ value->nextOffset = UNDEFINED_HASH_OFFSET; \
79
+ value->prevOffset = UNDEFINED_HASH_OFFSET; \
80
+ value->isActive = 1; \
81
+ ++pool.count; \
82
+ } while(0)
83
+
84
+ #define SET(type, index, max, pool, nodeHash, valueOffset) do { \
85
+ type *value = &((type *)pool.content)[valueOffset]; \
86
+ value->hash = nodeHash; \
87
+ value->prevOffset = UNDEFINED_HASH_OFFSET; \
88
+ value->nextOffset = index[(nodeHash % max) * 2]; \
89
+ index[(nodeHash % max) * 2] = valueOffset; \
90
+ if (value->nextOffset != UNDEFINED_HASH_OFFSET) { \
91
+ ((type *)pool.content)[value->nextOffset].prevOffset = valueOffset; \
92
+ } else { \
93
+ index[(nodeHash % max) * 2 + 1] = valueOffset; \
94
+ } \
95
+ } while(0)
96
+
97
+ #define DELETE(type, index, max, pool, valueOffset) do { \
98
+ type *value = &((type *)pool.content)[valueOffset]; \
99
+ if (!value->isActive) { \
100
+ return ERR_NODE_DELETED; \
101
+ } \
102
+ if (value->prevOffset == UNDEFINED_HASH_OFFSET) { \
103
+ index[(value->hash % max) * 2] = value->nextOffset; \
104
+ } else { \
105
+ type *prevValue = &((type *)pool.content)[value->prevOffset]; \
106
+ prevValue->nextOffset = value->nextOffset; \
107
+ } \
108
+ if (value->nextOffset == UNDEFINED_HASH_OFFSET) { \
109
+ index[(value->hash % max) * 2 + 1] = value->prevOffset; \
110
+ } else { \
111
+ type *nextValue = &((type *)pool.content)[value->nextOffset]; \
112
+ nextValue->prevOffset = value->prevOffset; \
113
+ } \
114
+ value->nextOffset = pool.freeOffset; \
115
+ value->prevOffset = UNDEFINED_HASH_OFFSET; \
116
+ value->isActive = 0; \
117
+ if (pool.freeOffset != UNDEFINED_HASH_OFFSET) { \
118
+ type *freeValue = &((type *)pool.content)[pool.freeOffset]; \
119
+ freeValue->prevOffset = valueOffset; \
120
+ } \
121
+ pool.freeOffset = valueOffset; \
122
+ --pool.count; \
123
+ } while (0)
124
+
125
+ unsigned int fnv1Hash32(char *str, unsigned int length) {
10
126
  unsigned int hash = FNV_32_OFFSET_BASIS;
11
- for(unsigned int i = 0; i < len; str++, i++) {
127
+ for(unsigned int i = 0; i < length; str++, i++) {
12
128
  hash ^= (*str);
13
129
  hash *= FNV_32_PRIME;
14
130
  }
15
131
  return hash;
16
132
  }
17
133
 
18
- static unsigned int evictEntry(ruleset *tree) {
19
- stateEntry *lruEntry = &tree->state[tree->lruStateOffset];
20
- unsigned int lruBucket = lruEntry->sidHash % tree->stateBucketsLength;
21
- unsigned int offset = tree->stateBuckets[lruBucket];
22
- unsigned int lastOffset = UNDEFINED_HASH_OFFSET;
23
- unsigned char found = 0;
24
- while (!found) {
25
- stateEntry *current = &tree->state[offset];
26
- if (current->sidHash == lruEntry->sidHash) {
27
- if (!strcmp(current->sid, lruEntry->sid)) {
28
- if (lastOffset == UNDEFINED_HASH_OFFSET) {
29
- tree->stateBuckets[lruBucket] = current->nextHashOffset;
30
- } else {
31
- tree->state[lastOffset].nextHashOffset = current->nextHashOffset;
32
- }
134
+ unsigned int getHash(char *sid, char *key) {
135
+ unsigned int fullKeyLength = strlen(sid) + strlen(key) + 2;
136
+ #ifdef _WIN32
137
+ char *fullKey = (char *)_alloca(sizeof(char)*(fullKeyLength));
138
+ sprintf_s(fullKey, sizeof(char)*(fullKeyLength), "%s!%s", sid, key);
139
+ #else
140
+ char fullKey[fullKeyLength];
141
+ snprintf(fullKey, sizeof(char)*(fullKeyLength), "%s!%s", sid, key);
142
+ #endif
143
+ return fnv1Hash32(fullKey, fullKeyLength - 1);
144
+ }
33
145
 
34
- if (current->state) {
35
- free(current->state);
36
- current->state = NULL;
37
- }
146
+ unsigned int getLocationHash(frameLocation location) {
147
+ unsigned int hash = FNV_32_OFFSET_BASIS;
148
+ hash ^= location.frameType;
149
+ hash *= FNV_32_PRIME;
150
+ hash ^= location.nodeIndex;
151
+ hash *= FNV_32_PRIME;
152
+ hash ^= location.frameOffset;
153
+ hash *= FNV_32_PRIME;
154
+
155
+ return hash;
156
+ }
157
+
158
+ unsigned int initStatePool(void *tree) {
159
+ INIT(stateNode, ((ruleset*)tree)->statePool, MAX_STATE_NODES);
160
+ return RULES_OK;
161
+ }
162
+
163
+ unsigned int addFrameLocation(stateNode *state,
164
+ frameLocation location,
165
+ unsigned int messageNodeOffset) {
166
+ messageNode *message = MESSAGE_NODE(state, messageNodeOffset);
167
+ unsigned int locationNodeOffset;
168
+ NEW(locationNode,
169
+ message->locationPool,
170
+ locationNodeOffset);
171
+
172
+ locationNode *newLocationNode = LOCATION_NODE(message, locationNodeOffset);
173
+ newLocationNode->location.frameType = location.frameType;
174
+ newLocationNode->location.nodeIndex = location.nodeIndex;
175
+ newLocationNode->location.frameOffset = location.frameOffset;
176
+
177
+ unsigned int hash = getLocationHash(newLocationNode->location);
178
+ SET(locationNode,
179
+ message->locationIndex,
180
+ MAX_LOCATION_INDEX_LENGTH,
181
+ message->locationPool,
182
+ hash,
183
+ locationNodeOffset);
184
+
185
+ return RULES_OK;
186
+ }
187
+
188
+ unsigned int deleteFrameLocation(stateNode *state,
189
+ unsigned int messageNodeOffset,
190
+ frameLocation location) {
191
+ messageNode *message = MESSAGE_NODE(state, messageNodeOffset);
192
+ if (!message->isActive) {
193
+ return RULES_OK;
194
+ }
38
195
 
39
- free(current->sid);
40
- current->sid = NULL;
41
- current->sidHash = 0;
42
- current->bindingIndex = 0;
43
- current->lastRefresh = 0;
44
- current->jo.propertiesLength = 0;
45
- found = 1;
196
+ unsigned int hash = getLocationHash(location);
197
+ unsigned int locationNodeOffset;
198
+ GET_FIRST(locationNode,
199
+ message->locationIndex,
200
+ MAX_LOCATION_INDEX_LENGTH,
201
+ message->locationPool,
202
+ hash,
203
+ locationNodeOffset);
204
+
205
+ while (locationNodeOffset != UNDEFINED_HASH_OFFSET) {
206
+ locationNode *newLocationNode = LOCATION_NODE(message, locationNodeOffset);
207
+ if (newLocationNode->hash != hash) {
208
+ locationNodeOffset = UNDEFINED_HASH_OFFSET;
209
+ } else {
210
+ if (newLocationNode->location.frameType == location.frameType &&
211
+ newLocationNode->location.nodeIndex == location.nodeIndex &&
212
+ newLocationNode->location.frameOffset == location.frameOffset) {
213
+ DELETE(locationNode,
214
+ message->locationIndex,
215
+ MAX_LOCATION_INDEX_LENGTH,
216
+ message->locationPool,
217
+ locationNodeOffset);
218
+
219
+ return RULES_OK;
46
220
  }
221
+
222
+ locationNodeOffset = newLocationNode->nextOffset;
47
223
  }
224
+ }
48
225
 
49
- lastOffset = offset;
50
- offset = current->nextHashOffset;
226
+ return RULES_OK;
227
+ }
228
+
229
+ unsigned int deleteMessageFromFrame(unsigned int messageNodeOffset,
230
+ leftFrameNode *frame) {
231
+
232
+ for (int i = 0, c = 0; c < frame->messageCount; ++i) {
233
+ if (frame->messages[i].hash) {
234
+ ++c;
235
+ if (frame->messages[i].messageNodeOffset == messageNodeOffset) {
236
+ frame->messages[i].hash = 0;
237
+ frame->messages[i].messageNodeOffset = UNDEFINED_HASH_OFFSET;
238
+ }
239
+ }
51
240
  }
52
241
 
53
- unsigned int result = tree->lruStateOffset;
54
- tree->lruStateOffset = lruEntry->nextLruOffset;
55
- tree->state[tree->lruStateOffset].prevLruOffset = UNDEFINED_HASH_OFFSET;
56
- return result;
242
+ return RULES_OK;
57
243
  }
58
244
 
59
- static void deleteEntry(ruleset *tree, char *sid, unsigned int sidHash) {
60
- unsigned int bucket = sidHash % tree->stateBucketsLength;
61
- unsigned int offset = tree->stateBuckets[bucket];
62
- unsigned int lastOffset = UNDEFINED_HASH_OFFSET;
63
- unsigned char found = 0;
64
- while (!found && offset != UNDEFINED_HASH_OFFSET) {
65
- stateEntry *current = &tree->state[offset];
66
- if (current->sidHash == sidHash) {
67
- if (!strcmp(current->sid, sid)) {
68
- if (lastOffset == UNDEFINED_HASH_OFFSET) {
69
- tree->stateBuckets[bucket] = current->nextHashOffset;
70
- } else {
71
- tree->state[lastOffset].nextHashOffset = current->nextHashOffset;
72
- }
245
+ unsigned int getMessageFromFrame(stateNode *state,
246
+ messageFrame *messages,
247
+ unsigned int hash,
248
+ jsonObject **message) {
249
+ unsigned short size = 0;
250
+ unsigned short index = hash % MAX_MESSAGE_FRAMES;
251
+ unsigned int messageNodeOffset = UNDEFINED_HASH_OFFSET;
252
+ while (messages[index].hash && messageNodeOffset == UNDEFINED_HASH_OFFSET && size < MAX_MESSAGE_FRAMES) {
253
+ if (messages[index].hash == hash) {
254
+ messageNodeOffset = messages[index].messageNodeOffset;
255
+ }
256
+ ++size;
257
+ index = (index + 1) % MAX_MESSAGE_FRAMES;
258
+ }
73
259
 
74
- if (current->state) {
75
- free(current->state);
76
- current->state = NULL;
77
- }
260
+ if (messageNodeOffset == UNDEFINED_HASH_OFFSET) {
261
+ return ERR_MESSAGE_NOT_FOUND;
262
+ }
78
263
 
79
- free(current->sid);
80
- current->sid = NULL;
81
- current->sidHash = 0;
82
- current->bindingIndex = 0;
83
- current->lastRefresh = 0;
84
- current->jo.propertiesLength = 0;
85
- found = 1;
86
-
87
-
88
- // remove entry from lru double linked list
89
- if (current->prevLruOffset != UNDEFINED_HASH_OFFSET) {
90
- tree->state[current->prevLruOffset].nextLruOffset = current->nextLruOffset;
91
- if (tree->mruStateOffset == offset) {
92
- tree->mruStateOffset = current->prevLruOffset;
93
- }
94
- }
264
+ messageNode *node = MESSAGE_NODE(state, messageNodeOffset);
265
+ *message = &node->jo;
266
+ return RULES_OK;
267
+ }
95
268
 
96
- if (current->nextLruOffset != UNDEFINED_HASH_OFFSET) {
97
- tree->state[current->nextLruOffset].prevLruOffset = current->prevLruOffset;
98
- if (tree->lruStateOffset == offset) {
99
- tree->lruStateOffset = current->nextLruOffset;
100
- }
101
- }
102
- }
269
+ unsigned int setMessageInFrame(leftFrameNode *node,
270
+ unsigned int nameOffset,
271
+ unsigned int hash,
272
+ unsigned int messageNodeOffset) {
273
+ unsigned short size = 0;
274
+ unsigned short index = hash % MAX_MESSAGE_FRAMES;
275
+ while (node->messages[index].hash) {
276
+ index = (index + 1) % MAX_MESSAGE_FRAMES;
277
+ ++size;
278
+ if (size == MAX_MESSAGE_FRAMES) {
279
+ return ERR_MAX_MESSAGES_IN_FRAME;
103
280
  }
281
+ }
282
+ node->messages[index].nameOffset = nameOffset;
283
+ node->messages[index].hash = hash;
284
+ node->messages[index].messageNodeOffset = messageNodeOffset;
285
+ node->reverseIndex[node->messageCount] = index;
286
+ ++node->messageCount;
287
+ return RULES_OK;
288
+ }
289
+
290
+ unsigned int getLastLeftFrame(stateNode *state,
291
+ unsigned int index,
292
+ unsigned int hash,
293
+ frameLocation *location,
294
+ leftFrameNode **node) {
295
+ unsigned int valueOffset;
296
+ GET_LAST(leftFrameNode,
297
+ state->betaState[index].leftFrameIndex,
298
+ MAX_LEFT_FRAME_INDEX_LENGTH,
299
+ state->betaState[index].leftFramePool,
300
+ hash,
301
+ valueOffset);
302
+ if (valueOffset == UNDEFINED_HASH_OFFSET) {
303
+ *node = NULL;
304
+ return RULES_OK;
305
+ }
104
306
 
105
- lastOffset = offset;
106
- offset = current->nextHashOffset;
307
+ *node = LEFT_FRAME_NODE(state, index, valueOffset);
308
+ if (location) {
309
+ location->frameType = LEFT_FRAME;
310
+ location->nodeIndex = index;
311
+ location->frameOffset = valueOffset;
107
312
  }
313
+ return RULES_OK;
314
+ }
315
+
316
+ unsigned int setLeftFrame(stateNode *state,
317
+ unsigned int hash,
318
+ frameLocation location) {
319
+ SET(leftFrameNode,
320
+ state->betaState[location.nodeIndex].leftFrameIndex,
321
+ MAX_LEFT_FRAME_INDEX_LENGTH,
322
+ state->betaState[location.nodeIndex].leftFramePool,
323
+ hash,
324
+ location.frameOffset);
325
+ return RULES_OK;
326
+ }
327
+
328
+ unsigned int deleteLeftFrame(stateNode *state,
329
+ frameLocation location) {
330
+ DELETE(leftFrameNode,
331
+ state->betaState[location.nodeIndex].leftFrameIndex,
332
+ MAX_LEFT_FRAME_INDEX_LENGTH,
333
+ state->betaState[location.nodeIndex].leftFramePool,
334
+ location.frameOffset);
335
+ return RULES_OK;
108
336
  }
109
337
 
110
- static unsigned int addEntry(ruleset *tree, char *sid, unsigned int sidHash) {
111
- unsigned newOffset;
112
- if (tree->stateLength == tree->maxStateLength) {
113
- newOffset = evictEntry(tree);
338
+ static unsigned int copyLeftFrame(stateNode *state,
339
+ leftFrameNode *oldNode,
340
+ leftFrameNode *targetNode,
341
+ frameLocation newLocation) {
342
+ if (!oldNode) {
343
+ memset(targetNode->messages, 0, MAX_MESSAGE_FRAMES * sizeof(messageFrame));
344
+ memset(targetNode->reverseIndex, 0, MAX_MESSAGE_FRAMES * sizeof(unsigned short));
345
+ targetNode->messageCount = 0;
114
346
  } else {
115
- newOffset = tree->stateLength;
116
- ++tree->stateLength;
117
- }
118
-
119
- stateEntry *current = &tree->state[newOffset];
120
- current->prevLruOffset = UNDEFINED_HASH_OFFSET;
121
- current->nextLruOffset = UNDEFINED_HASH_OFFSET;
122
- current->nextHashOffset = UNDEFINED_HASH_OFFSET;
123
- current->sid = malloc(strlen(sid) + 1);
124
- strcpy(current->sid, sid);
125
- current->sidHash = sidHash;
126
- unsigned int bucket = sidHash % tree->stateBucketsLength;
127
- unsigned int offset = tree->stateBuckets[bucket];
128
- if (offset == UNDEFINED_HASH_OFFSET) {
129
- tree->stateBuckets[bucket] = newOffset;
130
- }
131
- else {
132
- while (1) {
133
- current = &tree->state[offset];
134
- if (current->nextHashOffset == UNDEFINED_HASH_OFFSET) {
135
- current->nextHashOffset = newOffset;
136
- break;
137
- }
347
+ memcpy(targetNode->messages, oldNode->messages, MAX_MESSAGE_FRAMES * sizeof(messageFrame));
348
+ memcpy(targetNode->reverseIndex, oldNode->reverseIndex, MAX_MESSAGE_FRAMES * sizeof(unsigned short));
349
+ targetNode->messageCount = oldNode->messageCount;
350
+ for (unsigned short i = 0; i < targetNode->messageCount; ++i) {
351
+ CHECK_RESULT(addFrameLocation(state,
352
+ newLocation,
353
+ targetNode->messages[targetNode->reverseIndex[i]].messageNodeOffset));
354
+ }
355
+ }
138
356
 
139
- offset = current->nextHashOffset;
357
+ return RULES_OK;
358
+ }
359
+
360
+ unsigned int createLeftFrame(stateNode *state,
361
+ node *reteNode,
362
+ leftFrameNode *oldNode,
363
+ leftFrameNode **newNode,
364
+ frameLocation *newLocation) {
365
+ unsigned int newValueOffset;
366
+ NEW(leftFrameNode,
367
+ state->betaState[reteNode->value.b.index].leftFramePool,
368
+ newValueOffset);
369
+
370
+ leftFrameNode *targetNode = LEFT_FRAME_NODE(state, reteNode->value.b.index, newValueOffset);
371
+ newLocation->frameType = LEFT_FRAME;
372
+ newLocation->nodeIndex = reteNode->value.b.index;
373
+ newLocation->frameOffset = newValueOffset;
374
+ targetNode->nameOffset = reteNode->nameOffset;
375
+ targetNode->isDispatching = 0;
376
+
377
+ CHECK_RESULT(copyLeftFrame(state,
378
+ oldNode,
379
+ targetNode,
380
+ *newLocation));
381
+
382
+ *newNode = targetNode;
383
+ state->betaState[reteNode->value.b.index].reteNode = reteNode;
384
+ return RULES_OK;
385
+ }
386
+
387
+ unsigned int getLastConnectorFrame(stateNode *state,
388
+ unsigned int frameType,
389
+ unsigned int index,
390
+ unsigned int *valueOffset,
391
+ leftFrameNode **node) {
392
+ if (frameType == A_FRAME) {
393
+ GET_LAST(leftFrameNode,
394
+ state->connectorState[index].aFrameIndex,
395
+ 1,
396
+ state->connectorState[index].aFramePool,
397
+ 0,
398
+ *valueOffset);
399
+ if (*valueOffset == UNDEFINED_HASH_OFFSET) {
400
+ *node = NULL;
401
+ return RULES_OK;
402
+ }
403
+
404
+ *node = A_FRAME_NODE(state, index, *valueOffset);
405
+ } else {
406
+ GET_LAST(leftFrameNode,
407
+ state->connectorState[index].bFrameIndex,
408
+ 1,
409
+ state->connectorState[index].bFramePool,
410
+ 0,
411
+ *valueOffset);
412
+ if (*valueOffset == UNDEFINED_HASH_OFFSET) {
413
+ *node = NULL;
414
+ return RULES_OK;
140
415
  }
416
+
417
+ *node = B_FRAME_NODE(state, index, *valueOffset);
141
418
  }
142
419
 
143
- return newOffset;
420
+ return RULES_OK;
144
421
  }
145
422
 
146
- static unsigned char ensureEntry(ruleset *tree, char *sid, unsigned int sidHash, stateEntry **result) {
147
- unsigned int bucket = sidHash % tree->stateBucketsLength;
148
- unsigned int offset = tree->stateBuckets[bucket];
149
- stateEntry *current = NULL;
150
- unsigned char found = 0;
151
- // find state entry by sid in hash table
152
- while (offset != UNDEFINED_HASH_OFFSET) {
153
- current = &tree->state[offset];
154
- if (current->sidHash == sidHash) {
155
- if (!strcmp(current->sid, sid)) {
156
- found = 1;
157
- break;
158
- }
423
+ unsigned int setConnectorFrame(stateNode *state,
424
+ unsigned int frameType,
425
+ frameLocation location) {
426
+ if (frameType == A_FRAME) {
427
+ SET(leftFrameNode,
428
+ state->connectorState[location.nodeIndex].aFrameIndex,
429
+ 1,
430
+ state->connectorState[location.nodeIndex].aFramePool,
431
+ 0,
432
+ location.frameOffset);
433
+ } else {
434
+ SET(leftFrameNode,
435
+ state->connectorState[location.nodeIndex].bFrameIndex,
436
+ 1,
437
+ state->connectorState[location.nodeIndex].bFramePool,
438
+ 0,
439
+ location.frameOffset);
440
+ }
441
+
442
+ return RULES_OK;
443
+ }
444
+
445
+ unsigned int deleteConnectorFrame(stateNode *state,
446
+ unsigned int frameType,
447
+ frameLocation location) {
448
+ if (frameType == A_FRAME) {
449
+ DELETE(leftFrameNode,
450
+ state->connectorState[location.nodeIndex].aFrameIndex,
451
+ 1,
452
+ state->connectorState[location.nodeIndex].aFramePool,
453
+ location.frameOffset);
454
+ } else {
455
+ DELETE(leftFrameNode,
456
+ state->connectorState[location.nodeIndex].bFrameIndex,
457
+ 1,
458
+ state->connectorState[location.nodeIndex].bFramePool,
459
+ location.frameOffset);
460
+
461
+ }
462
+
463
+ return RULES_OK;
464
+ }
465
+
466
+ unsigned int createConnectorFrame(stateNode *state,
467
+ unsigned int frameType,
468
+ node *reteNode,
469
+ leftFrameNode *oldNode,
470
+ leftFrameNode **newNode,
471
+ frameLocation *newLocation) {
472
+ unsigned int newValueOffset;
473
+ leftFrameNode *targetNode = NULL;
474
+ if (frameType == A_FRAME) {
475
+ NEW(leftFrameNode,
476
+ state->connectorState[reteNode->value.b.index].aFramePool,
477
+ newValueOffset);
478
+
479
+ targetNode = A_FRAME_NODE(state, reteNode->value.b.index, newValueOffset);
480
+ } else {
481
+ NEW(leftFrameNode,
482
+ state->connectorState[reteNode->value.b.index].bFramePool,
483
+ newValueOffset);
484
+
485
+ targetNode = B_FRAME_NODE(state, reteNode->value.b.index, newValueOffset);
486
+ }
487
+
488
+ newLocation->frameType = frameType;
489
+ newLocation->nodeIndex = reteNode->value.b.index;
490
+ newLocation->frameOffset = newValueOffset;
491
+ targetNode->nameOffset = reteNode->nameOffset;
492
+ targetNode->isDispatching = 0;
493
+
494
+ CHECK_RESULT(copyLeftFrame(state,
495
+ oldNode,
496
+ targetNode,
497
+ *newLocation));
498
+
499
+ *newNode = targetNode;
500
+ state->connectorState[reteNode->value.b.index].reteNode = reteNode;
501
+ return RULES_OK;
502
+ }
503
+
504
+ unsigned int getActionFrame(stateNode *state,
505
+ frameLocation resultLocation,
506
+ leftFrameNode **resultNode) {
507
+ actionStateNode *resultStateNode = &state->actionState[resultLocation.nodeIndex];
508
+ *resultNode = RESULT_FRAME(resultStateNode, resultLocation.frameOffset);
509
+ if (!(*resultNode)->isActive) {
510
+ *resultNode = NULL;
511
+ return ERR_NODE_DELETED;
512
+ }
513
+ return RULES_OK;
514
+ }
515
+
516
+ unsigned int setActionFrame(stateNode *state,
517
+ frameLocation location) {
518
+ SET(leftFrameNode,
519
+ state->actionState[location.nodeIndex].resultIndex,
520
+ 1,
521
+ state->actionState[location.nodeIndex].resultPool,
522
+ 0,
523
+ location.frameOffset);
524
+ return RULES_OK;
525
+ }
526
+
527
+ unsigned int deleteDispatchingActionFrame(stateNode *state,
528
+ frameLocation location) {
529
+ DELETE(leftFrameNode,
530
+ state->actionState[location.nodeIndex].resultIndex,
531
+ 1,
532
+ state->actionState[location.nodeIndex].resultPool,
533
+ location.frameOffset);
534
+ return RULES_OK;
535
+ }
536
+
537
+ unsigned int deleteActionFrame(stateNode *state,
538
+ frameLocation location) {
539
+
540
+ leftFrameNode *targetNode = ACTION_FRAME_NODE(state, location.nodeIndex, location.frameOffset);
541
+ if (targetNode->isDispatching) {
542
+ return ERR_NODE_DISPATCHING;
543
+ }
544
+
545
+ DELETE(leftFrameNode,
546
+ state->actionState[location.nodeIndex].resultIndex,
547
+ 1,
548
+ state->actionState[location.nodeIndex].resultPool,
549
+ location.frameOffset);
550
+ return RULES_OK;
551
+ }
552
+
553
+ unsigned int createActionFrame(stateNode *state,
554
+ node *reteNode,
555
+ leftFrameNode *oldNode,
556
+ leftFrameNode **newNode,
557
+ frameLocation *newLocation) {
558
+
559
+ unsigned int newValueOffset;
560
+ actionStateNode *actionNode = &state->actionState[reteNode->value.c.index];
561
+ NEW(leftFrameNode,
562
+ actionNode->resultPool,
563
+ newValueOffset);
564
+ leftFrameNode *targetNode = ACTION_FRAME_NODE(state, reteNode->value.c.index, newValueOffset);
565
+ newLocation->frameType = ACTION_FRAME;
566
+ newLocation->nodeIndex = reteNode->value.c.index;
567
+ newLocation->frameOffset = newValueOffset;
568
+ targetNode->nameOffset = reteNode->nameOffset;
569
+ targetNode->isDispatching = 0;
570
+
571
+ CHECK_RESULT(copyLeftFrame(state,
572
+ oldNode,
573
+ targetNode,
574
+ *newLocation));
575
+
576
+ *newNode = targetNode;
577
+ state->actionState[reteNode->value.c.index].reteNode = reteNode;
578
+ return RULES_OK;
579
+ }
580
+
581
+ unsigned int getLastRightFrame(stateNode *state,
582
+ unsigned int index,
583
+ unsigned int hash,
584
+ rightFrameNode **node) {
585
+ unsigned int valueOffset;
586
+ GET_LAST(rightFrameNode,
587
+ state->betaState[index].rightFrameIndex,
588
+ MAX_RIGHT_FRAME_INDEX_LENGTH,
589
+ state->betaState[index].rightFramePool,
590
+ hash,
591
+ valueOffset);
592
+ if (valueOffset == UNDEFINED_HASH_OFFSET) {
593
+ *node = NULL;
594
+ return RULES_OK;
595
+ }
596
+
597
+ *node = RIGHT_FRAME_NODE(state, index, valueOffset);
598
+ return RULES_OK;
599
+ }
600
+
601
+ unsigned int setRightFrame(stateNode *state,
602
+ unsigned int hash,
603
+ frameLocation location) {
604
+ SET(rightFrameNode,
605
+ state->betaState[location.nodeIndex].rightFrameIndex,
606
+ MAX_RIGHT_FRAME_INDEX_LENGTH,
607
+ state->betaState[location.nodeIndex].rightFramePool,
608
+ hash,
609
+ location.frameOffset);
610
+ return RULES_OK;
611
+ }
612
+
613
+ unsigned int deleteRightFrame(stateNode *state,
614
+ frameLocation location) {
615
+ DELETE(rightFrameNode,
616
+ state->betaState[location.nodeIndex].rightFrameIndex,
617
+ MAX_RIGHT_FRAME_INDEX_LENGTH,
618
+ state->betaState[location.nodeIndex].rightFramePool,
619
+ location.frameOffset);
620
+ return RULES_OK;
621
+ }
622
+
623
+ unsigned int createRightFrame(stateNode *state,
624
+ node *reteNode,
625
+ rightFrameNode **node,
626
+ frameLocation *location) {
627
+ unsigned int valueOffset;
628
+ NEW(rightFrameNode,
629
+ state->betaState[reteNode->value.b.index].rightFramePool,
630
+ valueOffset);
631
+ *node = RIGHT_FRAME_NODE(state, reteNode->value.b.index, valueOffset);
632
+
633
+ location->frameType = RIGHT_FRAME;
634
+ location->nodeIndex = reteNode->value.b.index;
635
+ location->frameOffset = valueOffset;
636
+
637
+ state->betaState[reteNode->value.b.index].reteNode = reteNode;
638
+ return RULES_OK;
639
+ }
640
+
641
+ unsigned int deleteMessage(stateNode *state,
642
+ unsigned int messageNodeOffset) {
643
+
644
+ messageNode *node = MESSAGE_NODE(state, messageNodeOffset);
645
+ if (node->jo.content) {
646
+ free(node->jo.content);
647
+ free(node->locationPool.content);
648
+ node->jo.content = NULL;
649
+ node->locationPool.content = NULL;
650
+ }
651
+
652
+ DELETE(messageNode,
653
+ state->messageIndex,
654
+ MAX_MESSAGE_INDEX_LENGTH,
655
+ state->messagePool,
656
+ messageNodeOffset);
657
+ return RULES_OK;
658
+ }
659
+
660
+ unsigned int getMessage(stateNode *state,
661
+ char *mid,
662
+ unsigned int *valueOffset) {
663
+ *valueOffset = UNDEFINED_HASH_OFFSET;
664
+ unsigned int hash = fnv1Hash32(mid, strlen(mid));
665
+
666
+ GET_FIRST(messageNode,
667
+ state->messageIndex,
668
+ MAX_MESSAGE_INDEX_LENGTH,
669
+ state->messagePool,
670
+ hash,
671
+ *valueOffset);
672
+
673
+ return RULES_OK;
674
+ }
675
+
676
+ static unsigned int copyMessage(jsonObject *targetMessage,
677
+ jsonObject *sourceMessage) {
678
+ memcpy(targetMessage, sourceMessage, sizeof(jsonObject));
679
+ unsigned int messageLength = (strlen(sourceMessage->content) + 1) * sizeof(char);
680
+ targetMessage->content = malloc(messageLength);
681
+ if (!targetMessage->content) {
682
+ return ERR_OUT_OF_MEMORY;
683
+ }
684
+ memcpy(targetMessage->content, sourceMessage->content, messageLength);
685
+ for (unsigned int i = 0; i < targetMessage->propertiesLength; ++i) {
686
+ if (targetMessage->properties[i].type == JSON_STRING &&
687
+ targetMessage->properties[i].hash != HASH_SID &&
688
+ targetMessage->properties[i].hash != HASH_ID) {
689
+ targetMessage->properties[i].value.s = targetMessage->content + targetMessage->properties[i].valueOffset;
690
+ }
691
+ }
692
+ return RULES_OK;
693
+ }
694
+
695
+ unsigned int storeMessage(stateNode *state,
696
+ char *mid,
697
+ jsonObject *message,
698
+ unsigned char messageType,
699
+ unsigned int *valueOffset) {
700
+ unsigned int hash = fnv1Hash32(mid, strlen(mid));
701
+ *valueOffset = UNDEFINED_HASH_OFFSET;
702
+
703
+ GET_FIRST(messageNode,
704
+ state->messageIndex,
705
+ MAX_MESSAGE_INDEX_LENGTH,
706
+ state->messagePool,
707
+ hash,
708
+ *valueOffset);
709
+
710
+ if (*valueOffset != UNDEFINED_HASH_OFFSET) {
711
+ return ERR_EVENT_OBSERVED;
712
+ }
713
+
714
+ NEW(messageNode,
715
+ state->messagePool,
716
+ *valueOffset);
717
+
718
+ SET(messageNode,
719
+ state->messageIndex,
720
+ MAX_MESSAGE_INDEX_LENGTH,
721
+ state->messagePool,
722
+ hash,
723
+ *valueOffset);
724
+
725
+ messageNode *node = MESSAGE_NODE(state, *valueOffset);
726
+ INIT(locationNode,
727
+ node->locationPool,
728
+ MAX_LOCATION_NODES);
729
+
730
+ memset(node->locationIndex, 0, MAX_LOCATION_INDEX_LENGTH * sizeof(unsigned int) * 2);
731
+
732
+ node->messageType = messageType;
733
+ return copyMessage(&node->jo, message);
734
+ }
735
+
736
+ unsigned int ensureStateNode(void *tree,
737
+ char *sid,
738
+ unsigned char *isNew,
739
+ stateNode **state) {
740
+ unsigned int sidHash = fnv1Hash32(sid, strlen(sid));
741
+ unsigned int nodeOffset;
742
+ ruleset *rulesetTree = (ruleset*)tree;
743
+
744
+ GET_FIRST(stateNode,
745
+ rulesetTree->stateIndex,
746
+ MAX_STATE_INDEX_LENGTH,
747
+ ((ruleset*)tree)->statePool,
748
+ sidHash,
749
+ nodeOffset);
750
+
751
+ if (nodeOffset != UNDEFINED_HASH_OFFSET) {
752
+ *isNew = 0;
753
+ *state = STATE_NODE(tree, nodeOffset);
754
+ } else {
755
+ *isNew = 1;
756
+ NEW(stateNode,
757
+ rulesetTree->statePool,
758
+ nodeOffset);
759
+
760
+ SET(stateNode,
761
+ rulesetTree->stateIndex,
762
+ MAX_STATE_INDEX_LENGTH,
763
+ rulesetTree->statePool,
764
+ sidHash,
765
+ nodeOffset);
766
+
767
+ rulesetTree->reverseStateIndex[rulesetTree->statePool.count - 1] = nodeOffset;
768
+ stateNode *node = STATE_NODE(tree, nodeOffset);
769
+ node->offset = nodeOffset;
770
+
771
+ int sidLength = sizeof(char) * (strlen(sid) + 1);
772
+ node->sid = malloc(sidLength);
773
+ if (!node->sid) {
774
+ return ERR_OUT_OF_MEMORY;
775
+ }
776
+ memcpy(node->sid, sid, sidLength);
777
+
778
+ INIT(messageNode,
779
+ node->messagePool,
780
+ MAX_MESSAGE_NODES);
781
+
782
+ memset(node->messageIndex, 0, MAX_MESSAGE_INDEX_LENGTH * sizeof(unsigned int) * 2);
783
+
784
+ node->betaState = malloc(((ruleset*)tree)->betaCount * sizeof(betaStateNode));
785
+ for (unsigned int i = 0; i < ((ruleset*)tree)->betaCount; ++i) {
786
+ betaStateNode *betaNode = &node->betaState[i];
787
+ betaNode->reteNode = NULL;
788
+
789
+ INIT(leftFrameNode,
790
+ betaNode->leftFramePool,
791
+ MAX_LEFT_FRAME_NODES);
792
+
793
+ memset(betaNode->leftFrameIndex, 0, MAX_LEFT_FRAME_INDEX_LENGTH * sizeof(unsigned int) * 2);
794
+
795
+ INIT(rightFrameNode,
796
+ betaNode->rightFramePool,
797
+ MAX_RIGHT_FRAME_NODES);
798
+
799
+ memset(betaNode->rightFrameIndex, 0, MAX_RIGHT_FRAME_INDEX_LENGTH * sizeof(unsigned int) * 2);
800
+ }
801
+
802
+ node->connectorState = malloc(((ruleset*)tree)->connectorCount * sizeof(connectorStateNode));
803
+ for (unsigned int i = 0; i < ((ruleset*)tree)->connectorCount; ++i) {
804
+ connectorStateNode *connectorNode = &node->connectorState[i];
805
+ connectorNode->reteNode = NULL;
806
+
807
+ INIT(leftFrameNode,
808
+ connectorNode->aFramePool,
809
+ MAX_LEFT_FRAME_NODES);
810
+
811
+ connectorNode->aFrameIndex[0] = UNDEFINED_HASH_OFFSET;
812
+ connectorNode->aFrameIndex[1] = UNDEFINED_HASH_OFFSET;
813
+
814
+ INIT(leftFrameNode,
815
+ connectorNode->bFramePool,
816
+ MAX_LEFT_FRAME_NODES);
817
+
818
+ connectorNode->bFrameIndex[0] = UNDEFINED_HASH_OFFSET;
819
+ connectorNode->bFrameIndex[1] = UNDEFINED_HASH_OFFSET;
159
820
  }
160
821
 
161
- offset = current->nextHashOffset;
162
- }
822
+ node->actionState = malloc(((ruleset*)tree)->actionCount * sizeof(actionStateNode));
823
+ for (unsigned int i = 0; i < ((ruleset*)tree)->actionCount; ++i) {
824
+ actionStateNode *actionNode = &node->actionState[i];
825
+ actionNode->reteNode = NULL;
826
+
827
+ actionNode->resultIndex[0] = UNDEFINED_HASH_OFFSET;
828
+ actionNode->resultIndex[1] = UNDEFINED_HASH_OFFSET;
829
+
830
+ INIT(leftFrameNode,
831
+ actionNode->resultPool,
832
+ MAX_LEFT_FRAME_NODES);
833
+ }
163
834
 
164
- // create entry if not found
165
- if (offset == UNDEFINED_HASH_OFFSET) {
166
- offset = addEntry(tree, sid, sidHash);
167
- current = &tree->state[offset];
835
+ node->factOffset = UNDEFINED_HASH_OFFSET;
836
+ node->lockExpireTime = 0;
837
+ *state = node;
168
838
  }
839
+
840
+ return RULES_OK;
841
+ }
169
842
 
170
- // remove entry from lru double linked list
171
- if (current->prevLruOffset != UNDEFINED_HASH_OFFSET) {
172
- tree->state[current->prevLruOffset].nextLruOffset = current->nextLruOffset;
173
- if (tree->mruStateOffset == offset) {
174
- tree->mruStateOffset = current->prevLruOffset;
843
+ static unsigned int getResultFrameLength(ruleset *tree,
844
+ stateNode *state,
845
+ leftFrameNode *frame) {
846
+ unsigned int resultLength = 2;
847
+ for (int i = 0; i < frame->messageCount; ++i) {
848
+ messageFrame *currentFrame = &frame->messages[frame->reverseIndex[i]];
849
+ messageNode *currentNode = MESSAGE_NODE(state, currentFrame->messageNodeOffset);
850
+ char *name = &tree->stringPool[currentFrame->nameOffset];
851
+ char *value = currentNode->jo.content;
852
+ if (i < (frame->messageCount -1)) {
853
+ resultLength += strlen(name) + strlen(value) + 4;
854
+ } else {
855
+ resultLength += strlen(name) + strlen(value) + 3;
175
856
  }
176
857
  }
177
858
 
178
- if (current->nextLruOffset != UNDEFINED_HASH_OFFSET) {
179
- tree->state[current->nextLruOffset].prevLruOffset = current->prevLruOffset;
180
- if (tree->lruStateOffset == offset) {
181
- tree->lruStateOffset = current->nextLruOffset;
859
+ return resultLength;
860
+ }
861
+
862
+ static void serializeResultFrame(ruleset *tree,
863
+ stateNode *state,
864
+ leftFrameNode *frame,
865
+ char *first,
866
+ char **last) {
867
+
868
+ first[0] = '{';
869
+ ++first;
870
+ for (int i = 0; i < frame->messageCount; ++i) {
871
+ unsigned int tupleLength;
872
+ messageFrame *currentFrame = &frame->messages[frame->reverseIndex[i]];
873
+ messageNode *currentNode = MESSAGE_NODE(state, currentFrame->messageNodeOffset);
874
+ char *name = &tree->stringPool[currentFrame->nameOffset];
875
+ char *value = currentNode->jo.content;
876
+ if (i < (frame->messageCount -1)) {
877
+ tupleLength = strlen(name) + strlen(value) + 5;
878
+ #ifdef _WIN32
879
+ sprintf_s(first, tupleLength, "\"%s\":%s,", name, value);
880
+ #else
881
+ snprintf(first, tupleLength, "\"%s\":%s,", name, value);
882
+ #endif
883
+ } else {
884
+ tupleLength = strlen(name) + strlen(value) + 4;
885
+ #ifdef _WIN32
886
+ sprintf_s(first, tupleLength, "\"%s\":%s", name, value);
887
+ #else
888
+ snprintf(first, tupleLength, "\"%s\":%s", name, value);
889
+ #endif
182
890
  }
891
+
892
+ first += (tupleLength - 1);
183
893
  }
184
894
 
185
- // attach entry to end of linked list
186
- current->nextLruOffset = UNDEFINED_HASH_OFFSET;
187
- current->prevLruOffset = tree->mruStateOffset;
188
- if (tree->mruStateOffset == UNDEFINED_HASH_OFFSET) {
189
- tree->lruStateOffset = offset;
895
+ first[0] = '}';
896
+ *last = first + 1;
897
+ }
898
+
899
+ unsigned int serializeResult(void *tree,
900
+ stateNode *state,
901
+ actionStateNode *actionNode,
902
+ unsigned int count,
903
+ char **result) {
904
+
905
+ if (actionNode->reteNode->value.c.count && count == 1) {
906
+ leftFrameNode *resultFrame = RESULT_FRAME(actionNode, actionNode->resultIndex[0]);
907
+ if (!resultFrame->isActive) {
908
+ return ERR_NODE_DELETED;
909
+ }
910
+
911
+ char *actionName = &((ruleset *)tree)->stringPool[resultFrame->nameOffset];
912
+ unsigned int resultLength = strlen(actionName) + 6 + getResultFrameLength(tree,
913
+ state,
914
+ resultFrame);
915
+ *result = malloc(resultLength * sizeof(char));
916
+ if (!*result) {
917
+ return ERR_OUT_OF_MEMORY;
918
+ }
919
+
920
+ char *first = *result;
921
+ // +1 to leave space for the 0 character
922
+ unsigned int tupleLength = strlen(actionName) + 5;
923
+ #ifdef _WIN32
924
+ sprintf_s(first, tupleLength, "{\"%s\":", actionName);
925
+ #else
926
+ snprintf(first, tupleLength, "{\"%s\":", actionName);
927
+ #endif
928
+ first += tupleLength - 1;
929
+
930
+ char *last;
931
+ resultFrame->isDispatching = 1;
932
+ serializeResultFrame(tree,
933
+ state,
934
+ resultFrame,
935
+ first,
936
+ &last);
937
+ last[0] = '}';
938
+ last[1] = 0;
190
939
  } else {
191
- tree->state[tree->mruStateOffset].nextLruOffset = offset;
940
+ leftFrameNode *resultFrame = RESULT_FRAME(actionNode, actionNode->resultIndex[0]);
941
+ if (!resultFrame->isActive) {
942
+ return ERR_NODE_DELETED;
943
+ }
944
+
945
+ char *actionName = &((ruleset *)tree)->stringPool[resultFrame->nameOffset];
946
+ unsigned int resultLength = strlen(actionName) + 8;
947
+ for (unsigned int currentCount = 0; currentCount < count; ++currentCount) {
948
+ resultLength += 1 + getResultFrameLength(tree,
949
+ state,
950
+ resultFrame);
951
+
952
+ if (resultFrame->nextOffset != UNDEFINED_HASH_OFFSET) {
953
+ resultFrame = RESULT_FRAME(actionNode, resultFrame->nextOffset);
954
+ }
955
+ }
956
+
957
+ *result = malloc(resultLength * sizeof(char));
958
+ if (!*result) {
959
+ return ERR_OUT_OF_MEMORY;
960
+ }
961
+
962
+ char *first = *result;
963
+ // +1 to leave space for the 0 character
964
+ unsigned int tupleLength = strlen(actionName) + 5;
965
+ #ifdef _WIN32
966
+ sprintf_s(first, tupleLength, "{\"%s\":", actionName);
967
+ #else
968
+ snprintf(first, tupleLength, "{\"%s\":", actionName);
969
+ #endif
970
+ first[tupleLength - 1] = '[';
971
+ first += tupleLength ;
972
+
973
+ char *last;
974
+ resultFrame = RESULT_FRAME(actionNode, actionNode->resultIndex[0]);
975
+ for (unsigned int currentCount = 0; currentCount < count; ++currentCount) {
976
+ resultFrame->isDispatching = 1;
977
+ serializeResultFrame(tree,
978
+ state,
979
+ resultFrame,
980
+ first,
981
+ &last);
982
+
983
+ if (resultFrame->nextOffset != UNDEFINED_HASH_OFFSET) {
984
+ resultFrame = RESULT_FRAME(actionNode, resultFrame->nextOffset);
985
+ }
986
+
987
+ if (currentCount < count - 1) {
988
+ last[0] = ',';
989
+ first = last + 1;
990
+ }
991
+ }
992
+
993
+ last[0] = ']';
994
+ last[1] = '}';
995
+ last[2] = 0;
996
+ }
997
+
998
+ return RULES_OK;
999
+ }
1000
+
1001
+ unsigned int serializeState(stateNode *state,
1002
+ char **stateFact) {
1003
+
1004
+ messageNode *stateFactNode = MESSAGE_NODE(state, state->factOffset);
1005
+ unsigned int stateFactLength = strlen(stateFactNode->jo.content) + 1;
1006
+ *stateFact = malloc(stateFactLength * sizeof(char));
1007
+ if (!*stateFact) {
1008
+ return ERR_OUT_OF_MEMORY;
192
1009
  }
193
- tree->mruStateOffset = offset;
1010
+ memcpy(*stateFact, stateFactNode->jo.content, stateFactLength);
194
1011
 
195
- *result = current;
196
- return found;
1012
+ return RULES_OK;
197
1013
  }
198
1014
 
199
- static stateEntry *getEntry(ruleset *tree, char *sid, unsigned int sidHash) {
200
- unsigned int bucket = sidHash % tree->stateBucketsLength;
201
- unsigned int offset = tree->stateBuckets[bucket];
202
- while (offset != UNDEFINED_HASH_OFFSET) {
203
- stateEntry *current = &tree->state[offset];
204
- if (current->sidHash == sidHash) {
205
- if (!strcmp(current->sid, sid)) {
206
- return current;
1015
+ unsigned int getNextResultInState(void *tree,
1016
+ stateNode *state,
1017
+ unsigned int *actionStateIndex,
1018
+ unsigned int *resultCount,
1019
+ unsigned int *resultFrameOffset,
1020
+ actionStateNode **resultAction) {
1021
+
1022
+ ruleset *rulesetTree = (ruleset*)tree;
1023
+ *resultAction = NULL;
1024
+ for (unsigned int index = 0; index < rulesetTree->actionCount; ++index) {
1025
+ actionStateNode *actionNode = &state->actionState[index];
1026
+ if (actionNode->reteNode) {
1027
+ if ((actionNode->reteNode->value.c.cap && actionNode->resultPool.count) ||
1028
+ (actionNode->reteNode->value.c.count && actionNode->resultPool.count >= actionNode->reteNode->value.c.count)) {
1029
+ *resultAction = actionNode;
1030
+ *actionStateIndex = index;
1031
+ *resultFrameOffset = actionNode->resultIndex[0];
1032
+ if (actionNode->reteNode->value.c.count) {
1033
+ *resultCount = actionNode->reteNode->value.c.count;
1034
+ } else {
1035
+ *resultCount = (actionNode->reteNode->value.c.cap > actionNode->resultPool.count ?
1036
+ actionNode->resultPool.count :
1037
+ actionNode->reteNode->value.c.cap);
1038
+ }
1039
+
1040
+ return RULES_OK;
207
1041
  }
208
1042
  }
1043
+ }
209
1044
 
210
- offset = current->nextHashOffset;
211
- }
1045
+ return ERR_NO_ACTION_AVAILABLE;
1046
+ }
1047
+
1048
+ unsigned int getNextResult(void *tree,
1049
+ time_t currentTime,
1050
+ stateNode **resultState,
1051
+ unsigned int *actionStateIndex,
1052
+ unsigned int *resultCount,
1053
+ unsigned int *resultFrameOffset,
1054
+ actionStateNode **resultAction) {
1055
+ unsigned int count = 0;
1056
+ ruleset *rulesetTree = (ruleset*)tree;
1057
+ *resultAction = NULL;
212
1058
 
213
- return NULL;
1059
+ // In case state pool has been modified.
1060
+ if (rulesetTree->statePool.count) {
1061
+ rulesetTree->currentStateIndex = rulesetTree->currentStateIndex % rulesetTree->statePool.count;
1062
+ }
1063
+
1064
+ while (count < rulesetTree->statePool.count && !*resultAction) {
1065
+ unsigned int nodeOffset = rulesetTree->reverseStateIndex[rulesetTree->currentStateIndex];
1066
+ *resultState = STATE_NODE(tree, nodeOffset);
1067
+ if (currentTime - (*resultState)->lockExpireTime > STATE_LEASE_TIME) {
1068
+ unsigned int result = getNextResultInState(tree,
1069
+ *resultState,
1070
+ actionStateIndex,
1071
+ resultCount,
1072
+ resultFrameOffset,
1073
+ resultAction);
1074
+ if (result != ERR_NO_ACTION_AVAILABLE) {
1075
+ return result;
1076
+ }
1077
+ }
1078
+
1079
+ rulesetTree->currentStateIndex = (rulesetTree->currentStateIndex + 1) % rulesetTree->statePool.count;
1080
+ ++count;
1081
+ }
1082
+
1083
+ return ERR_NO_ACTION_AVAILABLE;
214
1084
  }
215
1085
 
216
1086
  static void insertSortProperties(jsonObject *jo, jsonProperty **properties) {
@@ -248,33 +1118,37 @@ static void radixSortProperties(jsonObject *jo, jsonProperty **properties) {
248
1118
  }
249
1119
  }
250
1120
 
251
- static void calculateId(jsonObject *jo) {
1121
+ unsigned int calculateId(jsonObject *jo) {
252
1122
 
253
1123
  #ifdef _WIN32
254
1124
  jsonProperty **properties = (jsonProperty *)_alloca(sizeof(jsonProperty *) * (jo->propertiesLength));
255
1125
  #else
256
1126
  jsonProperty *properties[jo->propertiesLength];
257
1127
  #endif
258
-
1128
+
259
1129
  radixSortProperties(jo, properties);
260
1130
  insertSortProperties(jo, properties);
261
1131
 
262
1132
  unsigned long long hash = FNV_64_OFFSET_BASIS;
263
1133
  for (unsigned short i = 0; i < jo->propertiesLength; ++i) {
264
1134
  jsonProperty *property = properties[i];
265
- for (unsigned short ii = 0; ii < property->nameLength; ++ii) {
266
- hash ^= property->name[ii];
267
- hash *= FNV_64_PRIME;
268
- }
269
-
270
- unsigned short valueLength = property->valueLength;
271
- if (property->type != JSON_STRING) {
272
- ++valueLength;
273
- }
274
-
275
- for (unsigned short ii = 0; ii < valueLength; ++ii) {
276
- hash ^= property->valueString[ii];
1135
+ if (property->hash != HASH_ID) {
1136
+ hash ^= property->hash;
277
1137
  hash *= FNV_64_PRIME;
1138
+
1139
+ unsigned short valueLength = property->valueLength;
1140
+ if (property->type == JSON_STRING) {
1141
+ // Using value.s to cover generated sid
1142
+ for (unsigned short ii = 0; ii < valueLength; ++ii) {
1143
+ hash ^= property->value.s[ii];
1144
+ hash *= FNV_64_PRIME;
1145
+ }
1146
+ } else {
1147
+ for (unsigned short ii = 0; ii < valueLength; ++ii) {
1148
+ hash ^= jo->content[property->valueOffset + ii];
1149
+ hash *= FNV_64_PRIME;
1150
+ }
1151
+ }
278
1152
  }
279
1153
  }
280
1154
 
@@ -283,7 +1157,28 @@ static void calculateId(jsonObject *jo) {
283
1157
  #else
284
1158
  snprintf(jo->idBuffer, sizeof(char) * ID_BUFFER_LENGTH, "$%020llu", hash);
285
1159
  #endif
286
- jo->properties[jo->idIndex].valueLength = 20;
1160
+
1161
+ jsonProperty *property;
1162
+ property = &jo->properties[jo->propertiesLength];
1163
+ jo->idIndex = jo->propertiesLength;
1164
+ ++jo->propertiesLength;
1165
+ if (jo->propertiesLength == MAX_OBJECT_PROPERTIES) {
1166
+ return ERR_EVENT_MAX_PROPERTIES;
1167
+ }
1168
+
1169
+ unsigned int candidate = HASH_ID % MAX_OBJECT_PROPERTIES;
1170
+ while (jo->propertyIndex[candidate] != 0) {
1171
+ candidate = candidate + 1 % MAX_OBJECT_PROPERTIES;
1172
+ }
1173
+
1174
+ // Index intentionally offset by 1 to enable getObject
1175
+ jo->propertyIndex[candidate] = jo->propertiesLength;
1176
+ property->hash = HASH_ID;
1177
+ property->valueOffset = 0;
1178
+ property->valueLength = 20;
1179
+ property->type = JSON_STRING;
1180
+
1181
+ return RULES_OK;
287
1182
  }
288
1183
 
289
1184
  static unsigned int fixupIds(jsonObject *jo, char generateId) {
@@ -294,10 +1189,9 @@ static unsigned int fixupIds(jsonObject *jo, char generateId) {
294
1189
  //coerce value to string
295
1190
  property = &jo->properties[jo->sidIndex];
296
1191
  if (property->type != JSON_STRING) {
297
- ++property->valueLength;
1192
+ property->value.s = jo->content + property->valueOffset;
1193
+ property->type = JSON_STRING;
298
1194
  }
299
-
300
- property->type = JSON_STRING;
301
1195
  } else {
302
1196
  property = &jo->properties[jo->propertiesLength];
303
1197
  jo->sidIndex = jo->propertiesLength;
@@ -306,13 +1200,19 @@ static unsigned int fixupIds(jsonObject *jo, char generateId) {
306
1200
  return ERR_EVENT_MAX_PROPERTIES;
307
1201
  }
308
1202
 
1203
+ unsigned int candidate = HASH_SID % MAX_OBJECT_PROPERTIES;
1204
+ while (jo->propertyIndex[candidate] != 0) {
1205
+ candidate = candidate + 1 % MAX_OBJECT_PROPERTIES;
1206
+ }
1207
+
1208
+ // Index intentionally offset by 1 to enable getObject
1209
+ jo->propertyIndex[candidate] = jo->propertiesLength;
1210
+
309
1211
  strncpy(jo->sidBuffer, "0", 1);
310
1212
  property->hash = HASH_SID;
311
- property->isMaterial = 1;
312
- property->valueString = jo->sidBuffer;
1213
+ property->valueOffset = 0;
313
1214
  property->valueLength = 1;
314
- strncpy(property->name, "sid", 3);
315
- property->nameLength = 3;
1215
+ property->value.s = jo->sidBuffer;
316
1216
  property->type = JSON_STRING;
317
1217
  }
318
1218
 
@@ -320,29 +1220,91 @@ static unsigned int fixupIds(jsonObject *jo, char generateId) {
320
1220
  //coerce value to string
321
1221
  property = &jo->properties[jo->idIndex];
322
1222
  if (property->type != JSON_STRING) {
323
- ++property->valueLength;
1223
+ property->value.s = jo->content + property->valueOffset;
1224
+ property->type = JSON_STRING;
324
1225
  }
1226
+ } else if (generateId) {
1227
+ return calculateId(jo);
1228
+ }
325
1229
 
326
- property->type = JSON_STRING;
327
- } else {
328
- property = &jo->properties[jo->propertiesLength];
329
- jo->idIndex = jo->propertiesLength;
330
- ++jo->propertiesLength;
331
- if (jo->propertiesLength == MAX_OBJECT_PROPERTIES) {
332
- return ERR_EVENT_MAX_PROPERTIES;
333
- }
1230
+ return RULES_OK;
1231
+ }
334
1232
 
335
- jo->idBuffer[0] = 0;
336
- property->hash = HASH_ID;
337
- property->isMaterial = 1;
338
- property->valueString = jo->idBuffer;
339
- property->valueLength = 0;
340
- strncpy(property->name, "id", 2);
341
- property->nameLength = 2;
342
- property->type = JSON_STRING;
343
- if (generateId) {
344
- calculateId(jo);
1233
+ unsigned int getObjectProperty(jsonObject *jo,
1234
+ unsigned int hash,
1235
+ jsonProperty **property) {
1236
+ unsigned short size = 0;
1237
+ unsigned short index = hash % MAX_OBJECT_PROPERTIES;
1238
+ while (jo->propertyIndex[index] && size < MAX_OBJECT_PROPERTIES) {
1239
+ unsigned short subIndex = jo->propertyIndex[index] - 1;
1240
+ if (jo->properties[subIndex].hash == hash) {
1241
+ *property = &jo->properties[subIndex];
1242
+ return RULES_OK;
345
1243
  }
1244
+
1245
+ ++size;
1246
+ index = (index + 1) % MAX_OBJECT_PROPERTIES;
1247
+ }
1248
+
1249
+ return ERR_PROPERTY_NOT_FOUND;
1250
+ }
1251
+
1252
+ unsigned int setObjectProperty(jsonObject *jo,
1253
+ unsigned int hash,
1254
+ unsigned char type,
1255
+ unsigned short valueOffset,
1256
+ unsigned short valueLength) {
1257
+ jsonProperty *property = &jo->properties[jo->propertiesLength];
1258
+ ++jo->propertiesLength;
1259
+ if (jo->propertiesLength == MAX_OBJECT_PROPERTIES) {
1260
+ return ERR_EVENT_MAX_PROPERTIES;
1261
+ }
1262
+
1263
+ unsigned int candidate = hash % MAX_OBJECT_PROPERTIES;
1264
+ while (jo->propertyIndex[candidate] != 0) {
1265
+ candidate = candidate + 1 % MAX_OBJECT_PROPERTIES;
1266
+ }
1267
+
1268
+ // Index intentionally offset by 1 to enable getObject
1269
+ jo->propertyIndex[candidate] = jo->propertiesLength;
1270
+ if (hash == HASH_ID) {
1271
+ jo->idIndex = jo->propertiesLength - 1;
1272
+ } else if (hash == HASH_SID) {
1273
+ jo->sidIndex = jo->propertiesLength - 1;
1274
+ }
1275
+
1276
+ property->hash = hash;
1277
+ property->valueOffset = valueOffset;
1278
+ property->valueLength = valueLength;
1279
+ property->type = type;
1280
+
1281
+ char *first = jo->content + property->valueOffset;
1282
+ char temp;
1283
+ switch(type) {
1284
+ case JSON_INT:
1285
+ temp = first[property->valueLength];
1286
+ first[property->valueLength] = '\0';
1287
+ property->value.i = atol(first);
1288
+ first[property->valueLength] = temp;
1289
+ break;
1290
+ case JSON_DOUBLE:
1291
+ temp = first[property->valueLength];
1292
+ first[property->valueLength] = '\0';
1293
+ property->value.d = atof(first);
1294
+ first[property->valueLength] = temp;
1295
+ break;
1296
+ case JSON_BOOL:
1297
+ if (property->valueLength == 4 && strncmp("true", first, 4) == 0) {
1298
+ property->value.b = 1;
1299
+ } else {
1300
+ property->value.b = 0;
1301
+ }
1302
+
1303
+ break;
1304
+ case JSON_STRING:
1305
+ property->value.s = first;
1306
+ property->valueLength = property->valueLength - 1;
1307
+ break;
346
1308
  }
347
1309
 
348
1310
  return RULES_OK;
@@ -351,7 +1313,6 @@ static unsigned int fixupIds(jsonObject *jo, char generateId) {
351
1313
  unsigned int constructObject(char *root,
352
1314
  char *parentName,
353
1315
  char *object,
354
- char layout,
355
1316
  char generateId,
356
1317
  jsonObject *jo,
357
1318
  char **next) {
@@ -369,6 +1330,8 @@ unsigned int constructObject(char *root,
369
1330
  jo->idIndex = UNDEFINED_INDEX;
370
1331
  jo->sidIndex = UNDEFINED_INDEX;
371
1332
  jo->propertiesLength = 0;
1333
+ jo->content = root;
1334
+ memset(jo->propertyIndex, 0, MAX_OBJECT_PROPERTIES * sizeof(unsigned short));
372
1335
  }
373
1336
 
374
1337
  object = (object ? object : root);
@@ -379,62 +1342,15 @@ unsigned int constructObject(char *root,
379
1342
  return result;
380
1343
  }
381
1344
 
382
- jsonProperty *property = NULL;
383
- if (type != JSON_OBJECT) {
384
- switch (layout) {
385
- case JSON_OBJECT_SEQUENCED:
386
- property = &jo->properties[jo->propertiesLength];
387
- if (!parentName) {
388
- if (hash == HASH_ID) {
389
- jo->idIndex = jo->propertiesLength;
390
- } else if (hash == HASH_SID) {
391
- jo->sidIndex = jo->propertiesLength;
392
- }
393
- }
394
- break;
395
- case JSON_OBJECT_HASHED:
396
- {
397
- unsigned int candidate = hash % MAX_OBJECT_PROPERTIES;
398
- while (jo->properties[candidate].type != 0) {
399
- candidate = (candidate + 1) % MAX_OBJECT_PROPERTIES;
400
- }
401
-
402
- if (!parentName) {
403
- if (hash == HASH_ID) {
404
- jo->idIndex = candidate;
405
- } else if (hash == HASH_SID) {
406
- jo->sidIndex = candidate;
407
- }
408
- }
409
-
410
- property = &jo->properties[candidate];
411
- }
412
- break;
413
- }
414
-
415
- ++jo->propertiesLength;
416
- if (jo->propertiesLength == MAX_OBJECT_PROPERTIES) {
417
- return ERR_EVENT_MAX_PROPERTIES;
418
- }
419
-
420
- property->isMaterial = 0;
421
- property->valueString = first;
422
- property->valueLength = last - first;
423
- property->type = type;
424
- }
425
-
426
1345
  if (!parentName) {
427
- int nameLength = lastName - firstName;
428
- if (nameLength > MAX_NAME_LENGTH) {
429
- return ERR_MAX_PROPERTY_NAME_LENGTH;
430
- }
431
-
432
1346
  if (type != JSON_OBJECT) {
433
- strncpy(property->name, firstName, nameLength);
434
- property->nameLength = nameLength;
435
- property->hash = hash;
436
- } else {
437
-
1347
+ CHECK_RESULT(setObjectProperty(jo,
1348
+ hash,
1349
+ type,
1350
+ first - root,
1351
+ last - first + 1));
1352
+ } else {
1353
+ int nameLength = lastName - firstName;
438
1354
  #ifdef _WIN32
439
1355
  char *newParent = (char *)_alloca(sizeof(char)*(nameLength + 1));
440
1356
  #else
@@ -442,50 +1358,39 @@ unsigned int constructObject(char *root,
442
1358
  #endif
443
1359
  strncpy(newParent, firstName, nameLength);
444
1360
  newParent[nameLength] = '\0';
445
- result = constructObject(root,
446
- newParent,
447
- first,
448
- layout,
449
- 0,
450
- jo,
451
- next);
452
- if (result != RULES_OK) {
453
- return result;
454
- }
1361
+ CHECK_RESULT(constructObject(root,
1362
+ newParent,
1363
+ first,
1364
+ 0,
1365
+ jo,
1366
+ next));
455
1367
  }
456
1368
  } else {
457
1369
  int nameLength = lastName - firstName;
458
1370
  int fullNameLength = nameLength + parentNameLength + 1;
459
- if (fullNameLength > MAX_NAME_LENGTH) {
460
- return ERR_MAX_PROPERTY_NAME_LENGTH;
461
- }
462
-
463
- if (type != JSON_OBJECT) {
464
- strncpy(property->name, parentName, parentNameLength);
465
- property->name[parentNameLength] = '.';
466
- strncpy(&property->name[parentNameLength + 1], firstName, nameLength);
467
- property->nameLength = fullNameLength;
468
- property->hash = fnv1Hash32(property->name, fullNameLength);
469
- } else {
470
1371
  #ifdef _WIN32
471
- char *fullName = (char *)_alloca(sizeof(char)*(fullNameLength + 1));
1372
+ char *fullName = (char *)_alloca(sizeof(char)*(fullNameLength + 1));
472
1373
  #else
473
- char fullName[fullNameLength + 1];
1374
+ char fullName[fullNameLength + 1];
474
1375
  #endif
475
- strncpy(fullName, parentName, parentNameLength);
476
- fullName[parentNameLength] = '.';
477
- strncpy(&fullName[parentNameLength + 1], firstName, nameLength);
478
- fullName[fullNameLength] = '\0';
479
- result = constructObject(root,
480
- fullName,
481
- first,
482
- layout,
483
- 0,
484
- jo,
485
- next);
486
- if (result != RULES_OK) {
487
- return result;
488
- }
1376
+ strncpy(fullName, parentName, parentNameLength);
1377
+ fullName[parentNameLength] = '.';
1378
+ strncpy(&fullName[parentNameLength + 1], firstName, nameLength);
1379
+ fullName[fullNameLength] = '\0';
1380
+ if (type != JSON_OBJECT) {
1381
+ CHECK_RESULT(setObjectProperty(jo,
1382
+ fnv1Hash32(fullName, fullNameLength),
1383
+ type,
1384
+ first - root,
1385
+ last - first + 1));
1386
+ } else {
1387
+
1388
+ CHECK_RESULT(constructObject(root,
1389
+ fullName,
1390
+ first,
1391
+ 0,
1392
+ jo,
1393
+ next));
489
1394
  }
490
1395
  }
491
1396
 
@@ -494,196 +1399,87 @@ unsigned int constructObject(char *root,
494
1399
  }
495
1400
 
496
1401
  if (!parentName) {
497
- int idResult = fixupIds(jo, generateId);
498
- if (idResult != RULES_OK) {
499
- return idResult;
500
- }
1402
+ CHECK_RESULT(fixupIds(jo, generateId));
501
1403
  }
502
1404
 
503
1405
  return (result == PARSE_END ? RULES_OK: result);
504
1406
  }
505
1407
 
506
- void rehydrateProperty(jsonProperty *property, char *state) {
507
- if (!property->isMaterial) {
508
- unsigned short propertyLength = property->valueLength + 1;
509
- char *propertyFirst = property->valueString;
510
- unsigned char propertyType = property->type;
511
- unsigned char b = 0;
512
- char temp;
513
-
514
- switch(propertyType) {
515
- case JSON_INT:
516
- temp = propertyFirst[propertyLength];
517
- propertyFirst[propertyLength] = '\0';
518
- property->value.i = atol(propertyFirst);
519
- propertyFirst[propertyLength] = temp;
520
- break;
521
- case JSON_DOUBLE:
522
- temp = propertyFirst[propertyLength];
523
- propertyFirst[propertyLength] = '\0';
524
- property->value.d = atof(propertyFirst);
525
- propertyFirst[propertyLength] = temp;
526
- break;
527
- case JSON_BOOL:
528
- if (propertyLength == 4 && strncmp("true", propertyFirst, 4) == 0) {
529
- b = 1;
530
- }
531
-
532
- property->value.b = b;
533
- break;
534
- }
1408
+ unsigned int getState(unsigned int handle, char *sid, char **state) {
1409
+ ruleset *tree;
1410
+ RESOLVE_HANDLE(handle, &tree);
535
1411
 
536
- property->isMaterial = 1;
1412
+ if (!sid) {
1413
+ sid = "0";
537
1414
  }
538
- }
539
-
540
- static unsigned int resolveBindingAndEntry(ruleset *tree,
541
- char *sid,
542
- stateEntry **entry,
543
- void **rulesBinding) {
544
1415
  unsigned int sidHash = fnv1Hash32(sid, strlen(sid));
545
- if (!ensureEntry(tree, sid, sidHash, entry)) {
546
- unsigned int result = getBindingIndex(tree, sidHash, &(*entry)->bindingIndex);
547
- if (result != RULES_OK) {
548
- return result;
549
- }
550
- }
551
-
552
- bindingsList *list = tree->bindingsList;
553
- *rulesBinding = &list->bindings[(*entry)->bindingIndex];
554
- return RULES_OK;
555
- }
556
-
557
- unsigned int resolveBinding(void *tree,
558
- char *sid,
559
- void **rulesBinding) {
560
- stateEntry *entry = NULL;
561
- return resolveBindingAndEntry(tree, sid, &entry, rulesBinding);
562
- }
563
-
564
- unsigned int refreshState(void *tree,
565
- char *sid) {
566
- unsigned int result;
567
- stateEntry *entry = NULL;
568
- void *rulesBinding;
569
- result = resolveBindingAndEntry(tree, sid, &entry, &rulesBinding);
570
- if (result != RULES_OK) {
571
- return result;
572
- }
573
-
574
- if (entry->state) {
575
- free(entry->state);
576
- entry->state = NULL;
577
- }
578
-
579
- result = getSession(rulesBinding, sid, &entry->state);
580
- if (result != RULES_OK) {
581
- if (result == ERR_NEW_SESSION) {
582
- entry->lastRefresh = time(NULL);
583
- }
584
- return result;
585
- }
586
-
587
- memset(entry->jo.properties, 0, MAX_OBJECT_PROPERTIES * sizeof(jsonProperty));
588
- entry->jo.propertiesLength = 0;
589
- char *next;
590
- result = constructObject(entry->state,
591
- NULL,
592
- NULL,
593
- JSON_OBJECT_HASHED,
594
- 0,
595
- &entry->jo,
596
- &next);
597
- if (result != RULES_OK) {
598
- return result;
599
- }
600
-
601
- entry->lastRefresh = time(NULL);
602
- return RULES_OK;
603
- }
1416
+ unsigned int nodeOffset;
604
1417
 
605
- unsigned int fetchStateProperty(void *tree,
606
- char *sid,
607
- unsigned int propertyHash,
608
- unsigned int maxTime,
609
- unsigned char ignoreStaleState,
610
- char **state,
611
- jsonProperty **property) {
612
- unsigned int sidHash = fnv1Hash32(sid, strlen(sid));
613
- stateEntry *entry = getEntry(tree, sid, sidHash);
614
- if (entry == NULL || entry->lastRefresh == 0) {
615
- return ERR_STATE_NOT_LOADED;
616
- }
617
-
618
- if (!ignoreStaleState && (time(NULL) - entry->lastRefresh > maxTime)) {
619
- return ERR_STALE_STATE;
620
- }
1418
+ GET_FIRST(stateNode,
1419
+ tree->stateIndex,
1420
+ MAX_STATE_INDEX_LENGTH,
1421
+ ((ruleset*)tree)->statePool,
1422
+ sidHash,
1423
+ nodeOffset);
621
1424
 
622
- unsigned int propertyIndex = propertyHash % MAX_OBJECT_PROPERTIES;
623
- jsonProperty *result = &entry->jo.properties[propertyIndex];
624
- while (result->type != 0 && result->hash != propertyHash) {
625
- propertyIndex = (propertyIndex + 1) % MAX_OBJECT_PROPERTIES;
626
- result = &entry->jo.properties[propertyIndex];
1425
+ if (nodeOffset == UNDEFINED_HASH_OFFSET) {
1426
+ return ERR_SID_NOT_FOUND;
627
1427
  }
628
1428
 
629
- if (!result->type) {
630
- return ERR_PROPERTY_NOT_FOUND;
631
- }
1429
+ stateNode *node = STATE_NODE(tree, nodeOffset);
632
1430
 
633
- *state = entry->state;
634
- rehydrateProperty(result, *state);
635
- *property = result;
636
- return RULES_OK;
1431
+ return serializeState(node, state);
637
1432
  }
638
1433
 
639
- unsigned int getState(unsigned int handle, char *sid, char **state) {
1434
+ unsigned int deleteState(unsigned int handle, char *sid) {
640
1435
  ruleset *tree;
641
1436
  RESOLVE_HANDLE(handle, &tree);
642
1437
 
643
- void *rulesBinding = NULL;
644
1438
  if (!sid) {
645
1439
  sid = "0";
646
1440
  }
1441
+ unsigned int sidHash = fnv1Hash32(sid, strlen(sid));
1442
+ unsigned int nodeOffset;
647
1443
 
648
- unsigned int result = resolveBinding(tree, sid, &rulesBinding);
649
- if (result != RULES_OK) {
650
- return result;
651
- }
652
-
653
- return getSession(rulesBinding, sid, state);
654
- }
1444
+ GET_FIRST(stateNode,
1445
+ tree->stateIndex,
1446
+ MAX_STATE_INDEX_LENGTH,
1447
+ ((ruleset*)tree)->statePool,
1448
+ sidHash,
1449
+ nodeOffset);
655
1450
 
656
- unsigned int getStateVersion(void *tree, char *sid, unsigned long *stateVersion) {
657
- void *rulesBinding = NULL;
658
- unsigned int result = resolveBinding(tree, sid, &rulesBinding);
659
- if (result != RULES_OK) {
660
- return result;
1451
+ if (nodeOffset == UNDEFINED_HASH_OFFSET) {
1452
+ return ERR_SID_NOT_FOUND;
661
1453
  }
662
1454
 
663
- return getSessionVersion(rulesBinding, sid, stateVersion);
664
- }
665
-
666
-
667
- unsigned int deleteState(unsigned int handle, char *sid) {
668
- ruleset *tree;
669
- RESOLVE_HANDLE(handle, &tree);
1455
+ stateNode *node = STATE_NODE(tree, nodeOffset);
1456
+ free(node->sid);
670
1457
 
671
- if (!sid) {
672
- sid = "0";
1458
+ for (unsigned int i = 0; i < ((ruleset*)tree)->betaCount; ++i) {
1459
+ betaStateNode *betaNode = &node->betaState[i];
1460
+ free(betaNode->leftFramePool.content);
1461
+ free(betaNode->rightFramePool.content);
673
1462
  }
1463
+ free(node->betaState);
674
1464
 
675
- void *rulesBinding = NULL;
676
- unsigned int result = resolveBinding(tree, sid, &rulesBinding);
677
- if (result != RULES_OK) {
678
- return result;
1465
+ for (unsigned int i = 0; i < ((ruleset*)tree)->connectorCount; ++i) {
1466
+ connectorStateNode *connectorNode = &node->connectorState[i];
1467
+ free(connectorNode->aFramePool.content);
1468
+ free(connectorNode->bFramePool.content);
679
1469
  }
1470
+ free(node->connectorState);
680
1471
 
681
- unsigned int sidHash = fnv1Hash32(sid, strlen(sid));
682
- result = deleteSession(tree, rulesBinding, sid, sidHash);
683
- if (result != RULES_OK) {
684
- return result;
685
- }
1472
+ for (unsigned int i = 0; i < ((ruleset*)tree)->actionCount; ++i) {
1473
+ actionStateNode *actionNode = &node->actionState[i];
1474
+ free(actionNode->resultPool.content);
1475
+ }
1476
+ free(node->actionState);
1477
+
1478
+ DELETE(stateNode,
1479
+ tree->stateIndex,
1480
+ MAX_STATE_INDEX_LENGTH,
1481
+ tree->statePool,
1482
+ nodeOffset);
686
1483
 
687
- deleteEntry(tree, sid, sidHash);
688
1484
  return RULES_OK;
689
1485
  }