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