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