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  auto_ptr< Property<PropertyBag> > recurse_bag( new Property<PropertyBag>("recurse_bag","") );
100  // First at the explicitly listed parts:
101  for(vector<string>::iterator it = parts.begin(); it != parts.end(); ++it ) {
102  // we first force getMember to get to the type, then we do it again but with a reference set.
103  DataSourceBase::shared_ptr part = dsb->getMember( *it );
104  if (!part) {
105  log(Error) <<"memberDecomposition: Inconsistent type info for "<< dsb->getTypeName() << ": reported to have part '"<<*it<<"' but failed to return it."<<endlog();
106  continue;
107  }
108  if ( !part->isAssignable() ) {
109  // For example: the case for size() and capacity() in SequenceTypeInfo
110  log(Debug)<<"memberDecomposition: Part "<< *it << ":"<< part->getTypeName() << " is not changeable."<<endlog();
111  continue;
112  }
113  // now the reference magic:
114  DataSourceBase::shared_ptr ref = part->getTypeInfo()->buildReference( 0 );
115  dsb->getTypeInfo()->getMember( dynamic_cast<Reference*>(ref.get() ), dsb, *it); // fills in ref
116  // newpb will contain a reference to the port's datasource data !
117  PropertyBase* newpb = part->getTypeInfo()->buildProperty(*it,"Part", ref);
118  if ( !newpb ) {
119  log(Error)<< "Decomposition failed because Part '"<<*it<<"' is not known to type system."<<endlog();
120  continue;
121  }
122  // finally recurse or add it to the target bag:
123  if ( !memberDecomposition( ref, recurse_bag->value(), resized) ) {
124  assert( recurse_bag->value().empty() );
125  // finally: check for conversions (enums use this):
126  base::DataSourceBase::shared_ptr converted = newpb->getTypeInfo()->convertType( dsb );
127  if ( converted && converted != dsb ) {
128  // converted contains another type.
129  targetbag.add( converted->getTypeInfo()->buildProperty(*it, "", converted) );
130  delete newpb;
131  } else
132  targetbag.ownProperty( newpb ); // leaf
133  } else {
134  recurse_bag->setName(*it);
135  // setType() is done by recursive of self.
136  targetbag.ownProperty( recurse_bag.release() ); //recursed.
137  recurse_bag.reset( new Property<PropertyBag>("recurse_bag","") );
138  delete newpb; // since we recursed, the recurse_bag now 'embodies' newpb.
139  }
140  }
141 
142  // Next get the numbered parts. This is much more involved since sequences may be resizable.
143  // We keep track of the size, and if that changes, we will have to force a re-decomposition
144  // of the sequence's internals.
145  DataSource<int>::shared_ptr size = DataSource<int>::narrow( dsb->getMember("size").get() );
146  if (size) {
147  int msize = size->get();
148  for (int i=0; i < msize; ++i) {
149  string indx = boost::lexical_cast<string>( i );
150  DataSourceBase::shared_ptr item = dsb->getMember(indx);
151  resized = new CheckSizeDataSource( msize, size, resized );
152  if (item) {
153  if ( !item->isAssignable() ) {
154  // For example: the case for size() and capacity() in SequenceTypeInfo
155  log(Warning)<<"memberDecomposition: Item '"<< indx << "' of type "<< dsb->getTypeName() << " is not changeable."<<endlog();
156  continue;
157  }
158  // finally recurse or add it to the target bag:
159  PropertyBase* newpb = item->getTypeInfo()->buildProperty( indx,"",item);
160  if ( !memberDecomposition( item, recurse_bag->value(), resized) ) {
161  targetbag.ownProperty( newpb ); // leaf
162  } else {
163  delete newpb;
164  recurse_bag->setName( indx );
165  // setType() is done by recursive of self.
166  targetbag.ownProperty( recurse_bag.release() ); //recursed.
167  recurse_bag.reset( new Property<PropertyBag>("recurse_bag","") );
168  }
169  }
170  }
171  }
172  if (targetbag.empty() )
173  log(Debug) << "memberDecomposition: "<< dsb->getTypeName() << " returns an empty property bag." << endlog();
174  return true;
175  }
176 
177  ReportingComponent::ReportingComponent( std::string name /*= "Reporting" */ )
178  : TaskContext( name ),
179  report("Report"), snapshotted(false),
180  writeHeader("WriteHeader","Set to true to start each report with a header.", true),
181  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),
182  complexdecompose("ComplexDecompose","Use slow but more robust procedure for port data decomposition.", false),
183  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),
184  synchronize_with_logging("Synchronize","Set to true if the timestamp should be synchronized with the logging",false),
185  report_data("ReportData","A PropertyBag which defines which ports or components to report."),
186  report_policy( ConnPolicy::data(ConnPolicy::LOCK_FREE,true,false) ),
187  onlyNewData(false),
188  starttime(0),
189  timestamp("TimeStamp","The time at which the data was read.",0.0)
190  {
191  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.");
192 
193  this->properties()->addProperty( writeHeader );
194  this->properties()->addProperty( decompose );
196  this->properties()->addProperty( insnapshot );
199  this->properties()->addProperty( "ReportPolicy", report_policy).doc("The ConnPolicy for the reporter's port connections.");
200  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).");
201  // Add the methods, methods make sure that they are
202  // executed in the context of the (non realtime) caller.
203 
204  this->addOperation("snapshot", &ReportingComponent::snapshot , this, RTT::OwnThread).doc("Take a new shapshot of all data and cause them to be written out.");
205  this->addOperation("screenComponent", &ReportingComponent::screenComponent , this, RTT::ClientThread).doc("Display the variables and ports of a Component.").arg("Component", "Name of the Component");
206  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");
207  this->addOperation("unreportComponent", &ReportingComponent::unreportComponent , this, RTT::ClientThread).doc("Remove all Component's data ports from reporting.").arg("Component", "Name of the Component");
208  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.");
209  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.");
210  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.");
211  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.");
212 
213  }
214 
216 
217 
219  {
220  boost::shared_ptr<marsh::MarshallInterface> header(headerM);
221  boost::shared_ptr<marsh::MarshallInterface> body(bodyM);
222  if ( !header && !body)
223  return false;
224  if ( !header )
225  header.reset( new EmptyMarshaller() );
226  if ( !body)
227  body.reset( new EmptyMarshaller());
228 
229  marshallers.push_back( std::make_pair( header, body ) );
230  return true;
231  }
232 
234  {
235  marshallers.clear();
236  return true;
237  }
238 
240  {
241  root.clear(); // uses shared_ptr.
243  }
244 
246  {
247  Logger::In in("ReportingComponent");
248 
249  // we make a copy to be allowed to iterate over and exted report_data:
250  PropertyBag bag = report_data.value();
251 
252  if ( bag.empty() ) {
253  log(Error) <<"No port or component configuration loaded."<<endlog();
254  log(Error) <<"Please use marshalling.loadProperties(), reportComponent() (scripting) or LoadProperties (XML) in order to fill in ReportData." <<endlog();
255  return false;
256  }
257 
258  bool ok = true;
259  PropertyBag::const_iterator it = bag.getProperties().begin();
260  while ( it != bag.getProperties().end() )
261  {
262  Property<std::string>* compName = dynamic_cast<Property<std::string>* >( *it );
263  if ( !compName )
264  log(Error) << "Expected Property \""
265  << (*it)->getName() <<"\" to be of type string."<< endlog();
266  else if ( compName->getName() == "Component" ) {
267  std::string name = compName->value(); // we will delete this property !
268  this->unreportComponent( name );
269  ok &= this->reportComponent( name );
270  }
271  else if ( compName->getName() == "Port" ) {
272  string cname = compName->value().substr(0, compName->value().find("."));
273  string pname = compName->value().substr( compName->value().find(".")+1, string::npos);
274  if (cname.empty() || pname.empty() ) {
275  log(Error) << "The Port value '"<<compName->getName()<< "' must at least consist of a component name followed by a dot and the port name." <<endlog();
276  ok = false;
277  continue;
278  }
279  this->unreportPort(cname,pname);
280  ok &= this->reportPort(cname, pname);
281  }
282  else if ( compName->getName() == "Data" ) {
283  string cname = compName->value().substr(0, compName->value().find("."));
284  string pname = compName->value().substr( compName->value().find(".")+1, string::npos);
285  if (cname.empty() || pname.empty() ) {
286  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();
287  ok = false;
288  continue;
289  }
290  this->unreportData(cname,pname);
291  ok &= this->reportData(cname, pname);
292  }
293  else {
294  log(Error) << "Expected \"Component\", \"Port\" or \"Data\", got "
295  << compName->getName() << endlog();
296  ok = false;
297  }
298  ++it;
299  }
300  return ok;
301  }
302 
303  bool ReportingComponent::screenComponent( const std::string& comp )
304  {
305  Logger::In in("ReportingComponent::screenComponent");
306  log(Error) << "not implemented." <<comp<<endlog();
307  return false;
308  }
309 
310  bool ReportingComponent::screenImpl( const std::string& comp, std::ostream& output)
311  {
312  Logger::In in("ReportingComponent");
313  TaskContext* c = this->getPeer(comp);
314  if ( c == 0) {
315  log(Error) << "Unknown Component: " <<comp<<endlog();
316  return false;
317  }
318  output << "Screening Component '"<< comp << "' : "<< endl << endl;
319  PropertyBag* bag = c->properties();
320  if (bag) {
321  output << "Properties :" << endl;
322  for (PropertyBag::iterator it= bag->begin(); it != bag->end(); ++it)
323  output << " " << (*it)->getName() << " : " << (*it)->getDataSource() << endl;
324  }
325  ConfigurationInterface::AttributeNames atts = c->provides()->getAttributeNames();
326  if ( !atts.empty() ) {
327  output << "Attributes :" << endl;
328  for (ConfigurationInterface::AttributeNames::iterator it= atts.begin(); it != atts.end(); ++it)
329  output << " " << *it << " : " << c->provides()->getValue(*it)->getDataSource() << endl;
330  }
331 
332  vector<string> ports = c->ports()->getPortNames();
333  if ( !ports.empty() ) {
334  output << "Ports :" << endl;
335  for (vector<string>::iterator it= ports.begin(); it != ports.end(); ++it) {
336  output << " " << *it << " : ";
337  if (c->ports()->getPort(*it)->connected() )
338  output << "(connected)" << endl;
339  else
340  output << "(not connected)" << endl;
341  }
342  }
343  return true;
344  }
345 
346  bool ReportingComponent::reportComponent( const std::string& component ) {
347  Logger::In in("ReportingComponent");
348  // Users may add own data sources, so avoid duplicates
349  //std::vector<std::string> sources = comp->data()->getNames();
350  TaskContext* comp = this->getPeer(component);
351  if ( !comp ) {
352  log(Error) << "Could not report Component " << component <<" : no such peer."<<endlog();
353  return false;
354  }
355  if ( !report_data.value().findValue<string>(component) )
356  report_data.value().ownProperty( new Property<string>("Component","",component) );
357  Ports ports = comp->ports()->getPorts();
358  for (Ports::iterator it = ports.begin(); it != ports.end() ; ++it) {
359  log(Debug) << "Checking port " << (*it)->getName()<<"."<<endlog();
360  this->reportPort( component, (*it)->getName() );
361  }
362  return true;
363  }
364 
365 
366  bool ReportingComponent::unreportComponent( const std::string& component ) {
367  TaskContext* comp = this->getPeer(component);
368  if ( !comp ) {
369  log(Error) << "Could not unreport Component " << component <<" : no such peer."<<endlog();
370  return false;
371  }
372  Ports ports = comp->ports()->getPorts();
373  for (Ports::iterator it = ports.begin(); it != ports.end() ; ++it) {
374  this->unreportDataSource( component + "." + (*it)->getName() );
375  unreportPort(component, (*it)->getName() );
376  }
377  base::PropertyBase* pb = report_data.value().findValue<string>(component);
378  if (pb)
379  report_data.value().removeProperty( pb );// pb is deleted by bag
380  return true;
381  }
382 
383  // report a specific connection.
384  bool ReportingComponent::reportPort(const std::string& component, const std::string& port ) {
385  Logger::In in("ReportingComponent");
386  TaskContext* comp = this->getPeer(component);
387  if ( this->ports()->getPort(component +"_"+port) ) {
388  log(Warning) <<"Already reporting "<<component<<"."<<port<<": removing old port first."<<endlog();
389  this->unreportPort(component,port);
390  }
391  if ( !comp ) {
392  log(Error) << "Could not report Component " << component <<" : no such peer."<<endlog();
393  return false;
394  }
395  std::vector<std::string> strs;
396  boost::split(strs, port, boost::is_any_of("."));
397 
398  // strs could be empty because of a bug in Boost 1.44 (see https://svn.boost.org/trac/boost/ticket/4751)
399  if (strs.empty()) return false;
400 
401  Service::shared_ptr service=comp->provides();
402  while ( strs.size() != 1 && service) {
403  service = service->getService( strs.front() );
404  if (service)
405  strs.erase( strs.begin() );
406  }
407  if (!service) {
408  log(Error) <<"No such service: '"<< strs.front() <<"' while looking for port '"<< port<<"'"<<endlog();
409  return 0;
410  }
411  base::PortInterface* porti = 0;
412  porti = service->getPort(strs.front());
413  if ( !porti ) {
414  log(Error) << "Could not report Port " << port
415  <<" : no such port on Component "<<component<<"."<<endlog();
416  return false;
417  }
418 
419  base::InputPortInterface* ipi = dynamic_cast<base::InputPortInterface*>(porti);
420  if (ipi) {
421  log(Error) << "Can not report InputPort "<< porti->getName() <<" of Component " << component <<endlog();
422  return false;
423  }
424  // create new port temporarily
425  // this port is only created with the purpose of
426  // creating a connection object.
427  base::PortInterface* ourport = porti->antiClone();
428  assert(ourport);
429  ourport->setName(component + "_" + port);
430  ipi = dynamic_cast<base::InputPortInterface*> (ourport);
431  assert(ipi);
432 
434  log(Info) << "Not buffering of data flow connections. You may miss samples." <<endlog();
435  } else {
436  log(Info) << "Buffering ports with size "<< report_policy.size << ", as set in ReportPolicy property." <<endlog();
437  }
438 
439  this->ports()->addEventPort( *ipi );
440  if (porti->connectTo(ourport, report_policy ) == false)
441  {
442  log(Error) << "Could not connect to OutputPort " << porti->getName() << endlog();
443  this->ports()->removePort(ourport->getName());
444  delete ourport; // XXX/TODO We're leaking ourport !
445  return false;
446  }
447 
448  if (this->reportDataSource(component + "." + port, "Port",
449  ipi->getDataSource(),ipi, true) == false)
450  {
451  log(Error) << "Failed reporting port " << port << endlog();
452  this->ports()->removePort(ourport->getName());
453  delete ourport;
454  return false;
455  }
456 
457  log(Info) << "Monitoring OutputPort " << port << " : ok." << endlog();
458  // Add port to ReportData properties if component nor port are listed yet.
459  if ( !report_data.value().findValue<string>(component) && !report_data.value().findValue<string>( component+"."+port) )
460  report_data.value().ownProperty(new Property<string>("Port","",component+"."+port));
461  return true;
462  }
463 
464  bool ReportingComponent::unreportPort(const std::string& component, const std::string& port ) {
465  base::PortInterface* ourport = this->ports()->getPort(component + "_" + port);
466  if ( this->unreportDataSource( component + "." + port ) && report_data.value().removeProperty( report_data.value().findValue<string>(component+"."+port))) {
467  this->ports()->removePort(ourport->getName());
468  delete ourport; // also deletes datasource.
469  return true;
470  }
471  return false;
472  }
473 
474  // report a specific datasource, property,...
475  bool ReportingComponent::reportData(const std::string& component,const std::string& dataname)
476  {
477  Logger::In in("ReportingComponent");
478  TaskContext* comp = this->getPeer(component);
479  if ( !comp ) {
480  log(Error) << "Could not report Component " << component <<" : no such peer."<<endlog();
481  return false;
482  }
483  // Is it an attribute ?
484  if ( comp->provides()->getValue( dataname ) ) {
485  if (this->reportDataSource( component + "." + dataname, "Data",
486  comp->provides()->getValue( dataname )->getDataSource(), 0, false ) == false) {
487  log(Error) << "Failed reporting data " << dataname <<endlog();
488  return false;
489  }
490  }
491 
492  // Is it a property ?
493  if ( comp->properties() && comp->properties()->find( dataname ) ) {
494  if (this->reportDataSource( component + "." + dataname, "Data",
495  comp->properties()->find( dataname )->getDataSource(), 0, false ) == false) {
496  log(Error) << "Failed reporting data " << dataname <<endlog();
497  return false;
498  }
499  }
500  // Ok. we passed.
501  // Add port to ReportData properties if data not listed yet.
502  if ( !report_data.value().findValue<string>( component+"."+dataname) )
503  report_data.value().ownProperty(new Property<string>("Data","",component+"."+dataname));
504  return true;
505  }
506 
507  bool ReportingComponent::unreportData(const std::string& component,const std::string& datasource) {
508  return this->unreportDataSource( component +"." + datasource) && report_data.value().removeProperty( report_data.value().findValue<string>(component+"."+datasource));
509  }
510 
511  bool ReportingComponent::reportDataSource(std::string tag, std::string type, base::DataSourceBase::shared_ptr orig, base::InputPortInterface* ipi, bool track)
512  {
513  // check for duplicates:
514  for (Reports::iterator it = root.begin();
515  it != root.end(); ++it)
516  if ( it->get<T_QualName>() == tag ) {
517  return true;
518  }
519 
520  // creates a copy of the data and an update command to
521  // update the copy from the original.
522  base::DataSourceBase::shared_ptr clone = orig->getTypeInfo()->buildValue();
523  if ( !clone ) {
524  log(Error) << "Could not report '"<< tag <<"' : unknown type." << endlog();
525  return false;
526  }
527  PropertyBase* prop = 0;
528  root.push_back( boost::make_tuple( tag, orig, type, prop, ipi, false, track ) );
529  return true;
530  }
531 
533  {
534  for (Reports::iterator it = root.begin();
535  it != root.end(); ++it)
536  if ( it->get<T_QualName>() == tag ) {
537  root.erase(it);
538  return true;
539  }
540  return false;
541  }
542 
544  Logger::In in("ReportingComponent");
545  if (marshallers.begin() == marshallers.end()) {
546  log(Error) << "Need at least one marshaller to write reports." <<endlog();
547  return false;
548  }
549 
552  else
553  starttime = os::TimeService::Instance()->getTicks();
554 
555  // Get initial data samples
556  this->copydata();
557  this->makeReport2();
558 
559  // write headers
560  if (writeHeader.get()) {
561  // call all header marshallers.
562  for(Marshallers::iterator it=marshallers.begin(); it != marshallers.end(); ++it) {
563  it->first->serialize( report );
564  it->first->flush();
565  }
566  }
567 
568  // write initial values with all value marshallers (uses the forcing above)
569  if ( getActivity()->isPeriodic() ) {
570  for(Marshallers::iterator it=marshallers.begin(); it != marshallers.end(); ++it) {
571  it->second->serialize( report );
572  it->second->flush();
573  }
574  }
575 
576  // Turn off port triggering in snapshot mode, and vice versa.
577  // Also clears any old data in the buffers
578  for(Reports::iterator it = root.begin(); it != root.end(); ++it )
579  if ( it->get<T_Port>() ) {
580 #ifndef ORO_SIGNALLING_PORTS
581  it->get<T_Port>()->signalInterface( !insnapshot.get() );
582 #endif
583  it->get<T_Port>()->clear();
584  }
585 
586 
587  snapshotted = false;
588  return true;
589  }
590 
592  // this function always copies and reports all data It's run in ownthread, so updateHook will be run later.
593  if ( getActivity()->isPeriodic() )
594  return;
595  snapshotted = true;
596  updateHook();
597  }
598 
600  timestamp = os::TimeService::Instance()->secondsSince( starttime );
601 
602  // result will become true if more data is to be read.
603  bool result = false;
604  // This evaluates the InputPortDataSource evaluate() returns true upon new data.
605  for(Reports::iterator it = root.begin(); it != root.end(); ++it ) {
606  it->get<T_NewData>() = (it->get<T_PortDS>())->evaluate(); // stores 'NewData' flag.
607  // if its a property/attr, get<T_NewData> will always be true, so we override (clear) with get<T_Tracked>.
608  result = result || ( it->get<T_NewData>() && it->get<T_Tracked>() );
609  }
610  return result;
611  }
612 
614  {
615  // Uses the port DS itself to make the report.
616  assert( report.empty() );
617  // For the timestamp, we need to add a new property object:
620  for(Reports::iterator it = root.begin(); it != root.end(); ++it ) {
621  Property<PropertyBag>* subbag = new Property<PropertyBag>( it->get<T_QualName>(), "");
622  bool decompose_success = false;
623  if ( decompose.get() ) {
624  if ( complexdecompose.get() ) decompose_success = RTT::types::typeDecomposition( it->get<T_PortDS>(), subbag->value(), true );
625  else decompose_success = memberDecomposition( it->get<T_PortDS>(), subbag->value(), checker );
626  }
627  if ( decompose_success ) {
628  report.add( subbag );
629  it->get<T_Property>() = subbag;
630  } else {
631  // property or simple value port...
632  base::DataSourceBase::shared_ptr converted = it->get<T_PortDS>()->getTypeInfo()->convertType( it->get<T_PortDS>() );
633  if ( converted && converted != it->get<T_PortDS>() ) {
634  // converted contains another type.
635  PropertyBase* convProp = converted->getTypeInfo()->buildProperty(it->get<T_QualName>(), "", converted);
636  it->get<T_Property>() = convProp;
637  report.add(convProp);
638  } else {
639  PropertyBase* origProp = it->get<T_PortDS>()->getTypeInfo()->buildProperty(it->get<T_QualName>(), "", it->get<T_PortDS>());
640  it->get<T_Property>() = origProp;
641  report.add(origProp);
642  }
643  delete subbag;
644  }
645 
646  }
647  mchecker = checker;
648  }
649 
651  {
652  // Only clones were added to result, so delete them.
654  }
655 
657  //If not periodic and insnapshot is true, only continue if snapshot is called.
658  if( !getActivity()->isPeriodic() && insnapshot.get() && !snapshotted)
659  return;
660  else
661  snapshotted = false;
662 
663  // if any data sequence got resized, we rebuild the whole bunch.
664  // otherwise, we need to track every individual array (not impossible though, but still needs an upstream concept).
665  if ( mchecker && mchecker->get() == false ) {
666  cleanReport();
667  makeReport2();
668  } else
669  copydata();
670 
671  do {
672  // Step 3: print out the result
673  // write out to all marshallers
674  for(Marshallers::iterator it=marshallers.begin(); it != marshallers.end(); ++it) {
675  if ( onlyNewData ) {
676  // Serialize only changed ports:
677  it->second->serialize( *report.begin() ); // TimeStamp.
678  for (Reports::const_iterator i = root.begin();
679  i != root.end();
680  i++ )
681  {
682  if ( i->get<T_NewData>() )
683  it->second->serialize( i->get<T_Property>() );
684  }
685  } else {
686  // pass on all ports to the marshaller
687  it->second->serialize( report );
688  }
689  it->second->flush();
690  }
691  } while( !getActivity()->isPeriodic() && !insnapshot.get() && copydata() ); // repeat if necessary. In periodic mode we always only sample once.
692  }
693 
695  // tell body marshallers that serialization is done.
696  for(Marshallers::iterator it=marshallers.begin(); it != marshallers.end(); ++it) {
697  it->second->flush();
698  }
699  cleanReport();
700  }
701 
702 }
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 Wed Jun 26 2019 19:26:27