ReportingComponent.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Mon May 10 19:10:38 CEST 2004 ReportingComponent.cxx
3 
4  ReportingComponent.cxx - description
5  -------------------
6  begin : Mon May 10 2004
7  copyright : (C) 2004 Peter Soetens
8  email : peter.soetens@mech.kuleuven.ac.be
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU Lesser General Public *
13  * License as published by the Free Software Foundation; either *
14  * version 2.1 of the License, or (at your option) any later version. *
15  * *
16  * This library is distributed in the hope that it will be useful, *
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19  * Lesser General Public License for more details. *
20  * *
21  * You should have received a copy of the GNU Lesser General Public *
22  * License along with this library; if not, write to the Free Software *
23  * Foundation, Inc., 59 Temple Place, *
24  * Suite 330, Boston, MA 02111-1307 USA *
25  * *
26  ***************************************************************************/
27 
28 #include "ReportingComponent.hpp"
29 #include <rtt/Logger.hpp>
30 
31 // Impl.
32 #include "EmptyMarshaller.hpp"
35 #include <iostream>
36 #include <fstream>
37 #include <exception>
38 #include <boost/algorithm/string.hpp>
39 
40 #include "ocl/Component.hpp"
42 #include <boost/lexical_cast.hpp>
43 
45 
46 
47 namespace OCL
48 {
49  using namespace std;
50  using namespace RTT;
51  using namespace RTT::detail;
52 
55  class CheckSizeDataSource : public ValueDataSource<bool>
56  {
57  mutable int msize;
60  public:
62  : msize(size), mds(ds), mupstream(upstream)
63  {}
67  bool get() const{
68  // it's very important to first check upstream, because
69  // if upstream changed size, downstream might already be corrupt !
70  // (downstream will be corrupt upon capacity changes upstream)
71  bool result = true;
72  if (mupstream)
73  result = (mupstream->get() && msize == mds->get());
74  else
75  result = (msize == mds->get());
76  msize = mds->get();
77  return result;
78  }
79  };
80 
88  {
89  assert(dsb);
90 
91  vector<string> parts = dsb->getMemberNames();
92  if ( parts.empty() ) {
93  return false;
94  }
95 
96  targetbag.setType( dsb->getTypeName() );
97 
98  // needed for recursion.
99 #if __cplusplus < 201103L
100  auto_ptr< Property<PropertyBag> > recurse_bag( new Property<PropertyBag>("recurse_bag","") );
101 #else
102  unique_ptr< Property<PropertyBag> > recurse_bag( new Property<PropertyBag>("recurse_bag","") );
103 #endif
104  // First at the explicitly listed parts:
105  for(vector<string>::iterator it = parts.begin(); it != parts.end(); ++it ) {
106  // we first force getMember to get to the type, then we do it again but with a reference set.
107  DataSourceBase::shared_ptr part = dsb->getMember( *it );
108  if (!part) {
109  log(Error) <<"memberDecomposition: Inconsistent type info for "<< dsb->getTypeName() << ": reported to have part '"<<*it<<"' but failed to return it."<<endlog();
110  continue;
111  }
112  if ( !part->isAssignable() ) {
113  // For example: the case for size() and capacity() in SequenceTypeInfo
114  log(Debug)<<"memberDecomposition: Part "<< *it << ":"<< part->getTypeName() << " is not changeable."<<endlog();
115  continue;
116  }
117  // now the reference magic:
118  DataSourceBase::shared_ptr ref = part->getTypeInfo()->buildReference( 0 );
119  dsb->getTypeInfo()->getMember( dynamic_cast<Reference*>(ref.get() ), dsb, *it); // fills in ref
120  // newpb will contain a reference to the port's datasource data !
121  PropertyBase* newpb = part->getTypeInfo()->buildProperty(*it,"Part", ref);
122  if ( !newpb ) {
123  log(Error)<< "Decomposition failed because Part '"<<*it<<"' is not known to type system."<<endlog();
124  continue;
125  }
126  // finally recurse or add it to the target bag:
127  if ( !memberDecomposition( ref, recurse_bag->value(), resized) ) {
128  assert( recurse_bag->value().empty() );
129  // finally: check for conversions (enums use this):
130  base::DataSourceBase::shared_ptr converted = newpb->getTypeInfo()->convertType( dsb );
131  if ( converted && converted != dsb ) {
132  // converted contains another type.
133  targetbag.add( converted->getTypeInfo()->buildProperty(*it, "", converted) );
134  delete newpb;
135  } else
136  targetbag.ownProperty( newpb ); // leaf
137  } else {
138  recurse_bag->setName(*it);
139  // setType() is done by recursive of self.
140  targetbag.ownProperty( recurse_bag.release() ); //recursed.
141  recurse_bag.reset( new Property<PropertyBag>("recurse_bag","") );
142  delete newpb; // since we recursed, the recurse_bag now 'embodies' newpb.
143  }
144  }
145 
146  // Next get the numbered parts. This is much more involved since sequences may be resizable.
147  // We keep track of the size, and if that changes, we will have to force a re-decomposition
148  // of the sequence's internals.
149  DataSource<int>::shared_ptr size = DataSource<int>::narrow( dsb->getMember("size").get() );
150  if (size) {
151  int msize = size->get();
152  for (int i=0; i < msize; ++i) {
153  string indx = boost::lexical_cast<string>( i );
154  DataSourceBase::shared_ptr item = dsb->getMember(indx);
155  resized = new CheckSizeDataSource( msize, size, resized );
156  if (item) {
157  if ( !item->isAssignable() ) {
158  // For example: the case for size() and capacity() in SequenceTypeInfo
159  log(Warning)<<"memberDecomposition: Item '"<< indx << "' of type "<< dsb->getTypeName() << " is not changeable."<<endlog();
160  continue;
161  }
162  // finally recurse or add it to the target bag:
163  PropertyBase* newpb = item->getTypeInfo()->buildProperty( indx,"",item);
164  if ( !memberDecomposition( item, recurse_bag->value(), resized) ) {
165  targetbag.ownProperty( newpb ); // leaf
166  } else {
167  delete newpb;
168  recurse_bag->setName( indx );
169  // setType() is done by recursive of self.
170  targetbag.ownProperty( recurse_bag.release() ); //recursed.
171  recurse_bag.reset( new Property<PropertyBag>("recurse_bag","") );
172  }
173  }
174  }
175  }
176  if (targetbag.empty() )
177  log(Debug) << "memberDecomposition: "<< dsb->getTypeName() << " returns an empty property bag." << endlog();
178  return true;
179  }
180 
181  ReportingComponent::ReportingComponent( std::string name /*= "Reporting" */ )
182  : TaskContext( name ),
183  report("Report"), snapshotted(false),
184  writeHeader("WriteHeader","Set to true to start each report with a header.", true),
185  decompose("Decompose","Set to false in order to not decompose the port data. The marshaller must be able to handle this itself for this to work.", true),
186  complexdecompose("ComplexDecompose","Use slow but more robust procedure for port data decomposition.", false),
187  insnapshot("Snapshot","Set to true to enable snapshot mode. This will cause a non-periodic reporter to only report data upon the snapshot() operation.",false),
188  synchronize_with_logging("Synchronize","Set to true if the timestamp should be synchronized with the logging",false),
189  report_data("ReportData","A PropertyBag which defines which ports or components to report."),
190  report_policy( ConnPolicy::data(ConnPolicy::LOCK_FREE,true,false) ),
191  onlyNewData(false),
192  starttime(0),
193  timestamp("TimeStamp","The time at which the data was read.",0.0)
194  {
195  this->provides()->doc("Captures data on data ports. A periodic reporter will sample each added port according to its period, a non-periodic reporter will write out data as it comes in, or only during a snapshot() if the Snapshot property is true.");
196 
197  this->properties()->addProperty( writeHeader );
198  this->properties()->addProperty( decompose );
200  this->properties()->addProperty( insnapshot );
203  this->properties()->addProperty( "ReportPolicy", report_policy).doc("The ConnPolicy for the reporter's port connections.");
204  this->properties()->addProperty( "ReportOnlyNewData", onlyNewData).doc("Turn on in order to only write out NewData on ports and omit unchanged ports. Turn off in order to sample and write out all ports (even old data).");
205  // Add the methods, methods make sure that they are
206  // executed in the context of the (non realtime) caller.
207 
208  this->addOperation("snapshot", &ReportingComponent::snapshot , this, RTT::OwnThread).doc("Take a new shapshot of all data and cause them to be written out.");
209  this->addOperation("screenComponent", &ReportingComponent::screenComponent , this, RTT::ClientThread).doc("Display the variables and ports of a Component.").arg("Component", "Name of the Component");
210  this->addOperation("reportComponent", &ReportingComponent::reportComponent , this, RTT::ClientThread).doc("Add a peer Component and report all its data ports").arg("Component", "Name of the Component");
211  this->addOperation("unreportComponent", &ReportingComponent::unreportComponent , this, RTT::ClientThread).doc("Remove all Component's data ports from reporting.").arg("Component", "Name of the Component");
212  this->addOperation("reportData", &ReportingComponent::reportData , this, RTT::ClientThread).doc("Add a Component's Property or attribute for reporting.").arg("Component", "Name of the Component").arg("Data", "Name of the Data to report. A property's or attribute's name.");
213  this->addOperation("unreportData", &ReportingComponent::unreportData , this, RTT::ClientThread).doc("Remove a Data object from reporting.").arg("Component", "Name of the Component").arg("Data", "Name of the property or attribute.");
214  this->addOperation("reportPort", &ReportingComponent::reportPort , this, RTT::ClientThread).doc("Add a Component's OutputPort for reporting.").arg("Component", "Name of the Component").arg("Port", "Name of the Port.");
215  this->addOperation("unreportPort", &ReportingComponent::unreportPort , this, RTT::ClientThread).doc("Remove a Port from reporting.").arg("Component", "Name of the Component").arg("Port", "Name of the Port.");
216 
217  }
218 
220 
221 
223  {
224  boost::shared_ptr<marsh::MarshallInterface> header(headerM);
225  boost::shared_ptr<marsh::MarshallInterface> body(bodyM);
226  if ( !header && !body)
227  return false;
228  if ( !header )
229  header.reset( new EmptyMarshaller() );
230  if ( !body)
231  body.reset( new EmptyMarshaller());
232 
233  marshallers.push_back( std::make_pair( header, body ) );
234  return true;
235  }
236 
238  {
239  marshallers.clear();
240  return true;
241  }
242 
244  {
245  root.clear(); // uses shared_ptr.
247  }
248 
250  {
251  Logger::In in("ReportingComponent");
252 
253  // we make a copy to be allowed to iterate over and exted report_data:
254  PropertyBag bag = report_data.value();
255 
256  if ( bag.empty() ) {
257  log(Error) <<"No port or component configuration loaded."<<endlog();
258  log(Error) <<"Please use marshalling.loadProperties(), reportComponent() (scripting) or LoadProperties (XML) in order to fill in ReportData." <<endlog();
259  return false;
260  }
261 
262  bool ok = true;
263  PropertyBag::const_iterator it = bag.getProperties().begin();
264  while ( it != bag.getProperties().end() )
265  {
266  Property<std::string>* compName = dynamic_cast<Property<std::string>* >( *it );
267  if ( !compName )
268  log(Error) << "Expected Property \""
269  << (*it)->getName() <<"\" to be of type string."<< endlog();
270  else if ( compName->getName() == "Component" ) {
271  std::string name = compName->value(); // we will delete this property !
272  this->unreportComponent( name );
273  ok &= this->reportComponent( name );
274  }
275  else if ( compName->getName() == "Port" ) {
276  string cname = compName->value().substr(0, compName->value().find("."));
277  string pname = compName->value().substr( compName->value().find(".")+1, string::npos);
278  if (cname.empty() || pname.empty() ) {
279  log(Error) << "The Port value '"<<compName->getName()<< "' must at least consist of a component name followed by a dot and the port name." <<endlog();
280  ok = false;
281  continue;
282  }
283  this->unreportPort(cname,pname);
284  ok &= this->reportPort(cname, pname);
285  }
286  else if ( compName->getName() == "Data" ) {
287  string cname = compName->value().substr(0, compName->value().find("."));
288  string pname = compName->value().substr( compName->value().find(".")+1, string::npos);
289  if (cname.empty() || pname.empty() ) {
290  log(Error) << "The Data value '"<<compName->getName()<< "' must at least consist of a component name followed by a dot and the property/attribute name." <<endlog();
291  ok = false;
292  continue;
293  }
294  this->unreportData(cname,pname);
295  ok &= this->reportData(cname, pname);
296  }
297  else {
298  log(Error) << "Expected \"Component\", \"Port\" or \"Data\", got "
299  << compName->getName() << endlog();
300  ok = false;
301  }
302  ++it;
303  }
304  return ok;
305  }
306 
307  bool ReportingComponent::screenComponent( const std::string& comp )
308  {
309  Logger::In in("ReportingComponent::screenComponent");
310  log(Error) << "not implemented." <<comp<<endlog();
311  return false;
312  }
313 
314  bool ReportingComponent::screenImpl( const std::string& comp, std::ostream& output)
315  {
316  Logger::In in("ReportingComponent");
317  TaskContext* c = this->getPeer(comp);
318  if ( c == 0) {
319  log(Error) << "Unknown Component: " <<comp<<endlog();
320  return false;
321  }
322  output << "Screening Component '"<< comp << "' : "<< endl << endl;
323  PropertyBag* bag = c->properties();
324  if (bag) {
325  output << "Properties :" << endl;
326  for (PropertyBag::iterator it= bag->begin(); it != bag->end(); ++it)
327  output << " " << (*it)->getName() << " : " << (*it)->getDataSource() << endl;
328  }
329  ConfigurationInterface::AttributeNames atts = c->provides()->getAttributeNames();
330  if ( !atts.empty() ) {
331  output << "Attributes :" << endl;
332  for (ConfigurationInterface::AttributeNames::iterator it= atts.begin(); it != atts.end(); ++it)
333  output << " " << *it << " : " << c->provides()->getValue(*it)->getDataSource() << endl;
334  }
335 
336  vector<string> ports = c->ports()->getPortNames();
337  if ( !ports.empty() ) {
338  output << "Ports :" << endl;
339  for (vector<string>::iterator it= ports.begin(); it != ports.end(); ++it) {
340  output << " " << *it << " : ";
341  if (c->ports()->getPort(*it)->connected() )
342  output << "(connected)" << endl;
343  else
344  output << "(not connected)" << endl;
345  }
346  }
347  return true;
348  }
349 
350  bool ReportingComponent::reportComponent( const std::string& component ) {
351  Logger::In in("ReportingComponent");
352  // Users may add own data sources, so avoid duplicates
353  //std::vector<std::string> sources = comp->data()->getNames();
354  TaskContext* comp = this->getPeer(component);
355  if ( !comp ) {
356  log(Error) << "Could not report Component " << component <<" : no such peer."<<endlog();
357  return false;
358  }
359  if ( !report_data.value().findValue<string>(component) )
360  report_data.value().ownProperty( new Property<string>("Component","",component) );
361  Ports ports = comp->ports()->getPorts();
362  for (Ports::iterator it = ports.begin(); it != ports.end() ; ++it) {
363  log(Debug) << "Checking port " << (*it)->getName()<<"."<<endlog();
364  this->reportPort( component, (*it)->getName() );
365  }
366  return true;
367  }
368 
369 
370  bool ReportingComponent::unreportComponent( const std::string& component ) {
371  TaskContext* comp = this->getPeer(component);
372  if ( !comp ) {
373  log(Error) << "Could not unreport Component " << component <<" : no such peer."<<endlog();
374  return false;
375  }
376  Ports ports = comp->ports()->getPorts();
377  for (Ports::iterator it = ports.begin(); it != ports.end() ; ++it) {
378  this->unreportDataSource( component + "." + (*it)->getName() );
379  unreportPort(component, (*it)->getName() );
380  }
381  base::PropertyBase* pb = report_data.value().findValue<string>(component);
382  if (pb)
383  report_data.value().removeProperty( pb );// pb is deleted by bag
384  return true;
385  }
386 
387  // report a specific connection.
388  bool ReportingComponent::reportPort(const std::string& component, const std::string& port ) {
389  Logger::In in("ReportingComponent");
390  TaskContext* comp = this->getPeer(component);
391  if ( this->ports()->getPort(component +"_"+port) ) {
392  log(Warning) <<"Already reporting "<<component<<"."<<port<<": removing old port first."<<endlog();
393  this->unreportPort(component,port);
394  }
395  if ( !comp ) {
396  log(Error) << "Could not report Component " << component <<" : no such peer."<<endlog();
397  return false;
398  }
399  std::vector<std::string> strs;
400  boost::split(strs, port, boost::is_any_of("."));
401 
402  // strs could be empty because of a bug in Boost 1.44 (see https://svn.boost.org/trac/boost/ticket/4751)
403  if (strs.empty()) return false;
404 
405  Service::shared_ptr service=comp->provides();
406  while ( strs.size() != 1 && service) {
407  service = service->getService( strs.front() );
408  if (service)
409  strs.erase( strs.begin() );
410  }
411  if (!service) {
412  log(Error) <<"No such service: '"<< strs.front() <<"' while looking for port '"<< port<<"'"<<endlog();
413  return 0;
414  }
415  base::PortInterface* porti = 0;
416  porti = service->getPort(strs.front());
417  if ( !porti ) {
418  log(Error) << "Could not report Port " << port
419  <<" : no such port on Component "<<component<<"."<<endlog();
420  return false;
421  }
422 
423  base::InputPortInterface* ipi = dynamic_cast<base::InputPortInterface*>(porti);
424  if (ipi) {
425  log(Error) << "Can not report InputPort "<< porti->getName() <<" of Component " << component <<endlog();
426  return false;
427  }
428  // create new port temporarily
429  // this port is only created with the purpose of
430  // creating a connection object.
431  base::PortInterface* ourport = porti->antiClone();
432  assert(ourport);
433  ourport->setName(component + "_" + port);
434  ipi = dynamic_cast<base::InputPortInterface*> (ourport);
435  assert(ipi);
436 
438  log(Info) << "Not buffering of data flow connections. You may miss samples." <<endlog();
439  } else {
440  log(Info) << "Buffering ports with size "<< report_policy.size << ", as set in ReportPolicy property." <<endlog();
441  }
442 
443  this->ports()->addEventPort( *ipi );
444  if (porti->connectTo(ourport, report_policy ) == false)
445  {
446  log(Error) << "Could not connect to OutputPort " << porti->getName() << endlog();
447  this->ports()->removePort(ourport->getName());
448  delete ourport; // XXX/TODO We're leaking ourport !
449  return false;
450  }
451 
452  if (this->reportDataSource(component + "." + port, "Port",
453  ipi->getDataSource(),ipi, true) == false)
454  {
455  log(Error) << "Failed reporting port " << port << endlog();
456  this->ports()->removePort(ourport->getName());
457  delete ourport;
458  return false;
459  }
460 
461  log(Info) << "Monitoring OutputPort " << port << " : ok." << endlog();
462  // Add port to ReportData properties if component nor port are listed yet.
463  if ( !report_data.value().findValue<string>(component) && !report_data.value().findValue<string>( component+"."+port) )
464  report_data.value().ownProperty(new Property<string>("Port","",component+"."+port));
465  return true;
466  }
467 
468  bool ReportingComponent::unreportPort(const std::string& component, const std::string& port ) {
469  base::PortInterface* ourport = this->ports()->getPort(component + "_" + port);
470  if ( this->unreportDataSource( component + "." + port ) && report_data.value().removeProperty( report_data.value().findValue<string>(component+"."+port))) {
471  this->ports()->removePort(ourport->getName());
472  delete ourport; // also deletes datasource.
473  return true;
474  }
475  return false;
476  }
477 
478  // report a specific datasource, property,...
479  bool ReportingComponent::reportData(const std::string& component,const std::string& dataname)
480  {
481  Logger::In in("ReportingComponent");
482  TaskContext* comp = this->getPeer(component);
483  if ( !comp ) {
484  log(Error) << "Could not report Component " << component <<" : no such peer."<<endlog();
485  return false;
486  }
487  // Is it an attribute ?
488  if ( comp->provides()->getValue( dataname ) ) {
489  if (this->reportDataSource( component + "." + dataname, "Data",
490  comp->provides()->getValue( dataname )->getDataSource(), 0, false ) == false) {
491  log(Error) << "Failed reporting data " << dataname <<endlog();
492  return false;
493  }
494  }
495 
496  // Is it a property ?
497  if ( comp->properties() && comp->properties()->find( dataname ) ) {
498  if (this->reportDataSource( component + "." + dataname, "Data",
499  comp->properties()->find( dataname )->getDataSource(), 0, false ) == false) {
500  log(Error) << "Failed reporting data " << dataname <<endlog();
501  return false;
502  }
503  }
504  // Ok. we passed.
505  // Add port to ReportData properties if data not listed yet.
506  if ( !report_data.value().findValue<string>( component+"."+dataname) )
507  report_data.value().ownProperty(new Property<string>("Data","",component+"."+dataname));
508  return true;
509  }
510 
511  bool ReportingComponent::unreportData(const std::string& component,const std::string& datasource) {
512  return this->unreportDataSource( component +"." + datasource) && report_data.value().removeProperty( report_data.value().findValue<string>(component+"."+datasource));
513  }
514 
515  bool ReportingComponent::reportDataSource(std::string tag, std::string type, base::DataSourceBase::shared_ptr orig, base::InputPortInterface* ipi, bool track)
516  {
517  // check for duplicates:
518  for (Reports::iterator it = root.begin();
519  it != root.end(); ++it)
520  if ( it->get<T_QualName>() == tag ) {
521  return true;
522  }
523 
524  // creates a copy of the data and an update command to
525  // update the copy from the original.
526  base::DataSourceBase::shared_ptr clone = orig->getTypeInfo()->buildValue();
527  if ( !clone ) {
528  log(Error) << "Could not report '"<< tag <<"' : unknown type." << endlog();
529  return false;
530  }
531  PropertyBase* prop = 0;
532  root.push_back( boost::make_tuple( tag, orig, type, prop, ipi, false, track ) );
533  return true;
534  }
535 
537  {
538  for (Reports::iterator it = root.begin();
539  it != root.end(); ++it)
540  if ( it->get<T_QualName>() == tag ) {
541  root.erase(it);
542  return true;
543  }
544  return false;
545  }
546 
548  Logger::In in("ReportingComponent");
549  if (marshallers.begin() == marshallers.end()) {
550  log(Error) << "Need at least one marshaller to write reports." <<endlog();
551  return false;
552  }
553 
556  else
557  starttime = os::TimeService::Instance()->getTicks();
558 
559  // Get initial data samples
560  this->copydata();
561  this->makeReport2();
562 
563  // write headers
564  if (writeHeader.get()) {
565  // call all header marshallers.
566  for(Marshallers::iterator it=marshallers.begin(); it != marshallers.end(); ++it) {
567  it->first->serialize( report );
568  it->first->flush();
569  }
570  }
571 
572  // write initial values with all value marshallers (uses the forcing above)
573  if ( getActivity()->isPeriodic() ) {
574  for(Marshallers::iterator it=marshallers.begin(); it != marshallers.end(); ++it) {
575  it->second->serialize( report );
576  it->second->flush();
577  }
578  }
579 
580  // Turn off port triggering in snapshot mode, and vice versa.
581  // Also clears any old data in the buffers
582  for(Reports::iterator it = root.begin(); it != root.end(); ++it )
583  if ( it->get<T_Port>() ) {
584 #ifndef ORO_SIGNALLING_PORTS
585  it->get<T_Port>()->signalInterface( !insnapshot.get() );
586 #endif
587  it->get<T_Port>()->clear();
588  }
589 
590 
591  snapshotted = false;
592  return true;
593  }
594 
596  // this function always copies and reports all data It's run in ownthread, so updateHook will be run later.
597  if ( getActivity()->isPeriodic() )
598  return;
599  snapshotted = true;
600  updateHook();
601  }
602 
604  timestamp = os::TimeService::Instance()->secondsSince( starttime );
605 
606  // result will become true if more data is to be read.
607  bool result = false;
608  // This evaluates the InputPortDataSource evaluate() returns true upon new data.
609  for(Reports::iterator it = root.begin(); it != root.end(); ++it ) {
610  it->get<T_NewData>() = (it->get<T_PortDS>())->evaluate(); // stores 'NewData' flag.
611  // if its a property/attr, get<T_NewData> will always be true, so we override (clear) with get<T_Tracked>.
612  result = result || ( it->get<T_NewData>() && it->get<T_Tracked>() );
613  }
614  return result;
615  }
616 
618  {
619  // Uses the port DS itself to make the report.
620  assert( report.empty() );
621  // For the timestamp, we need to add a new property object:
624  for(Reports::iterator it = root.begin(); it != root.end(); ++it ) {
625  Property<PropertyBag>* subbag = new Property<PropertyBag>( it->get<T_QualName>(), "");
626  bool decompose_success = false;
627  if ( decompose.get() ) {
628  if ( complexdecompose.get() ) decompose_success = RTT::types::typeDecomposition( it->get<T_PortDS>(), subbag->value(), true );
629  else decompose_success = memberDecomposition( it->get<T_PortDS>(), subbag->value(), checker );
630  }
631  if ( decompose_success ) {
632  report.add( subbag );
633  it->get<T_Property>() = subbag;
634  } else {
635  // property or simple value port...
636  base::DataSourceBase::shared_ptr converted = it->get<T_PortDS>()->getTypeInfo()->convertType( it->get<T_PortDS>() );
637  if ( converted && converted != it->get<T_PortDS>() ) {
638  // converted contains another type.
639  PropertyBase* convProp = converted->getTypeInfo()->buildProperty(it->get<T_QualName>(), "", converted);
640  it->get<T_Property>() = convProp;
641  report.add(convProp);
642  } else {
643  PropertyBase* origProp = it->get<T_PortDS>()->getTypeInfo()->buildProperty(it->get<T_QualName>(), "", it->get<T_PortDS>());
644  it->get<T_Property>() = origProp;
645  report.add(origProp);
646  }
647  delete subbag;
648  }
649 
650  }
651  mchecker = checker;
652  }
653 
655  {
656  // Only clones were added to result, so delete them.
658  }
659 
661  //If not periodic and insnapshot is true, only continue if snapshot is called.
662  if( !getActivity()->isPeriodic() && insnapshot.get() && !snapshotted)
663  return;
664  else
665  snapshotted = false;
666 
667  // if any data sequence got resized, we rebuild the whole bunch.
668  // otherwise, we need to track every individual array (not impossible though, but still needs an upstream concept).
669  if ( mchecker && mchecker->get() == false ) {
670  cleanReport();
671  makeReport2();
672  } else
673  copydata();
674 
675  do {
676  // Step 3: print out the result
677  // write out to all marshallers
678  for(Marshallers::iterator it=marshallers.begin(); it != marshallers.end(); ++it) {
679  if ( onlyNewData ) {
680  // Serialize only changed ports:
681  it->second->serialize( *report.begin() ); // TimeStamp.
682  for (Reports::const_iterator i = root.begin();
683  i != root.end();
684  i++ )
685  {
686  if ( i->get<T_NewData>() )
687  it->second->serialize( i->get<T_Property>() );
688  }
689  } else {
690  // pass on all ports to the marshaller
691  it->second->serialize( report );
692  }
693  it->second->flush();
694  }
695  } while( !getActivity()->isPeriodic() && !insnapshot.get() && copydata() ); // repeat if necessary. In periodic mode we always only sample once.
696  }
697 
699  // tell body marshallers that serialization is done.
700  for(Marshallers::iterator it=marshallers.begin(); it != marshallers.end(); ++it) {
701  it->second->flush();
702  }
703  cleanReport();
704  }
705 
706 }
virtual base::DataSourceBase::shared_ptr getDataSource() const
DataSourceType get() const
DataSource< bool >::shared_ptr mupstream
virtual result_t get() const =0
iterator end()
void add(base::PropertyBase *p)
bool addMarshaller(RTT::marsh::MarshallInterface *headerM, RTT::marsh::MarshallInterface *bodyM)
base::PortInterface * getPort(const std::string &name) const
Service::shared_ptr provides()
RTT::Property< RTT::os::TimeService::Seconds > timestamp
PortNames getPortNames() const
RTT::Property< bool > synchronize_with_logging
bool unreportComponent(const std::string &component)
static Logger * Instance(std::ostream &str=std::cerr)
RTT::Property< bool > writeHeader
RTT::Property< bool > insnapshot
void setType(const std::string &newtype)
static int report(lua_State *L, int status)
Definition: lua-repl.c:75
RTT::internal::DataSource< bool >::shared_ptr mchecker
If false, a sequence size has changed.
const std::string & getName() const
A Dummy Empty MarshallInterface.
static const int DATA
base::InputPortInterface & addEventPort(const std::string &name, base::InputPortInterface &port, SlotFunction callback=SlotFunction())
bool unreportPort(const std::string &component, const std::string &port)
reference_t value()
bool ownProperty(base::PropertyBase *p)
RTT::DataFlowInterface::Ports Ports
virtual TaskContext * getPeer(const std::string &peer_name) const
boost::shared_ptr< Service > shared_ptr
RTT::Property< bool > complexdecompose
void deletePropertyBag(PropertyBag &target)
std::vector< std::string > AttributeNames
bool unreportDataSource(std::string tag)
DataFlowInterface * ports()
Property< T > & addProperty(const std::string &name, T &attr)
base::PortInterface * getPort(const std::string &name) const
base::PropertyBase * find(const std::string &name) const
void removePort(const std::string &name)
res evaluate()
CheckSizeDataSource(int size, DataSource< int >::shared_ptr ds, DataSource< bool >::shared_ptr upstream)
virtual DataSourceBase * getDataSource()=0
Debug
bool unreportData(const std::string &component, const std::string &datasource)
bool reportPort(const std::string &component, const std::string &port)
virtual const types::TypeInfo * getTypeInfo() const
bool setName(const std::string &name)
base::PropertyBase * buildProperty(const std::string &name, const std::string &desc, base::DataSourceBase::shared_ptr source=0) const
bool reportData(const std::string &component, const std::string &dataname)
Properties & getProperties()
virtual PortInterface * antiClone() const =0
Properties::const_iterator const_iterator
basic_ostreams & endl(basic_ostreams &s)
bool empty() const
Error
bool typeDecomposition(base::DataSourceBase::shared_ptr dsb, PropertyBag &targetbag, bool recurse)
boost::intrusive_ptr< DataSource< int > > shared_ptr
bool screenImpl(const std::string &comp, std::ostream &output)
Info
bool reportDataSource(std::string tag, std::string type, RTT::base::DataSourceBase::shared_ptr origm, RTT::base::InputPortInterface *ipi, bool)
static DataSource< int > * narrow(base::DataSourceBase *db)
PropertyBag * properties()
Warning
virtual bool connectTo(PortInterface *other, ConnPolicy const &policy)=0
const std::string & getName() const
bool memberDecomposition(base::DataSourceBase::shared_ptr dsb, PropertyBag &targetbag, DataSource< bool >::shared_ptr &resized)
Ports getPorts() const
RTT::Property< bool > decompose
virtual bool screenComponent(const std::string &comp)
RTT::Property< PropertyBag > report_data
Properties::iterator iterator
boost::intrusive_ptr< DataSourceBase > shared_ptr
DataSource< int >::shared_ptr mds
virtual bool connected() const =0
RTT::os::TimeService::ticks starttime
Operation< Signature > & addOperation(Operation< Signature > &op)
ORO_CREATE_COMPONENT_TYPE()
ClientThread
base::ActivityInterface * getActivity()
virtual DataSourceBase::shared_ptr getDataSource() const =0
iterator begin()
os::TimeService::ticks getReferenceTime() const
virtual void clear()
bool reportComponent(const std::string &component)


ocl
Author(s): OCL Development Team
autogenerated on Mon Mar 23 2020 04:47:19