CMSDK  2.0.1
Subscriptions.h
1 #if !defined(_SUBSCRIPTIONS_H_)
2 #define _SUBSCRIPTIONS_H_
3 
4 #include "PsyTime.h"
5 #include "Utils.h"
6 #include "HTML.h"
7 #include "ObjectIDs.h"
8 #include "xml_parser.h"
9 #include "DataMessage.h"
10 
11 // Component types
12 #define COMP_WHITEBOARD 1
13 #define COMP_CATALOG 2
14 #define COMP_STREAM 3
15 #define COMP_FEED 4
16 #define COMP_SERVICE 5
17 #define COMP_MODULE 6
18 #define COMP_INTERNAL 6
19 #define COMP_EXTERNAL 7
20 
21 // Migration types
22 #define COMP_MIGRATE_NO 0
23 #define COMP_MIGRATE_ALLOW 1
24 
25 
26 namespace cmlabs {
27 
28 #define TRIGGERFILTER_HASKEY 1
29 #define TRIGGERFILTER_EQUALS 2
30 #define TRIGGERFILTER_NOTEQUALS 3
31 #define TRIGGERFILTER_EQUALSNUMERIC 4
32 #define TRIGGERFILTER_NOTEQUALSNUMERIC 5
33 #define TRIGGERFILTER_GREATERTHAN 6
34 #define TRIGGERFILTER_LESSTHAN 7
35 #define TRIGGERFILTER_MAXAGE 8
36 
37 #define INDEX_TIME 1
38 #define INDEX_STRING 2
39 #define INDEX_INTEGER 3
40 #define INDEX_FLOAT 4
41 
42 struct FilterSpec {
43  uint8 filter;
44  uint64 time;
45  char key[MAXKEYNAMELEN+1];
46  char value[MAXVALUENAMELEN+1];
47  std::string toXML() {
48  return utils::StringFormat("\t<filter filter=\"%u\" time=\"%llu\" key=\"%s\" value=\"%s\" />\n",
49  filter, time, key, value);
50  }
51  bool fromXML(const char* xml) {
52  if (!xml) return false;
53  XMLResults xmlResults;
54  XMLNode node = XMLNode::parseString(xml, "filter", &xmlResults);
55  if (xmlResults.error != eXMLErrorNone)
56  return false;
57  if (node.isEmpty()) return false;
58  return fromXML(node);
59  }
60  bool fromXML(XMLNode &node) {
61  const char* str;
62  if (str = node.getAttribute("filter")) filter = (uint8)utils::Ascii2Uint32(str); else return false;
63  if (str = node.getAttribute("time")) time = utils::Ascii2Uint64(str); else return false;
64  if (str = node.getAttribute("key")) utils::strcpyavail(key, str, MAXKEYNAMELEN, true); else return false;
65  if (str = node.getAttribute("value")) utils::strcpyavail(value, str, MAXVALUENAMELEN, true); else return false;
66  return true;
67  }
68 };
69 
70 struct QuerySpec {
71  uint32 source;
72  uint32 origin;
73  uint64 maxage;
74  uint32 maxcount;
75  PsyContext context;
76  bool binary;
77  uint32 ipHost;
78  uint16 ipPort;
79  char sourceName[MAXKEYNAMELEN+1];
80  char hostName[MAXKEYNAMELEN + 1];
81  char name[MAXKEYNAMELEN+1];
82  char key[MAXKEYNAMELEN+1];
83  char value[MAXVALUENAMELEN+1];
84  char type[MAXKEYNAMELEN+1];
85  char subdir[MAXKEYNAMELEN+1];
86  char ext[MAXKEYNAMELEN+1];
87  char operation[MAXKEYNAMELEN+1];
88  std::string toXML() {
89  return utils::StringFormat("\t<query source=\"%u\" origin=\"%u\" maxage=\"%llu\" maxcount=\"%u\" binary=\"%s\" name=\"%s\" key=\"%s\" value=\"%s\" type=\"%s\" subdir=\"%s\" ext=\"%s\" operation=\"%s\" sourcename=\"%s\" hostname=\"%s\" iphost=\"%u\" port=\"%u\" />\n",
90  source, origin, maxage, maxcount, (binary ? "yes" : "no"), name, key, value, type, subdir, ext, operation,
91  sourceName, hostName, ipHost, ipPort);
92  }
93  bool fromXML(const char* xml) {
94  if (!xml) return false;
95  XMLResults xmlResults;
96  XMLNode node = XMLNode::parseString(xml, "query", &xmlResults);
97  if (xmlResults.error != eXMLErrorNone)
98  return false;
99  if (node.isEmpty()) return false;
100  return fromXML(node);
101  }
102  bool fromXML(XMLNode &node) {
103  const char* str;
104  if (str = node.getAttribute("source")) source = utils::Ascii2Uint32(str); else return false;
105  if (str = node.getAttribute("origin")) origin = utils::Ascii2Uint32(str); else return false;
106  if (str = node.getAttribute("maxage")) maxage = utils::Ascii2Uint64(str); else return false;
107  if (str = node.getAttribute("maxcount")) maxcount = utils::Ascii2Uint32(str); else return false;
108  if (str = node.getAttribute("context")) { if (!context.fromString(str)) return false; } else return false;
109  if (str = node.getAttribute("binary")) binary = (stricmp(str, "yes") == 0); else return false;
110  if (str = node.getAttribute("name")) utils::strcpyavail(name, str, MAXKEYNAMELEN, true); else return false;
111  if (str = node.getAttribute("key")) utils::strcpyavail(key, str, MAXKEYNAMELEN, true); else return false;
112  if (str = node.getAttribute("value")) utils::strcpyavail(value, str, MAXVALUENAMELEN, true); else return false;
113  if (str = node.getAttribute("type")) utils::strcpyavail(type, str, MAXKEYNAMELEN, true); else return false;
114  if (str = node.getAttribute("subdir")) utils::strcpyavail(subdir, str, MAXKEYNAMELEN, true); else return false;
115  if (str = node.getAttribute("ext")) utils::strcpyavail(ext, str, MAXKEYNAMELEN, true); else return false;
116  if (str = node.getAttribute("operation")) utils::strcpyavail(operation, str, MAXKEYNAMELEN, true); else return false;
117  if (str = node.getAttribute("sourcename")) utils::strcpyavail(sourceName, str, MAXKEYNAMELEN, true); else return false;
118  if (str = node.getAttribute("hostname")) utils::strcpyavail(hostName, str, MAXKEYNAMELEN, true); else return false;
119  if (str = node.getAttribute("iphost")) ipHost = utils::Ascii2Uint32(str); else return false;
120  if (str = node.getAttribute("ipport")) ipPort = utils::Ascii2Uint32(str); else return false;
121  return true;
122  }
123 };
124 
125 struct RetrieveSpec {
126  uint32 source;
127  uint32 origin;
128  uint64 maxage;
129  uint32 maxcount;
130  PsyType type;
131  PsyContext context;
132  uint32 tag;
133  char name[MAXKEYNAMELEN+1];
134  char key[MAXKEYNAMELEN+1];
135  uint8 keytype;
136  uint32 from;
137  uint32 to;
138  uint64 startTime;
139  uint64 endTime;
140  int64 startInt;
141  int64 endInt;
142  float64 startFloat;
143  float64 endFloat;
144  char startString[MAXVALUENAMELEN+1];
145  char endString[MAXVALUENAMELEN+1];
146  std::string toXML() {
147  return utils::StringFormat("\t<retrieve source=\"%u\" origin=\"%u\" maxage=\"%llu\" maxcount=\"%u\" type=\"%s\" context=\"%s\" tag=\"%u\" name=\"%s\" key=\"%s\" keytype=\"%u\" from=\"%u\" to=\"%u\" starttime=\"%llu\" endtime=\"%llu\" startint=\"%lld\" endint=\"%lld\" startfloat=\"%f\" endfloat=\"%f\" startstring=\"%s\" endstring=\"%s\" />\n",
148  source, origin, maxage, maxcount, type.toString().c_str(), context.toString().c_str(),
149  tag, name, key, keytype, from, to,
150  startTime, endTime, startInt, endInt, startFloat, endFloat, startString, endString);
151  }
152  bool fromXML(const char* xml) {
153  if (!xml) return false;
154  XMLResults xmlResults;
155  XMLNode node = XMLNode::parseString(xml, "retrieve", &xmlResults);
156  if (xmlResults.error != eXMLErrorNone)
157  return false;
158  if (node.isEmpty()) return false;
159  return fromXML(node);
160  }
161  bool fromXML(XMLNode &node) {
162  const char* str;
163  if (str = node.getAttribute("source")) source = utils::Ascii2Uint32(str); else return false;
164  if (str = node.getAttribute("origin")) origin = utils::Ascii2Uint32(str); else return false;
165  if (str = node.getAttribute("maxage")) maxage = utils::Ascii2Uint64(str); else return false;
166  if (str = node.getAttribute("maxcount")) maxcount = utils::Ascii2Uint32(str); else return false;
167  if (str = node.getAttribute("type")) { if (!type.fromString(str)) return false; } else return false;
168  if (str = node.getAttribute("context")) { if (!context.fromString(str)) return false; } else return false;
169  if (str = node.getAttribute("tag")) tag = utils::Ascii2Uint32(str); else return false;
170  if (str = node.getAttribute("name")) utils::strcpyavail(name, str, MAXKEYNAMELEN, true); else return false;
171  if (str = node.getAttribute("key")) utils::strcpyavail(key, str, MAXKEYNAMELEN, true); else return false;
172  if (str = node.getAttribute("keytype")) keytype = (uint8)utils::Ascii2Uint32(str); else return false;
173  if (str = node.getAttribute("from")) from = utils::Ascii2Uint32(str); else return false;
174  if (str = node.getAttribute("to")) to = utils::Ascii2Uint32(str); else return false;
175  if (str = node.getAttribute("starttime")) startTime = utils::Ascii2Uint64(str); else return false;
176  if (str = node.getAttribute("endtime")) endTime = utils::Ascii2Uint64(str); else return false;
177  if (str = node.getAttribute("startint")) startInt = utils::Ascii2Int64(str); else return false;
178  if (str = node.getAttribute("endint")) endInt = utils::Ascii2Int64(str); else return false;
179  if (str = node.getAttribute("startfloat")) startFloat = utils::Ascii2Float64(str); else return false;
180  if (str = node.getAttribute("endfloat")) endFloat = utils::Ascii2Float64(str); else return false;
181  if (str = node.getAttribute("startstring")) utils::strcpyavail(startString, str, MAXVALUENAMELEN, true); else return false;
182  if (str = node.getAttribute("endstring")) utils::strcpyavail(endString, str, MAXVALUENAMELEN, true); else return false;
183  return true;
184  }
185 };
186 
187 #define MESSAGE_NON_GUARANTEED 1
188 
189 struct PostSpec {
190  uint32 to;
191  PsyType type;
192  PsyContext context;
193  PsyContext contextchange;
194  uint32 tag;
195  uint64 ttl;
196  uint8 policy;
197  uint32 contentCount;
198  char name[MAXKEYNAMELEN+1];
199 // char contentKey[MAXKEYNAMELEN + 1];
200  char content[MAXCONTENTLEN + 1];
201  std::string toXML() {
202  if (contentCount) {
203  // ||S||key||val||I||key||val||S||key||val
204  const char* contentType, *key, *value;
205  std::string strContent;
206  std::vector<std::string> entries = utils::TextListSplit(content, "||", false, true);
207  uint32 slotCount = 3 * contentCount;
208  uint32 n = 0;
209  if (entries.size() == slotCount) {
210  while (n < slotCount) {
211  contentType = entries[n++].c_str();
212  key = entries[n++].c_str();
213  value = entries[n++].c_str();
214  if (strcmp(contentType, "S") == 0) {
215  strContent += utils::StringFormat("\t\t<content type=\"string\" key=\"%s\" value=\"%s\" />\n",
216  html::EncodeHTML(key).c_str(), html::EncodeHTML(value).c_str());
217  }
218  else if (strcmp(contentType, "I") == 0) {
219  strContent += utils::StringFormat("\t\t<content type=\"integer\" key=\"%s\" value=\"%s\" />\n",
220  html::EncodeHTML(key).c_str(), html::EncodeHTML(value).c_str());
221  }
222  else if (strcmp(contentType, "F") == 0) {
223  strContent += utils::StringFormat("\t\t<content type=\"float\" key=\"%s\" value=\"%s\" />\n",
224  html::EncodeHTML(key).c_str(), html::EncodeHTML(value).c_str());
225  }
226  }
227  }
228  return utils::StringFormat("\t<post to=\"%u\" type=\"%s\" context=\"%s\" contextchange=\"%s\" tag=\"%u\" ttl=\"%llu\" policy=\"%u\" name=\"%s\">\n%s</post>\n",
229  to, type.toString().c_str(), context.toString().c_str(), contextchange.toString().c_str(), tag, ttl, policy, name, strContent.c_str());
230  }
231  else {
232  return utils::StringFormat("\t<post to=\"%u\" type=\"%s\" context=\"%s\" contextchange=\"%s\" tag=\"%u\" ttl=\"%llu\" policy=\"%u\" name=\"%s\" />\n",
233  to, type.toString().c_str(), context.toString().c_str(), contextchange.toString().c_str(), tag, ttl, policy, name);
234  }
235  }
236  bool fromXML(const char* xml) {
237  if (!xml) return false;
238  XMLResults xmlResults;
239  XMLNode node = XMLNode::parseString(xml, "post", &xmlResults);
240  if (xmlResults.error != eXMLErrorNone)
241  return false;
242  if (node.isEmpty()) return false;
243  return fromXML(node);
244  }
245  bool fromXML(XMLNode &node) {
246  const char* str;
247  if (str = node.getAttribute("to")) to = utils::Ascii2Uint32(str); else return false;
248  if (str = node.getAttribute("type")) { if (!type.fromString(str)) return false; }
249  else return false;
250  if (str = node.getAttribute("context")) { if (!context.fromString(str)) return false; }
251  else return false;
252  if (str = node.getAttribute("contextchange")) { if (!contextchange.fromString(str)) return false; }
253  else return false;
254  if (str = node.getAttribute("tag")) tag = utils::Ascii2Uint32(str); else return false;
255  if (str = node.getAttribute("ttl")) ttl = utils::Ascii2Uint64(str); else return false;
256  if (str = node.getAttribute("policy")) policy = (uint8)utils::Ascii2Uint32(str); else return false;
257  if (str = node.getAttribute("name")) utils::strcpyavail(name, str, MAXKEYNAMELEN, true); else return false;
258  contentFromXML(node);
259  return true;
260  }
261  bool contentFromXML(XMLNode &node) {
262  std::string strContent;
263  const char* str, *key, *value;
264  if ((key = node.getAttribute("contentkey")) && (value = node.getAttribute("content"))) {
265  strContent = utils::StringFormat("%s||S||%s||%s", content, html::DecodeHTML(key).c_str(), html::DecodeHTML(value).c_str());
266  utils::strcpyavail(content, strContent.c_str(), MAXCONTENTLEN, false);
267  contentCount++;
268  }
269 
270  XMLNode subNode;
271  uint32 i, count = node.nChildNode("content");
272  for (i = 0; i < count; i++) {
273  if (!(subNode = node.getChildNode("content", i)).isEmpty()) {
274  if (!(key = subNode.getAttribute("key")) || !strlen(key))
275  continue;
276  if ( (!(value = subNode.getAttribute("content")) || !strlen(value)) &&
277  (!(value = subNode.getAttribute("value")) || !strlen(value)) )
278  continue;
279  str = subNode.getAttribute("type");
280  if (str && stricmp(str, "integer") == 0)
281  strContent = utils::StringFormat("%s||I||%s||%s", content, html::DecodeHTML(key).c_str(), html::DecodeHTML(value).c_str());
282  else if (str && ((stricmp(str, "double") == 0) || (stricmp(str, "float") == 0)))
283  strContent = utils::StringFormat("%s||F||%s||%s", content, html::DecodeHTML(key).c_str(), html::DecodeHTML(value).c_str());
284  else
285  strContent = utils::StringFormat("%s||S||%s||%s", content, html::DecodeHTML(key).c_str(), html::DecodeHTML(value).c_str());
286  utils::strcpyavail(content, strContent.c_str(), MAXCONTENTLEN, false);
287  contentCount++;
288  }
289  }
290  return true;
291  }
292  uint32 addContentToMsg(DataMessage* msg) {
293  if (!contentCount)
294  return 0;
295  uint32 count = 0;
296  const char* contentType, *key, *value;
297  std::string strContent;
298  std::vector<std::string> entries = utils::TextListSplit(content, "||", false, true);
299  uint32 slotCount = 3 * contentCount, n = 0;
300  if (entries.size() == slotCount) {
301  while (n < slotCount) {
302  contentType = entries[n++].c_str();
303  key = entries[n++].c_str();
304  value = entries[n++].c_str();
305  if (strcmp(contentType, "S") == 0)
306  msg->setString(key, value);
307  else if (strcmp(contentType, "I") == 0)
308  msg->setInt(key, utils::Ascii2Int64(value));
309  else if (strcmp(contentType, "F") == 0)
310  msg->setFloat(key, utils::Ascii2Float64(value));
311  count++;
312  }
313  }
314  return count;
315  }
316 };
317 
318 struct SignalSpec {
319  PsyType type;
320  char name[MAXKEYNAMELEN+1];
321  std::string toXML() {
322  return utils::StringFormat("\t<signal type=\"%s\" name=\"%s\" />\n", type.toString().c_str(), name);
323  }
324  bool fromXML(const char* xml) {
325  if (!xml) return false;
326  XMLResults xmlResults;
327  XMLNode node = XMLNode::parseString(xml, "signal", &xmlResults);
328  if (xmlResults.error != eXMLErrorNone)
329  return false;
330  if (node.isEmpty()) return false;
331  return fromXML(node);
332  }
333  bool fromXML(XMLNode &node) {
334  const char* str;
335  if (str = node.getAttribute("type")) { if (!type.fromString(str)) return false; } else return false;
336  if (str = node.getAttribute("name")) utils::strcpyavail(name, str, MAXKEYNAMELEN, true); else return false;
337  return true;
338  }
339 };
340 
341 struct TriggerSpec {
342  bool reset(uint32 s = 0) {
343  memset(this, 0, sizeof(TriggerSpec));
344  size = (s) ? s : sizeof(TriggerSpec);
345  cid = TRIGGERDATA;
346  return true;
347  }
348  FilterSpec* getFilterSpec(uint32 n) {
349  if (n >= filterCount) return NULL;
350  return (FilterSpec*)
351  (((char*)this) + sizeof(TriggerSpec) + (n*sizeof(FilterSpec)));
352  }
353  RetrieveSpec* getRetrieveSpec(uint32 n) {
354  if (n >= retrieveCount) return NULL;
355  return (RetrieveSpec*)
356  (((char*)this) + sizeof(TriggerSpec) + (filterCount*sizeof(FilterSpec)) + (n*sizeof(RetrieveSpec)));
357  }
358  RetrieveSpec* getRetrieveSpec(const char* name);
359  QuerySpec* getQuerySpec(uint32 n) {
360  if (n >= queryCount) return NULL;
361  return (QuerySpec*)
362  (((char*)this) + sizeof(TriggerSpec) + (filterCount*sizeof(FilterSpec)) +
363  (retrieveCount*sizeof(RetrieveSpec)) + (n*sizeof(QuerySpec)));
364  }
365  QuerySpec* getQuerySpec(const char* name);
366  std::list<PostSpec*>* getPostSpecs(const char* name);
367  std::list<PostSpec*>* getPostSpecs(PsyType type);
368  PostSpec* getPostSpec(const char* name);
369  PostSpec* getPostSpec(PsyType type);
370  PostSpec* getPostSpec(uint32 n) {
371  if (n >= postCount) return NULL;
372  return (PostSpec*)
373  (((char*)this) + sizeof(TriggerSpec) + (filterCount*sizeof(FilterSpec)) +
374  (retrieveCount*sizeof(RetrieveSpec)) + (queryCount*sizeof(QuerySpec)) +
375  (n * sizeof(PostSpec)));
376  }
377  SignalSpec* getSignalSpec(const char* name);
378  SignalSpec* getSignalSpec(PsyType type);
379  SignalSpec* getSignalSpec(uint32 n) {
380  if (n >= signalCount) return NULL;
381  return (SignalSpec*)
382  (((char*)this) + sizeof(TriggerSpec) + (filterCount*sizeof(FilterSpec)) +
383  (retrieveCount*sizeof(RetrieveSpec)) + (queryCount*sizeof(QuerySpec)) +
384  (postCount*sizeof(PostSpec)) + (n * sizeof(SignalSpec)));
385  }
386  std::string toXML();
387 
388  uint32 size;
389  uint32 cid;
390  uint32 id;
391  uint32 componentID;
392  uint32 interval;
393  uint32 from;
394  uint32 to;
395  uint32 tag;
396  uint32 delay;
397  uint8 grouppolicy;
398  uint32 groupparam;
399  uint16 crankID;
400  uint32 group;
401  PsyType type;
402  PsyContext context;
403  PsyContext triggerContext;
404  char name[MAXKEYNAMELEN+1];
405  uint16 filterCount;
406  uint16 retrieveCount;
407  uint16 queryCount;
408  uint16 postCount;
409  uint16 signalCount;
410  // l x FilterSpec
411  // n x RetrieveSpec
412  // m x PostSpec
413 };
414 
416  bool reset() {
417  memset(this, 0, sizeof(ComponentSetup));
418  size = sizeof(ComponentSetup);
419  cid = COMPONENTSETUPDATA;
420  return true;
421  }
422  uint32 size;
423  uint32 cid;
424  uint32 componentID;
425  uint16 spaceID;
426  uint32 tag;
427  uint8 type;
428  char name[MAXKEYNAMELEN+1];
429  char logfile[MAXKEYNAMELEN+1];
430  uint8 verbose;
431  uint8 debug;
432  uint8 migration;
433  uint8 priority;
434  char function[MAXKEYNAMELEN+1];
435  char root[MAXKEYNAMELEN+1]; // dir or URL
436  bool rotate;
437  uint8 consoleOutput;
438  uint8 autoRestart;
439 
440  // Whiteboard, Stream, Catalog, Service, Feed
441  char subdir[MAXKEYNAMELEN+1];
442  char extension[MAXKEYNAMELEN+1]; // filetype
443  char base[MAXKEYNAMELEN+1]; // filename base
444  char keys[MAXVALUENAMELEN+1];
445  char value[MAXVALUENAMELEN+1];
446  char operation[MAXKEYNAMELEN+1];
447  uint32 timeout;
448 
449  // Recording & Playback
450  uint32 maxcount;
451  uint64 maxsize;
452  uint32 interval;
453 
454  // Executable
455  char cmdline[MAXKEYNAMELEN+1];
456 
457  // Setup
458  char setup[1024*1024]; // 1MB max
459 };
460 
461 // Local only, not transmitted
462 
463 struct CustomView {
464  uint32 compID;
465  char name[MAXKEYNAMELEN+1];
466  char templateURL[MAXKEYNAMELEN+1];
467 };
468 
470 public:
471  ComponentSpec() {
472  setup = new ComponentSetup;
473  setup->reset();
474  };
475  ~ComponentSpec() {
476  delete(setup);
477  setup = NULL;
478  while (triggers.size()) {
479  delete(triggers.front());
480  triggers.pop_front();
481  }
482  };
483 
484  ComponentSetup* setup;
485  std::list<TriggerSpec*> triggers;
486  std::list<CustomView> customViews;
487 };
488 
489 } // namespace cmlabs
490 
491 #endif //_SUBSCRIPTIONS_H_
492 
Definition: Subscriptions.h:189
Definition: Subscriptions.h:415
Definition: Bitmap.h:7
Definition: Subscriptions.h:341
Definition: Subscriptions.h:42
Definition: Subscriptions.h:125
bool setFloat(const char *key, float64 value)
Definition: DataMessage.cpp:1795
bool setString(const char *key, const char *value)
Definition: DataMessage.cpp:1776
Definition: Subscriptions.h:469
Definition: Types.h:207
Definition: Types.h:80
Definition: Subscriptions.h:318
Definition: xml_parser.h:171
bool setInt(const char *key, int64 value)
Definition: DataMessage.cpp:1786
Definition: Subscriptions.h:70
Definition: xml_parser.h:153
Definition: Subscriptions.h:463
Definition: DataMessage.h:95