]> SALOME platform Git repositories - modules/kernel.git/blob - src/Container/Component_i.cxx
Salome HOME
Delete multi-study related code
[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 implementet 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 #ifndef WIN32
855   std::string ret="lib";
856   ret+=componentName;
857   ret+="Engine.so";
858 #else
859   std::string ret=componentName;
860   ret+="Engine.dll";
861 #endif
862   return ret;
863 }
864
865 //=============================================================================
866 /*!
867  *  C++ method: DumpPython default implementation
868  */
869 //=============================================================================
870
871 Engines::TMPFile* Engines_Component_i::DumpPython(CORBA::Boolean isPublished,
872                                                   CORBA::Boolean isMultiFile,
873                                                   CORBA::Boolean& isValidScript)
874 {
875   const char* aScript = isMultiFile ? "def RebuildData(): pass" : "";
876   char* aBuffer = new char[strlen(aScript)+1];
877   strcpy(aBuffer, aScript);
878   CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
879   int aBufferSize = strlen(aBuffer)+1;
880   Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aBufferSize, aBufferSize, anOctetBuf, 1);
881   isValidScript = true;
882   return aStreamFile._retn();
883 }
884
885 Engines::Salome_file_ptr
886 Engines_Component_i::getInputFileToService(const char* service_name,
887                                            const char* Salome_file_name)
888 {
889   // Try to find the service, if it doesn't exist, we throw an exception.
890   _Service_file_map_it = _Input_Service_file_map.find(service_name);
891   if (_Service_file_map_it ==  _Input_Service_file_map.end()) {
892     SALOME::ExceptionStruct es;
893     es.type = SALOME::INTERNAL_ERROR;
894     es.text = "service doesn't have salome files";
895     throw SALOME::SALOME_Exception(es);
896   }
897   _t_Salome_file_map * _map = _Input_Service_file_map[service_name];
898
899   // Try to find the Salome_file ...
900   _Salome_file_map_it = _map->find(Salome_file_name);
901   if (_Salome_file_map_it ==  _map->end()) {
902     SALOME::ExceptionStruct es;
903     es.type = SALOME::INTERNAL_ERROR;
904     es.text = "service doesn't have this Salome_file";
905     throw SALOME::SALOME_Exception(es);
906   }
907   Salome_file_i * Sfile = (*_map)[Salome_file_name];
908
909   return Sfile->_this();
910 }
911
912 Engines::Salome_file_ptr
913 Engines_Component_i::setInputFileToService(const char* service_name,
914                                            const char* Salome_file_name)
915 {
916   // Try to find the service, if it doesn't exist, we add it.
917   _Service_file_map_it = _Input_Service_file_map.find(service_name);
918   if (_Service_file_map_it ==  _Input_Service_file_map.end()) {
919     _t_Salome_file_map * _map = new _t_Salome_file_map();
920     _Input_Service_file_map[service_name] = _map;
921   }
922   _t_Salome_file_map * _map = _Input_Service_file_map[service_name];
923
924   // Try to find the Salome_file ...
925   _Salome_file_map_it = _map->find(Salome_file_name);
926   if (_Salome_file_map_it ==  _map->end()) {
927     Salome_file_i * Sfile = new Salome_file_i();
928     Engines::Container_ptr container = this->GetContainerRef();
929     Sfile->setContainer(Engines::Container::_duplicate(container));
930     (*_map)[Salome_file_name] = Sfile;
931   }
932
933   Salome_file_i * Sfile = (*_map)[Salome_file_name];
934   return Sfile->_this();
935 }
936
937 void
938 Engines_Component_i::checkInputFilesToService(const char* service_name)
939 {
940   // Try to find the service, if it doesn't exist, nothing to do.
941   _Service_file_map_it = _Input_Service_file_map.find(service_name);
942   if (_Service_file_map_it !=  _Input_Service_file_map.end()) {
943     _t_Salome_file_map * _map = _Input_Service_file_map[service_name];
944     _t_Salome_file_map::iterator begin = _map->begin();
945     _t_Salome_file_map::iterator end = _map->end();
946
947     for(;begin!=end;begin++) {
948       Salome_file_i * file = begin->second;
949       std::string file_port_name = begin->first;
950       configureSalome_file(service_name, file_port_name, file);
951       file->recvFiles();
952     }
953   }
954 }
955
956 Engines::Salome_file_ptr
957 Engines_Component_i::getOutputFileToService(const char* service_name,
958                                             const char* Salome_file_name)
959 {
960   // Try to find the service, if it doesn't exist, we throw an exception.
961   _Service_file_map_it = _Output_Service_file_map.find(service_name);
962   if (_Service_file_map_it ==  _Output_Service_file_map.end()) {
963     SALOME::ExceptionStruct es;
964     es.type = SALOME::INTERNAL_ERROR;
965     es.text = "service doesn't have salome files";
966     throw SALOME::SALOME_Exception(es);
967   }
968   _t_Salome_file_map * _map = _Output_Service_file_map[service_name];
969
970   // Try to find the Salome_file ...
971   _Salome_file_map_it = _map->find(Salome_file_name);
972   if (_Salome_file_map_it ==  _map->end()) {
973     SALOME::ExceptionStruct es;
974     es.type = SALOME::INTERNAL_ERROR;
975     es.text = "service doesn't have this Salome_file";
976     throw SALOME::SALOME_Exception(es);
977   }
978   Salome_file_i * Sfile = (*_map)[Salome_file_name];
979
980   return Sfile->_this();
981 }
982
983 Engines::Salome_file_ptr
984 Engines_Component_i::setOutputFileToService(const char* service_name,
985                                            const char* Salome_file_name)
986 {
987   // Try to find the service, if it doesn't exist, we add it.
988   _Service_file_map_it = _Output_Service_file_map.find(service_name);
989   if (_Service_file_map_it ==  _Output_Service_file_map.end()) {
990     _t_Salome_file_map * _map = new _t_Salome_file_map();
991     _Output_Service_file_map[service_name] = _map;
992   }
993   _t_Salome_file_map * _map = _Output_Service_file_map[service_name];
994
995   // Try to find the Salome_file ...
996   _Salome_file_map_it = _map->find(Salome_file_name);
997   if (_Salome_file_map_it ==  _map->end()) {
998     Salome_file_i * Sfile = new Salome_file_i();
999     Engines::Container_ptr container = this->GetContainerRef();
1000     Sfile->setContainer(Engines::Container::_duplicate(container));
1001     (*_map)[Salome_file_name] = Sfile;
1002   }
1003
1004   Salome_file_i * Sfile = (*_map)[Salome_file_name];
1005   return Sfile->_this();
1006 }
1007
1008 void
1009 Engines_Component_i::checkOutputFilesToService(const char* service_name)
1010 {
1011   // Try to find the service, if it doesn't exist, nothing to do.
1012   _Service_file_map_it = _Output_Service_file_map.find(service_name);
1013   if (_Service_file_map_it !=  _Output_Service_file_map.end()) {
1014     _t_Salome_file_map * _map = _Output_Service_file_map[service_name];
1015     _t_Salome_file_map::iterator begin = _map->begin();
1016     _t_Salome_file_map::iterator end = _map->end();
1017
1018     for(;begin!=end;begin++) {
1019       Salome_file_i * file = begin->second;
1020       std::string file_port_name = begin->first;
1021       configureSalome_file(service_name, file_port_name, file);
1022       file->recvFiles();
1023     }
1024   }
1025
1026 }
1027
1028 //=============================================================================
1029 /*!
1030  *  C++ method: used to configure the Salome_file into the runtime.
1031  *  \param service_name name of the service that use this Salome_file
1032  *  \param file_port_name name of the Salome_file
1033  *  \param file Salome_file C++ object
1034  */
1035 //=============================================================================
1036 void
1037 Engines_Component_i::configureSalome_file(std::string service_name,
1038                                           std::string file_port_name,
1039                                           Salome_file_i * file)
1040 {
1041   // By default this method does nothing
1042 }
1043
1044 //=============================================================================
1045 /*!
1046  *  C++ method: return the name of the container associated with this component
1047  *  This name does not contains the "/Containers" string and all "/" are replaced by "_"
1048  *  \return the container name (reformatted)
1049  */
1050 //=============================================================================
1051 std::string Engines_Component_i::getContainerName()
1052 {
1053   return _containerName;
1054 }
1055 //=============================================================================
1056 /*!
1057  *  C++ method: set the name of the container associated with this component (attribute _containerName)
1058  *  This name does not contains the "/Containers" string and all "/" are replaced by "_"
1059  *  \return the container name (reformatted)
1060  */
1061 //=============================================================================
1062 void Engines_Component_i::setContainerName()
1063 {
1064   CORBA::String_var containerName=_container->name();
1065   std::string name(containerName);
1066   name.erase(0,12);
1067   std::string::size_type slash =name.find_first_of('/');
1068   if(slash != std::string::npos)
1069     name[slash]='_';
1070   _containerName=name;
1071 }
1072
1073 //=============================================================================
1074 /*!
1075   \brief Get version of the component
1076
1077   This method is supposed to be implemented in all derived classes; default implementation
1078   returns empty string that means that no version information about the component is available.
1079
1080   \note The version of the component is stored to the study, as a part of general persistence
1081   mechanism; once stored, version information in the study cannot be changed.
1082
1083   \return string containing component's version, e.g. "1.0"
1084 */
1085 char* Engines_Component_i::getVersion()
1086 {
1087   return CORBA::string_dup( "" );
1088 }