durable_rules 0.34.57 → 2.00.001
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/librb/durable.rb +46 -28
- data/librb/engine.rb +257 -548
- data/src/rules/Makefile +6 -7
- data/src/rules/events.c +1690 -1559
- data/src/rules/json.h +10 -6
- data/src/rules/rete.c +829 -1046
- data/src/rules/rete.h +66 -52
- data/src/rules/rules.h +67 -109
- data/src/rules/state.c +1245 -449
- data/src/rules/state.h +305 -31
- data/src/rulesrb/extconf.rb +1 -8
- data/src/rulesrb/rules.c +71 -369
- metadata +2 -36
- data/deps/hiredis/COPYING +0 -29
- data/deps/hiredis/Makefile +0 -217
- data/deps/hiredis/async.c +0 -687
- data/deps/hiredis/async.h +0 -129
- data/deps/hiredis/dict.c +0 -338
- data/deps/hiredis/dict.h +0 -126
- data/deps/hiredis/fmacros.h +0 -21
- data/deps/hiredis/hiredis.c +0 -1021
- data/deps/hiredis/hiredis.h +0 -223
- data/deps/hiredis/net.c +0 -458
- data/deps/hiredis/net.h +0 -53
- data/deps/hiredis/read.c +0 -525
- data/deps/hiredis/read.h +0 -116
- data/deps/hiredis/sds.c +0 -1095
- data/deps/hiredis/sds.h +0 -105
- data/deps/hiredis/test.c +0 -807
- data/deps/hiredis/win32.h +0 -42
- data/librb/interface.rb +0 -126
- data/src/rules/net.c +0 -3257
- data/src/rules/net.h +0 -165
data/src/rules/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
|
30
|
-
#define
|
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
|
-
|
34
|
-
|
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
|
37
|
-
}
|
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
|
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
|
64
|
+
unsigned int expressionOffset;
|
54
65
|
regexReference regex;
|
55
|
-
|
66
|
+
identifier id;
|
56
67
|
} value;
|
57
|
-
}
|
68
|
+
} operand;
|
58
69
|
|
59
|
-
typedef struct
|
70
|
+
typedef struct expression {
|
60
71
|
unsigned char operator;
|
61
|
-
|
62
|
-
|
63
|
-
}
|
72
|
+
operand left;
|
73
|
+
operand right;
|
74
|
+
} expression;
|
64
75
|
|
65
|
-
typedef struct
|
76
|
+
typedef struct expressionSequence {
|
66
77
|
unsigned int nameOffset;
|
67
78
|
unsigned int aliasOffset;
|
68
|
-
unsigned short
|
69
|
-
unsigned char distinct;
|
79
|
+
unsigned short length;
|
70
80
|
unsigned char not;
|
71
|
-
|
72
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
128
|
-
unsigned int idiomOffset;
|
129
|
-
join *joinPool;
|
130
|
-
unsigned int joinOffset;
|
139
|
+
|
131
140
|
char *regexStateMachinePool;
|
132
141
|
unsigned int regexStateMachineOffset;
|
133
|
-
|
134
|
-
|
135
|
-
unsigned int
|
136
|
-
unsigned int
|
137
|
-
|
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
|
4
|
-
#define
|
5
|
-
|
6
|
-
#define
|
7
|
-
#define
|
8
|
-
#define
|
9
|
-
#define
|
10
|
-
#define
|
11
|
-
#define
|
12
|
-
#define
|
13
|
-
#define
|
14
|
-
#define
|
15
|
-
#define
|
16
|
-
#define
|
17
|
-
#define
|
18
|
-
#define
|
19
|
-
#define
|
20
|
-
#define
|
21
|
-
#define
|
22
|
-
#define
|
23
|
-
#define
|
24
|
-
#define
|
25
|
-
#define
|
26
|
-
#define
|
27
|
-
#define
|
28
|
-
#define
|
29
|
-
#define
|
30
|
-
#define
|
31
|
-
#define
|
32
|
-
#define
|
33
|
-
#define
|
34
|
-
#define
|
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
|
186
|
-
|
187
|
-
|
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 **
|
161
|
+
char **stateFact,
|
197
162
|
char **messages,
|
198
|
-
|
199
|
-
void **actionBinding);
|
163
|
+
unsigned int *stateOffset);
|
200
164
|
|
201
|
-
unsigned int
|
202
|
-
|
203
|
-
|
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
|
207
|
-
void *actionHandle,
|
171
|
+
unsigned int stateOffset,
|
208
172
|
char **messages);
|
209
173
|
|
210
174
|
unsigned int abandonAction(unsigned int handle,
|
211
|
-
|
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 "
|
8
|
-
|
9
|
-
|
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 <
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
50
|
-
|
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
|
-
|
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
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
unsigned
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
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
|
-
|
75
|
-
|
76
|
-
|
77
|
-
}
|
260
|
+
if (messageNodeOffset == UNDEFINED_HASH_OFFSET) {
|
261
|
+
return ERR_MESSAGE_NOT_FOUND;
|
262
|
+
}
|
78
263
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
106
|
-
|
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
|
111
|
-
|
112
|
-
|
113
|
-
|
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
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
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
|
-
|
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
|
420
|
+
return RULES_OK;
|
144
421
|
}
|
145
422
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
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
|
-
|
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
|
-
|
165
|
-
|
166
|
-
|
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
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
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
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
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
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|
-
|
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
|
-
|
1010
|
+
memcpy(*stateFact, stateFactNode->jo.content, stateFactLength);
|
194
1011
|
|
195
|
-
|
196
|
-
return found;
|
1012
|
+
return RULES_OK;
|
197
1013
|
}
|
198
1014
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
266
|
-
hash ^= property->
|
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
|
-
|
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
|
-
|
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->
|
312
|
-
property->valueString = jo->sidBuffer;
|
1213
|
+
property->valueOffset = 0;
|
313
1214
|
property->valueLength = 1;
|
314
|
-
|
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
|
-
|
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
|
-
|
327
|
-
|
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
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
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
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
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
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
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
|
-
|
1372
|
+
char *fullName = (char *)_alloca(sizeof(char)*(fullNameLength + 1));
|
472
1373
|
#else
|
473
|
-
|
1374
|
+
char fullName[fullNameLength + 1];
|
474
1375
|
#endif
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
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
|
-
|
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
|
-
|
507
|
-
|
508
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
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
|
-
|
623
|
-
|
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
|
-
|
630
|
-
return ERR_PROPERTY_NOT_FOUND;
|
631
|
-
}
|
1429
|
+
stateNode *node = STATE_NODE(tree, nodeOffset);
|
632
1430
|
|
633
|
-
|
634
|
-
rehydrateProperty(result, *state);
|
635
|
-
*property = result;
|
636
|
-
return RULES_OK;
|
1431
|
+
return serializeState(node, state);
|
637
1432
|
}
|
638
1433
|
|
639
|
-
unsigned int
|
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
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
}
|
1444
|
+
GET_FIRST(stateNode,
|
1445
|
+
tree->stateIndex,
|
1446
|
+
MAX_STATE_INDEX_LENGTH,
|
1447
|
+
((ruleset*)tree)->statePool,
|
1448
|
+
sidHash,
|
1449
|
+
nodeOffset);
|
655
1450
|
|
656
|
-
|
657
|
-
|
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
|
-
|
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
|
-
|
672
|
-
|
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
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
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
|
682
|
-
|
683
|
-
|
684
|
-
|
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
|
}
|