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