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