LSSTApplications  8.0.0.0+107,8.0.0.1+13,9.1+18,9.2,master-g084aeec0a4,master-g0aced2eed8+6,master-g15627eb03c,master-g28afc54ef9,master-g3391ba5ea0,master-g3d0fb8ae5f,master-g4432ae2e89+36,master-g5c3c32f3ec+17,master-g60f1e072bb+1,master-g6a3ac32d1b,master-g76a88a4307+1,master-g7bce1f4e06+57,master-g8ff4092549+31,master-g98e65bf68e,master-ga6b77976b1+53,master-gae20e2b580+3,master-gb584cd3397+53,master-gc5448b162b+1,master-gc54cf9771d,master-gc69578ece6+1,master-gcbf758c456+22,master-gcec1da163f+63,master-gcf15f11bcc,master-gd167108223,master-gf44c96c709
LSSTDataManagementBasePackage
Event.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
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 <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
34 #include <iomanip>
35 #include <sstream>
36 #include <stdexcept>
37 #include <limits>
38 #include <cstring>
39 #include <unistd.h>
40 #include <sys/socket.h>
41 #include <sys/un.h>
42 #include <netdb.h>
43 #include <time.h>
44 
45 #include "boost/scoped_array.hpp"
46 
47 #include "lsst/ctrl/events/Event.h"
49 #include "lsst/daf/base/DateTime.h"
51 #include "lsst/pex/exceptions.h"
53 
54 #include "activemq/core/ActiveMQConnectionFactory.h"
55 
56 namespace pexExceptions = lsst::pex::exceptions;
57 namespace pexLogging = lsst::pex::logging;
58 namespace dafBase = lsst::daf::base;
59 
60 
61 using namespace std;
62 using std::numeric_limits;
63 
64 namespace lsst {
65 namespace ctrl {
66 namespace events {
67 
73 // NOTE: While it would be nice to implement this as a wrapper for a TextMessage,
74 // the JMS/ActiveMQ API doesn't have straight constructors Message objects.
75 // They are all created through a JMS/ActiveMQ Session object. This
76 // makes implementation of some methods (like getFilterablePropertyNames)
77 // more than just a straight call to a JMS method, since there is no
78 // underlying Message wrapped.
79 
80 const std::string Event::TYPE = "TYPE";
81 const std::string Event::EVENTTIME = "EVENTTIME";
82 const std::string Event::HOSTID = "HOSTID";
83 const std::string Event::RUNID = "RUNID";
84 const std::string Event::STATUS = "STATUS";
85 const std::string Event::TOPIC = "TOPIC";
86 const std::string Event::PUBTIME = "PUBTIME";
87 
88 const std::string Event::UNINITIALIZED = "uninitialized";
89 
90 Event::Event() {
91  _init();
92 }
93 
94 void Event::_init() {
95  _keywords.insert(TYPE);
96  _keywords.insert(EVENTTIME);
97  _keywords.insert(HOSTID);
98  _keywords.insert(RUNID);
99  _keywords.insert(STATUS);
100  _keywords.insert(TOPIC);
101  _keywords.insert(PUBTIME);
102 }
103 
104 Event::Event(cms::TextMessage *msg) {
105  _init();
106 
107  _psp = processTextMessage(msg);
108 
109  _psp->set(TYPE, msg->getStringProperty(TYPE));
110  _psp->set(HOSTID, msg->getStringProperty(HOSTID));
111  _psp->set(RUNID, msg->getStringProperty(RUNID));
112  _psp->set(STATUS, msg->getStringProperty(STATUS));
113  _psp->set(TOPIC, msg->getStringProperty(TOPIC));
114  _psp->set(EVENTTIME, msg->getLongProperty(EVENTTIME));
115  _psp->set(PUBTIME, msg->getLongProperty(PUBTIME));
116 /*
117 */
118 }
119 
120 vector<std::string> Event::getFilterablePropertyNames() {
121  vector<std::string> _names;
122  set<std::string>::iterator keyIterator;
123  for (keyIterator = _keywords.begin(); keyIterator != _keywords.end(); keyIterator++) {
124  _names.push_back(*keyIterator);
125  }
126  return _names;
127 }
128 
129 vector<std::string> Event::getCustomPropertyNames() {
130  vector<std::string> names = _psp->names();
131 
132  vector<std::string>::iterator nameIterator;
133  set<std::string>::iterator keyIterator;
134 
135  for (nameIterator = names.begin(); nameIterator != names.end();) {
136  keyIterator = _keywords.find(*nameIterator);
137  if (keyIterator == _keywords.end())
138  nameIterator++;
139  else
140  names.erase(nameIterator);
141  }
142  return names;
143 }
144 
145 Event::Event( const std::string& runId, const PropertySet::Ptr psp) {
146  _constructor(runId, *psp);
147 }
148 
149 Event::Event( const std::string& runId, const PropertySet& ps) {
150  _constructor(runId, ps);
151 }
152 
153 void Event::_constructor( const std::string& runId, const PropertySet& ps) {
154  long int host_len = sysconf(_SC_HOST_NAME_MAX);
155 
156  boost::scoped_array<char> hostname(new char[host_len]);
157  //time_t rawtime;
158 
159  _init();
160 
161  _psp = ps.deepCopy();
162 
163 
164  // do NOT alter the property set we were given. Make a copy of it,
165  // and modify that one.
166 
167  /*
168  std::string foo = psp->toString();
169  std::cout << "foo = " << foo << std::endl;
170  */
171 
172  if (!_psp->exists(STATUS)) {
173  _psp->set(STATUS, "unknown");
174  }
175 
176  if (!_psp->exists(EVENTTIME)) {
177  updateEventTime();
178  }
179 
180 
181  if (!_psp->exists(HOSTID)) {
182  std::string name;
183  gethostname(hostname.get(), host_len);
184  name = hostname.get();
185  _psp->set(HOSTID, name);
186  }
187 
188  // _runId is filled in here and is ignored in the passed PropertySet
189  _psp->set(RUNID, runId);
190 
191  // _type is filled in here and is ignored in the passed PropertySet
192  _psp->set(TYPE, EventTypes::EVENT);
193 
194  // _topic is filled in on publish and is ignored in the passed PropertySet
195  _psp->set(TOPIC, Event::UNINITIALIZED);
196 
197  // _pubTime is filled in on publish and is ignored in the passed PropertySet
198  _psp->set(PUBTIME, (long long)0);
199 }
200 
201 void Event::populateHeader(cms::TextMessage* msg) const {
202  msg->setStringProperty(TYPE, _psp->get<std::string>(TYPE));
203  msg->setLongProperty(EVENTTIME, _psp->get<long long>(EVENTTIME));
204  msg->setStringProperty(HOSTID, _psp->get<std::string>(HOSTID));
205  msg->setStringProperty(RUNID, _psp->get<std::string>(RUNID));
206  msg->setStringProperty(STATUS, _psp->get<std::string>(STATUS));
207  msg->setStringProperty(TOPIC, _psp->get<std::string>(TOPIC));
208  msg->setLongProperty(PUBTIME, _psp->get<long long>(PUBTIME));
209 }
210 
211 long long Event::getEventTime() {
212  return _psp->get<long long>(EVENTTIME);
213 }
214 
215 void Event::setEventTime(long long nsecs) {
216  _psp->set(EVENTTIME, nsecs);
217 }
218 
219 void Event::updateEventTime() {
220  _psp->set(EVENTTIME, (long long)dafBase::DateTime::now().nsecs());
221 }
222 
226 std::string Event::getEventDate() {
227  long long eventTime = _psp->get<long long>(EVENTTIME);
228  dafBase::DateTime dateTime(eventTime);
229 
230  struct tm gmTime = dateTime.gmtime();
231  return asctime(&gmTime);
232 }
233 
234 
235 PropertySet::Ptr Event::getCustomPropertySet() const {
236  PropertySet::Ptr psp = _psp->deepCopy();
237 
238  set<std::string>::iterator keyIterator;
239  for (keyIterator = _keywords.begin(); keyIterator != _keywords.end(); keyIterator++)
240  psp->remove(*keyIterator);
241  return psp;
242 }
243 
244 PropertySet::Ptr Event::getPropertySet() const {
245  if (_psp != 0) {
246  PropertySet::Ptr psp = _psp->deepCopy();
247  return psp;
248  }
249  PropertySet::Ptr psp(new PropertySet);
250  return psp;
251 }
252 
253 void Event::setPubTime(long long t) {
254  _psp->set(PUBTIME, t);
255 }
256 
257 long long Event::getPubTime() {
258  return _psp->get<long long>(PUBTIME);
259 }
260 
264 std::string Event::getPubDate() {
265  long long _pubTime = _psp->get<long long>(PUBTIME);
266  if (_pubTime == 0)
267  return std::string();
268 
269  dafBase::DateTime dateTime(_pubTime);
270 
271  struct tm pubTime = dateTime.gmtime();
272  return asctime(&pubTime);
273 }
274 
275 
276 std::string Event::getHostId() {
277  return _psp->get<std::string>(HOSTID);
278 }
279 
280 std::string Event::getRunId() {
281  return _psp->get<std::string>(RUNID);
282 }
283 
284 std::string Event::getType() {
285  return _psp->get<std::string>(TYPE);
286 }
287 
288 std::string Event::getStatus() {
289  return _psp->get<std::string>(STATUS);
290 }
291 
292 void Event::setStatus(std::string status) {
293  return _psp->set(STATUS, status);
294 }
295 
296 void Event::setTopic(std::string topic) {
297  _psp->set(TOPIC, topic);
298 }
299 
300 std::string Event::getTopic() {
301  return _psp->get<std::string>(TOPIC);
302 }
303 
304 void Event::marshall(cms::TextMessage *msg) {
305  PropertySet::Ptr psp;
306 
307  populateHeader(msg);
308  psp = getCustomPropertySet();
309  std::string payload = marshall(*psp);
310  msg->setText(payload);
311 }
312 
313 
314 std::string Event::marshall(const PropertySet& ps) {
315  std::vector<std::string> v = ps.paramNames(false);
316 
317  // TODO: optimize this to get use getArray only when necessary
318  std::ostringstream payload;
319  unsigned int i;
320  payload << "nodelist||nodelist||" << (v.size()) << "~~";
321  for (i = 0; i < v.size(); i++) {
322  std::string name = v[i];
323  if (ps.typeOf(name) == typeid(bool)) {
324  std::vector<bool> vec = ps.getArray<bool>(name);
325  std::vector<bool>::iterator iter;
326  for (iter = vec.begin(); iter != vec.end(); iter++) {
327  payload << "bool||"<< name << "||" << *iter << "~~";
328  }
329  } else if (ps.typeOf(name) == typeid(long)) {
330  std::vector<long> vec = ps.getArray<long>(name);
331  std::vector<long>::iterator iter;
332  for (iter = vec.begin(); iter != vec.end(); iter++) {
333  payload << "long||" << name << "||"<< *iter << "~~";
334  }
335  } else if (ps.typeOf(name) == typeid(int)) {
336  std::vector<int> vec = ps.getArray<int>(name);
337  std::vector<int>::iterator iter;
338  for (iter = vec.begin(); iter != vec.end(); iter++) {
339  payload << "int||" << name << "||"<< *iter << "~~";
340  }
341  } else if (ps.typeOf(name) == typeid(float)) {
342  std::vector<float> vec = ps.getArray<float>(name);
343  std::vector<float>::iterator iter;
344  payload.precision(numeric_limits<float>::digits10+1);
345  for (iter = vec.begin(); iter != vec.end(); iter++) {
346  payload << "float||"<< name << "||"<< *iter << "~~";
347  }
348  } else if (ps.typeOf(name) == typeid(double)) {
349  std::vector<double> vec = ps.getArray<double>(name);
350  std::vector<double>::iterator iter;
351  payload.precision(numeric_limits<double>::digits10+1);
352  for (iter = vec.begin(); iter != vec.end(); iter++) {
353  payload << "double||"<< name << "||"<< *iter << "~~";
354  }
355  } else if (ps.typeOf(name) == typeid(std::string)) {
356  std::vector<std::string> vec = ps.getArray<std::string>(name);
357  std::vector<std::string>::iterator iter;
358  for (iter = vec.begin(); iter != vec.end(); iter++) {
359  payload << "string||" << name << "||"<< *iter << "~~";
360  }
361  } else if (ps.typeOf(name) == typeid(lsst::daf::base::DateTime)) {
362  std::vector<lsst::daf::base::DateTime> vec = ps.getArray<lsst::daf::base::DateTime>(name);
363  std::vector<lsst::daf::base::DateTime>::iterator iter;
364  for (iter = vec.begin(); iter != vec.end(); iter++) {
365  payload << "datetime||" << name << "||"<< (*iter).nsecs() << "~~";
366  }
367  } else {
368  std::cout << "Couldn't marshall "<< name << std::endl;
369  }
370  }
371  return payload.str();
372 }
373 
376 PropertySet::Ptr Event::processTextMessage(cms::TextMessage* textMessage) {
377  if (textMessage == NULL)
378  return PropertySet::Ptr();
379 
380  std::string text = textMessage->getText();
381 
382  return unmarshall(text);
383 }
384 
387 PropertySet::Ptr Event::unmarshall(const std::string& text) {
388  std::vector<string> tuples;
389 
390  // split the text into tuples
391  splitString(text, "~~", tuples);
392 
393 
394  PropertySet::Ptr psp(new PropertySet);
395 
396  unsigned int i;
397  for (i = 0; i < tuples.size(); i++) {
398  std::string line = tuples.at(i);
399  std::vector<string> vec;
400  splitTuple(line, "||", vec);
401 
402  std::string type = vec.at(0);
403  std::string key = vec.at(1);
404  std::string val = vec.at(2);
405 
406  std::istringstream iss(val);
407  boost::any value;
408 
409  if (type == "int") {
410  int int_value;
411  iss >> int_value;
412  value = boost::any(int_value);
413  psp->add(key, int_value);
414  } else if (type == "bool") {
415  bool bool_value;
416  iss >> bool_value;
417  value = boost::any(bool_value);
418  psp->add(key, bool_value);
419  } else if (type == "long long") {
420  long long longlong_value;
421  iss >> longlong_value;
422  value = boost::any(longlong_value);
423  psp->add(key, longlong_value);
424  } else if (type == "long") {
425  long long_value;
426  iss >> long_value;
427  value = boost::any(long_value);
428  psp->add(key, long_value);
429  } else if (type == "float") {
430  float float_value;
431  iss >> float_value;
432  value = boost::any(float_value);
433  psp->add(key, float_value);
434  } else if (type == "double") {
435  double double_value;
436  iss >> double_value;
437  value = boost::any(double_value);
438  psp->add(key, double_value);
439  } else if (type == "string") {
440  psp->add(key, val);
441  } else if (type == "datetime") {
442  long long longlong_value;
443  iss >> longlong_value;
444  psp->add(key, lsst::daf::base::DateTime(longlong_value, lsst::daf::base::DateTime::UTC));
445  }
446  // type == nodelist can be ignored
447  }
448 
449  return psp;
450 }
451 
455 void Event::splitString(std::string str, std::string delim,
456  std::vector<std::string>&results) {
457  std::string::size_type cutAt;
458  std::string::size_type delim_len = delim.length();
459 
460  while( (cutAt = str.find(delim)) != str.npos ) {
461  if(cutAt > 0) {
462  results.push_back(str.substr(0,cutAt));
463  }
464  str = str.substr(cutAt+delim_len);
465  }
466  if(str.length() > 0) {
467  results.push_back(str);
468  }
469 }
470 
474 void Event::splitTuple(std::string str, std::string delim,
475  std::vector<std::string>&results) {
476  std::string::size_type cutAt;
477  std::string::size_type delim_len = delim.length();
478 
479  cutAt = str.find(delim);
480  results.push_back(str.substr(0,cutAt));
481  str = str.substr(cutAt+delim_len);
482 
483  cutAt = str.find(delim);
484  results.push_back(str.substr(0,cutAt));
485  str = str.substr(cutAt+delim_len);
486 
487  cutAt = str.find(delim);
488  results.push_back(str.substr(0,cutAt));
489 }
490 
493 Event::~Event() {
494 }
495 
496 }
497 }
498 }
499 
int status
std::vector< std::string > paramNames(bool topLevelOnly=true) const
Definition: PropertySet.cc:142
static DateTime now(void)
Definition: DateTime.cc:553
Class for handling dates/times, including MJD, UTC, and TAI.
Definition: DateTime.h:58
int iter
boost::shared_ptr< PropertySet > Ptr
Definition: PropertySet.h:90
defines EventTypes
Include files required for standard LSST Exception handling.
defines the EventLibrary class
defines the Event class
Interface for DateTime class.
std::type_info const & typeOf(std::string const &name) const
Definition: PropertySet.cc:227
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:491
boost::enable_if< typename ExpressionTraits< Scalar >::IsScalar, bool >::type any(Scalar const &scalar)
Definition: operators.h:1165
Interface for PropertySet class.
std::vector< T > getArray(std::string const &name) const
ImageT val
Definition: CR.cc:154