GammaWare  Head Version for release 0.9
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
BaseEmulator.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2004-2006 by Olivier Stezowski & Christian Finck *
3  * stezow(AT)ipnl.in2p3.fr, cfinck(AT)ires.in2p3.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
20 
23 #include "BaseEmulator.h"
24 #include <stdexcept>
25 
26 using namespace Gw;
27 
28 BaseEmulator::BaseEmulator(std::string name) : fLog(name.data()), fName(name), fGlobals(), fAllActors() , fAllConnections(), fTopology()
29 {
30  // some general path
31  fGlobals.push_back ( new NamedItem<std::string> ("ConfDir",std::string("./")) ) ;
32  fGlobals.push_back ( new NamedItem<std::string> ("ReadDir",std::string("./")) ) ;
33  fGlobals.push_back ( new NamedItem<std::string> ("SaveDir",std::string("./")) ) ;
34  // to be used in case of dynamic loading of libraries i.e. follows rigourusly Narval like way of doing
35  fGlobals.push_back ( new NamedItem<std::string> ("LibDir", std::string("./")) ) ;
36  fGlobals.push_back ( new NamedItem<std::string> ("LibName",std::string("lib.so")) ) ;
37  // definition of the connection
38  // if a new actor is linked with an existing actor, the following are used to define the connection
39  // with C used if the new actor is a consumer regarding the old one, and P if it is the producer
40  fGlobals.push_back ( new NamedItem<UInt_t> ("SizeDataBlockC",aMByte) ) ;
41  fGlobals.push_back ( new NamedItem<std::string> ("TypeDataBlockC",std::string("")) ) ;
42  fGlobals.push_back ( new NamedItem<UInt_t> ("SizeDataBlockP",aMByte) ) ;
43  fGlobals.push_back ( new NamedItem<std::string> ("TypeDataBlockP",std::string("expand")) ) ;
44 
45  // option of the emulator
46  fGlobals.push_back ( new NamedItem<std::string> ("InitSequence", std::string("config load init")) ) ;
47  fGlobals.push_back ( new NamedItem<Short_t> ("Generation",0) ) ;
48  // -2 is for almost-pure narval emulator (Joa's one) i.e. it get the configure / register from the C library. then other methods are called using the NarvalInterface::process_XXX methods
49  // -1 femul like. actors are created directly. The real process::config method could be set during the emulator construction so that a direct call of the mother class could be done. others are NarvalInterface::process_XXX methods
50  // 0 ADF's like, first generation. like femul except ProcessBlock(FrameBlock ....) is called instead of process_block
51  // ---> all these generations can handle only producers, consumers and Filters. femul Builder cannot be called since they are not based on NarvalInterface.
52  // 1 ADF new interface using ProcessBlocks() method. It allows to define the same interface for consumer, producer, filter and shunter (N input x M output)
53  //
54  // since once using the BaseEmulator.Add method the created loaded actor get a local copy of the Global of the emulator, in principle, generation can be mixed !
55 }
56 
58 {
59  fLog.SetProcessMethod("~BaseEmulator()");
60 
61  // delete all globals
62  try {
63  fLog << "deleting globals ... " ;
64  for (size_t i = 0; i < fGlobals.size(); i++) {
65  delete fGlobals[i];
66  }
67  fLog << "deleting actors ... " ;
68  for (size_t i = 0; i < fAllActors.size(); i++) {
69  delete fAllActors[i];
70  }
71  fLog << "deleting connections ... " ;
72  for (size_t i = 0; i < fAllConnections.size(); i++) {
73  delete fAllConnections[i];
74  }
75  }
76  catch (std::exception &e) {
77  fLog << error << e.what() << nline;
78  }
79  fLog << dolog;
80 }
81 
82 void BaseEmulator::SetGlobal( const ANamedItem &global )
83 {
84  Bool_t add_new = true;
85  //
86  for (size_t j = 0; j < fGlobals.size(); j++) {
87  //
88  if ( global.GetName() == fGlobals[j]->GetName() ) {
89  // change is possible means same name same type
90  if ( fGlobals[j]->Set(&global) ) {
91  add_new = false;
92  break;
93  }
94  }
95  }
96  if ( add_new ) {
97  fGlobals.push_back( global.MakeAClone() );
98  }
99 }
100 
102 {
103  BuildTopology();
104  std::cout << "[+]============================= Topology of " << GetName() << " =============================" << std::endl;
105  std::cout << " List of registered actors : " ;
106  for (UInt_t i = 0; i < fAllActors.size(); i++ ) {
107  std::cout << fAllActors[i]->GetName() << " ";
108  }
109  std::cout << std::endl << "Topology depth " << fTopology.size() << std::endl;
110  for (UInt_t i = 0; i < fTopology.size(); i++ ) {
111  for (UInt_t k = 0; k < i ; k++ ) {
112  std::cout << " ";
113  }
114  std::cout << "Actors @ level " << i << std::endl;
115  for (UInt_t j = 0; j < fTopology[i].size() ; j++) {
116  for (UInt_t k = 0; k < i+1 ; k++ ) {
117  std::cout << " ";
118  }
119  std::cout << fTopology[i][j]->GetName() << " has "
120  << fTopology[i][j]->GetNbInput() << " input(s) and " << fTopology[i][j]->GetNbOutput() << " output(s) " << std::endl ;
121  }
122  }
123  std::cout << "[c]============================= Topology of " << GetName() << " =============================" << std::endl;
124  std::cout << "Configured with : " << std::endl;
125  for (size_t i = 0; i < fGlobals.size(); i++) {
126  fGlobals[i]->Print();
127  std::cout << std::endl;
128  }
129  std::cout << "[-]============================= Topology of " << GetName() << " =============================" << std::endl;
130 
131 }
132 
134 {
135  Int_t depth;
136 
137  // clear the topology
138  fTopology.clear();
139 
140  // for all nodes, look for the max depth for all
141  for (UInt_t i = 0; i < fAllActors.size(); i++ ) {
142 
143  if ( fAllActors[i] == 0x0 )
144  continue;
145 
146  depth = 0;
147  fAllActors[i]->ComputeDepth(depth);
148 
149  while ( depth >= Int_t(fTopology.size()) ) {
150  //
151  std::vector <ALoadedActor *> vv;
152  fTopology.push_back(vv);
153  }
154  fTopology[depth].push_back( fAllActors[i] ); fAllActors[i]->SetDepth(depth);
155  }
156 }
157 
158 void BaseEmulator::Init( const NamedItem<std::string> &init_sequence )
159 {
160  UInt_t error = 0u; fLog.SetProcessMethod("Init"); std::string action;
161 
162  // change InitSequence in globals with the new value and use it to really do the jo
163  // NOTE : if sequential calls (Ex : Init( NamedItem<std::string>("InitSequence","config")),Init( NamedItem<std::string>("InitSequence","load")) ... ), only the last value is kept
164  SetGlobal(init_sequence);
165 
166  // needed first to fix the topology
167  BuildTopology();
168 
169  for (UInt_t i = 0; i < fAllActors.size(); i++ ) {
170 
171  // now do what is asked by the init_sequence
172  std::istringstream actions( GetItem<std::string>("InitSequence",fGlobals)->Get() );
173  actions.clear();
174 
175  while ( actions.good() ) {
176  actions >> action;
177  fLog << info << "Apply action " << action << " on " << fAllActors[i]->GetName() ;
178 
179  Bool_t is_done = false;
180 
181  if ( action == "config" ) {
182  is_done = true;
183  fAllActors[i]->SetLastError(0u);
184  fAllActors[i]->ConfigureActor();
185  if ( fAllActors[i]->GetLastError() != 0u ) {
186  fLog << error << " : Cannot configure " << fAllActors[i]->GetName() << ". CODE ERROR is : " << fAllActors[i]->GetLastError() << dolog;
187  throw std::runtime_error(std::string("Cannot configure"));;
188  }
189  else { fAllActors[i]->SetStatus(ALoadedActor::kConfigured); fLog << info << " --> done " << nline; }
190  }
191  if ( action == "load" ) {
192  is_done = true;
193  fAllActors[i]->SetLastError(0u);
194  fAllActors[i]->RegisterActor();
195  if ( fAllActors[i]->GetLastError() != 0u ) {
196  fLog << error << " : Cannot Register " << fAllActors[i]->GetName() << ". CODE ERROR is : " << fAllActors[i]->GetLastError() << dolog;
197  throw std::runtime_error(std::string("Cannot Register"));;
198  }
199  else {
200  // check whether or not the allocated actor supports the number of input/output asked
201  if ( fAllActors[i]->GetNbInput() > fAllActors[i]->GetActor()->GetMaxInput() ) {
202  fLog << error << " : Cannot Register " << fAllActors[i]->GetName() << ", too much inputs " << fAllActors[i]->GetNbInput() << " asked while MAX is " << fAllActors[i]->GetActor()->GetMaxInput() << dolog;
203  throw std::out_of_range("incompatible inputs");
204  }
205  if ( fAllActors[i]->GetNbOutput() > fAllActors[i]->GetActor()->GetMaxOutput() ) {
206  fLog << error << " Cannot Register " << fAllActors[i]->GetName() << ", too much outputs " << fAllActors[i]->GetNbOutput() << " asked while MAX is " << fAllActors[i]->GetActor()->GetMaxOutput() << dolog;
207  throw std::out_of_range("incompatible outputs");
208  }
209  //
210  fAllActors[i]->SetStatus(ALoadedActor::kLoaded);
211  fLog << info << " --> done " << nline;
212  }
213  }
214  if ( action == "init" ) {
215  is_done = true;
216  fAllActors[i]->SetLastError(0u);
217  fAllActors[i]->InitActor();
218  if ( fAllActors[i]->GetLastError() != 0u ) {
219  fLog << error << " : Cannot initialise " << fAllActors[i]->GetName() << ". CODE ERROR is : " << fAllActors[i]->GetLastError() << dolog;
220  throw std::runtime_error(std::string("Cannot initialise"));
221  }
222  else { fAllActors[i]->SetStatus(ALoadedActor::kInitialised); fLog << info << " --> done " << nline; }
223  }
224  if ( is_done == false )
225  fLog << warning << " : is NOT a valid action. Valid are config, load or init " << nline;
226  }
227  }
228  //
229  fLog << dolog;
230 }
231 
232 void BaseEmulator::Run(Int_t max_loop)
233 {
234  fLog.SetProcessMethod("Run");
235 
236  UInt_t nb_loop = 0u, nb_run = 0u, nb_try = 0u, max_try = 3u;
237 
238  // if there in principle all actors are initialised. so set them to kIdle
239  for (UInt_t i = 0u; i < fAllActors.size(); i++) {
240  if ( fAllActors[i]->GetStatus() < ALoadedActor::kInitialised ) {
241  fLog << error << "Actor " << fAllActors[i]->GetName() << " is not in the expected state " << fAllActors[i]->GetStatus() << dolog;
242  return;
243  }
244  }
245 
246  // now start the loop
247  while ( nb_loop != (UInt_t)max_loop ) {
248  // start from lowest level
249  nb_run = 0;
250  for (UInt_t i = 0; i < fTopology.size(); i++ ) {
251  for (UInt_t j = 0; j < fTopology[i].size() ; j++) {
252 
253  if ( nb_try > 0 ) {
254  if ( fTopology[i][j]->GetStatus() == ALoadedActor::kRunning )
255  fTopology[i][j]->SetStatus(ALoadedActor::kDoRunning);
256  // at least one loop with no active actors, reste running into do running
257  }
258 
259  switch (fTopology[i][j]->GetStatus()) {
261  case ALoadedActor::kIdle :
263  fTopology[i][j]->SetStatus(ALoadedActor::kDoRunning);
264  fTopology[i][j]->ProcessActor();
265  if ( fTopology[i][j]->GetStatus() == ALoadedActor::kHasRun ) {
266  nb_run++;
267  //fTopology[i][j]->SetStatus(ALoadedActor::kIdle);
268  }
269  fTopology[i][j]->SetStatus(ALoadedActor::kIdle);
270 
271  break;
272 
273  default:
274  break;
275  }
276  if ( fTopology[i][j]->GetLastError() > 0u ) {
277  fLog << error << "Error " << fTopology[i][j]->GetLastError() << " during processing of actor " << fTopology[i][j]->GetName() << nline;
278  fTopology[i][j]->SetStatus(ALoadedActor::kDead);
279  break;
280  }
281  }
282  } // @ depth i
283  if ( nb_run == 0 ) {
284  if ( nb_try >= max_try )
285  break;
286  else
287  nb_try++;
288  fLog << info << " No active actors ==> STOP emulator after " << max_try << " # of tries. nb_try = " << nb_try << " nb_loop "<< nb_loop << nline;
289  }
290  else nb_try = 0;
291 
292  nb_loop++;
293  } // while
294 
295  fLog << dolog;
296 }
297 
298 ALoadedActor *BaseEmulator::GetLoaderByName(const Char_t *name) const
299 {
300  ALoadedActor *result = 0x0;
301 
302  for (UInt_t i = 0; i < fAllActors.size(); i++ ) {
303  if ( fAllActors[i]->GetName().compare(name) == 0 ) {
304  result = fAllActors[i] ;
305  break;
306  }
307  }
308  return result;
309 }
310 
312 {
313  ALoadedActor *l_actor = GetLoaderByName(name);
314  if ( l_actor ) {
315  return l_actor->GetActor();
316  }
317  else {
318  return 0x0;
319  }
320 }
321 
322 
323 
324 
325 
326 
327 
328 
329 
330 
std::vector< ANamedItem * > fGlobals
to configure the emulator. The name of each item should be unique !
Definition: BaseEmulator.h:70
header file for BaseEmulator.cpp
virtual void SetGlobal(const ANamedItem &)
This method allows to modified some options of the emulator.
std::vector< std::vector< ALoadedActor * > > fTopology
Actors are memorized depending on their depth in the data processing chain.
Definition: BaseEmulator.h:79
virtual ANamedItem * MakeAClone() const =0
clone that named item
LogMessage & error(LogMessage &)
std::string & GetName()
Name of the emulator.
Definition: BaseEmulator.h:375
LogMessage & warning(LogMessage &)
virtual void Run(Int_t max_loop=-1)
Run max loop.
LogMessage & nline(LogMessage &)
BaseEmulator(std::string name)
std::vector< AnActorConnection * > fAllConnections
list of all connections. Owned by the emulator thus delete by this
Definition: BaseEmulator.h:76
std::string GetName() const
change value of this nmaed item using the passed one. it checks if asked, it check first if of the sa...
Definition: DataHandling.h:219
const UInt_t aMByte
Definition: BaseBuffer.h:36
virtual void PrintTopology()
print topology
virtual ~BaseEmulator()
LogMessage & info(LogMessage &)
manipulator to modify the LogMessage
An actor looded in an emulator.
Definition: ALoadedActor.h:88
virtual NarvalInterface * GetActor() const
get loaded actor, should have the narval interface
Definition: ALoadedActor.h:160
LogMessage & dolog(LogMessage &)
virtual void Init(const NamedItem< std::string > &init_sequence=NamedItem< std::string >("InitSequence","config load init"))
Init the emulator. To be called before calling Run.
ANamedItem.
Definition: DataHandling.h:188
ADF::LogMessage & endl(ADF::LogMessage &log)
virtual ALoadedActor * GetLoaderByName(const Char_t *) const
search for a node in the emulator
void BuildTopology()
Built the map, starting from producer is calculates the depth of each actor in the data flow...
virtual void SetProcessMethod(const char *)
To set the current method.
std::vector< ALoadedActor * > fAllActors
list of all actors to start building the map and to delete them @ the end
Definition: BaseEmulator.h:73
It defines the general interface needed to be a narval actor.
virtual NarvalInterface * GetActorByName(const Char_t *) const
search for an actor in the emulator