Salome HOME
MPI fixes.
[modules/kernel.git] / src / Container / Component_i.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SALOME Container : implementation of container and engine for Kernel
24 //  File   : Component_i.cxx
25 //  Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA
26 //  Module : SALOME
27 //  $Header$
28 //#define private protected  // for pd_refCount trace
29 //
30 #include "SALOME_Component_i.hxx"
31 #include "SALOME_Container_i.hxx"
32 #include "RegistryConnexion.hxx"
33 #include "Basics_Utils.hxx"
34 #include <stdio.h>
35 #ifndef WIN32
36 #include <dlfcn.h>
37 #endif
38 #include <cstdlib>
39 #include "utilities.h"
40
41 #ifndef WIN32
42 #include <sys/time.h>
43 #include <sys/resource.h>
44 #include <unistd.h>
45 #else
46 #include <sys/timeb.h>
47 int SIGUSR11 = 1000;
48 #include <process.h>
49 #endif
50
51 extern bool _Sleeping ;
52 static Engines_Component_i * theEngines_Component ;
53
54 bool Engines_Component_i::_isMultiStudy = true;
55 bool Engines_Component_i::_isMultiInstance = false;
56
57 /*! \class Engines_Component_i
58  *  \brief C++ implementation of Engines::Component interface
59  *
60  */
61
62 //=============================================================================
63 /*!
64  *  Default constructor, not for use
65  */
66 //=============================================================================
67
68 Engines_Component_i::Engines_Component_i():_myConnexionToRegistry(0), _notifSupplier(0), _id(0)
69 {
70   //ASSERT(0);
71   MESSAGE("Default Constructor, not for normal use...");
72 }
73
74 //=============================================================================
75 /*!  \brief  Standard Constructor for generic Component, used in derived class
76  *
77  *  Connection to Registry and Notification
78  *  \param orb Object Request broker given by Container
79  *  \param poa Portable Object Adapter from Container (normally root_poa)
80  *  \param contId container CORBA id inside the server
81  *  \param instanceName unique instance name for this object (see Container_i)
82  *  \param interfaceName component class name
83  *  \param notif use of notification
84  *  \param regist (true or false) use of registry (default true)
85  */
86 //=============================================================================
87
88 Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb,
89                                          PortableServer::POA_ptr poa,
90                                          PortableServer::ObjectId * contId,
91                                          const char *instanceName,
92                                          const char *interfaceName,
93                                          bool notif,
94                                          bool regist ) :
95   _instanceName(instanceName),
96   _interfaceName(interfaceName),
97   _myConnexionToRegistry(0),
98   _notifSupplier(0),
99   _ThreadId(0) ,
100   _ThreadCpuUsed(0) ,
101   _Executed(false) ,
102   _graphName("") ,
103   _nodeName(""),
104   _studyId(-1),
105   _id(0),
106   _contId(0),
107   _CanceledThread(false)
108 {
109   MESSAGE("Component constructor with instanceName "<< _instanceName);
110   _orb = CORBA::ORB::_duplicate(orb);
111   _poa = PortableServer::POA::_duplicate(poa);
112   _contId = contId ;
113   CORBA::Object_var o = _poa->id_to_reference(*contId); // container ior...
114   _container=Engines::Container::_narrow(o);
115   setContainerName();
116
117   if(regist)
118     {
119       const CORBA::String_var ior = _orb->object_to_string(o);
120       _myConnexionToRegistry = new RegistryConnexion(0, 0, ior,"theSession",
121                                                      _instanceName.c_str());
122     }
123
124   if(notif)
125     _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
126 }
127
128 //=============================================================================
129 /*!  \brief  Standard Constructor for standalone Component, used in derived class
130  *
131  *  Connection to Registry and Notification
132  *  \param orb Object Request broker given by Container
133  *  \param poa Portable Object Adapter from Container (normally root_poa)
134  *  \param container container CORBA reference
135  *  \param instanceName unique instance name for this object (see Container_i)
136  *  \param interfaceName component class name
137  *  \param notif use of notification
138  *  \param regist (true or false) use of registry (default true)
139  */
140 //=============================================================================
141
142 Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb,
143                                          PortableServer::POA_ptr poa,
144                                          Engines::Container_ptr container,
145                                          const char *instanceName,
146                                          const char *interfaceName,
147                                          bool notif,
148                                          bool regist) :
149   _instanceName(instanceName),
150   _interfaceName(interfaceName),
151   _myConnexionToRegistry(0),
152   _notifSupplier(0),
153   _ThreadId(0) ,
154   _ThreadCpuUsed(0) ,
155   _Executed(false) ,
156   _graphName("") ,
157   _nodeName(""),
158   _studyId(-1),
159   _id(0),
160   _contId(0),
161   _CanceledThread(false)
162 {
163   MESSAGE("Component constructor with instanceName "<< _instanceName);
164   _orb = CORBA::ORB::_duplicate(orb);
165   _poa = PortableServer::POA::_duplicate(poa);
166   _container=Engines::Container::_duplicate(container);
167   setContainerName();
168   const CORBA::String_var ior = _orb->object_to_string(_container);
169   if(regist)
170   {
171     _myConnexionToRegistry = new RegistryConnexion(0, 0, ior,"theSession", _instanceName.c_str());
172   }
173   if(notif)
174     _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
175
176 }
177
178
179 //=============================================================================
180 /*!
181  *  Destructor: call Container for decrement of instances count.
182  *  When instances count falls to 0, the container tries to remove the
183  *  component library (dlclose)
184  */
185 //=============================================================================
186
187 Engines_Component_i::~Engines_Component_i()
188 {
189   MESSAGE("Component destructor");
190   Engines_Container_i::decInstanceCnt(_interfaceName);
191   if(_myConnexionToRegistry)delete _myConnexionToRegistry;
192   _myConnexionToRegistry = 0 ;
193
194   if(_id) delete _id;
195   _id=0;
196
197   if(_notifSupplier)
198     {
199       SCRUTE(_notifSupplier->_refcount_value());
200       PortableServer::POA_var poa=_notifSupplier->_default_POA();
201       PortableServer::ObjectId_var anObjectId = poa->servant_to_id(_notifSupplier);
202       poa->deactivate_object(anObjectId.in());
203       SCRUTE(_notifSupplier->_refcount_value());
204       _notifSupplier->_remove_ref();
205     }
206 }
207
208 //=============================================================================
209 /*!
210  *  CORBA method: return name of the instance, unique in this Container
211  */
212 //=============================================================================
213
214 char* Engines_Component_i::instanceName()
215 {
216    return CORBA::string_dup(_instanceName.c_str()) ;
217 }
218
219 //=============================================================================
220 /*!
221  *  CORBA method: return name of the component class
222  */
223 //=============================================================================
224
225 char* Engines_Component_i::interfaceName()
226 {
227   return CORBA::string_dup(_interfaceName.c_str()) ;
228 }
229
230 //=============================================================================
231 /*!
232  *  CORBA method: Get study Id
233  *  \return -1: not initialised (Internal Error)
234  *           0: multistudy component instance
235  *          >0: study id associated to this instance
236  */
237 //=============================================================================
238
239 CORBA::Long Engines_Component_i::getStudyId()
240 {
241   return _studyId;
242 }
243
244 //=============================================================================
245 /*!
246  *  CORBA method: Test if instance is alive and responds
247  */
248 //=============================================================================
249
250 void Engines_Component_i::ping()
251 {
252 #ifndef WIN32
253   MESSAGE("Engines_Component_i::ping() pid "<< getpid() << " threadid "
254           << pthread_self());
255 #else
256   MESSAGE("Engines_Component_i::ping() pid "<< _getpid()<< " threadid "
257           << pthread_self().p );
258 #endif
259 }
260
261 //=============================================================================
262 /*!
263  *  CORBA method: Deactivate this instance. CORBA object is deactivated (do not
264  *  respond any more to CORBA calls), the connection to Regsitry is removed
265  *  (Registry informed of deactivation), internal server reference counter on
266  *  the derived servant class is decremented, to allow destruction of the class
267  *  (delete) by POA, when there are no more references.
268  *  -- TO BE USED BY CONTAINER ONLY (Container housekeeping) --
269  */
270 //=============================================================================
271
272 void Engines_Component_i::destroy()
273 {
274   MESSAGE("Engines_Component_i::destroy()");
275   //SCRUTE(_refcount_value());
276   _poa->deactivate_object(*_id);
277   //SCRUTE(_refcount_value());
278   _remove_ref();
279   //SCRUTE(_refcount_value());
280   MESSAGE("Engines_Component_i::destroyed") ;
281 }
282
283 //=============================================================================
284 /*!
285  *  CORBA method: return CORBA reference of the Container
286  *
287  */
288 //=============================================================================
289
290 Engines::Container_ptr Engines_Component_i::GetContainerRef()
291 {
292   return Engines::Container::_duplicate(_container);
293 }
294
295 //=============================================================================
296 /*!
297  *  CORBA method:
298  *  Gives a sequence of (key=string,value=any) to the component.
299  *  Base class component stores the sequence in a map.
300  *  The map is cleared before.
301  *  This map is for use by derived classes.
302  *  \param dico sequence of (key=string,value=any)
303  */
304 //=============================================================================
305
306 void Engines_Component_i::setProperties(const Engines::FieldsDict& dico)
307 {
308   _fieldsDict.clear();
309   for (CORBA::ULong i=0; i<dico.length(); i++)
310     {
311       std::string cle(dico[i].key);
312       _fieldsDict[cle] = dico[i].value;
313     }
314 }
315
316 //=============================================================================
317 /*!
318  *  CORBA method:
319  *  returns a previously stored map (key=string,value=any) as a sequence.
320  *  (see setProperties)
321  */
322 //=============================================================================
323
324 Engines::FieldsDict* Engines_Component_i::getProperties()
325 {
326   Engines::FieldsDict_var copie = new Engines::FieldsDict;
327   copie->length(_fieldsDict.size());
328   std::map<std::string,CORBA::Any>::iterator it;
329   CORBA::ULong i = 0;
330   for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++, i++)
331     {
332       std::string cle((*it).first);
333       copie[i].key = CORBA::string_dup(cle.c_str());
334       copie[i].value = _fieldsDict[cle];
335     }
336   return copie._retn();
337 }
338
339 //=============================================================================
340 /*!
341  *  CORBA method:
342  *  This method is to set an option specific to a certain EngineComponent.
343  */
344 //=============================================================================
345
346 void Engines_Component_i::SetOption(const char*, const char*)
347 {
348 }
349
350 //=============================================================================
351 /*!
352  *  CORBA method:
353  *  This method is to get value of an option specific to a certain EngineComponent.
354  */
355 //=============================================================================
356
357 char* Engines_Component_i::GetOption(const char*)
358 {
359   return CORBA::string_dup("") ;
360 }
361
362 //=============================================================================
363 /*!
364  *  CORBA method: used by Supervision to give names to this instance
365  */
366 //=============================================================================
367
368 void Engines_Component_i::Names( const char * graphName ,
369                                  const char * nodeName )
370 {
371   _graphName = graphName ;
372   _nodeName = nodeName ;
373   //  MESSAGE("Engines_Component_i::Names( '" << _graphName << "' , '"
374   //          << _nodeName << "' )");
375 }
376
377 //=============================================================================
378 /*!
379  *  CORBA method: used in Supervision
380  */
381 //=============================================================================
382
383 bool Engines_Component_i::Kill_impl()
384 {
385 //  MESSAGE("Engines_Component_i::Kill_i() pthread_t "<< pthread_self()
386 //          << " pid " << getpid() << " instanceName "
387 //          << _instanceName.c_str() << " interface " << _interfaceName.c_str()
388 //          << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
389 //          << dec << " _ThreadId " << _ThreadId << " this " << hex << this
390 //          << dec ) ;
391
392   bool RetVal = false ;
393 #ifndef WIN32
394   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
395     {
396       RetVal = Killer( _ThreadId , SIGUSR2 ) ;
397       _ThreadId = (pthread_t ) -1 ;
398     }
399
400 #else
401   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
402     {
403       RetVal = Killer( *_ThreadId , 0 ) ;
404       _ThreadId = (pthread_t* ) 0 ;
405     }
406
407 #endif
408   return RetVal ;
409 }
410
411 //=============================================================================
412 /*!
413  *  CORBA method: used in Supervision
414  */
415 //=============================================================================
416
417 bool Engines_Component_i::Stop_impl()
418 {
419 #ifndef WIN32
420   MESSAGE("Engines_Component_i::Stop_i() pthread_t "<< pthread_self()
421           << " pid " << getpid() << " instanceName "
422           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
423           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << std::hex << _id
424           << std::dec << " _ThreadId " << _ThreadId );
425 #else
426   MESSAGE("Engines_Component_i::Stop_i() pthread_t "<< pthread_self().p
427           << " pid " << _getpid() << " instanceName "
428           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
429           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << std::hex << _id
430           << std::dec << " _ThreadId " << _ThreadId );
431 #endif
432
433
434   bool RetVal = false ;
435 #ifndef WIN32
436   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
437     {
438       RetVal = Killer( _ThreadId , 0 ) ;
439       _ThreadId = (pthread_t ) -1 ;
440     }
441 #else
442   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
443     {
444       RetVal = Killer( *_ThreadId , 0 ) ;
445       _ThreadId = (pthread_t* ) 0 ;
446     }
447 #endif
448   return RetVal ;
449 }
450
451 //=============================================================================
452 /*!
453  *  CORBA method: used in Supervision
454  */
455 //=============================================================================
456
457 bool Engines_Component_i::Suspend_impl()
458 {
459 #ifndef WIN32
460   MESSAGE("Engines_Component_i::Suspend_i() pthread_t "<< pthread_self()
461           << " pid " << getpid() << " instanceName "
462           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
463           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << std::hex << _id
464           << std::dec << " _ThreadId " << _ThreadId );
465 #else
466   MESSAGE("Engines_Component_i::Suspend_i() pthread_t "<< pthread_self().p
467           << " pid " << _getpid() << " instanceName "
468           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
469           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << std::hex << _id
470           << std::dec << " _ThreadId " << _ThreadId );
471 #endif
472
473   bool RetVal = false ;
474 #ifndef WIN32
475   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
476 #else
477   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
478 #endif
479     {
480       if ( _Sleeping )
481         {
482           return false ;
483         }
484     else
485       {
486 #ifndef WIN32
487         RetVal = Killer( _ThreadId ,SIGINT ) ;
488 #else
489         RetVal = Killer( *_ThreadId ,SIGINT ) ;
490 #endif
491         //if ( RetVal ) _Sleeping = true;
492
493       }
494     }
495   return RetVal ;
496 }
497
498 //=============================================================================
499 /*!
500  *  CORBA method: used in Supervision
501  */
502 //=============================================================================
503
504 bool Engines_Component_i::Resume_impl()
505 {
506 #ifndef WIN32
507   MESSAGE("Engines_Component_i::Resume_i() pthread_t "<< pthread_self()
508           << " pid " << getpid() << " instanceName "
509           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
510           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << std::hex << _id
511           << std::dec << " _ThreadId " << _ThreadId );
512 #else
513   MESSAGE("Engines_Component_i::Resume_i() pthread_t "<< pthread_self().p
514           << " pid " << _getpid() << " instanceName "
515           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
516           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << std::hex << _id
517           << std::dec << " _ThreadId " << _ThreadId );
518 #endif
519   bool RetVal = false ;
520 #ifndef WIN32
521   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
522 #else
523   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
524 #endif
525     {
526     if ( _Sleeping )
527       {
528         _Sleeping = false ;
529         RetVal = true ;
530       }
531     else
532       {
533         RetVal = false ;
534       }
535     }
536   return RetVal ;
537 }
538
539 //=============================================================================
540 /*!
541  *  CORBA method:
542  */
543 //=============================================================================
544
545 CORBA::Long Engines_Component_i::CpuUsed_impl()
546 {
547   long cpu = 0 ;
548   if ( _ThreadId || _Executed )
549     {
550     if ( _ThreadId > 0 )
551       {
552 #ifndef WIN32
553       if ( pthread_self() != _ThreadId )
554 #else
555       if ( pthread_self().p != _ThreadId->p )
556 #endif
557         {
558         if ( _Sleeping )
559           {
560           }
561         else
562           {
563             // Get Cpu in the appropriate thread with that object !...
564             theEngines_Component = this ;
565 #ifndef WIN32
566             Killer( _ThreadId ,SIGUSR1 ) ;
567 #else
568             Killer( *_ThreadId ,SIGUSR11 ) ;
569 #endif
570           }
571         cpu = _ThreadCpuUsed ;
572         }
573       else
574         {
575           _ThreadCpuUsed = CpuUsed() ;
576           cpu = _ThreadCpuUsed ;
577           // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl "
578           //      << _serviceName << " " << cpu << endl ;
579       }
580     }
581     else
582       {
583         cpu = _ThreadCpuUsed ;
584         // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl "
585         //      << _serviceName << " " << cpu<< endl ;
586       }
587     }
588   else
589     {
590       // cout<< pthread_self()<<"Engines_Component_i::CpuUsed_impl _ThreadId "
591       //     <<_ThreadId <<" "<<_serviceName<<" _StartUsed "<<_StartUsed<<endl;
592     }
593   return cpu ;
594 }
595
596
597 //=============================================================================
598 /*!
599  *  C++ method: return Container Servant
600  */
601 //=============================================================================
602
603 Engines_Container_i *Engines_Component_i::GetContainerPtr()
604 {
605   PortableServer::ObjectId_var  contId=_poa->reference_to_id(_container);
606   return dynamic_cast<Engines_Container_i*>(_poa->id_to_servant(contId)) ;
607 }
608
609 //=============================================================================
610 /*!
611  *  C++ method: set study Id
612  *  \param studyId         0 if instance is not associated to a study,
613  *                         >0 otherwise (== study id)
614  *  \return true if the set of study Id is OK
615  *  must be set once by Container, at instance creation,
616  *  and cannot be changed after.
617  */
618 //=============================================================================
619
620 CORBA::Boolean Engines_Component_i::setStudyId(CORBA::Long studyId)
621 {
622   ASSERT( studyId >= 0);
623   CORBA::Boolean ret = false;
624   if (_studyId < 0) // --- not yet initialized
625     {
626       _studyId = studyId;
627       ret = true;
628     }
629   else
630     if ( _studyId == studyId) ret = true;
631   return ret;
632 }
633
634 //=============================================================================
635 /*!
636  *  C++ method: return CORBA instance id, the id is set in derived class
637  *  constructor, when instance is activated.
638  */
639 //=============================================================================
640
641 PortableServer::ObjectId * Engines_Component_i::getId()
642 {
643 //  MESSAGE("PortableServer::ObjectId * Engines_Component_i::getId()");
644   return _id ;
645 }
646
647 //=============================================================================
648 /*!
649  *  C++ method: used by derived classes for supervision
650  */
651 //=============================================================================
652
653 void Engines_Component_i::beginService(const char *serviceName)
654 {
655   std::cerr << "beginService for " << serviceName << " Component instance : " << _instanceName << std::endl;
656
657 #ifndef WIN32
658   _ThreadId = pthread_self() ;
659 #else
660   _ThreadId = new pthread_t;
661   _ThreadId->p = pthread_self().p ;
662   _ThreadId->x = pthread_self().x ;
663 #endif
664   _StartUsed = 0 ;
665   _StartUsed = CpuUsed_impl() ;
666   _ThreadCpuUsed = 0 ;
667   _Executed = true ;
668   _serviceName = serviceName ;
669   theEngines_Component = this ;
670   if ( pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS , NULL ) )
671     {
672       perror("pthread_setcanceltype ") ;
673       exit(0) ;
674     }
675   if ( pthread_setcancelstate( PTHREAD_CANCEL_ENABLE , NULL ) )
676     {
677       perror("pthread_setcancelstate ") ;
678       exit(0) ;
679     }
680
681   // --- all strings given with setProperties are set in environment
682   std::map<std::string,CORBA::Any>::iterator it;
683   for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++)
684     {
685       std::string cle((*it).first);
686       if ((*it).second.type()->kind() == CORBA::tk_string)
687         {
688           const char* value;
689           (*it).second >>= value;
690           std::string s(cle);
691           s+='=';
692           s+=value;
693           putenv((char *)s.c_str());
694           MESSAGE("--- setenv: "<<cle<<" = "<< value);
695         }
696     }
697 }
698
699 //=============================================================================
700 /*!
701  *  C++ method: used by derived classes for supervision
702  */
703 //=============================================================================
704
705 void Engines_Component_i::endService(const char *serviceName)
706 {
707   if ( !_CanceledThread )
708     _ThreadCpuUsed = CpuUsed_impl() ;
709
710   float cpus=_ThreadCpuUsed/1000.;
711   std::cerr << "endService for " << serviceName << " Component instance : " << _instanceName ;
712   std::cerr << " Cpu Used: " << cpus << " (s) " << std::endl;
713   MESSAGE("Send EndService notification for " << serviceName
714           << std::endl << " Component instance : " << _instanceName << " StartUsed "
715           << _StartUsed << " _ThreadCpuUsed "<< _ThreadCpuUsed << std::endl <<std::endl);
716   _ThreadId = 0 ;
717 }
718
719 //=============================================================================
720 /*!
721  *  C++ method: -- CHECK IF USED --
722  */
723 //=============================================================================
724
725 char* Engines_Component_i::graphName()
726 {
727   return CORBA::string_dup( _graphName.c_str() ) ;
728 }
729
730 //=============================================================================
731 /*!
732  *  C++ method: -- CHECK IF USED --
733  */
734 //=============================================================================
735
736 char* Engines_Component_i::nodeName()
737 {
738   return CORBA::string_dup( _nodeName.c_str() ) ;
739 }
740
741 //=============================================================================
742 /*!
743  *  C++ method: used in Supervision (see kill_impl)
744  */
745 //=============================================================================
746
747 bool Engines_Component_i::Killer( pthread_t ThreadId , int signum )
748 {
749 #ifndef WIN32
750   if ( ThreadId )
751 #else
752   if ( ThreadId.p )
753 #endif
754     {
755       if ( signum == 0 )
756         {
757           if ( pthread_cancel( ThreadId ) )
758             {
759               perror("Killer pthread_cancel error") ;
760               return false ;
761             }
762           else
763             {
764 #ifdef WIN32
765               MESSAGE("Killer : ThreadId " << ThreadId.p << " pthread_canceled") ;
766 #else
767               MESSAGE("Killer : ThreadId " << ThreadId << " pthread_canceled") ;
768 #endif
769             }
770         }
771       else
772         {
773           if ( pthread_kill( ThreadId , signum ) == -1 )
774             {
775               perror("Killer pthread_kill error") ;
776               return false ;
777             }
778           else
779             {
780 #ifdef WIN32
781               MESSAGE("Killer : ThreadId " << ThreadId.p << " pthread_killed(" << signum << ")") ;
782 #else
783               MESSAGE("Killer : ThreadId " << ThreadId << " pthread_killed(" << signum << ")") ;
784 #endif
785             }
786         }
787     }
788   return true ;
789 }
790
791 void SetCpuUsed();
792 void CallCancelThread();
793
794 //=============================================================================
795 /*!
796  *  C++ method:
797  */
798 //=============================================================================
799
800 void SetCpuUsed()
801 {
802   if ( theEngines_Component )
803     theEngines_Component->SetCurCpu() ;
804 }
805
806 //=============================================================================
807 /*!
808  *  C++ method:
809  */
810 //=============================================================================
811
812 void Engines_Component_i::SetCurCpu()
813 {
814   _ThreadCpuUsed =  CpuUsed() ;
815   //  MESSAGE(pthread_self() <<
816   //  " Engines_Component_i::SetCurCpu() _ThreadCpuUsed " << _ThreadCpuUsed) ;
817 }
818
819 //=============================================================================
820 /*!
821  *  C++ method:
822  */
823 //=============================================================================
824
825 long Engines_Component_i::CpuUsed()
826 {
827   long cpu = 0 ;
828 #ifndef WIN32
829   struct rusage usage ;
830   if ( _ThreadId || _Executed )
831     {
832       if ( getrusage( RUSAGE_SELF , &usage ) == -1 )
833         {
834           perror("Engines_Component_i::CpuUsed") ;
835           return 0 ;
836         }
837       //cpu time is calculated in millisecond (user+system times)
838       cpu = usage.ru_utime.tv_sec*1000 +usage.ru_utime.tv_usec/1000;
839       cpu = cpu+ usage.ru_stime.tv_sec*1000 +usage.ru_stime.tv_usec/1000;
840       cpu=cpu-_StartUsed ;
841       // std::cout << pthread_self() << " Engines_Component_i::CpuUsed " << " "
842       //      << _serviceName   << usage.ru_utime.tv_sec << " - " << _StartUsed
843       //      << " = " << cpu << std::endl ;
844     }
845   else
846     {
847       // std::cout << pthread_self() << "Engines_Component_i::CpuUsed _ThreadId "
848       //      << _ThreadId << " " << _serviceName<< " _StartUsed "
849       //      << _StartUsed << std::endl ;
850     }
851 #else
852         // NOT implementet yet
853 #endif
854
855
856   return cpu ;
857 }
858
859 void CallCancelThread()
860 {
861   if ( theEngines_Component )
862     theEngines_Component->CancelThread() ;
863 }
864
865 //=============================================================================
866 /*!
867  *  C++ method:
868  */
869 //=============================================================================
870
871 void Engines_Component_i::CancelThread()
872 {
873   _CanceledThread = true;
874 }
875
876 //=============================================================================
877 /*!
878  *  C++ method: Send message to event channel
879  */
880 //=============================================================================
881
882 void Engines_Component_i::sendMessage(const char *event_type,
883                                       const char *message)
884 {
885     _notifSupplier->Send(_graphName.c_str(), _nodeName.c_str(), event_type, message);
886 }
887
888 //=============================================================================
889 /*!
890  *  C++ method: return standard library name built on component name
891  */
892 //=============================================================================
893
894 std::string Engines_Component_i::GetDynLibraryName(const char *componentName)
895 {
896 #ifndef WIN32
897   std::string ret="lib";
898   ret+=componentName;
899   ret+="Engine.so";
900 #else
901   std::string ret=componentName;
902   ret+="Engine.dll";
903 #endif
904   return ret;
905 }
906
907 //=============================================================================
908 /*!
909  *  C++ method: DumpPython default implementation
910  */
911 //=============================================================================
912
913 Engines::TMPFile* Engines_Component_i::DumpPython(CORBA::Object_ptr theStudy,
914                                                   CORBA::Boolean isPublished,
915                                                   CORBA::Boolean isMultiFile,
916                                                   CORBA::Boolean& isValidScript)
917 {
918   const char* aScript = isMultiFile ? "def RebuildData(theStudy): pass" : "";
919   char* aBuffer = new char[strlen(aScript)+1];
920   strcpy(aBuffer, aScript);
921   CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
922   int aBufferSize = strlen(aBuffer)+1;
923   Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aBufferSize, aBufferSize, anOctetBuf, 1);
924   isValidScript = true;
925   return aStreamFile._retn();
926 }
927
928 Engines::Salome_file_ptr
929 Engines_Component_i::getInputFileToService(const char* service_name,
930                                            const char* Salome_file_name)
931 {
932   // Try to find the service, if it doesn't exist, we throw an exception.
933   _Service_file_map_it = _Input_Service_file_map.find(service_name);
934   if (_Service_file_map_it ==  _Input_Service_file_map.end()) {
935     SALOME::ExceptionStruct es;
936     es.type = SALOME::INTERNAL_ERROR;
937     es.text = "service doesn't have salome files";
938     throw SALOME::SALOME_Exception(es);
939   }
940   _t_Salome_file_map * _map = _Input_Service_file_map[service_name];
941
942   // Try to find the Salome_file ...
943   _Salome_file_map_it = _map->find(Salome_file_name);
944   if (_Salome_file_map_it ==  _map->end()) {
945     SALOME::ExceptionStruct es;
946     es.type = SALOME::INTERNAL_ERROR;
947     es.text = "service doesn't have this Salome_file";
948     throw SALOME::SALOME_Exception(es);
949   }
950   Salome_file_i * Sfile = (*_map)[Salome_file_name];
951
952   return Sfile->_this();
953 }
954
955 Engines::Salome_file_ptr
956 Engines_Component_i::setInputFileToService(const char* service_name,
957                                            const char* Salome_file_name)
958 {
959   // Try to find the service, if it doesn't exist, we add it.
960   _Service_file_map_it = _Input_Service_file_map.find(service_name);
961   if (_Service_file_map_it ==  _Input_Service_file_map.end()) {
962     _t_Salome_file_map * _map = new _t_Salome_file_map();
963     _Input_Service_file_map[service_name] = _map;
964   }
965   _t_Salome_file_map * _map = _Input_Service_file_map[service_name];
966
967   // Try to find the Salome_file ...
968   _Salome_file_map_it = _map->find(Salome_file_name);
969   if (_Salome_file_map_it ==  _map->end()) {
970     Salome_file_i * Sfile = new Salome_file_i();
971     Engines::Container_ptr container = this->GetContainerRef();
972     Sfile->setContainer(Engines::Container::_duplicate(container));
973     (*_map)[Salome_file_name] = Sfile;
974   }
975
976   Salome_file_i * Sfile = (*_map)[Salome_file_name];
977   return Sfile->_this();
978 }
979
980 void
981 Engines_Component_i::checkInputFilesToService(const char* service_name)
982 {
983   // Try to find the service, if it doesn't exist, nothing to do.
984   _Service_file_map_it = _Input_Service_file_map.find(service_name);
985   if (_Service_file_map_it !=  _Input_Service_file_map.end()) {
986     _t_Salome_file_map * _map = _Input_Service_file_map[service_name];
987     _t_Salome_file_map::iterator begin = _map->begin();
988     _t_Salome_file_map::iterator end = _map->end();
989
990     for(;begin!=end;begin++) {
991       Salome_file_i * file = begin->second;
992       std::string file_port_name = begin->first;
993       configureSalome_file(service_name, file_port_name, file);
994       file->recvFiles();
995     }
996   }
997 }
998
999 Engines::Salome_file_ptr
1000 Engines_Component_i::getOutputFileToService(const char* service_name,
1001                                             const char* Salome_file_name)
1002 {
1003   // Try to find the service, if it doesn't exist, we throw an exception.
1004   _Service_file_map_it = _Output_Service_file_map.find(service_name);
1005   if (_Service_file_map_it ==  _Output_Service_file_map.end()) {
1006     SALOME::ExceptionStruct es;
1007     es.type = SALOME::INTERNAL_ERROR;
1008     es.text = "service doesn't have salome files";
1009     throw SALOME::SALOME_Exception(es);
1010   }
1011   _t_Salome_file_map * _map = _Output_Service_file_map[service_name];
1012
1013   // Try to find the Salome_file ...
1014   _Salome_file_map_it = _map->find(Salome_file_name);
1015   if (_Salome_file_map_it ==  _map->end()) {
1016     SALOME::ExceptionStruct es;
1017     es.type = SALOME::INTERNAL_ERROR;
1018     es.text = "service doesn't have this Salome_file";
1019     throw SALOME::SALOME_Exception(es);
1020   }
1021   Salome_file_i * Sfile = (*_map)[Salome_file_name];
1022
1023   return Sfile->_this();
1024 }
1025
1026 Engines::Salome_file_ptr
1027 Engines_Component_i::setOutputFileToService(const char* service_name,
1028                                            const char* Salome_file_name)
1029 {
1030   // Try to find the service, if it doesn't exist, we add it.
1031   _Service_file_map_it = _Output_Service_file_map.find(service_name);
1032   if (_Service_file_map_it ==  _Output_Service_file_map.end()) {
1033     _t_Salome_file_map * _map = new _t_Salome_file_map();
1034     _Output_Service_file_map[service_name] = _map;
1035   }
1036   _t_Salome_file_map * _map = _Output_Service_file_map[service_name];
1037
1038   // Try to find the Salome_file ...
1039   _Salome_file_map_it = _map->find(Salome_file_name);
1040   if (_Salome_file_map_it ==  _map->end()) {
1041     Salome_file_i * Sfile = new Salome_file_i();
1042     Engines::Container_ptr container = this->GetContainerRef();
1043     Sfile->setContainer(Engines::Container::_duplicate(container));
1044     (*_map)[Salome_file_name] = Sfile;
1045   }
1046
1047   Salome_file_i * Sfile = (*_map)[Salome_file_name];
1048   return Sfile->_this();
1049 }
1050
1051 void
1052 Engines_Component_i::checkOutputFilesToService(const char* service_name)
1053 {
1054   // Try to find the service, if it doesn't exist, nothing to do.
1055   _Service_file_map_it = _Output_Service_file_map.find(service_name);
1056   if (_Service_file_map_it !=  _Output_Service_file_map.end()) {
1057     _t_Salome_file_map * _map = _Output_Service_file_map[service_name];
1058     _t_Salome_file_map::iterator begin = _map->begin();
1059     _t_Salome_file_map::iterator end = _map->end();
1060
1061     for(;begin!=end;begin++) {
1062       Salome_file_i * file = begin->second;
1063       std::string file_port_name = begin->first;
1064       configureSalome_file(service_name, file_port_name, file);
1065       file->recvFiles();
1066     }
1067   }
1068
1069 }
1070
1071 //=============================================================================
1072 /*!
1073  *  C++ method: used to configure the Salome_file into the runtime.
1074  *  \param service_name name of the service that use this Salome_file
1075  *  \param file_port_name name of the Salome_file
1076  *  \param file Salome_file C++ object
1077  */
1078 //=============================================================================
1079 void
1080 Engines_Component_i::configureSalome_file(std::string service_name,
1081                                           std::string file_port_name,
1082                                           Salome_file_i * file)
1083 {
1084   // By default this method does nothing
1085 }
1086
1087 //=============================================================================
1088 /*!
1089  *  C++ method: return the name of the container associated with this component
1090  *  This name does not contains the "/Containers" string and all "/" are replaced by "_"
1091  *  \return the container name (reformatted)
1092  */
1093 //=============================================================================
1094 std::string Engines_Component_i::getContainerName()
1095 {
1096   return _containerName;
1097 }
1098 //=============================================================================
1099 /*!
1100  *  C++ method: set the name of the container associated with this component (attribute _containerName)
1101  *  This name does not contains the "/Containers" string and all "/" are replaced by "_"
1102  *  \return the container name (reformatted)
1103  */
1104 //=============================================================================
1105 void Engines_Component_i::setContainerName()
1106 {
1107   CORBA::String_var containerName=_container->name();
1108   std::string name(containerName);
1109   name.erase(0,12);
1110   std::string::size_type slash =name.find_first_of('/');
1111   if(slash != std::string::npos)
1112     name[slash]='_';
1113   _containerName=name;
1114 }
1115
1116 //=============================================================================
1117 /*!
1118   \brief Get version of the component
1119
1120   This method is supposed to be implemented in all derived classes; default implementation
1121   returns empty string that means that no version information about the component is available.
1122
1123   \note The version of the component is stored to the study, as a part of general persistence
1124   mechanism; once stored, version information in the study cannot be changed.
1125
1126   \return string containing component's version, e.g. "1.0"
1127 */
1128 char* Engines_Component_i::getVersion()
1129 {
1130   return CORBA::string_dup( "" );
1131 }