Salome HOME
Base implementation of Notebook
[modules/kernel.git] / src / Container / Component_i.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SALOME Container : implementation of container and engine for Kernel
23 //  File   : Component_i.cxx
24 //  Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA
25 //  Module : SALOME
26 //  $Header$
27 //#define private protected  // for pd_refCount trace
28 //
29 #include "SALOME_Component_i.hxx"
30 #include "SALOME_Container_i.hxx"
31 #include "RegistryConnexion.hxx"
32 #include "Basics_Utils.hxx"
33 #include <stdio.h>
34 #ifndef WIN32
35 #include <dlfcn.h>
36 #endif
37 #include <cstdlib>
38 #include "utilities.h"
39
40 #ifndef WIN32
41 #include <sys/time.h>
42 #include <sys/resource.h>
43 #include <unistd.h>
44 #else
45 #include <sys/timeb.h>
46 int SIGUSR11 = 1000;
47 #include <process.h>
48 #endif
49
50
51 using namespace std;
52
53 extern bool _Sleeping ;
54 static Engines_Component_i * theEngines_Component ;
55
56 bool Engines_Component_i::_isMultiStudy = true;
57 bool Engines_Component_i::_isMultiInstance = false;
58
59 /*! \class Engines_Component_i
60  *  \brief C++ implementation of Engines::Component interface
61  *
62  */
63
64 //=============================================================================
65 /*! 
66  *  Default constructor, not for use
67  */
68 //=============================================================================
69
70 Engines_Component_i::Engines_Component_i():_myConnexionToRegistry(0), _notifSupplier(0), _id(0)
71 {
72   //ASSERT(0);
73   MESSAGE("Default Constructor, not for normal use...");
74 }
75
76 //=============================================================================
77 /*!  \brief  Standard Constructor for generic Component, used in derived class
78  *
79  *  Connection to Registry and Notification
80  *  \param orb Object Request broker given by Container
81  *  \param poa Portable Object Adapter from Container (normally root_poa)
82  *  \param contId container CORBA id inside the server
83  *  \param instanceName unique instance name for this object (see Container_i)
84  *  \param interfaceName component class name
85  *  \param notif use of notification
86  *  \param regist (true or false) use of registry (default true)
87  */
88 //=============================================================================
89
90 Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb,
91                                          PortableServer::POA_ptr poa, 
92                                          PortableServer::ObjectId * contId, 
93                                          const char *instanceName,
94                                          const char *interfaceName,
95                                          bool notif,
96                                          bool regist ) :
97   _instanceName(instanceName),
98   _interfaceName(interfaceName),
99   _myConnexionToRegistry(0),
100   _notifSupplier(0),
101   _ThreadId(0) ,
102   _ThreadCpuUsed(0) ,
103   _Executed(false) ,
104   _graphName("") ,
105   _nodeName(""),
106   _studyId(-1),
107   _id(0),
108   _contId(0),
109   _CanceledThread(false)
110 {
111   MESSAGE("Component constructor with instanceName "<< _instanceName);
112   _orb = CORBA::ORB::_duplicate(orb);
113   _poa = PortableServer::POA::_duplicate(poa);
114   _contId = contId ;
115   CORBA::Object_var o = _poa->id_to_reference(*contId); // container ior...
116   _container=Engines::Container::_narrow(o);
117
118   if(regist)
119     {
120       const CORBA::String_var ior = _orb->object_to_string(o);
121       _myConnexionToRegistry = new RegistryConnexion(0, 0, ior,"theSession",
122                                                      _instanceName.c_str());
123     }
124
125   _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
126 }
127
128 //=============================================================================
129 /*!  \brief  Standard Constructor for standalone Component, used in derived class
130  *
131  *  Connection to Registry and Notification
132  *  \param orb Object Request broker given by Container
133  *  \param poa Portable Object Adapter from Container (normally root_poa)
134  *  \param container container CORBA reference
135  *  \param instanceName unique instance name for this object (see Container_i)
136  *  \param interfaceName component class name
137  *  \param notif use of notification
138  *  \param regist (true or false) use of registry (default true)
139  */
140 //=============================================================================
141
142 Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb,
143                                          PortableServer::POA_ptr poa,
144                                          Engines::Container_ptr container,
145                                          const char *instanceName,
146                                          const char *interfaceName,
147                                          bool notif,
148                                          bool regist) :
149   _instanceName(instanceName),
150   _interfaceName(interfaceName),
151   _myConnexionToRegistry(0),
152   _notifSupplier(0),
153   _ThreadId(0) ,
154   _ThreadCpuUsed(0) ,
155   _Executed(false) ,
156   _graphName("") ,
157   _nodeName(""),
158   _studyId(-1),
159   _id(0),
160   _contId(0),
161   _CanceledThread(false)
162 {
163   MESSAGE("Component constructor with instanceName "<< _instanceName);
164   _orb = CORBA::ORB::_duplicate(orb);
165   _poa = PortableServer::POA::_duplicate(poa);
166   _container=Engines::Container::_duplicate(container);
167   const CORBA::String_var ior = _orb->object_to_string(_container);
168   if(regist)
169     _myConnexionToRegistry = new RegistryConnexion(0, 0, ior,"theSession", _instanceName.c_str());
170   _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
171 }
172
173
174 //=============================================================================
175 /*! 
176  *  Destructor: call Container for decrement of instances count.
177  *  When instances count falls to 0, the container tries to remove the
178  *  component library (dlclose)
179  */
180 //=============================================================================
181
182 Engines_Component_i::~Engines_Component_i()
183 {
184   MESSAGE("Component destructor");
185   Engines_Container_i::decInstanceCnt(_interfaceName);
186   if(_myConnexionToRegistry)delete _myConnexionToRegistry;
187   _myConnexionToRegistry = 0 ;
188   if(_notifSupplier)delete _notifSupplier;
189   _notifSupplier = 0;
190   if(_id) delete _id;
191   _id=0;
192 }
193
194 //=============================================================================
195 /*! 
196  *  CORBA method: return name of the instance, unique in this Container
197  */
198 //=============================================================================
199
200 char* Engines_Component_i::instanceName()
201 {
202    return CORBA::string_dup(_instanceName.c_str()) ;
203 }
204
205 //=============================================================================
206 /*! 
207  *  CORBA method: return name of the component class
208  */
209 //=============================================================================
210
211 char* Engines_Component_i::interfaceName()
212 {
213   return CORBA::string_dup(_interfaceName.c_str()) ;
214 }
215
216 //=============================================================================
217 /*! 
218  *  CORBA method: Get study Id
219  *  \return -1: not initialised (Internal Error)
220  *           0: multistudy component instance
221  *          >0: study id associated to this instance
222  */
223 //=============================================================================
224
225 CORBA::Long Engines_Component_i::getStudyId()
226 {
227   return _studyId;
228 }
229
230 //=============================================================================
231 /*! 
232  *  CORBA method: Test if instance is alive and responds
233  */
234 //=============================================================================
235
236 void Engines_Component_i::ping()
237 {
238 #ifndef WIN32
239   MESSAGE("Engines_Component_i::ping() pid "<< getpid() << " threadid "
240           << pthread_self());
241 #else
242   MESSAGE("Engines_Component_i::ping() pid "<< _getpid()<< " threadid "
243           << pthread_self().p );
244 #endif
245 }
246
247 //=============================================================================
248 /*! 
249  *  CORBA method: Deactivate this instance. CORBA object is deactivated (do not
250  *  respond any more to CORBA calls), the connection to Regsitry is removed
251  *  (Registry informed of deactivation), internal server reference counter on
252  *  the derived servant class is decremented, to allow destruction of the class
253  *  (delete) by POA, when there are no more references.
254  *  -- TO BE USED BY CONTAINER ONLY (Container housekeeping) --
255  */
256 //=============================================================================
257
258 void Engines_Component_i::destroy()
259 {
260   MESSAGE("Engines_Component_i::destroy()");
261   //SCRUTE(_refcount_value());
262   _poa->deactivate_object(*_id);
263   //SCRUTE(_refcount_value());
264   _remove_ref();
265   //SCRUTE(_refcount_value());
266   MESSAGE("Engines_Component_i::destroyed") ;
267 }
268
269 //=============================================================================
270 /*! 
271  *  CORBA method: return CORBA reference of the Container
272  *
273  */
274 //=============================================================================
275
276 Engines::Container_ptr Engines_Component_i::GetContainerRef()
277 {
278   return Engines::Container::_duplicate(_container);
279 }
280
281 //=============================================================================
282 /*! 
283  *  CORBA method: 
284  *  Gives a sequence of (key=string,value=any) to the component. 
285  *  Base class component stores the sequence in a map.
286  *  The map is cleared before.
287  *  This map is for use by derived classes. 
288  *  \param dico sequence of (key=string,value=any)
289  */
290 //=============================================================================
291
292 void Engines_Component_i::setProperties(const Engines::FieldsDict& dico)
293 {
294   _fieldsDict.clear();
295   for (CORBA::ULong i=0; i<dico.length(); i++)
296     {
297       std::string cle(dico[i].key);
298       _fieldsDict[cle] = dico[i].value;
299     }
300 }
301
302 //=============================================================================
303 /*! 
304  *  CORBA method: 
305  *  returns a previously stored map (key=string,value=any) as a sequence.
306  *  (see setProperties)
307  */
308 //=============================================================================
309
310 Engines::FieldsDict* Engines_Component_i::getProperties()
311 {
312   Engines::FieldsDict_var copie = new Engines::FieldsDict;
313   copie->length(_fieldsDict.size());
314   map<std::string,CORBA::Any>::iterator it;
315   CORBA::ULong i = 0;
316   for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++, i++)
317     {
318       std::string cle((*it).first);
319       copie[i].key = CORBA::string_dup(cle.c_str());
320       copie[i].value = _fieldsDict[cle];
321     }
322   return copie._retn();
323 }
324
325 //=============================================================================
326 /*! 
327  *  CORBA method: used by Supervision to give names to this instance
328  */
329 //=============================================================================
330
331 void Engines_Component_i::Names( const char * graphName ,
332                                  const char * nodeName )
333 {
334   _graphName = graphName ;
335   _nodeName = nodeName ;
336   //  MESSAGE("Engines_Component_i::Names( '" << _graphName << "' , '"
337   //          << _nodeName << "' )");
338 }
339
340 //=============================================================================
341 /*! 
342  *  CORBA method: used in Supervision
343  */
344 //=============================================================================
345
346 bool Engines_Component_i::Kill_impl() 
347 {
348 //  MESSAGE("Engines_Component_i::Kill_i() pthread_t "<< pthread_self()
349 //          << " pid " << getpid() << " instanceName "
350 //          << _instanceName.c_str() << " interface " << _interfaceName.c_str()
351 //          << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
352 //          << dec << " _ThreadId " << _ThreadId << " this " << hex << this
353 //          << dec ) ;
354
355   bool RetVal = false ;
356 #ifndef WIN32
357   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
358     {
359       RetVal = Killer( _ThreadId , SIGUSR2 ) ;
360       _ThreadId = (pthread_t ) -1 ;
361     }
362
363 #else
364   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
365     {
366       RetVal = Killer( *_ThreadId , 0 ) ;
367       _ThreadId = (pthread_t* ) 0 ;
368     }
369
370 #endif
371   return RetVal ;
372 }
373
374 //=============================================================================
375 /*! 
376  *  CORBA method: used in Supervision
377  */
378 //=============================================================================
379
380 bool Engines_Component_i::Stop_impl()
381 {
382 #ifndef WIN32
383   MESSAGE("Engines_Component_i::Stop_i() pthread_t "<< pthread_self()
384           << " pid " << getpid() << " instanceName "
385           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
386           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
387           << dec << " _ThreadId " << _ThreadId );
388 #else
389   MESSAGE("Engines_Component_i::Stop_i() pthread_t "<< pthread_self().p
390           << " pid " << _getpid() << " instanceName "
391           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
392           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
393           << dec << " _ThreadId " << _ThreadId );
394 #endif
395   
396
397   bool RetVal = false ;
398 #ifndef WIN32
399   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
400     {
401       RetVal = Killer( _ThreadId , 0 ) ;
402       _ThreadId = (pthread_t ) -1 ;
403     }
404 #else
405   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
406     {
407       RetVal = Killer( *_ThreadId , 0 ) ;
408       _ThreadId = (pthread_t* ) 0 ;
409     }
410 #endif
411   return RetVal ;
412 }
413
414 //=============================================================================
415 /*! 
416  *  CORBA method: used in Supervision
417  */
418 //=============================================================================
419
420 bool Engines_Component_i::Suspend_impl()
421 {
422 #ifndef WIN32
423   MESSAGE("Engines_Component_i::Suspend_i() pthread_t "<< pthread_self()
424           << " pid " << getpid() << " instanceName "
425           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
426           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
427           << dec << " _ThreadId " << _ThreadId );
428 #else
429   MESSAGE("Engines_Component_i::Suspend_i() pthread_t "<< pthread_self().p
430           << " pid " << _getpid() << " instanceName "
431           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
432           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
433           << dec << " _ThreadId " << _ThreadId );
434 #endif
435
436   bool RetVal = false ;
437 #ifndef WIN32
438   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
439 #else
440   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
441 #endif
442     {
443       if ( _Sleeping )
444         {
445           return false ;
446         }
447     else 
448       {
449 #ifndef WIN32
450         RetVal = Killer( _ThreadId ,SIGINT ) ;
451 #else
452         RetVal = Killer( *_ThreadId ,SIGINT ) ;
453 #endif
454         //if ( RetVal ) _Sleeping = true;
455
456       }
457     }
458   return RetVal ;
459 }
460
461 //=============================================================================
462 /*! 
463  *  CORBA method: used in Supervision
464  */
465 //=============================================================================
466
467 bool Engines_Component_i::Resume_impl()
468 {
469 #ifndef WIN32
470   MESSAGE("Engines_Component_i::Resume_i() pthread_t "<< pthread_self()
471           << " pid " << getpid() << " instanceName "
472           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
473           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
474           << dec << " _ThreadId " << _ThreadId );
475 #else
476   MESSAGE("Engines_Component_i::Resume_i() pthread_t "<< pthread_self().p
477           << " pid " << _getpid() << " instanceName "
478           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
479           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
480           << dec << " _ThreadId " << _ThreadId );
481 #endif
482   bool RetVal = false ;
483 #ifndef WIN32
484   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
485 #else
486   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
487 #endif
488     {
489     if ( _Sleeping ) 
490       {
491         _Sleeping = false ;
492         RetVal = true ;
493       }
494     else
495       {
496         RetVal = false ;
497       }
498     }
499   return RetVal ;
500 }
501
502 //=============================================================================
503 /*! 
504  *  CORBA method: 
505  */
506 //=============================================================================
507
508 CORBA::Long Engines_Component_i::CpuUsed_impl()
509 {
510   long cpu = 0 ;
511   if ( _ThreadId || _Executed )
512     {
513     if ( _ThreadId > 0 )
514       {
515 #ifndef WIN32
516       if ( pthread_self() != _ThreadId )
517 #else
518       if ( pthread_self().p != _ThreadId->p )
519 #endif
520         {
521         if ( _Sleeping )
522           {
523           }
524         else
525           {
526             // Get Cpu in the appropriate thread with that object !...
527             theEngines_Component = this ;
528 #ifndef WIN32
529             Killer( _ThreadId ,SIGUSR1 ) ;
530 #else
531             Killer( *_ThreadId ,SIGUSR11 ) ;
532 #endif
533           }
534         cpu = _ThreadCpuUsed ;
535         }
536       else
537         {
538           _ThreadCpuUsed = CpuUsed() ;
539           cpu = _ThreadCpuUsed ;
540           // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl "
541           //      << _serviceName << " " << cpu << endl ;
542       }
543     }
544     else 
545       {
546         cpu = _ThreadCpuUsed ;
547         // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl "
548         //      << _serviceName << " " << cpu<< endl ;
549       }
550     }
551   else
552     {
553       // cout<< pthread_self()<<"Engines_Component_i::CpuUsed_impl _ThreadId "
554       //     <<_ThreadId <<" "<<_serviceName<<" _StartUsed "<<_StartUsed<<endl;
555     }
556   return cpu ;
557 }
558
559 //=============================================================================
560 /*! 
561  *  CORBA method: 
562  */
563 //=============================================================================
564 SALOME::GenericObj_ptr Engines_Component_i::FindObjectByInternalEntry( const char* theEntry )
565 {
566   return SALOME::GenericObj_ptr();
567 }
568
569 //=============================================================================
570 /*! 
571  *  C++ method: return Container Servant
572  */
573 //=============================================================================
574
575 Engines_Container_i *Engines_Component_i::GetContainerPtr()
576 {
577   PortableServer::ObjectId_var  contId=_poa->reference_to_id(_container);
578   return dynamic_cast<Engines_Container_i*>(_poa->id_to_servant(contId)) ;
579 }
580
581 //=============================================================================
582 /*! 
583  *  C++ method: set study Id
584  *  \param studyId         0 if instance is not associated to a study, 
585  *                         >0 otherwise (== study id)
586  *  \return true if the set of study Id is OK
587  *  must be set once by Container, at instance creation,
588  *  and cannot be changed after.
589  */
590 //=============================================================================
591
592 CORBA::Boolean Engines_Component_i::setStudyId(CORBA::Long studyId)
593 {
594   ASSERT( studyId >= 0);
595   CORBA::Boolean ret = false;
596   if (_studyId < 0) // --- not yet initialized 
597     {
598       _studyId = studyId;
599       ret = true;
600     }
601   else
602     if ( _studyId == studyId) ret = true;
603   return ret;
604 }
605
606 //=============================================================================
607 /*! 
608  *  C++ method: return CORBA instance id, the id is set in derived class
609  *  constructor, when instance is activated.
610  */
611 //=============================================================================
612
613 PortableServer::ObjectId * Engines_Component_i::getId()
614 {
615 //  MESSAGE("PortableServer::ObjectId * Engines_Component_i::getId()");
616   return _id ;
617 }
618
619 //=============================================================================
620 /*! 
621  *  C++ method: used by derived classes for supervision
622  */
623 //=============================================================================
624
625 void Engines_Component_i::beginService(const char *serviceName)
626 {
627   std::cerr << "beginService for " << serviceName << " Component instance : " << _instanceName << std::endl;
628
629 #ifndef WIN32
630   _ThreadId = pthread_self() ;
631 #else
632   _ThreadId = new pthread_t;
633   _ThreadId->p = pthread_self().p ;
634   _ThreadId->x = pthread_self().x ;
635 #endif
636   _StartUsed = 0 ;
637   _StartUsed = CpuUsed_impl() ;
638   _ThreadCpuUsed = 0 ;
639   _Executed = true ;
640   _serviceName = serviceName ;
641   theEngines_Component = this ;
642   if ( pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS , NULL ) )
643     {
644       perror("pthread_setcanceltype ") ;
645       exit(0) ;
646     }
647   if ( pthread_setcancelstate( PTHREAD_CANCEL_ENABLE , NULL ) )
648     {
649       perror("pthread_setcancelstate ") ;
650       exit(0) ;
651     }
652
653   // --- all strings given with setProperties are set in environment
654   map<std::string,CORBA::Any>::iterator it;
655   for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++)
656     {
657       std::string cle((*it).first);
658       if ((*it).second.type()->kind() == CORBA::tk_string)
659         {
660           const char* value;
661           (*it).second >>= value;
662           std::string s(cle);
663           s+='=';
664           s+=value;
665           putenv((char *)s.c_str());
666           MESSAGE("--- setenv: "<<cle<<" = "<< value);
667         }
668     }
669 }
670
671 //=============================================================================
672 /*! 
673  *  C++ method: used by derived classes for supervision
674  */
675 //=============================================================================
676
677 void Engines_Component_i::endService(const char *serviceName)
678 {
679   if ( !_CanceledThread )
680     _ThreadCpuUsed = CpuUsed_impl() ;
681
682   float cpus=_ThreadCpuUsed/1000.;
683   std::cerr << "endService for " << serviceName << " Component instance : " << _instanceName ;
684   std::cerr << " Cpu Used: " << cpus << " (s) " << std::endl;
685   MESSAGE("Send EndService notification for " << serviceName
686           << endl << " Component instance : " << _instanceName << " StartUsed "
687           << _StartUsed << " _ThreadCpuUsed "<< _ThreadCpuUsed << endl <<endl);
688   _ThreadId = 0 ;
689 }
690
691 //=============================================================================
692 /*! 
693  *  C++ method: -- CHECK IF USED --
694  */
695 //=============================================================================
696
697 char* Engines_Component_i::graphName()
698 {
699   return CORBA::string_dup( _graphName.c_str() ) ;
700 }
701
702 //=============================================================================
703 /*! 
704  *  C++ method: -- CHECK IF USED --
705  */
706 //=============================================================================
707
708 char* Engines_Component_i::nodeName()
709 {
710   return CORBA::string_dup( _nodeName.c_str() ) ;
711 }
712
713 //=============================================================================
714 /*! 
715  *  C++ method: used in Supervision (see kill_impl)
716  */
717 //=============================================================================
718
719 bool Engines_Component_i::Killer( pthread_t ThreadId , int signum )
720 {
721 #ifndef WIN32
722   if ( ThreadId )
723 #else
724   if ( ThreadId.p )
725 #endif
726     {
727       if ( signum == 0 )
728         {
729           if ( pthread_cancel( ThreadId ) )
730             {
731               perror("Killer pthread_cancel error") ;
732               return false ;
733             }
734           else
735             {
736 #ifdef WNT
737               MESSAGE("Killer : ThreadId " << ThreadId.p << " pthread_canceled") ;
738 #else
739               MESSAGE("Killer : ThreadId " << ThreadId << " pthread_canceled") ;
740 #endif
741             }
742         }
743       else
744         {
745           if ( pthread_kill( ThreadId , signum ) == -1 )
746             {
747               perror("Killer pthread_kill error") ;
748               return false ;
749             }
750           else 
751             {
752 #ifdef WNT
753               MESSAGE("Killer : ThreadId " << ThreadId.p << " pthread_killed(" << signum << ")") ;
754 #else
755               MESSAGE("Killer : ThreadId " << ThreadId << " pthread_killed(" << signum << ")") ;
756 #endif
757             }
758         }
759     }
760   return true ;
761 }
762
763 //=============================================================================
764 /*! 
765  *  C++ method:
766  */ 
767 //=============================================================================
768
769 void SetCpuUsed()
770 {
771   if ( theEngines_Component )
772     theEngines_Component->SetCurCpu() ;
773 }
774
775 //=============================================================================
776 /*! 
777  *  C++ method:
778  */
779 //=============================================================================
780
781 void Engines_Component_i::SetCurCpu()
782 {
783   _ThreadCpuUsed =  CpuUsed() ;
784   //  MESSAGE(pthread_self() << 
785   //  " Engines_Component_i::SetCurCpu() _ThreadCpuUsed " << _ThreadCpuUsed) ;
786 }
787
788 //=============================================================================
789 /*! 
790  *  C++ method:
791  */
792 //=============================================================================
793
794 long Engines_Component_i::CpuUsed()
795 {
796   long cpu = 0 ;
797 #ifndef WIN32
798   struct rusage usage ;
799   if ( _ThreadId || _Executed )
800     {
801       if ( getrusage( RUSAGE_SELF , &usage ) == -1 )
802         {
803           perror("Engines_Component_i::CpuUsed") ;
804           return 0 ;
805         }
806       //cpu time is calculated in millisecond (user+system times)
807       cpu = usage.ru_utime.tv_sec*1000 +usage.ru_utime.tv_usec/1000;
808       cpu = cpu+ usage.ru_stime.tv_sec*1000 +usage.ru_stime.tv_usec/1000;
809       cpu=cpu-_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.c_str(), _nodeName.c_str(), 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
1050 //=============================================================================
1051 /*! 
1052  *  C++ method: return the name of the container associated with this component
1053  *  This name does not contains the "/Containers" string and all "/" are replaced by "_"
1054  *  \return the container name (reformatted)
1055  */
1056 //=============================================================================
1057 std::string Engines_Component_i::getContainerName()
1058 {
1059   CORBA::String_var containerName=_container->name();
1060   std::string name(containerName);
1061   name.erase(0,12);
1062   string::size_type slash =name.find_first_of('/');
1063   if(slash != std::string::npos)
1064     name[slash]='_';
1065   return name;
1066 }