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