]> SALOME platform Git repositories - modules/yacs.git/blob - src/Container/Component_i.cxx
Salome HOME
Merge from V6_main_20120808 08Aug12
[modules/yacs.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 }