durable_rules 2.0.5 → 2.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4f2783f44507366a2029205429dd94b99da4fdb8
4
- data.tar.gz: 15e4d147d321f18e701583d1cb0f1a77dac4a977
3
+ metadata.gz: c4dd49e4357fbd2d4df00d1055d3f28413f81631
4
+ data.tar.gz: 8f27a057991ac417017ad5127a2161a0be2accd8
5
5
  SHA512:
6
- metadata.gz: 73533cb05af0e9d0a5190187f5636e49fcbe000e7c2f374d3d142d20a998a94f22016a4570f1623e4809c8698d2d1a403afc1ca5aa2879a991998f2b93fa36d5
7
- data.tar.gz: 9ba5938a86bb9737246f6779a9d499f06eb116b2d079d5b2ac521769cbfde26b220c4dd68af14e12d1e5238927d155518e714aed5764d3b7a0e65dc8a06726a2
6
+ metadata.gz: a8c5ad57d5aa1cbdc2b798dfc2c91bab920d127b4ac05190c5a61a2eada58dc2261ee6bf062078ad1c7a4aa42e82e338b2580646ea5f3accefe8459f54063777
7
+ data.tar.gz: baa4b3ac0b646cf45cd427df314d015dc6a76d3d5d34b6126e2bc24cce39d971b43f540171422e7a874faa896d69573d8a6bba4f7baf5b1cf8e2861ead5d4473
data/src/rules/events.c CHANGED
@@ -13,13 +13,6 @@
13
13
  #include "regex.h"
14
14
  #include "rete.h"
15
15
 
16
- #define ACTION_ASSERT_FACT 1
17
- #define ACTION_ASSERT_EVENT 2
18
- #define ACTION_RETRACT_FACT 3
19
- #define ACTION_RETRACT_EVENT 4
20
- #define ACTION_UPDATE_STATE 5
21
-
22
-
23
16
  #define MAX_RESULT_NODES 32
24
17
  #define MAX_NODE_RESULTS 16
25
18
  #define MAX_STACK_SIZE 64
@@ -998,6 +991,7 @@ static unsigned int handleBetaFrame(ruleset *tree,
998
991
 
999
992
  static unsigned int handleDeleteMessage(ruleset *tree,
1000
993
  stateNode *state,
994
+ char *mid,
1001
995
  unsigned int messageOffset) {
1002
996
  unsigned int result;
1003
997
  unsigned int count = 0;
@@ -1139,7 +1133,10 @@ static unsigned int handleDeleteMessage(ruleset *tree,
1139
1133
  }
1140
1134
  }
1141
1135
 
1142
- result = deleteMessage(state, messageOffset);
1136
+ result = deleteMessage(tree,
1137
+ state,
1138
+ mid,
1139
+ messageOffset);
1143
1140
  if (result == ERR_NODE_DELETED) {
1144
1141
  return RULES_OK;
1145
1142
  } else if (result != RULES_OK) {
@@ -1590,14 +1587,17 @@ static unsigned int handleAlpha(ruleset *tree,
1590
1587
  stateNode *state,
1591
1588
  char *mid,
1592
1589
  jsonObject *jo,
1593
- unsigned int currentMessageOffset,
1594
- alpha *alphaNode) {
1590
+ unsigned char messageType,
1591
+ alpha *alphaNode,
1592
+ unsigned int *messageOffset) {
1595
1593
  unsigned short top = 1;
1596
1594
  unsigned int entry;
1595
+ unsigned char messageStored = 0;
1597
1596
  alpha *stack[MAX_STACK_SIZE];
1598
1597
  stack[0] = alphaNode;
1599
1598
  alpha *currentAlpha;
1600
1599
  unsigned int result = ERR_EVENT_NOT_HANDLED;
1600
+ *messageOffset = UNDEFINED_HASH_OFFSET;
1601
1601
 
1602
1602
  while (top) {
1603
1603
  --top;
@@ -1665,6 +1665,17 @@ static unsigned int handleAlpha(ruleset *tree,
1665
1665
  }
1666
1666
 
1667
1667
  if (currentAlpha->betaListOffset) {
1668
+ if (!messageStored) {
1669
+ CHECK_RESULT(storeMessage(tree,
1670
+ state,
1671
+ mid,
1672
+ jo,
1673
+ messageType,
1674
+ messageOffset));
1675
+
1676
+ messageStored = 1;
1677
+ }
1678
+
1668
1679
  result = RULES_OK;
1669
1680
  unsigned int *betaList = &tree->nextPool[currentAlpha->betaListOffset];
1670
1681
  for (unsigned int entry = 0; betaList[entry] != 0; ++entry) {
@@ -1672,7 +1683,7 @@ static unsigned int handleAlpha(ruleset *tree,
1672
1683
  state,
1673
1684
  &tree->nodePool[betaList[entry]],
1674
1685
  jo,
1675
- currentMessageOffset));
1686
+ *messageOffset));
1676
1687
  }
1677
1688
  }
1678
1689
  }
@@ -1702,7 +1713,7 @@ static unsigned int handleMessageCore(ruleset *tree,
1702
1713
 
1703
1714
  sid[sidProperty->valueLength] = '\0';
1704
1715
 
1705
- #ifdef _WIN32
1716
+ #ifdef _WIN32
1706
1717
  char *mid = (char *)_alloca(sizeof(char)*(midProperty->valueLength + 1));
1707
1718
  #else
1708
1719
  char mid[midProperty->valueLength + 1];
@@ -1713,38 +1724,59 @@ static unsigned int handleMessageCore(ruleset *tree,
1713
1724
  strncpy(mid, jo->idBuffer, midProperty->valueLength);
1714
1725
  }
1715
1726
 
1727
+ *stateOffset = UNDEFINED_HASH_OFFSET;
1716
1728
  mid[midProperty->valueLength] = '\0';
1717
- unsigned char isNewState;
1718
- CHECK_RESULT(ensureStateNode(tree,
1719
- sid,
1720
- &isNewState,
1721
- &sidState));
1729
+ unsigned int result = getStateNode(tree,
1730
+ sid,
1731
+ &sidState);
1732
+ if (result != RULES_OK && result != ERR_SID_NOT_FOUND) {
1733
+ return result;
1734
+ } else if (result == ERR_SID_NOT_FOUND) {
1735
+ if (!tree->queueMessageCallback) {
1736
+ CHECK_RESULT(createStateNode(tree,
1737
+ sid,
1738
+ &sidState));
1739
+ } else {
1740
+ CHECK_RESULT(tree->queueMessageCallback(tree->queueMessageCallbackContext,
1741
+ &tree->stringPool[tree->nameOffset],
1742
+ sid,
1743
+ actionType,
1744
+ jo->content));
1745
+
1746
+ return ERR_EVENT_DEFERRED;
1747
+ }
1748
+ }
1722
1749
 
1723
1750
  *stateOffset = sidState->offset;
1724
1751
  if (actionType == ACTION_UPDATE_STATE) {
1725
1752
  if (sidState->factOffset != UNDEFINED_HASH_OFFSET) {
1726
1753
  CHECK_RESULT(handleDeleteMessage(tree,
1727
1754
  sidState,
1755
+ mid,
1728
1756
  sidState->factOffset));
1729
1757
 
1730
1758
  }
1731
1759
 
1732
- CHECK_RESULT(storeMessage(sidState,
1760
+ result = handleAlpha(tree,
1761
+ sidState,
1762
+ mid,
1763
+ jo,
1764
+ MESSAGE_TYPE_FACT,
1765
+ &tree->nodePool[NODE_M_OFFSET].value.a,
1766
+ messageOffset);
1767
+ if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
1768
+ return result;
1769
+ } else if (result == ERR_EVENT_NOT_HANDLED) {
1770
+ CHECK_RESULT(storeMessage(tree,
1771
+ sidState,
1733
1772
  mid,
1734
1773
  jo,
1735
1774
  MESSAGE_TYPE_FACT,
1736
1775
  messageOffset));
1737
-
1776
+ }
1738
1777
 
1739
1778
  sidState->factOffset = *messageOffset;
1740
- CHECK_RESULT(handleAlpha(tree,
1741
- sidState,
1742
- mid,
1743
- jo,
1744
- sidState->factOffset,
1745
- &tree->nodePool[NODE_M_OFFSET].value.a));
1746
-
1747
- } else if (actionType == ACTION_RETRACT_FACT || actionType == ACTION_RETRACT_EVENT) {
1779
+ } else if (actionType == ACTION_RETRACT_FACT) {
1748
1780
  CHECK_RESULT(getMessage(sidState,
1749
1781
  mid,
1750
1782
  messageOffset));
@@ -1752,24 +1784,20 @@ static unsigned int handleMessageCore(ruleset *tree,
1752
1784
  if (*messageOffset != UNDEFINED_HASH_OFFSET) {
1753
1785
  CHECK_RESULT(handleDeleteMessage(tree,
1754
1786
  sidState,
1787
+ mid,
1755
1788
  *messageOffset));
1756
1789
  }
1757
1790
  } else {
1758
- CHECK_RESULT(storeMessage(sidState,
1759
- mid,
1760
- jo,
1761
- (actionType == ACTION_ASSERT_FACT ? MESSAGE_TYPE_FACT : MESSAGE_TYPE_EVENT),
1762
- messageOffset));
1763
-
1764
1791
  unsigned int result = handleAlpha(tree,
1765
1792
  sidState,
1766
1793
  mid,
1767
1794
  jo,
1768
- *messageOffset,
1769
- &tree->nodePool[NODE_M_OFFSET].value.a);
1795
+ (actionType == ACTION_ASSERT_FACT ? MESSAGE_TYPE_FACT : MESSAGE_TYPE_EVENT),
1796
+ &tree->nodePool[NODE_M_OFFSET].value.a,
1797
+ messageOffset);
1770
1798
 
1771
1799
  if (result == RULES_OK || result == ERR_EVENT_NOT_HANDLED) {
1772
- if (isNewState) {
1800
+ if (sidState->factOffset == UNDEFINED_HASH_OFFSET) {
1773
1801
  #ifdef _WIN32
1774
1802
  char *stateMessage = (char *)_alloca(sizeof(char)*(50 + sidProperty->valueLength * 2));
1775
1803
  sprintf_s(stateMessage, sizeof(char)*(50 + sidProperty->valueLength * 2), "{ \"sid\":\"%s\", \"id\":\"sid-%s\", \"$s\":1}", sid, sid);
@@ -1781,7 +1809,7 @@ static unsigned int handleMessageCore(ruleset *tree,
1781
1809
  unsigned int stateMessageOffset;
1782
1810
  unsigned int stateResult = handleMessage(tree,
1783
1811
  stateMessage,
1784
- ACTION_ASSERT_FACT,
1812
+ ACTION_UPDATE_STATE,
1785
1813
  &stateMessageOffset,
1786
1814
  stateOffset);
1787
1815
  if (stateResult != RULES_OK && stateResult != ERR_EVENT_NOT_HANDLED) {
@@ -1861,12 +1889,12 @@ static unsigned int handleMessages(ruleset *tree,
1861
1889
  stateOffset);
1862
1890
 
1863
1891
  *last = lastTemp;
1864
- if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED) {
1892
+ if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED && result != ERR_EVENT_OBSERVED) {
1865
1893
  return result;
1866
1894
  }
1867
1895
 
1868
- if (result == ERR_EVENT_NOT_HANDLED) {
1869
- returnResult = ERR_EVENT_NOT_HANDLED;
1896
+ if (result == ERR_EVENT_NOT_HANDLED || result == ERR_EVENT_OBSERVED) {
1897
+ returnResult = result;
1870
1898
  }
1871
1899
 
1872
1900
  first = last;
@@ -1949,6 +1977,149 @@ unsigned int updateState(unsigned int handle,
1949
1977
  return result;
1950
1978
  }
1951
1979
 
1980
+ static unsigned int replayMessages(ruleset *tree,
1981
+ char *messages,
1982
+ unsigned int *stateOffset) {
1983
+ unsigned int result;
1984
+ unsigned int messageOffset;
1985
+ jsonObject jo;
1986
+ unsigned char type;
1987
+ unsigned char actionType;
1988
+ char *first = messages;
1989
+ char *last = NULL;
1990
+ char lastTemp;
1991
+
1992
+ while (readNextArrayValue(first,
1993
+ &first,
1994
+ &last,
1995
+ &type) == PARSE_OK) {
1996
+
1997
+ if (type != JSON_INT) {
1998
+ return ERR_UNEXPECTED_TYPE;
1999
+ }
2000
+
2001
+ char temp = last[1];
2002
+ last[1] = '\0';
2003
+ actionType = atol(first);
2004
+ last[1] = temp;
2005
+ first = last;
2006
+
2007
+ CHECK_PARSE_RESULT(readNextArrayValue(first,
2008
+ &first,
2009
+ &last,
2010
+ &type));
2011
+
2012
+ if (type != JSON_OBJECT) {
2013
+ return ERR_UNEXPECTED_TYPE;
2014
+ }
2015
+
2016
+ CHECK_RESULT(constructObject(first,
2017
+ NULL,
2018
+ NULL,
2019
+ 1,
2020
+ &jo,
2021
+ &last));
2022
+
2023
+ while (*last != ',' && *last != '\0' ) {
2024
+ ++last;
2025
+ }
2026
+
2027
+ if (*last == '\0') {
2028
+ --last;
2029
+ }
2030
+
2031
+ lastTemp = *last;
2032
+ *last = '\0';
2033
+ result = handleMessageCore(tree,
2034
+ &jo,
2035
+ actionType,
2036
+ &messageOffset,
2037
+ stateOffset);
2038
+
2039
+ *last = lastTemp;
2040
+ if (result != RULES_OK && result != ERR_EVENT_NOT_HANDLED && result != ERR_EVENT_OBSERVED) {
2041
+ return result;
2042
+ }
2043
+
2044
+ first = last;
2045
+ }
2046
+
2047
+ return RULES_OK;
2048
+ }
2049
+
2050
+
2051
+ static unsigned int flushQueuedActions(ruleset *tree) {
2052
+ if (tree->getIdleStateCallback) {
2053
+ char *sid;
2054
+ CHECK_RESULT(tree->getIdleStateCallback(tree->getIdleStateCallbackContext,
2055
+ &tree->stringPool[tree->nameOffset],
2056
+ &sid));
2057
+ if (sid) {
2058
+ stateNode *state;
2059
+ unsigned int result = getStateNode(tree,
2060
+ sid,
2061
+ &state);
2062
+ if (result != RULES_OK && result != ERR_SID_NOT_FOUND) {
2063
+ return result;
2064
+ } else if (result == RULES_OK) {
2065
+ CHECK_RESULT(deleteStateNode(tree,
2066
+ state));
2067
+ }
2068
+
2069
+ CHECK_RESULT(createStateNode(tree,
2070
+ sid,
2071
+ &state));
2072
+
2073
+ free(sid);
2074
+ if (tree->getStoredMessagesCallback) {
2075
+ char *messages;
2076
+ unsigned int stateOffset;
2077
+ CHECK_RESULT(tree->getStoredMessagesCallback(tree->getStoredMessagesCallbackContext,
2078
+ &tree->stringPool[tree->nameOffset],
2079
+ state->sid,
2080
+ &messages));
2081
+ if (messages) {
2082
+ result = replayMessages(tree,
2083
+ messages,
2084
+ &stateOffset);
2085
+
2086
+ free(messages);
2087
+ if (result != RULES_OK) {
2088
+ return result;
2089
+ }
2090
+
2091
+ }
2092
+ }
2093
+ }
2094
+ }
2095
+
2096
+
2097
+ if (tree->getQueuedMessagesCallback) {
2098
+ for (unsigned int index = 0; index < tree->statePool.count; ++index) {
2099
+ unsigned int nodeOffset = tree->reverseStateIndex[index];
2100
+ stateNode *currentState = STATE_NODE(tree, nodeOffset);
2101
+
2102
+ char *messages;
2103
+ unsigned int stateOffset;
2104
+ CHECK_RESULT(tree->getQueuedMessagesCallback(tree->getQueuedMessagesCallbackContext,
2105
+ &tree->stringPool[tree->nameOffset],
2106
+ currentState->sid,
2107
+ &messages));
2108
+ if (messages) {
2109
+ unsigned int result = replayMessages(tree,
2110
+ messages,
2111
+ &stateOffset);
2112
+ free(messages);
2113
+ if (result != RULES_OK) {
2114
+ return result;
2115
+ }
2116
+ }
2117
+ }
2118
+ }
2119
+
2120
+ return RULES_OK;
2121
+ }
2122
+
1952
2123
  unsigned int startAction(unsigned int handle,
1953
2124
  char **stateFact,
1954
2125
  char **messages,
@@ -1962,6 +2133,8 @@ unsigned int startAction(unsigned int handle,
1962
2133
  unsigned int resultFrameOffset;
1963
2134
  time_t currentTime = time(NULL);
1964
2135
 
2136
+ CHECK_RESULT(flushQueuedActions(tree));
2137
+
1965
2138
  CHECK_RESULT(getNextResult(tree,
1966
2139
  currentTime,
1967
2140
  &resultState,
@@ -1995,6 +2168,11 @@ unsigned int startActionForState(unsigned int handle,
1995
2168
  unsigned int stateOffset,
1996
2169
  char **stateFact,
1997
2170
  char **messages) {
2171
+
2172
+ if (stateOffset == UNDEFINED_HASH_OFFSET) {
2173
+ return ERR_NO_ACTION_AVAILABLE;
2174
+ }
2175
+
1998
2176
  ruleset *tree;
1999
2177
  RESOLVE_HANDLE(handle, &tree);
2000
2178
  stateNode *resultState = STATE_NODE(tree, stateOffset);
@@ -2052,10 +2230,26 @@ static unsigned int deleteCurrentAction(ruleset *tree,
2052
2230
  messageNode *currentMessageNode = MESSAGE_NODE(state,
2053
2231
  currentMessageFrame->messageNodeOffset);
2054
2232
 
2055
-
2056
2233
  if (currentMessageNode->messageType == MESSAGE_TYPE_EVENT) {
2234
+ jsonObject *jo = &currentMessageNode->jo;
2235
+ jsonProperty *midProperty = &jo->properties[jo->idIndex];
2236
+
2237
+ #ifdef _WIN32
2238
+ char *mid = (char *)_alloca(sizeof(char)*(midProperty->valueLength + 1));
2239
+ #else
2240
+ char mid[midProperty->valueLength + 1];
2241
+ #endif
2242
+ if (midProperty->valueOffset) {
2243
+ strncpy(mid, jo->content + midProperty->valueOffset, midProperty->valueLength);
2244
+ } else {
2245
+ strncpy(mid, jo->idBuffer, midProperty->valueLength);
2246
+ }
2247
+
2248
+ mid[midProperty->valueLength] = '\0';
2249
+
2057
2250
  CHECK_RESULT(handleDeleteMessage(tree,
2058
- state,
2251
+ state,
2252
+ mid,
2059
2253
  currentMessageFrame->messageNodeOffset));
2060
2254
  }
2061
2255
  }
@@ -2091,7 +2285,6 @@ unsigned int completeAndStartAction(unsigned int handle,
2091
2285
  ruleset *tree;
2092
2286
  RESOLVE_HANDLE(handle, &tree);
2093
2287
  stateNode *resultState = STATE_NODE(tree, stateOffset);
2094
-
2095
2288
  CHECK_RESULT(deleteCurrentAction(tree,
2096
2289
  resultState,
2097
2290
  resultState->context.actionStateIndex,
@@ -2138,7 +2331,6 @@ unsigned int abandonAction(unsigned int handle, unsigned int stateOffset) {
2138
2331
 
2139
2332
  unsigned int renewActionLease(unsigned int handle, char *sid) {
2140
2333
  ruleset *tree;
2141
- unsigned char isNewState;
2142
2334
  stateNode *state = NULL;
2143
2335
 
2144
2336
  RESOLVE_HANDLE(handle, &tree);
@@ -2146,10 +2338,9 @@ unsigned int renewActionLease(unsigned int handle, char *sid) {
2146
2338
  sid = "0";
2147
2339
  }
2148
2340
 
2149
- CHECK_RESULT(ensureStateNode(tree,
2150
- sid,
2151
- &isNewState,
2152
- &state));
2341
+ CHECK_RESULT(getStateNode(tree,
2342
+ sid,
2343
+ &state));
2153
2344
 
2154
2345
  state->lockExpireTime = time(NULL) + STATE_LEASE_TIME;
2155
2346
  return RULES_OK;
@@ -2209,7 +2400,6 @@ unsigned int assertTimers(unsigned int handle) {
2209
2400
 
2210
2401
  unsigned int cancelTimer(unsigned int handle, char *sid, char *timerName) {
2211
2402
  ruleset *tree;
2212
- unsigned char isNewState;
2213
2403
  unsigned int messageOffset;
2214
2404
  unsigned int stateOffset;
2215
2405
  stateNode *state = NULL;
@@ -2219,10 +2409,9 @@ unsigned int cancelTimer(unsigned int handle, char *sid, char *timerName) {
2219
2409
  sid = "0";
2220
2410
  }
2221
2411
 
2222
- CHECK_RESULT(ensureStateNode(tree,
2223
- sid,
2224
- &isNewState,
2225
- &state));
2412
+ CHECK_RESULT(getStateNode(tree,
2413
+ sid,
2414
+ &state));
2226
2415
 
2227
2416
  CHECK_RESULT(getMessage(state,
2228
2417
  timerName,
data/src/rules/rete.c CHANGED
@@ -1852,6 +1852,19 @@ unsigned int createRuleset(unsigned int *handle, char *name, char *rules) {
1852
1852
  tree->actionCount = 0;
1853
1853
  tree->bindingsList = NULL;
1854
1854
  tree->currentStateIndex = 0;
1855
+ tree->storeMessageCallback = NULL;
1856
+ tree->storeMessageCallbackContext = NULL;
1857
+ tree->deleteMessageCallback = NULL;
1858
+ tree->deleteMessageCallbackContext = NULL;
1859
+ tree->queueMessageCallback = NULL;
1860
+ tree->queueMessageCallbackContext = NULL;
1861
+ tree->getQueuedMessagesCallback = NULL;
1862
+ tree->getQueuedMessagesCallbackContext = NULL;
1863
+ tree->getStoredMessagesCallback = NULL;
1864
+ tree->getStoredMessagesCallbackContext = NULL;
1865
+ tree->getIdleStateCallback = NULL;
1866
+ tree->getIdleStateCallbackContext = NULL;
1867
+
1855
1868
  memset(tree->stateIndex, 0, MAX_STATE_INDEX_LENGTH * sizeof(unsigned int) * 2);
1856
1869
  memset(tree->reverseStateIndex, 0, MAX_STATE_INDEX_LENGTH * sizeof(unsigned int));
1857
1870
  initStatePool(tree);
@@ -1894,4 +1907,66 @@ unsigned int deleteRuleset(unsigned int handle) {
1894
1907
  return RULES_OK;
1895
1908
  }
1896
1909
 
1910
+ unsigned int setStoreMessageCallback(unsigned int handle,
1911
+ void *context,
1912
+ unsigned int (*callback)(void *, char *, char *, char *, unsigned char, char *)) {
1913
+ ruleset *tree;
1914
+ RESOLVE_HANDLE(handle, &tree);
1915
+ tree->storeMessageCallbackContext = context;
1916
+ tree->storeMessageCallback = callback;
1917
+ return RULES_OK;
1918
+ }
1919
+
1920
+ unsigned int setDeleteMessageCallback(unsigned int handle,
1921
+ void *context,
1922
+ unsigned int (*callback)(void *, char *, char *, char *)) {
1923
+ ruleset *tree;
1924
+ RESOLVE_HANDLE(handle, &tree);
1925
+ tree->deleteMessageCallbackContext = context;
1926
+ tree->deleteMessageCallback = callback;
1927
+ return RULES_OK;
1928
+ }
1929
+
1930
+ unsigned int setQueueMessageCallback(unsigned int handle,
1931
+ void *context,
1932
+ unsigned int (*callback)(void *, char *, char *, unsigned char, char *)) {
1933
+ ruleset *tree;
1934
+ RESOLVE_HANDLE(handle, &tree);
1935
+ tree->queueMessageCallbackContext = context;
1936
+ tree->queueMessageCallback = callback;
1937
+ return RULES_OK;
1938
+ }
1939
+
1940
+ unsigned int setGetQueuedMessagesCallback(unsigned int handle,
1941
+ void *context,
1942
+ unsigned int (*callback)(void *, char *, char *, char **)) {
1943
+ ruleset *tree;
1944
+ RESOLVE_HANDLE(handle, &tree);
1945
+
1946
+ tree->getQueuedMessagesCallbackContext = context;
1947
+ tree->getQueuedMessagesCallback = callback;
1948
+ return RULES_OK;
1949
+ }
1950
+
1951
+ unsigned int setGetStoredMessagesCallback(unsigned int handle,
1952
+ void *context,
1953
+ unsigned int (*callback)(void *, char *, char *, char **)) {
1954
+ ruleset *tree;
1955
+ RESOLVE_HANDLE(handle, &tree);
1956
+
1957
+ tree->getStoredMessagesCallbackContext = context;
1958
+ tree->getStoredMessagesCallback = callback;
1959
+ return RULES_OK;
1960
+ }
1961
+
1962
+ unsigned int setGetIdleStateCallback(unsigned int handle,
1963
+ void *context,
1964
+ unsigned int (*callback)(void *, char *, char **)) {
1965
+ ruleset *tree;
1966
+ RESOLVE_HANDLE(handle, &tree);
1967
+
1968
+ tree->getIdleStateCallbackContext = context;
1969
+ tree->getIdleStateCallback = callback;
1970
+ return RULES_OK;
1971
+ }
1897
1972
 
data/src/rules/rete.h CHANGED
@@ -146,6 +146,27 @@ typedef struct ruleset {
146
146
  unsigned int stateIndex[MAX_STATE_INDEX_LENGTH];
147
147
  unsigned int reverseStateIndex[MAX_STATE_INDEX_LENGTH];
148
148
  unsigned int currentStateIndex;
149
+
150
+
151
+ unsigned int (*storeMessageCallback)(void *, char *, char *, char *, unsigned char, char *);
152
+ void *storeMessageCallbackContext;
153
+
154
+ unsigned int (*deleteMessageCallback)(void *, char *, char *, char *);
155
+ void *deleteMessageCallbackContext;
156
+
157
+ unsigned int (*queueMessageCallback)(void *, char *, char *, unsigned char, char *);
158
+ void *queueMessageCallbackContext;
159
+
160
+ unsigned int (*getQueuedMessagesCallback)(void *, char *, char *, char **);
161
+ void *getQueuedMessagesCallbackContext;
162
+
163
+ unsigned int (*getStoredMessagesCallback)(void *, char *, char *, char **);
164
+ void *getStoredMessagesCallbackContext;
165
+
166
+ unsigned int (*getIdleStateCallback)(void *, char *, char **);
167
+ void *getIdleStateCallbackContext;
168
+
169
+
149
170
  } ruleset;
150
171
 
151
172
  #ifdef _PRINT
data/src/rules/rules.h CHANGED
@@ -2,6 +2,7 @@
2
2
  #define RULES_OK 0
3
3
  #define ERR_EVENT_NOT_HANDLED 1
4
4
  #define ERR_EVENT_OBSERVED 2
5
+ #define ERR_EVENT_DEFERRED 3
5
6
 
6
7
  #define ERR_OUT_OF_MEMORY 101
7
8
  #define ERR_UNEXPECTED_TYPE 102
@@ -108,10 +109,37 @@ extern char entriesInitialized;
108
109
  if (!firstEmptyEntry) firstEmptyEntry = lastEmptyEntry; \
109
110
  } while(0)
110
111
 
112
+
113
+ unsigned int cloneString(char **target, char *source);
114
+
111
115
  unsigned int createRuleset(unsigned int *handle,
112
116
  char *name,
113
117
  char *rules);
114
118
 
119
+ unsigned int setStoreMessageCallback(unsigned int handle,
120
+ void *context,
121
+ unsigned int (*callback)(void *, char *, char *, char *, unsigned char, char *));
122
+
123
+ unsigned int setDeleteMessageCallback(unsigned int handle,
124
+ void *context,
125
+ unsigned int (*callback)(void *, char *, char *, char *));
126
+
127
+ unsigned int setQueueMessageCallback(unsigned int handle,
128
+ void *context,
129
+ unsigned int (*callback)(void *, char *, char *, unsigned char, char *));
130
+
131
+ unsigned int setGetQueuedMessagesCallback(unsigned int handle,
132
+ void *context,
133
+ unsigned int (*callback)(void *, char *, char *, char **));
134
+
135
+ unsigned int setGetStoredMessagesCallback(unsigned int handle,
136
+ void *context,
137
+ unsigned int (*callback)(void *, char *, char *, char **));
138
+
139
+ unsigned int setGetIdleStateCallback(unsigned int handle,
140
+ void *context,
141
+ unsigned int (*callback)(void *, char *, char **));
142
+
115
143
  unsigned int deleteRuleset(unsigned int handle);
116
144
 
117
145
  unsigned int createClient(unsigned int *handle,
data/src/rules/state.c CHANGED
@@ -154,6 +154,17 @@ int asprintf(char** ret, char* format, ...){
154
154
  --pool.count; \
155
155
  } while (0)
156
156
 
157
+ unsigned int cloneString(char **target, char *source) {
158
+ unsigned int length = (strlen(source) + 1) * sizeof(char);
159
+ *target = malloc(length);
160
+ if (!*target) {
161
+ return ERR_OUT_OF_MEMORY;
162
+ }
163
+ memcpy(*target, source, length);
164
+
165
+ return RULES_OK;
166
+ }
167
+
157
168
  unsigned int fnv1Hash32(char *str, unsigned int length) {
158
169
  unsigned int hash = FNV_32_OFFSET_BASIS;
159
170
  for(unsigned int i = 0; i < length; str++, i++) {
@@ -670,10 +681,19 @@ unsigned int createRightFrame(stateNode *state,
670
681
  return RULES_OK;
671
682
  }
672
683
 
673
- unsigned int deleteMessage(stateNode *state,
684
+ unsigned int deleteMessage(void *tree,
685
+ stateNode *state,
686
+ char *mid,
674
687
  unsigned int messageNodeOffset) {
675
-
676
688
  messageNode *node = MESSAGE_NODE(state, messageNodeOffset);
689
+ ruleset *rulesetTree = (ruleset*)tree;
690
+ if (rulesetTree->deleteMessageCallback) {
691
+ CHECK_RESULT(rulesetTree->deleteMessageCallback(rulesetTree->deleteMessageCallbackContext,
692
+ &rulesetTree->stringPool[rulesetTree->nameOffset],
693
+ state->sid,
694
+ mid));
695
+ }
696
+
677
697
  if (node->jo.content) {
678
698
  free(node->jo.content);
679
699
  free(node->locationPool.content);
@@ -686,6 +706,7 @@ unsigned int deleteMessage(stateNode *state,
686
706
  MAX_MESSAGE_INDEX_LENGTH,
687
707
  state->messagePool,
688
708
  messageNodeOffset);
709
+
689
710
  return RULES_OK;
690
711
  }
691
712
 
@@ -724,7 +745,8 @@ static unsigned int copyMessage(jsonObject *targetMessage,
724
745
  return RULES_OK;
725
746
  }
726
747
 
727
- unsigned int storeMessage(stateNode *state,
748
+ unsigned int storeMessage(void *tree,
749
+ stateNode *state,
728
750
  char *mid,
729
751
  jsonObject *message,
730
752
  unsigned char messageType,
@@ -762,13 +784,29 @@ unsigned int storeMessage(stateNode *state,
762
784
  memset(node->locationIndex, 0, MAX_LOCATION_INDEX_LENGTH * sizeof(unsigned int) * 2);
763
785
 
764
786
  node->messageType = messageType;
765
- return copyMessage(&node->jo, message);
787
+ CHECK_RESULT(copyMessage(&node->jo, message));
788
+
789
+ ruleset *rulesetTree = (ruleset*)tree;
790
+ if (rulesetTree->storeMessageCallback) {
791
+ unsigned char actionType = ACTION_ASSERT_FACT;
792
+ if (messageType == MESSAGE_TYPE_EVENT) {
793
+ actionType = ACTION_ASSERT_EVENT;
794
+ }
795
+
796
+ return rulesetTree->storeMessageCallback(rulesetTree->storeMessageCallbackContext,
797
+ &rulesetTree->stringPool[rulesetTree->nameOffset],
798
+ state->sid,
799
+ mid,
800
+ actionType,
801
+ message->content);
802
+ }
803
+
804
+ return RULES_OK;
766
805
  }
767
806
 
768
- unsigned int ensureStateNode(void *tree,
769
- char *sid,
770
- unsigned char *isNew,
771
- stateNode **state) {
807
+ unsigned int getStateNode(void *tree,
808
+ char *sid,
809
+ stateNode **state) {
772
810
  unsigned int sidHash = fnv1Hash32(sid, strlen(sid));
773
811
  unsigned int nodeOffset;
774
812
  ruleset *rulesetTree = (ruleset*)tree;
@@ -779,102 +817,144 @@ unsigned int ensureStateNode(void *tree,
779
817
  ((ruleset*)tree)->statePool,
780
818
  sidHash,
781
819
  nodeOffset);
820
+ if (nodeOffset == UNDEFINED_HASH_OFFSET) {
821
+ return ERR_SID_NOT_FOUND;
822
+ }
782
823
 
783
- if (nodeOffset != UNDEFINED_HASH_OFFSET) {
784
- *isNew = 0;
785
- *state = STATE_NODE(tree, nodeOffset);
786
- } else {
787
- *isNew = 1;
788
- NEW(stateNode,
789
- rulesetTree->statePool,
790
- nodeOffset);
791
-
792
- SET(stateNode,
793
- rulesetTree->stateIndex,
794
- MAX_STATE_INDEX_LENGTH,
795
- rulesetTree->statePool,
796
- sidHash,
797
- nodeOffset);
798
-
799
- if (rulesetTree->statePool.count > MAX_STATE_INDEX_LENGTH) {
800
- return ERR_OUT_OF_MEMORY;
801
- }
802
- rulesetTree->reverseStateIndex[rulesetTree->statePool.count - 1] = nodeOffset;
803
- stateNode *node = STATE_NODE(tree, nodeOffset);
804
- node->offset = nodeOffset;
824
+ *state = STATE_NODE(tree, nodeOffset);
825
+ return RULES_OK;
826
+ }
805
827
 
806
- int sidLength = sizeof(char) * (strlen(sid) + 1);
807
- node->sid = malloc(sidLength);
808
- if (!node->sid) {
809
- return ERR_OUT_OF_MEMORY;
810
- }
811
- memcpy(node->sid, sid, sidLength);
828
+ unsigned int createStateNode(void *tree,
829
+ char *sid,
830
+ stateNode **state) {
831
+ unsigned int sidHash = fnv1Hash32(sid, strlen(sid));
832
+ unsigned int nodeOffset;
833
+ ruleset *rulesetTree = (ruleset*)tree;
834
+
835
+ NEW(stateNode,
836
+ rulesetTree->statePool,
837
+ nodeOffset);
812
838
 
813
- INIT(messageNode,
814
- node->messagePool,
815
- MAX_MESSAGE_NODES);
839
+ SET(stateNode,
840
+ rulesetTree->stateIndex,
841
+ MAX_STATE_INDEX_LENGTH,
842
+ rulesetTree->statePool,
843
+ sidHash,
844
+ nodeOffset);
816
845
 
817
- memset(node->messageIndex, 0, MAX_MESSAGE_INDEX_LENGTH * sizeof(unsigned int) * 2);
846
+ if (rulesetTree->statePool.count > MAX_STATE_INDEX_LENGTH) {
847
+ return ERR_OUT_OF_MEMORY;
848
+ }
849
+ rulesetTree->reverseStateIndex[rulesetTree->statePool.count - 1] = nodeOffset;
850
+ stateNode *node = STATE_NODE(tree, nodeOffset);
851
+ node->offset = nodeOffset;
852
+
853
+ int sidLength = sizeof(char) * (strlen(sid) + 1);
854
+ node->sid = malloc(sidLength);
855
+ if (!node->sid) {
856
+ return ERR_OUT_OF_MEMORY;
857
+ }
858
+ memcpy(node->sid, sid, sidLength);
859
+
860
+ INIT(messageNode,
861
+ node->messagePool,
862
+ MAX_MESSAGE_NODES);
863
+
864
+ memset(node->messageIndex, 0, MAX_MESSAGE_INDEX_LENGTH * sizeof(unsigned int) * 2);
865
+
866
+ node->betaState = malloc(((ruleset*)tree)->betaCount * sizeof(betaStateNode));
867
+ for (unsigned int i = 0; i < ((ruleset*)tree)->betaCount; ++i) {
868
+ betaStateNode *betaNode = &node->betaState[i];
869
+ betaNode->reteNode = NULL;
870
+
871
+ INIT(leftFrameNode,
872
+ betaNode->leftFramePool,
873
+ MAX_LEFT_FRAME_NODES);
874
+
875
+ memset(betaNode->leftFrameIndex, 0, MAX_LEFT_FRAME_INDEX_LENGTH * sizeof(unsigned int) * 2);
818
876
 
819
- node->betaState = malloc(((ruleset*)tree)->betaCount * sizeof(betaStateNode));
820
- for (unsigned int i = 0; i < ((ruleset*)tree)->betaCount; ++i) {
821
- betaStateNode *betaNode = &node->betaState[i];
822
- betaNode->reteNode = NULL;
823
-
824
- INIT(leftFrameNode,
825
- betaNode->leftFramePool,
826
- MAX_LEFT_FRAME_NODES);
827
-
828
- memset(betaNode->leftFrameIndex, 0, MAX_LEFT_FRAME_INDEX_LENGTH * sizeof(unsigned int) * 2);
829
-
830
- INIT(rightFrameNode,
831
- betaNode->rightFramePool,
832
- MAX_RIGHT_FRAME_NODES);
833
-
834
- memset(betaNode->rightFrameIndex, 0, MAX_RIGHT_FRAME_INDEX_LENGTH * sizeof(unsigned int) * 2);
835
- }
877
+ INIT(rightFrameNode,
878
+ betaNode->rightFramePool,
879
+ MAX_RIGHT_FRAME_NODES);
836
880
 
837
- node->connectorState = malloc(((ruleset*)tree)->connectorCount * sizeof(connectorStateNode));
838
- for (unsigned int i = 0; i < ((ruleset*)tree)->connectorCount; ++i) {
839
- connectorStateNode *connectorNode = &node->connectorState[i];
840
- connectorNode->reteNode = NULL;
881
+ memset(betaNode->rightFrameIndex, 0, MAX_RIGHT_FRAME_INDEX_LENGTH * sizeof(unsigned int) * 2);
882
+ }
841
883
 
842
- INIT(leftFrameNode,
843
- connectorNode->aFramePool,
844
- MAX_LEFT_FRAME_NODES);
845
-
846
- connectorNode->aFrameIndex[0] = UNDEFINED_HASH_OFFSET;
847
- connectorNode->aFrameIndex[1] = UNDEFINED_HASH_OFFSET;
884
+ node->connectorState = malloc(((ruleset*)tree)->connectorCount * sizeof(connectorStateNode));
885
+ for (unsigned int i = 0; i < ((ruleset*)tree)->connectorCount; ++i) {
886
+ connectorStateNode *connectorNode = &node->connectorState[i];
887
+ connectorNode->reteNode = NULL;
848
888
 
849
- INIT(leftFrameNode,
850
- connectorNode->bFramePool,
851
- MAX_LEFT_FRAME_NODES);
889
+ INIT(leftFrameNode,
890
+ connectorNode->aFramePool,
891
+ MAX_LEFT_FRAME_NODES);
852
892
 
853
- connectorNode->bFrameIndex[0] = UNDEFINED_HASH_OFFSET;
854
- connectorNode->bFrameIndex[1] = UNDEFINED_HASH_OFFSET;
855
- }
893
+ connectorNode->aFrameIndex[0] = UNDEFINED_HASH_OFFSET;
894
+ connectorNode->aFrameIndex[1] = UNDEFINED_HASH_OFFSET;
895
+
896
+ INIT(leftFrameNode,
897
+ connectorNode->bFramePool,
898
+ MAX_LEFT_FRAME_NODES);
856
899
 
857
- node->actionState = malloc(((ruleset*)tree)->actionCount * sizeof(actionStateNode));
858
- for (unsigned int i = 0; i < ((ruleset*)tree)->actionCount; ++i) {
859
- actionStateNode *actionNode = &node->actionState[i];
860
- actionNode->reteNode = NULL;
861
-
862
- actionNode->resultIndex[0] = UNDEFINED_HASH_OFFSET;
863
- actionNode->resultIndex[1] = UNDEFINED_HASH_OFFSET;
864
-
865
- INIT(leftFrameNode,
866
- actionNode->resultPool,
867
- MAX_LEFT_FRAME_NODES);
868
- }
869
-
870
- node->factOffset = UNDEFINED_HASH_OFFSET;
871
- node->lockExpireTime = 0;
872
- *state = node;
900
+ connectorNode->bFrameIndex[0] = UNDEFINED_HASH_OFFSET;
901
+ connectorNode->bFrameIndex[1] = UNDEFINED_HASH_OFFSET;
873
902
  }
903
+
904
+ node->actionState = malloc(((ruleset*)tree)->actionCount * sizeof(actionStateNode));
905
+ for (unsigned int i = 0; i < ((ruleset*)tree)->actionCount; ++i) {
906
+ actionStateNode *actionNode = &node->actionState[i];
907
+ actionNode->reteNode = NULL;
908
+
909
+ actionNode->resultIndex[0] = UNDEFINED_HASH_OFFSET;
910
+ actionNode->resultIndex[1] = UNDEFINED_HASH_OFFSET;
911
+
912
+ INIT(leftFrameNode,
913
+ actionNode->resultPool,
914
+ MAX_LEFT_FRAME_NODES);
915
+ }
916
+
917
+ node->factOffset = UNDEFINED_HASH_OFFSET;
918
+ node->lockExpireTime = 0;
919
+ *state = node;
874
920
 
875
921
  return RULES_OK;
876
922
  }
877
923
 
924
+ unsigned int deleteStateNode(void *tree,
925
+ stateNode *node) {
926
+ ruleset *rulesetTree = (ruleset*)tree;
927
+ free(node->sid);
928
+
929
+ for (unsigned int i = 0; i < rulesetTree->betaCount; ++i) {
930
+ betaStateNode *betaNode = &node->betaState[i];
931
+ free(betaNode->leftFramePool.content);
932
+ free(betaNode->rightFramePool.content);
933
+ }
934
+ free(node->betaState);
935
+
936
+ for (unsigned int i = 0; i < rulesetTree->connectorCount; ++i) {
937
+ connectorStateNode *connectorNode = &node->connectorState[i];
938
+ free(connectorNode->aFramePool.content);
939
+ free(connectorNode->bFramePool.content);
940
+ }
941
+ free(node->connectorState);
942
+
943
+ for (unsigned int i = 0; i < rulesetTree->actionCount; ++i) {
944
+ actionStateNode *actionNode = &node->actionState[i];
945
+ free(actionNode->resultPool.content);
946
+ }
947
+ free(node->actionState);
948
+
949
+ DELETE(stateNode,
950
+ rulesetTree->stateIndex,
951
+ MAX_STATE_INDEX_LENGTH,
952
+ rulesetTree->statePool,
953
+ node->offset);
954
+
955
+ return RULES_OK;
956
+ }
957
+
878
958
  static unsigned int getResultFrameLength(ruleset *tree,
879
959
  stateNode *state,
880
960
  leftFrameNode *frame) {
@@ -1466,6 +1546,8 @@ unsigned int getState(unsigned int handle, char *sid, char **state) {
1466
1546
  return serializeState(node, state);
1467
1547
  }
1468
1548
 
1549
+
1550
+
1469
1551
  unsigned int deleteState(unsigned int handle, char *sid) {
1470
1552
  ruleset *tree;
1471
1553
  RESOLVE_HANDLE(handle, &tree);
@@ -1488,33 +1570,5 @@ unsigned int deleteState(unsigned int handle, char *sid) {
1488
1570
  }
1489
1571
 
1490
1572
  stateNode *node = STATE_NODE(tree, nodeOffset);
1491
- free(node->sid);
1492
-
1493
- for (unsigned int i = 0; i < ((ruleset*)tree)->betaCount; ++i) {
1494
- betaStateNode *betaNode = &node->betaState[i];
1495
- free(betaNode->leftFramePool.content);
1496
- free(betaNode->rightFramePool.content);
1497
- }
1498
- free(node->betaState);
1499
-
1500
- for (unsigned int i = 0; i < ((ruleset*)tree)->connectorCount; ++i) {
1501
- connectorStateNode *connectorNode = &node->connectorState[i];
1502
- free(connectorNode->aFramePool.content);
1503
- free(connectorNode->bFramePool.content);
1504
- }
1505
- free(node->connectorState);
1506
-
1507
- for (unsigned int i = 0; i < ((ruleset*)tree)->actionCount; ++i) {
1508
- actionStateNode *actionNode = &node->actionState[i];
1509
- free(actionNode->resultPool.content);
1510
- }
1511
- free(node->actionState);
1512
-
1513
- DELETE(stateNode,
1514
- tree->stateIndex,
1515
- MAX_STATE_INDEX_LENGTH,
1516
- tree->statePool,
1517
- nodeOffset);
1518
-
1519
- return RULES_OK;
1573
+ return deleteStateNode(tree, node);
1520
1574
  }
data/src/rules/state.h CHANGED
@@ -10,6 +10,11 @@
10
10
  #define MESSAGE_TYPE_EVENT 0
11
11
  #define MESSAGE_TYPE_FACT 1
12
12
 
13
+ #define ACTION_ASSERT_FACT 1
14
+ #define ACTION_ASSERT_EVENT 2
15
+ #define ACTION_RETRACT_FACT 3
16
+ #define ACTION_UPDATE_STATE 4
17
+
13
18
  #define UNDEFINED_HASH_OFFSET 0
14
19
  #define MAX_OBJECT_PROPERTIES 32
15
20
  #define MAX_MESSAGE_FRAMES 16
@@ -307,24 +312,33 @@ unsigned int createActionFrame(stateNode *state,
307
312
  leftFrameNode **newNode,
308
313
  frameLocation *newLocation);
309
314
 
310
- unsigned int deleteMessage(stateNode *state,
315
+ unsigned int deleteMessage(void *tree,
316
+ stateNode *state,
317
+ char *mid,
311
318
  unsigned int messageNodeOffset);
312
319
 
313
320
  unsigned int getMessage(stateNode *state,
314
321
  char *mid,
315
322
  unsigned int *valueOffset);
316
323
 
317
- unsigned int storeMessage(stateNode *state,
324
+ unsigned int storeMessage(void *tree,
325
+ stateNode *state,
318
326
  char *mid,
319
327
  jsonObject *message,
320
328
  unsigned char messageType,
321
329
  unsigned int *valueOffset);
322
330
 
323
- unsigned int ensureStateNode(void *tree,
331
+ unsigned int getStateNode(void *tree,
332
+ char *sid,
333
+ stateNode **state);
334
+
335
+ unsigned int createStateNode(void *tree,
324
336
  char *sid,
325
- unsigned char *isNew,
326
337
  stateNode **state);
327
338
 
339
+ unsigned int deleteStateNode(void *tree,
340
+ stateNode *state);
341
+
328
342
  unsigned int serializeResult(void *tree,
329
343
  stateNode *state,
330
344
  actionStateNode *actionNode,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: durable_rules
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.5
4
+ version: 2.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesus Ruiz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-21 00:00:00.000000000 Z
11
+ date: 2019-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake