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