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