Salome HOME
PR: container lifecycle, new design, first part
[modules/kernel.git] / src / Container / Component_i.cxx
1 //  SALOME Container : implementation of container and engine for Kernel
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : Component_i.cxx
25 //  Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA
26 //  Module : SALOME
27 //  $Header$
28
29 #define private protected
30 #include "SALOME_Component_i.hxx"
31 #include "SALOME_Container_i.hxx"
32 #include "RegistryConnexion.hxx"
33 #include "OpUtil.hxx"
34 #include <stdio.h>
35 #include <dlfcn.h>
36 #include <cstdlib>
37 #include "utilities.h"
38
39 #include <sys/time.h>
40 #include <sys/resource.h>
41 #include <unistd.h>
42
43 using namespace std;
44
45 extern bool _Sleeping ;
46 static Engines_Component_i * theEngines_Component ;
47
48 bool Engines_Component_i::_isMultiStudy = true;
49 bool Engines_Component_i::_isMultiInstance = false;
50
51 //=============================================================================
52 /*! 
53  *
54  */
55 //=============================================================================
56
57 Engines_Component_i::Engines_Component_i()
58 {
59 //  MESSAGE("Component constructor");
60 }
61
62 //=============================================================================
63 /*! 
64  *
65  */
66 //=============================================================================
67
68 Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb,
69                                          PortableServer::POA_ptr poa, 
70                                          PortableServer::ObjectId * contId, 
71                                          const char *instanceName,
72                                          const char *interfaceName,
73                                          bool notif) :
74   _instanceName(instanceName),
75   _interfaceName(interfaceName),
76   _myConnexionToRegistry(0),
77   _ThreadId(0) ,
78   _ThreadCpuUsed(0) ,
79   _Executed(false) ,
80   _graphName("") ,
81   _nodeName(""),
82  _studyId(-1)
83 {
84   MESSAGE("Component constructor with instanceName "<< _instanceName);
85   SCRUTE(pd_refCount);
86   _orb = CORBA::ORB::_duplicate(orb);
87   _poa = PortableServer::POA::_duplicate(poa);
88   _contId = contId ;
89   CORBA::Object_var o = _poa->id_to_reference(*contId); // container ior...
90   const CORBA::String_var ior = _orb->object_to_string(o);
91   _myConnexionToRegistry = new RegistryConnexion(0, 0, ior,"theSession",
92                                                  _instanceName.c_str());
93
94   _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
95   SCRUTE(pd_refCount);
96 }
97
98 //=============================================================================
99 /*! 
100  *
101  */
102 //=============================================================================
103
104 // Constructeur pour composant parallele: ne pas faire appel au registry!!
105 Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb,
106                                          PortableServer::POA_ptr poa, 
107                                          PortableServer::ObjectId * contId, 
108                                          const char *instanceName,
109                                          const char *interfaceName,
110                                          int flag,
111                                          bool notif ) :
112  _instanceName(instanceName),
113  _interfaceName(interfaceName),
114  _myConnexionToRegistry(0),
115  _ThreadId(0) ,
116  _ThreadCpuUsed(0) ,
117  _Executed(false) ,
118  _graphName("") ,
119  _nodeName(""),
120  _studyId(-1)
121 {
122   //  MESSAGE("Component constructor with instanceName "<< _instanceName);
123   _orb = CORBA::ORB::_duplicate(orb);
124   _poa = PortableServer::POA::_duplicate(poa);
125   _contId = contId ;
126
127   _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
128 }
129
130 //=============================================================================
131 /*! 
132  *
133  */
134 //=============================================================================
135
136 Engines_Component_i::~Engines_Component_i()
137 {
138   MESSAGE("Component destructor");
139 }
140
141 //=============================================================================
142 /*! 
143  *
144  */
145 //=============================================================================
146
147 char* Engines_Component_i::instanceName()
148 {
149    return CORBA::string_dup(_instanceName.c_str()) ;
150 }
151
152 //=============================================================================
153 /*! 
154  *
155  */
156 //=============================================================================
157
158 char* Engines_Component_i::interfaceName()
159 {
160   return CORBA::string_dup(_interfaceName.c_str()) ;
161 }
162
163 //=============================================================================
164 /*! 
165  *
166  */
167 //=============================================================================
168
169 CORBA::Boolean Engines_Component_i::setStudyId(CORBA::Long studyId)
170 {
171   ASSERT( studyId >= 0);
172   CORBA::Boolean ret = false;
173   if (_studyId < 0)
174     {
175       _studyId = studyId;
176       ret = true;
177     }
178   else
179     if ( _studyId == studyId) ret = true;
180   return ret;
181 }
182
183 //=============================================================================
184 /*! 
185  *
186  */
187 //=============================================================================
188
189 CORBA::Long Engines_Component_i::getStudyId()
190 {
191   return _studyId;
192 }
193
194 //=============================================================================
195 /*! 
196  *
197  */
198 //=============================================================================
199
200 void Engines_Component_i::ping()
201 {
202   MESSAGE("Engines_Component_i::ping() pid "<< getpid() << " threadid "
203           << pthread_self());
204 }
205
206 //=============================================================================
207 /*! 
208  *
209  */
210 //=============================================================================
211
212 void Engines_Component_i::destroy()
213 {
214   MESSAGE("Engines_Component_i::destroy()");
215   SCRUTE(pd_refCount);
216
217   delete _notifSupplier;
218   _notifSupplier = 0;
219
220   delete _myConnexionToRegistry;
221   _myConnexionToRegistry = 0 ;
222   _poa->deactivate_object(*_id) ;
223   CORBA::release(_poa) ;
224   delete(_id) ;
225   SCRUTE(pd_refCount);
226   _thisObj->_remove_ref();
227   SCRUTE(pd_refCount);
228   MESSAGE("Engines_Component_i::destroyed") ;
229 }
230
231 //=============================================================================
232 /*! 
233  *
234  */
235 //=============================================================================
236
237 Engines::Container_ptr Engines_Component_i::GetContainerRef()
238 {
239   MESSAGE("Engines_Component_i::GetContainerRef");
240   CORBA::Object_ptr o = _poa->id_to_reference(*_contId) ;
241   return Engines::Container::_narrow(o);
242 }
243
244 //=============================================================================
245 /*! 
246  *
247  */
248 //=============================================================================
249
250 PortableServer::ObjectId * Engines_Component_i::getId()
251 {
252 //  MESSAGE("PortableServer::ObjectId * Engines_Component_i::getId()");
253   return _id ;
254 }
255
256 //=============================================================================
257 /*! 
258  *
259  */
260 //=============================================================================
261
262 void Engines_Component_i::setProperties(const Engines::FieldsDict& dico)
263 {
264   _fieldsDict.clear();
265   for (CORBA::ULong i=0; i<dico.length(); i++)
266     {
267       std::string cle(dico[i].key);
268       _fieldsDict[cle] = dico[i].value;
269     }
270 }
271
272 //=============================================================================
273 /*! 
274  *
275  */
276 //=============================================================================
277
278 Engines::FieldsDict* Engines_Component_i::getProperties()
279 {
280   Engines::FieldsDict_var copie = new Engines::FieldsDict;
281   copie->length(_fieldsDict.size());
282   map<std::string,CORBA::Any>::iterator it;
283   CORBA::ULong i = 0;
284   for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++, i++)
285     {
286       std::string cle((*it).first);
287       copie[i].key = CORBA::string_dup(cle.c_str());
288       copie[i].value = _fieldsDict[cle];
289     }
290   return copie._retn();
291 }
292
293 //=============================================================================
294 /*! 
295  *
296  */
297 //=============================================================================
298
299 void Engines_Component_i::beginService(const char *serviceName)
300 {
301   MESSAGE(pthread_self() << "Send BeginService notification for " <<serviceName
302           << endl << "Component instance : " << _instanceName << endl << endl);
303   _ThreadId = pthread_self() ;
304   _StartUsed = 0 ;
305   _StartUsed = CpuUsed_impl() ;
306   _ThreadCpuUsed = 0 ;
307   _Executed = true ;
308   _serviceName = serviceName ;
309   if ( pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS , NULL ) )
310     {
311       perror("pthread_setcanceltype ") ;
312       exit(0) ;
313     }
314   if ( pthread_setcancelstate( PTHREAD_CANCEL_ENABLE , NULL ) )
315     {
316       perror("pthread_setcancelstate ") ;
317       exit(0) ;
318     }
319 //  MESSAGE(pthread_self() << " Return from BeginService for " << serviceName
320 //          << " ThreadId " << _ThreadId << " StartUsed " << _StartUsed
321 //          << " _graphName " << _graphName << " _nodeName " << _nodeName );
322
323   // --- for supervisor : all strings given with setProperties
324   //     are set in environment
325   bool overwrite = true;
326   map<std::string,CORBA::Any>::iterator it;
327   for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++)
328     {
329       std::string cle((*it).first);
330       if ((*it).second.type()->kind() == CORBA::tk_string)
331         {
332           const char* value;
333           (*it).second >>= value;
334           // --- todo: replace __GNUC__ test by an autoconf macro AC_CHECK_FUNC.
335 #if defined __GNUC__
336           int ret = setenv(cle.c_str(), value, overwrite);
337 #else
338           //CCRT porting : setenv not defined in stdlib.h
339           std::string s(cle);
340           s+='=';
341           s+=value;
342           //char* cast because 1st arg of linux putenv function is not a const char* !
343           int ret=putenv((char *)s.c_str());
344           //End of CCRT porting
345 #endif
346           MESSAGE("--- setenv: "<<cle<<" = "<< value);
347         }
348     }
349 }
350
351 //=============================================================================
352 /*! 
353  *
354  */
355 //=============================================================================
356
357 void Engines_Component_i::endService(const char *serviceName)
358 {
359   _ThreadCpuUsed = CpuUsed_impl() ;
360   MESSAGE(pthread_self() << " Send EndService notification for " << serviceName
361           << endl << " Component instance : " << _instanceName << " StartUsed "
362           << _StartUsed << " _ThreadCpuUsed "<< _ThreadCpuUsed << endl <<endl);
363   _ThreadId = 0 ;
364 }
365
366 //=============================================================================
367 /*! 
368  *
369  */
370 //=============================================================================
371
372 void Engines_Component_i::Names( const char * graphName ,
373                                  const char * nodeName )
374 {
375   _graphName = graphName ;
376   _nodeName = nodeName ;
377   //  MESSAGE("Engines_Component_i::Names( '" << _graphName << "' , '"
378   //          << _nodeName << "' )");
379 }
380
381 //=============================================================================
382 /*! 
383  *
384  */
385 //=============================================================================
386
387 char* Engines_Component_i::graphName()
388 {
389   return CORBA::string_dup( _graphName.c_str() ) ;
390 }
391
392 //=============================================================================
393 /*! 
394  *
395  */
396 //=============================================================================
397
398 char* Engines_Component_i::nodeName()
399 {
400   return CORBA::string_dup( _nodeName.c_str() ) ;
401 }
402
403 //=============================================================================
404 /*! 
405  *
406  */
407 //=============================================================================
408
409 bool Engines_Component_i::Killer( pthread_t ThreadId , int signum )
410 {
411   if ( ThreadId )
412     {
413       if ( signum == 0 )
414         {
415           if ( pthread_cancel( ThreadId ) )
416             {
417               perror("Killer pthread_cancel error") ;
418               return false ;
419             }
420           else
421             {
422               MESSAGE(pthread_self() << "Killer : ThreadId " << ThreadId
423                       << " pthread_canceled") ;
424             }
425         }
426       else
427         {
428           if ( pthread_kill( ThreadId , signum ) == -1 )
429             {
430               perror("Killer pthread_kill error") ;
431               return false ;
432             }
433           else 
434             {
435               MESSAGE(pthread_self() << "Killer : ThreadId " << ThreadId
436                       << " pthread_killed(" << signum << ")") ;
437             }
438         }
439     }
440   return true ;
441 }
442
443 //=============================================================================
444 /*! 
445  *
446  */
447 //=============================================================================
448
449 bool Engines_Component_i::Kill_impl() {
450 //  MESSAGE("Engines_Component_i::Kill_i() pthread_t "<< pthread_self()
451 //          << " pid " << getpid() << " instanceName "
452 //          << _instanceName.c_str() << " interface " << _interfaceName.c_str()
453 //          << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
454 //          << dec << " _ThreadId " << _ThreadId << " this " << hex << this
455 //          << dec ) ;
456   bool RetVal = false ;
457   if ( _ThreadId > 0 && pthread_self() != _ThreadId ) {
458     RetVal = Killer( _ThreadId , 0 ) ;
459     _ThreadId = (pthread_t ) -1 ;
460   }
461   return RetVal ;
462 }
463
464 //=============================================================================
465 /*! 
466  *
467  */
468 //=============================================================================
469
470 bool Engines_Component_i::Stop_impl()
471 {
472   MESSAGE("Engines_Component_i::Stop_i() pthread_t "<< pthread_self()
473           << " pid " << getpid() << " instanceName "
474           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
475           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
476           << dec << " _ThreadId " << _ThreadId );
477   
478   bool RetVal = false ;
479   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
480     {
481       RetVal = Killer( _ThreadId , 0 ) ;
482       _ThreadId = (pthread_t ) -1 ;
483     }
484   return RetVal ;
485 }
486
487 //=============================================================================
488 /*! 
489  *
490  */
491 //=============================================================================
492
493 bool Engines_Component_i::Suspend_impl()
494 {
495   MESSAGE("Engines_Component_i::Suspend_i() pthread_t "<< pthread_self()
496           << " pid " << getpid() << " instanceName "
497           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
498           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
499           << dec << " _ThreadId " << _ThreadId );
500   bool RetVal = false ;
501   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
502     {
503       if ( _Sleeping )
504         {
505           return false ;
506         }
507     else 
508       {
509         RetVal = Killer( _ThreadId ,SIGINT ) ;
510       }
511     }
512   return RetVal ;
513 }
514
515 //=============================================================================
516 /*! 
517  *
518  */
519 //=============================================================================
520
521 bool Engines_Component_i::Resume_impl()
522 {
523   MESSAGE("Engines_Component_i::Resume_i() pthread_t "<< pthread_self()
524           << " pid " << getpid() << " instanceName "
525           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
526           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
527           << dec << " _ThreadId " << _ThreadId );
528   bool RetVal = false ;
529   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
530     {
531     if ( _Sleeping ) 
532       {
533         _Sleeping = false ;
534         RetVal = true ;
535       }
536     else
537       {
538         RetVal = false ;
539       }
540     }
541   return RetVal ;
542
543 }
544
545 //=============================================================================
546 /*! 
547  *
548  */
549 //=============================================================================
550
551 void SetCpuUsed()
552 {
553   theEngines_Component->SetCurCpu() ;
554 }
555
556 //=============================================================================
557 /*! 
558  *
559  */
560 //=============================================================================
561
562 void Engines_Component_i::SetCurCpu()
563 {
564   _ThreadCpuUsed =  CpuUsed() ;
565   //  MESSAGE(pthread_self() << 
566   //  " Engines_Component_i::SetCurCpu() _ThreadCpuUsed " << _ThreadCpuUsed) ;
567 }
568
569 //=============================================================================
570 /*! 
571  *
572  */
573 //=============================================================================
574
575 long Engines_Component_i::CpuUsed()
576 {
577   long cpu = 0 ;
578   struct rusage usage ;
579   if ( _ThreadId || _Executed )
580     {
581       if ( getrusage( RUSAGE_SELF , &usage ) == -1 )
582         {
583           perror("Engines_Component_i::CpuUsed") ;
584           return 0 ;
585         }
586       cpu = usage.ru_utime.tv_sec - _StartUsed ;
587       // cout << pthread_self() << " Engines_Component_i::CpuUsed " << " "
588       //      << _serviceName   << usage.ru_utime.tv_sec << " - " << _StartUsed
589       //      << " = " << cpu << endl ;
590     }
591   else
592     {
593       // cout << pthread_self() << "Engines_Component_i::CpuUsed _ThreadId "
594       //      << _ThreadId << " " << _serviceName<< " _StartUsed " 
595       //      << _StartUsed << endl ;
596     }
597   return cpu ;
598 }
599
600 //=============================================================================
601 /*! 
602  *
603  */
604 //=============================================================================
605
606 CORBA::Long Engines_Component_i::CpuUsed_impl()
607 {
608   long cpu = 0 ;
609   if ( _ThreadId || _Executed )
610     {
611     if ( _ThreadId > 0 )
612       {
613       if ( pthread_self() != _ThreadId )
614         {
615         if ( _Sleeping )
616           {
617           }
618         else
619           {
620             // Get Cpu in the appropriate thread with that object !...
621             theEngines_Component = this ;
622             Killer( _ThreadId ,SIGUSR1 ) ;
623           }
624         cpu = _ThreadCpuUsed ;
625         }
626       else
627         {
628           _ThreadCpuUsed = CpuUsed() ;
629           cpu = _ThreadCpuUsed ;
630           // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl "
631           //      << _serviceName << " " << cpu << endl ;
632       }
633     }
634     else 
635       {
636         cpu = _ThreadCpuUsed ;
637         // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl "
638         //      << _serviceName << " " << cpu<< endl ;
639       }
640     }
641   else
642     {
643       // cout << pthread_self()<<"Engines_Component_i::CpuUsed_impl _ThreadId "
644       //      <<_ThreadId <<" "<<_serviceName<<" _StartUsed "<<_StartUsed<<endl;
645     }
646   return cpu ;
647 }
648
649 //=============================================================================
650 /*! 
651  *  Send message to event channel
652  */
653 //=============================================================================
654
655 void Engines_Component_i::sendMessage(const char *event_type,
656                                       const char *message)
657 {
658     _notifSupplier->Send(graphName(), nodeName(), event_type, message);
659 }
660
661 //=============================================================================
662 /*! 
663  *
664  */
665 //=============================================================================
666
667 string Engines_Component_i::GetDynLibraryName(const char *componentName)
668 {
669   string ret="lib";
670   ret+=componentName;
671   ret+="Engine.so";
672   return ret;
673 }
674
675 //=============================================================================
676 /*! 
677  *
678  */
679 //=============================================================================
680
681 string Engines_Component_i::BuildComponentNameForNS(const char *ComponentName,
682                                                     const char *ContainerName,
683                                                     const char *hostname)
684 {
685   string ret=Engines_Container_i::BuildContainerNameForNS(ContainerName,hostname);
686   ret+="/";
687   ret+=ComponentName;
688   return ret;
689 }
690