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