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