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