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/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
  }