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