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