LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
Event.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008-2015 AURA/LSST.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <https://www.lsstcorp.org/LegalNotices/>.
23  */
24 
33 #include <iomanip>
34 #include <sstream>
35 #include <stdexcept>
36 #include <limits>
37 #include <cstring>
38 #include <unistd.h>
39 #include <sys/socket.h>
40 #include <sys/un.h>
41 #include <netdb.h>
42 #include <time.h>
43 #include <typeinfo>
44 
45 #include "boost/scoped_array.hpp"
46 #include "boost/property_tree/ptree.hpp"
47 #include "boost/property_tree/json_parser.hpp"
48 #include "boost/foreach.hpp"
49 
50 #include "lsst/ctrl/events/Host.h"
51 #include "lsst/ctrl/events/Event.h"
53 #include "lsst/daf/base/DateTime.h"
55 #include "lsst/pex/exceptions.h"
57 
58 #include "activemq/core/ActiveMQConnectionFactory.h"
59 
60 namespace pexExceptions = lsst::pex::exceptions;
61 namespace dafBase = lsst::daf::base;
62 
63 
64 using namespace std;
65 using std::numeric_limits;
66 
67 namespace lsst {
68 namespace ctrl {
69 namespace events {
70 
71 
72 const std::string Event::TYPE = "TYPE";
73 const std::string Event::EVENTTIME = "EVENTTIME";
74 const std::string Event::RUNID = "RUNID";
75 const std::string Event::STATUS = "STATUS";
76 const std::string Event::TOPIC = "TOPIC";
77 const std::string Event::PUBTIME = "PUBTIME";
78 
79 const std::string Event::UNINITIALIZED = "uninitialized";
80 
81 Event::Event() {
82  _init();
83 }
84 
85 void Event::_init() {
86  _keywords.insert(TYPE);
87  _keywords.insert(EVENTTIME);
88  _keywords.insert(STATUS);
89  _keywords.insert(TOPIC);
90  _keywords.insert(PUBTIME);
91 }
92 
93 Event::Event(cms::TextMessage *msg) {
94 
95  vector<std::string>names = msg->getPropertyNames();
96 
97  _psp = processTextMessage(msg);
98 
99  for (vector<std::string>::iterator name = names.begin(); name != names.end(); ++name) {
100  _keywords.insert(*name);
101  }
102 
103  _psp->set(EVENTTIME, msg->getCMSTimestamp());
104 
105  for (vector<std::string>::iterator n = names.begin(); n != names.end(); ++n) {
106  std::string const& name = *n;
107  cms::Message::ValueType vType = msg->getPropertyValueType(name);
108  switch(vType) {
109  case cms::Message::NULL_TYPE:
110  _psp->set(name, NULL);
111  break;
112  case cms::Message::BOOLEAN_TYPE:
113  _psp->set(name, msg->getBooleanProperty(name));
114  break;
115  case cms::Message::BYTE_TYPE:
116  case cms::Message::CHAR_TYPE:
117  _psp->set(name, msg->getByteProperty(name));
118  break;
119  case cms::Message::SHORT_TYPE:
120  _psp->set(name, msg->getShortProperty(name));
121  break;
122  case cms::Message::INTEGER_TYPE:
123  _psp->set(name, msg->getIntProperty(name));
124  break;
125  case cms::Message::LONG_TYPE:
126  _psp->set(name, msg->getLongProperty(name));
127  break;
128  case cms::Message::DOUBLE_TYPE:
129  _psp->set(name, msg->getDoubleProperty(name));
130  break;
131  case cms::Message::FLOAT_TYPE:
132  _psp->set(name, msg->getFloatProperty(name));
133  break;
134  case cms::Message::STRING_TYPE:
135  _psp->set(name, msg->getStringProperty(name));
136  break;
137  case cms::Message::BYTE_ARRAY_TYPE:
138  case cms::Message::UNKNOWN_TYPE:
139  default:
140  std::string msg("Data type represented by "+name+" is not permitted supported");
141  throw LSST_EXCEPT(pexExceptions::RuntimeError, msg);
142  break;
143  }
144  }
145 
146 }
147 
148 vector<std::string> Event::getFilterablePropertyNames() {
149  vector<std::string> _names;
150  set<std::string>::iterator keyIterator;
151  for (keyIterator = _keywords.begin(); keyIterator != _keywords.end(); keyIterator++) {
152  _names.push_back(*keyIterator);
153  }
154  return _names;
155 }
156 
157 vector<std::string> Event::getCustomPropertyNames() {
158  vector<std::string> names = _psp->names();
159 
160  vector<std::string>::iterator nameIterator;
161  set<std::string>::iterator keyIterator;
162 
163  for (nameIterator = names.begin(); nameIterator != names.end();) {
164  keyIterator = _keywords.find(*nameIterator);
165  if (keyIterator == _keywords.end())
166  nameIterator++;
167  else
168  names.erase(nameIterator);
169  }
170  return names;
171 }
172 
173 Event::Event(PropertySet const& ps) {
174  const std::string empty;
175  PropertySet p;
176  _constructor(empty, ps, p);
177 }
178 
179 Event::Event(PropertySet const& ps, PropertySet const& filterable) {
180  const std::string empty;
181  _constructor(empty, ps, filterable);
182 }
183 
184 Event::Event(std::string const& runId, PropertySet::Ptr const psp) {
185  PropertySet p;
186  _constructor(runId, *psp, p);
187 }
188 
189 Event::Event(std::string const& runId, PropertySet const& ps) {
190  PropertySet p;
191  _constructor(runId, ps, p);
192 }
193 
194 Event::Event(std::string const& runId, PropertySet const& ps, PropertySet const& filterable) {
195  _constructor(runId, ps, filterable);
196 }
197 
198 void Event::_constructor(std::string const& runId, PropertySet const& ps, PropertySet const& filterable) {
199  _init();
200 
201  _psp = ps.deepCopy();
202 
203 
204  // do NOT alter the property set we were given. Make a copy of it,
205  // and modify that one.
206 
207  if (!_psp->exists(STATUS)) {
208  _psp->set(STATUS, "unknown");
209  }
210 
211  if (!_psp->exists(EVENTTIME)) {
212  updateEventTime();
213  }
214 
215  // _runId is filled in here and is ignored in the passed PropertySet
216  if (!runId.empty()) {
217  _keywords.insert(RUNID);
218  _psp->set(RUNID, runId);
219  }
220 
221  // _type is filled in here and is ignored in the passed PropertySet
222  _psp->set(TYPE, EventTypes::EVENT);
223 
224  // _topic is filled in on publish and is ignored in the passed PropertySet
225  _psp->set(TOPIC, Event::UNINITIALIZED);
226 
227  // _pubTime is filled in on publish and is ignored in the passed PropertySet
228  _psp->set(PUBTIME, (long long)0);
229 
230  if (filterable.nameCount() > 0) {
231  vector<std::string> names = filterable.names();
232 
233  for (vector<std::string>::iterator name = names.begin(); name != names.end(); ++name) {
234  _keywords.insert(*name);
235  }
236 
237  _psp->combine(filterable.PropertySet::deepCopy());
238  }
239 }
240 
241 void Event::populateHeader(cms::TextMessage* msg) const {
242  set<std::string>::iterator keyIterator;
243  for (keyIterator = _keywords.begin(); keyIterator != _keywords.end(); keyIterator++) {
244  std::string const& name = *keyIterator;
245  std::type_info const& t = _psp->typeOf(name);
246  if (t == typeid(bool)) {
247  msg->setBooleanProperty(name, _psp->get<bool>(name));
248  } else if (t == typeid(short)) {
249  msg->setShortProperty(name, _psp->get<short>(name));
250  } else if (t == typeid(int)) {
251  msg->setIntProperty(name, _psp->get<int>(name));
252  } else if (t == typeid(long)) {
253  msg->setLongProperty(name, _psp->get<long>(name));
254  } else if (t == typeid(long long)) {
255  msg->setLongProperty(name, _psp->get<long long>(name));
256  } else if (t == typeid(double)) {
257  msg->setDoubleProperty(name, _psp->get<double>(name));
258  } else if (t == typeid(float)) {
259  msg->setFloatProperty(name, _psp->get<float>(name));
260  } else if (t == typeid(std::string)) {
261  msg->setStringProperty(name, _psp->get<std::string>(name));
262  } else {
263  std::string msg("Data type represented in "+ name +" is not permitted in event header");
264  throw LSST_EXCEPT(pexExceptions::RuntimeError, msg);
265  }
266  }
267 }
268 
269 
270 long long Event::getEventTime() {
271  return _psp->get<long long>(EVENTTIME);
272 }
273 
274 void Event::setEventTime(long long nsecs) {
275  _psp->set(EVENTTIME, nsecs);
276 }
277 
278 void Event::updateEventTime() {
279  _psp->set(EVENTTIME, (long long)dafBase::DateTime::now().nsecs());
280 }
281 
282 
283 std::string Event::getEventDate() {
284  long long eventTime = _psp->get<long long>(EVENTTIME);
285  dafBase::DateTime dateTime(eventTime);
286 
287  struct tm gmTime = dateTime.gmtime();
288  return asctime(&gmTime);
289 }
290 
291 
292 PropertySet::Ptr Event::getCustomPropertySet() const {
293  PropertySet::Ptr psp = _psp->deepCopy();
294 
295  set<std::string>::iterator keyIterator;
296  for (keyIterator = _keywords.begin(); keyIterator != _keywords.end(); keyIterator++)
297  psp->remove(*keyIterator);
298  return psp;
299 }
300 
301 PropertySet::Ptr Event::getPropertySet() const {
302  if (_psp != 0) {
303  PropertySet::Ptr psp = _psp->deepCopy();
304  return psp;
305  }
306  PropertySet::Ptr psp(new PropertySet);
307  return psp;
308 }
309 
310 void Event::setPubTime(long long t) {
311  _psp->set(PUBTIME, t);
312 }
313 
314 long long Event::getPubTime() {
315  return _psp->get<long long>(PUBTIME);
316 }
317 
318 std::string Event::getPubDate() {
319  long long _pubTime = _psp->get<long long>(PUBTIME);
320  if (_pubTime == 0)
321  return std::string();
322 
323  dafBase::DateTime dateTime(_pubTime);
324 
325  struct tm pubTime = dateTime.gmtime();
326  return asctime(&pubTime);
327 }
328 
329 std::string Event::getRunId() {
330  if (_psp->exists(RUNID))
331  return _psp->get<std::string>(RUNID);
332  throw LSST_EXCEPT(pexExceptions::RuntimeError, std::string("property RUNID not found"));
333 }
334 
335 std::string Event::getType() {
336  return _psp->get<std::string>(TYPE);
337 }
338 
339 std::string Event::getStatus() {
340  return _psp->get<std::string>(STATUS);
341 }
342 
343 void Event::setStatus(std::string status) {
344  return _psp->set(STATUS, status);
345 }
346 
347 void Event::setTopic(std::string topic) {
348  _psp->set(TOPIC, topic);
349 }
350 
351 std::string Event::getTopic() {
352  return _psp->get<std::string>(TOPIC);
353 }
354 
355 void Event::marshall(cms::TextMessage *msg) {
356  PropertySet::Ptr psp;
357 
358  populateHeader(msg);
359  psp = getCustomPropertySet();
360  std::string payload = marshall(*psp);
361  msg->setText(payload);
362 }
363 
364 template<typename T>void Event::add(std::string const& name, std::string const& tag, PropertySet const& ps, boost::property_tree::ptree& child) {
365 
366  std::vector<T> vec = ps.getArray<T>(name);
367 
368  typename std::vector<T>::iterator iter;
369  for (iter = vec.begin(); iter != vec.end(); iter++) {
370  boost::property_tree::ptree pt;
371  pt.put(tag, *iter);
372  child.put_child(name, pt);
373  }
374 }
375 
376 std::string Event::marshall(PropertySet const& ps) {
377  std::vector<std::string> names = ps.paramNames(false);
378 
379  boost::property_tree::ptree child;
380 
381  for (vector<std::string>::iterator n = names.begin(); n != names.end(); ++n) {
382  std::string name = *n;
383 
384  if (ps.typeOf(name) == typeid(bool)) {
385  add<bool>(name, "bool", ps, child);
386  } else if (ps.typeOf(name) == typeid(long)) {
387  add<long>(name, "long", ps, child);
388  } else if (ps.typeOf(name) == typeid(long long)) {
389  add<long long>(name, "long long", ps, child);
390  } else if (ps.typeOf(name) == typeid(int)) {
391  add<int>(name, "int", ps, child);
392  } else if (ps.typeOf(name) == typeid(float)) {
393  add<float>(name, "float", ps, child);
394  } else if (ps.typeOf(name) == typeid(double)) {
395  add<double>(name, "double", ps, child);
396  } else if (ps.typeOf(name) == typeid(std::string)) {
397  add<std::string>(name, "string", ps, child);
398  } else if (ps.typeOf(name) == typeid(lsst::daf::base::DateTime)) {
399  std::vector<lsst::daf::base::DateTime> vec = ps.getArray<lsst::daf::base::DateTime>(name);
400  std::vector<lsst::daf::base::DateTime>::iterator iter;
401  for (iter = vec.begin(); iter != vec.end(); iter++) {
402  boost::property_tree::ptree pt;
403  pt.put("datetime", (*iter).nsecs());
404  child.put_child(name, pt);
405  }
406  } else {
407  std::string msg("Couldn't marshall "+name);
408  throw LSST_EXCEPT(pexExceptions::RuntimeError, msg);
409  }
410  }
411  std::ostringstream payload;
412  write_json(payload, child, false);
413 
414  return payload.str();
415 }
416 
419 PropertySet::Ptr Event::processTextMessage(cms::TextMessage* textMessage) {
420  if (textMessage == NULL)
421  return PropertySet::Ptr();
422 
423  std::string text = textMessage->getText();
424 
425  return unmarshall(text);
426 }
427 
435 bool Event::addDataItem(std::string const& typeInfo, boost::property_tree::ptree& item, std::string const& key, PropertySet& ps) {
436  if (typeInfo == "string") {
437  std::string value = item.get_value<std::string>();
438  ps.add(key, value);
439  } else if (typeInfo == "bool") {
440  bool value = item.get_value<bool>();
441  ps.add(key, value);
442  } else if (typeInfo == "long") {
443  long value = item.get_value<long>();
444  ps.add(key, value);
445  } else if (typeInfo == "long long") {
446  long long value = item.get_value<long long>();
447  ps.add(key, value);
448  } else if (typeInfo == "int") {
449  int value = item.get_value<int>();
450  ps.add(key, value);
451  } else if (typeInfo == "float") {
452  float value = item.get_value<float>();
453  ps.add(key, value);
454  } else if (typeInfo == "double") {
455  double value = item.get_value<double>();
456  ps.add(key, value);
457  } else if (typeInfo == "datetime") {
458  long long value = item.get_value<long long>();
460  } else {
461  return false;
462  }
463  return true;
464 }
465 
471 PropertySet::Ptr Event::parsePropertySet(boost::property_tree::ptree child) {
472  PropertySet::Ptr psp(new PropertySet);
473 
474  BOOST_FOREACH(boost::property_tree::ptree::value_type const &v, child.get_child("")) {
475  std::string label = v.first;
476  BOOST_FOREACH(boost::property_tree::ptree::value_type &v2, child.get_child(label)) {
477  const bool b = addDataItem(v2.first, v2.second, label, *psp);
478  if (!b) {
479  PropertySet::Ptr p2 = parsePropertySet(child.get_child(label));
480  psp->add(label, p2);
481  break;
482  }
483  }
484  }
485  return psp;
486 }
487 
492 PropertySet::Ptr Event::unmarshall(std::string const& text) {
493 
494  boost::property_tree::ptree pt;
495  std::istringstream is (text);
496  read_json(is, pt);
497 
498  PropertySet::Ptr psp(new PropertySet);
499 
500  BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt) {
501  std::string key = v.first;
502 
503  boost::property_tree::ptree child = v.second;
504  BOOST_FOREACH(boost::property_tree::ptree::value_type &v2, child) {
505  std::string key2 = v2.first;
506 
507  const bool b = addDataItem(key2, v2.second, key, *psp);
508  if (!b) {
509  std::string value = v2.second.get_value<std::string>();
510  PropertySet::Ptr p = parsePropertySet(child);
511  psp->add(key, p);
512  break;
513  }
514  }
515  }
516 
517  return psp;
518 }
519 
520 Event::~Event() {
521 }
522 
523 template void Event::add<bool>(std::string const& name, std::string const& tag, PropertySet const& ps, boost::property_tree::ptree& child);
524 
525 template void Event::add<int>(std::string const& name, std::string const& tag, PropertySet const& ps, boost::property_tree::ptree& child);
526 
527 template void Event::add<float>(std::string const& name, std::string const& tag, PropertySet const& ps, boost::property_tree::ptree& child);
528 
529 template void Event::add<double>(std::string const& name, std::string const& tag, PropertySet const& ps, boost::property_tree::ptree& child);
530 
531 template void Event::add<long>(std::string const& name, std::string const& tag,PropertySet const& ps, boost::property_tree::ptree& child);
532 
533 template void Event::add<long long>(std::string const& name, std::string const& tag, PropertySet const& ps, boost::property_tree::ptree& child);
534 
535 template void Event::add<std::string>(std::string const& name, std::string const& tag, PropertySet const& ps, boost::property_tree::ptree& child);
536 
537 }}}
int iter
std::vector< std::string > paramNames(bool topLevelOnly=true) const
Definition: PropertySet.cc:142
static DateTime now(void)
Definition: DateTime.cc:554
Class for handling dates/times, including MJD, UTC, and TAI.
Definition: DateTime.h:58
table::Key< std::string > name
Definition: ApCorrMap.cc:71
defines the Host class
size_t nameCount(bool topLevelOnly=true) const
Definition: PropertySet.cc:97
Include files required for standard LSST Exception handling.
boost::shared_ptr< PropertySet > Ptr
Definition: PropertySet.h:90
defines EventTypes
std::vector< std::string > names(bool topLevelOnly=true) const
Definition: PropertySet.cc:117
defines the EventLibrary class
defines the Event class
Interface for DateTime class.
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
std::type_info const & typeOf(std::string const &name) const
Definition: PropertySet.cc:227
int status
Class for storing generic metadata.
Definition: PropertySet.h:82
virtual Ptr deepCopy(void) const
Definition: PropertySet.cc:70
struct tm gmtime(void) const
Definition: DateTime.cc:492
afw::table::Key< double > b
Interface for PropertySet class.
void add(std::string const &name, T const &value)
Definition: PropertySet.cc:619
std::vector< T > getArray(std::string const &name) const