Salome HOME
Synchronize adm files
[modules/kernel.git] / src / Container / Component_i.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SALOME Container : implementation of container and engine for Kernel
24 //  File   : Component_i.cxx
25 //  Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA
26 //  Module : SALOME
27 //  $Header$
28 //#define private protected  // for pd_refCount trace
29 //
30 #include "SALOME_Component_i.hxx"
31 #include "SALOME_Container_i.hxx"
32 #include "RegistryConnexion.hxx"
33 #include "Basics_Utils.hxx"
34 #include <stdio.h>
35 #ifndef WIN32
36 #include <dlfcn.h>
37 #endif
38 #include <cstdlib>
39 #include "utilities.h"
40
41 #ifndef WIN32
42 #include <sys/time.h>
43 #include <sys/resource.h>
44 #include <unistd.h>
45 #else
46 #include <sys/timeb.h>
47 int SIGUSR11 = 1000;
48 #include <process.h>
49 #endif
50
51 extern bool _Sleeping ;
52 static Engines_Component_i * theEngines_Component ;
53
54 bool Engines_Component_i::_isMultiStudy = 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 WIN32
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 WIN32
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 #ifndef WIN32
895   std::string ret="lib";
896   ret+=componentName;
897   ret+="Engine.so";
898 #else
899   std::string ret=componentName;
900   ret+="Engine.dll";
901 #endif 
902   return ret;
903 }
904
905 //=============================================================================
906 /*! 
907  *  C++ method: DumpPython default implementation
908  */
909 //=============================================================================
910
911 Engines::TMPFile* Engines_Component_i::DumpPython(CORBA::Object_ptr theStudy, 
912                                                   CORBA::Boolean isPublished, 
913                                                   CORBA::Boolean isMultiFile, 
914                                                   CORBA::Boolean& isValidScript)
915 {
916   const char* aScript = isMultiFile ? "def RebuildData(theStudy): pass" : "";
917   char* aBuffer = new char[strlen(aScript)+1];
918   strcpy(aBuffer, aScript);
919   CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
920   int aBufferSize = strlen(aBuffer)+1;
921   Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aBufferSize, aBufferSize, anOctetBuf, 1); 
922   isValidScript = true;
923   return aStreamFile._retn(); 
924 }
925
926 Engines::Salome_file_ptr 
927 Engines_Component_i::getInputFileToService(const char* service_name, 
928                                            const char* Salome_file_name) 
929 {
930   // Try to find the service, if it doesn't exist, we throw an exception.
931   _Service_file_map_it = _Input_Service_file_map.find(service_name);
932   if (_Service_file_map_it ==  _Input_Service_file_map.end()) {
933     SALOME::ExceptionStruct es;
934     es.type = SALOME::INTERNAL_ERROR;
935     es.text = "service doesn't have salome files";
936     throw SALOME::SALOME_Exception(es);
937   }
938   _t_Salome_file_map * _map = _Input_Service_file_map[service_name];
939
940   // Try to find the Salome_file ...
941   _Salome_file_map_it = _map->find(Salome_file_name);
942   if (_Salome_file_map_it ==  _map->end()) {
943     SALOME::ExceptionStruct es;
944     es.type = SALOME::INTERNAL_ERROR;
945     es.text = "service doesn't have this Salome_file";
946     throw SALOME::SALOME_Exception(es);
947   }
948   Salome_file_i * Sfile = (*_map)[Salome_file_name];
949
950   return Sfile->_this();
951 }
952
953 Engines::Salome_file_ptr 
954 Engines_Component_i::setInputFileToService(const char* service_name, 
955                                            const char* Salome_file_name) 
956 {
957   // Try to find the service, if it doesn't exist, we add it.
958   _Service_file_map_it = _Input_Service_file_map.find(service_name);
959   if (_Service_file_map_it ==  _Input_Service_file_map.end()) {
960     _t_Salome_file_map * _map = new _t_Salome_file_map();
961     _Input_Service_file_map[service_name] = _map;
962   }
963   _t_Salome_file_map * _map = _Input_Service_file_map[service_name];
964   
965   // Try to find the Salome_file ...
966   _Salome_file_map_it = _map->find(Salome_file_name);
967   if (_Salome_file_map_it ==  _map->end()) {
968     Salome_file_i * Sfile = new Salome_file_i();
969     Engines::Container_ptr container = this->GetContainerRef();
970     Sfile->setContainer(Engines::Container::_duplicate(container));
971     (*_map)[Salome_file_name] = Sfile;
972   }
973
974   Salome_file_i * Sfile = (*_map)[Salome_file_name];
975   return Sfile->_this();
976 }
977
978 void 
979 Engines_Component_i::checkInputFilesToService(const char* service_name) 
980 {
981   // Try to find the service, if it doesn't exist, nothing to do.
982   _Service_file_map_it = _Input_Service_file_map.find(service_name);
983   if (_Service_file_map_it !=  _Input_Service_file_map.end()) {
984     _t_Salome_file_map * _map = _Input_Service_file_map[service_name];
985     _t_Salome_file_map::iterator begin = _map->begin();
986     _t_Salome_file_map::iterator end = _map->end();
987
988     for(;begin!=end;begin++) {
989       Salome_file_i * file = begin->second;
990       std::string file_port_name = begin->first;
991       configureSalome_file(service_name, file_port_name, file);
992       file->recvFiles();
993     }
994   }
995 }
996
997 Engines::Salome_file_ptr 
998 Engines_Component_i::getOutputFileToService(const char* service_name, 
999                                             const char* Salome_file_name) 
1000 {
1001   // Try to find the service, if it doesn't exist, we throw an exception.
1002   _Service_file_map_it = _Output_Service_file_map.find(service_name);
1003   if (_Service_file_map_it ==  _Output_Service_file_map.end()) {
1004     SALOME::ExceptionStruct es;
1005     es.type = SALOME::INTERNAL_ERROR;
1006     es.text = "service doesn't have salome files";
1007     throw SALOME::SALOME_Exception(es);
1008   }
1009   _t_Salome_file_map * _map = _Output_Service_file_map[service_name];
1010
1011   // Try to find the Salome_file ...
1012   _Salome_file_map_it = _map->find(Salome_file_name);
1013   if (_Salome_file_map_it ==  _map->end()) {
1014     SALOME::ExceptionStruct es;
1015     es.type = SALOME::INTERNAL_ERROR;
1016     es.text = "service doesn't have this Salome_file";
1017     throw SALOME::SALOME_Exception(es);
1018   }
1019   Salome_file_i * Sfile = (*_map)[Salome_file_name];
1020
1021   return Sfile->_this();
1022 }
1023
1024 Engines::Salome_file_ptr 
1025 Engines_Component_i::setOutputFileToService(const char* service_name, 
1026                                            const char* Salome_file_name) 
1027 {
1028   // Try to find the service, if it doesn't exist, we add it.
1029   _Service_file_map_it = _Output_Service_file_map.find(service_name);
1030   if (_Service_file_map_it ==  _Output_Service_file_map.end()) {
1031     _t_Salome_file_map * _map = new _t_Salome_file_map();
1032     _Output_Service_file_map[service_name] = _map;
1033   }
1034   _t_Salome_file_map * _map = _Output_Service_file_map[service_name];
1035   
1036   // Try to find the Salome_file ...
1037   _Salome_file_map_it = _map->find(Salome_file_name);
1038   if (_Salome_file_map_it ==  _map->end()) {
1039     Salome_file_i * Sfile = new Salome_file_i();
1040     Engines::Container_ptr container = this->GetContainerRef();
1041     Sfile->setContainer(Engines::Container::_duplicate(container));
1042     (*_map)[Salome_file_name] = Sfile;
1043   }
1044
1045   Salome_file_i * Sfile = (*_map)[Salome_file_name];
1046   return Sfile->_this();
1047 }
1048
1049 void 
1050 Engines_Component_i::checkOutputFilesToService(const char* service_name) 
1051 {
1052   // Try to find the service, if it doesn't exist, nothing to do.
1053   _Service_file_map_it = _Output_Service_file_map.find(service_name);
1054   if (_Service_file_map_it !=  _Output_Service_file_map.end()) {
1055     _t_Salome_file_map * _map = _Output_Service_file_map[service_name];
1056     _t_Salome_file_map::iterator begin = _map->begin();
1057     _t_Salome_file_map::iterator end = _map->end();
1058
1059     for(;begin!=end;begin++) {
1060       Salome_file_i * file = begin->second;
1061       std::string file_port_name = begin->first;
1062       configureSalome_file(service_name, file_port_name, file);
1063       file->recvFiles();
1064     }
1065   }
1066
1067 }
1068
1069 //=============================================================================
1070 /*! 
1071  *  C++ method: used to configure the Salome_file into the runtime.
1072  *  \param service_name name of the service that use this Salome_file
1073  *  \param file_port_name name of the Salome_file
1074  *  \param file Salome_file C++ object
1075  */
1076 //=============================================================================
1077 void
1078 Engines_Component_i::configureSalome_file(std::string service_name,
1079                                           std::string file_port_name,
1080                                           Salome_file_i * file) 
1081 {
1082   // By default this method does nothing
1083 }
1084
1085 //=============================================================================
1086 /*! 
1087  *  C++ method: allows to import data file into the Component internal data 
1088     structure (like import operation of BRep file in GEOM module).
1089  *  \param studyId identifier of the working study
1090  *  \param data container of the file content
1091  *  \param options additional options for import (if needed)
1092  */
1093 //=============================================================================
1094 Engines::ListOfIdentifiers* Engines_Component_i::importData(CORBA::Long studyId,
1095                                      Engines::DataContainer_ptr data,
1096                                      const Engines::ListOfOptions& options)
1097 {
1098   // By default this method does nothing
1099   Engines::ListOfIdentifiers_var aList = new Engines::ListOfIdentifiers;
1100   return aList._retn();
1101 }
1102
1103 //=============================================================================
1104 /*! 
1105  *  C++ method: allows to export data files from the Component internal data 
1106     structure (like Export operation of Step file in GEOM module).
1107  *  \param studyId identifier of the working study
1108  */
1109 //=============================================================================
1110 Engines::ListOfData* Engines_Component_i::getModifiedData(CORBA::Long studyId)
1111 {
1112   // By default this method does nothing
1113   Engines::ListOfData_var aList = new Engines::ListOfData;
1114   return aList._retn();
1115 }
1116
1117 //=============================================================================
1118 /*! 
1119  *  C++ method: return the name of the container associated with this component
1120  *  This name does not contains the "/Containers" string and all "/" are replaced by "_"
1121  *  \return the container name (reformatted)
1122  */
1123 //=============================================================================
1124 std::string Engines_Component_i::getContainerName()
1125 {
1126   return _containerName;
1127 }
1128 //=============================================================================
1129 /*! 
1130  *  C++ method: set the name of the container associated with this component (attribute _containerName)
1131  *  This name does not contains the "/Containers" string and all "/" are replaced by "_"
1132  *  \return the container name (reformatted)
1133  */
1134 //=============================================================================
1135 void Engines_Component_i::setContainerName()
1136 {
1137   CORBA::String_var containerName=_container->name();
1138   std::string name(containerName);
1139   name.erase(0,12);
1140   std::string::size_type slash =name.find_first_of('/');
1141   if(slash != std::string::npos)
1142     name[slash]='_';
1143   _containerName=name;
1144 }
1145
1146 //=============================================================================
1147 /*!
1148   \brief Get version of the component
1149
1150   This method is supposed to be implemented in all derived classes; default implementation
1151   returns empty string that means that no version information about the component is available.
1152
1153   \note The version of the component is stored to the study, as a part of general persistence
1154   mechanism; once stored, version information in the study cannot be changed.
1155   
1156   \return string containing component's version, e.g. "1.0"
1157 */
1158 char* Engines_Component_i::getVersion()
1159 {
1160   return CORBA::string_dup( "" );
1161 }