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