Salome HOME
Porting to Mandrake 10.1 and new products:
[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 #include "SALOME_Component_i.hxx"
30 #include "SALOME_Container_i.hxx"
31 #include "RegistryConnexion.hxx"
32 #include "OpUtil.hxx"
33 #include <stdio.h>
34 #include <dlfcn.h>
35 #include <cstdlib>
36 #include "utilities.h"
37 using namespace std;
38
39 extern bool _Sleeping ;
40 static Engines_Component_i * theEngines_Component ;
41
42 Engines_Component_i::Engines_Component_i()
43 {
44 //  MESSAGE("Component constructor");
45 }
46
47 Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb,
48                                          PortableServer::POA_ptr poa, 
49                                          PortableServer::ObjectId * contId, 
50                                          const char *instanceName,
51                                          const char *interfaceName,
52                                          bool notif) :
53   _instanceName(instanceName),
54   _interfaceName(interfaceName),
55   _myConnexionToRegistry(0),
56   _ThreadId(0) , _ThreadCpuUsed(0) , _Executed(false) , _graphName("") , _nodeName("") {
57   MESSAGE("Component constructor with instanceName "<< _instanceName);
58   _orb = CORBA::ORB::_duplicate(orb);
59   _poa = PortableServer::POA::_duplicate(poa);
60   _contId = contId ;
61   CORBA::Object_var o = _poa->id_to_reference(*contId); // container ior...
62   const CORBA::String_var ior = _orb->object_to_string(o);
63   _myConnexionToRegistry = new RegistryConnexion(0, 0, ior, "theSession", _instanceName.c_str());
64
65   _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
66 }
67
68 // Constructeur pour composant parallele: ne pas faire appel au registry!!
69 Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb,
70                                          PortableServer::POA_ptr poa, 
71                                          PortableServer::ObjectId * contId, 
72                                          const char *instanceName,
73                                          const char *interfaceName,
74                                          int flag,
75                                          bool notif )
76   : _instanceName(instanceName),
77     _interfaceName(interfaceName),
78     _myConnexionToRegistry(0),
79     _ThreadId(0) , _ThreadCpuUsed(0) , _Executed(false) , _graphName("") , _nodeName("") {
80 //  MESSAGE("Component constructor with instanceName "<< _instanceName);
81   _orb = CORBA::ORB::_duplicate(orb);
82   _poa = PortableServer::POA::_duplicate(poa);
83   _contId = contId ;
84   //  CORBA::Object_var myself = this->_this(); //appel a _this = increment reference
85
86   _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
87 }
88
89 Engines_Component_i::~Engines_Component_i()
90 {
91   MESSAGE("Component destructor");
92 //   delete _myConnexionToRegistry;
93 //   _myConnexionToRegistry = 0 ;
94 }
95
96 char* Engines_Component_i::instanceName() {
97    return CORBA::string_dup(_instanceName.c_str()) ;
98 }
99
100 char* Engines_Component_i::interfaceName() {
101    return CORBA::string_dup(_interfaceName.c_str()) ;
102 }
103
104 void Engines_Component_i::ping()
105 {
106   MESSAGE("Engines_Component_i::ping() pid "<< getpid() << " threadid "
107           << pthread_self());
108 }
109
110 void Engines_Component_i::destroy()
111 {
112   MESSAGE("Engines_Component_i::destroy()");
113
114   delete _notifSupplier;
115   _notifSupplier = 0;
116
117   delete _myConnexionToRegistry;
118   _myConnexionToRegistry = 0 ;
119   _poa->deactivate_object(*_id) ;
120   CORBA::release(_poa) ;
121   delete(_id) ;
122   _thisObj->_remove_ref();
123   MESSAGE("Engines_Component_i::destroyed") ;
124 }
125
126 Engines::Container_ptr Engines_Component_i::GetContainerRef()
127 {
128   MESSAGE("Engines_Component_i::GetContainerRef");
129   CORBA::Object_ptr o = _poa->id_to_reference(*_contId) ;
130   return Engines::Container::_narrow(o);
131 }
132
133 PortableServer::ObjectId * Engines_Component_i::getId()
134 {
135 //  MESSAGE("PortableServer::ObjectId * Engines_Component_i::getId()");
136   return _id ;
137 }
138
139 void Engines_Component_i::setProperties(const Engines::FieldsDict& dico)
140 {
141   _fieldsDict.clear();
142   for (CORBA::ULong i=0; i<dico.length(); i++)
143     {
144       std::string cle(dico[i].key);
145       _fieldsDict[cle] = dico[i].value;
146     }
147 }
148
149 Engines::FieldsDict* Engines_Component_i::getProperties()
150 {
151   Engines::FieldsDict_var copie = new Engines::FieldsDict;
152   copie->length(_fieldsDict.size());
153   map<std::string,CORBA::Any>::iterator it;
154   CORBA::ULong i = 0;
155   for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++, i++)
156     {
157       std::string cle((*it).first);
158       copie[i].key = CORBA::string_dup(cle.c_str());
159       copie[i].value = _fieldsDict[cle];
160     }
161   return copie._retn();
162 }
163
164 void Engines_Component_i::beginService(const char *serviceName)
165 {
166   MESSAGE(pthread_self() << "Send BeginService notification for " << serviceName << endl
167           << "Component instance : " << _instanceName << endl << endl);
168   _ThreadId = pthread_self() ;
169   _StartUsed = 0 ;
170   _StartUsed = CpuUsed_impl() ;
171   _ThreadCpuUsed = 0 ;
172   _Executed = true ;
173   _serviceName = serviceName ;
174   if ( pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS , NULL ) ) {
175     perror("pthread_setcanceltype ") ;
176     exit(0) ;
177   }
178   if ( pthread_setcancelstate( PTHREAD_CANCEL_ENABLE , NULL ) ) {
179     perror("pthread_setcancelstate ") ;
180     exit(0) ;
181   }
182 //  MESSAGE(pthread_self() << " Return from BeginService for " << serviceName
183 //          << " ThreadId " << _ThreadId << " StartUsed " << _StartUsed
184 //          << " _graphName " << _graphName << " _nodeName " << _nodeName );
185
186   // --- for supervisor : all strings given with setProperties
187   //     are set in environment
188   bool overwrite = true;
189   map<std::string,CORBA::Any>::iterator it;
190   for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++)
191     {
192       std::string cle((*it).first);
193       if ((*it).second.type()->kind() == CORBA::tk_string)
194         {
195           const char* value;
196           (*it).second >>= value;
197           // --- todo: replace __GNUC__ test by an autoconf macro AC_CHECK_FUNC...
198 #if defined __GNUC__
199           int ret = setenv(cle.c_str(), value, overwrite);
200 #else
201           //CCRT porting : setenv not defined in stdlib.h
202           std::string s(cle);
203           s+='=';
204           s+=value;
205           //char* cast because 1st arg of linux putenv function is not a const char* !!!
206           int ret=putenv((char *)s.c_str());
207           //End of CCRT porting
208 #endif
209           MESSAGE("--- setenv: "<<cle<<" = "<< value);
210         }
211     }
212 }
213
214 void Engines_Component_i::endService(const char *serviceName)
215 {
216   _ThreadCpuUsed = CpuUsed_impl() ;
217   MESSAGE(pthread_self() << " Send EndService notification for " << serviceName << endl
218           << " Component instance : " << _instanceName << " StartUsed " << _StartUsed << " _ThreadCpuUsed "
219           << _ThreadCpuUsed << endl << endl);
220   _ThreadId = 0 ;
221 }
222
223 void Engines_Component_i::Names( const char * graphName ,
224                                  const char * nodeName ) {
225   _graphName = graphName ;
226   _nodeName = nodeName ;
227 //  MESSAGE("Engines_Component_i::Names( '" << _graphName << "' , '"
228 //          << _nodeName << "' )");
229 }
230
231 char* Engines_Component_i::graphName() {
232   return CORBA::string_dup( _graphName.c_str() ) ;
233 }
234
235 char* Engines_Component_i::nodeName() {
236   return CORBA::string_dup( _nodeName.c_str() ) ;
237 }
238
239 bool Engines_Component_i::Killer( pthread_t ThreadId , int signum ) {
240   if ( ThreadId ) {
241     if ( signum == 0 ) {
242       if ( pthread_cancel( ThreadId ) ) {
243         perror("Killer pthread_cancel error") ;
244         return false ;
245       }
246       else {
247         MESSAGE(pthread_self() << "Killer : ThreadId " << ThreadId << " pthread_canceled") ;
248       }
249     }
250     else {
251       if ( pthread_kill( ThreadId , signum ) == -1 ) {
252         perror("Killer pthread_kill error") ;
253         return false ;
254       }
255       else {
256         MESSAGE(pthread_self() << "Killer : ThreadId " << ThreadId << " pthread_killed("
257                 << signum << ")") ;
258       }
259     }
260   }
261   return true ;
262 }
263
264 bool Engines_Component_i::Kill_impl() {
265 //  MESSAGE("Engines_Component_i::Kill_i() pthread_t "<< pthread_self()
266 //          << " pid " << getpid() << " instanceName "
267 //          << _instanceName.c_str() << " interface " << _interfaceName.c_str()
268 //          << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
269 //          << dec << " _ThreadId " << _ThreadId << " this " << hex << this
270 //          << dec ) ;
271   bool RetVal = false ;
272   if ( _ThreadId > 0 && pthread_self() != _ThreadId ) {
273     RetVal = Killer( _ThreadId , 0 ) ;
274     _ThreadId = (pthread_t ) -1 ;
275   }
276   return RetVal ;
277 }
278
279 bool Engines_Component_i::Stop_impl() {
280   MESSAGE("Engines_Component_i::Stop_i() pthread_t "<< pthread_self()
281           << " pid " << getpid() << " instanceName "
282           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
283           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
284           << dec << " _ThreadId " << _ThreadId );
285   bool RetVal = false ;
286   if ( _ThreadId > 0 && pthread_self() != _ThreadId ) {
287     RetVal = Killer( _ThreadId , 0 ) ;
288     _ThreadId = (pthread_t ) -1 ;
289   }
290   return RetVal ;
291 }
292
293 bool Engines_Component_i::Suspend_impl() {
294   MESSAGE("Engines_Component_i::Suspend_i() pthread_t "<< pthread_self()
295           << " pid " << getpid() << " instanceName "
296           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
297           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
298           << dec << " _ThreadId " << _ThreadId );
299   bool RetVal = false ;
300   if ( _ThreadId > 0 && pthread_self() != _ThreadId ) {
301     if ( _Sleeping ) {
302       return false ;
303     }
304     else {
305       RetVal = Killer( _ThreadId ,SIGINT ) ;
306     }
307   }
308   return RetVal ;
309 }
310
311 bool Engines_Component_i::Resume_impl() {
312   MESSAGE("Engines_Component_i::Resume_i() pthread_t "<< pthread_self()
313           << " pid " << getpid() << " instanceName "
314           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
315           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
316           << dec << " _ThreadId " << _ThreadId );
317   bool RetVal = false ;
318   if ( _ThreadId > 0 && pthread_self() != _ThreadId ) {
319     if ( _Sleeping ) {
320       _Sleeping = false ;
321       RetVal = true ;
322     }
323     else {
324       RetVal = false ;
325     }
326   }
327   return RetVal ;
328
329 }
330
331 void SetCpuUsed() {
332   theEngines_Component->SetCurCpu() ;
333 }
334 void Engines_Component_i::SetCurCpu() {
335   _ThreadCpuUsed =  CpuUsed() ;
336 //  MESSAGE(pthread_self() << " Engines_Component_i::SetCurCpu() _ThreadCpuUsed " << _ThreadCpuUsed) ;
337 }
338
339 #include <sys/time.h>
340 #include <sys/resource.h>
341 #include <unistd.h>
342
343 long Engines_Component_i::CpuUsed() {
344   long cpu = 0 ;
345   struct rusage usage ;
346   if ( _ThreadId || _Executed ) {
347     if ( getrusage( RUSAGE_SELF , &usage ) == -1 ) {
348       perror("Engines_Component_i::CpuUsed") ;
349       return 0 ;
350     }
351     cpu = usage.ru_utime.tv_sec - _StartUsed ;
352 //    cout << pthread_self() << " Engines_Component_i::CpuUsed " << " " << _serviceName
353 //         << usage.ru_utime.tv_sec << " - " << _StartUsed << " = " << cpu << endl ;
354   }
355   else {
356 //    cout << pthread_self() << "Engines_Component_i::CpuUsed _ThreadId " << _ThreadId << " " << _serviceName
357 //         << " _StartUsed " << _StartUsed << endl ;
358   }
359   return cpu ;
360 }
361
362 CORBA::Long Engines_Component_i::CpuUsed_impl() {
363   long cpu = 0 ;
364   if ( _ThreadId || _Executed ) {
365     if ( _ThreadId > 0 ) {
366       if ( pthread_self() != _ThreadId ) {
367         if ( _Sleeping ) {
368         }
369         else {
370 // Get Cpu in the appropriate thread with that object !...
371           theEngines_Component = this ;
372           Killer( _ThreadId ,SIGUSR1 ) ;
373         }
374         cpu = _ThreadCpuUsed ;
375       }
376       else {
377         _ThreadCpuUsed = CpuUsed() ;
378         cpu = _ThreadCpuUsed ;
379 //        cout << pthread_self() << " Engines_Component_i::CpuUsed_impl " << _serviceName << " " << cpu
380 //             << endl ;
381       }
382     }
383     else {
384       cpu = _ThreadCpuUsed ;
385 //      cout << pthread_self() << " Engines_Component_i::CpuUsed_impl " << _serviceName << " " << cpu
386 //           << endl ;
387     }
388   }
389   else {
390 //    cout << pthread_self() << "Engines_Component_i::CpuUsed_impl _ThreadId " << _ThreadId << " "
391 //         << _serviceName << " _StartUsed " << _StartUsed << endl ;
392   }
393   return cpu ;
394 }
395
396 // Send message to event channel
397
398 void Engines_Component_i::sendMessage(const char *event_type, const char *message) {
399     _notifSupplier->Send(graphName(), nodeName(), event_type, message);
400 }
401
402 string Engines_Component_i::GetDynLibraryName(const char *componentName)
403 {
404   string ret="lib";
405   ret+=componentName;
406   ret+="Engine.so";
407   return ret;
408 }
409
410 string Engines_Component_i::BuildComponentNameForNS(const char *ComponentName, const char *ContainerName, const char *hostname)
411 {
412   string ret=Engines_Container_i::BuildContainerNameForNS(ContainerName,hostname);
413   ret+="/";
414   ret+=ComponentName;
415   return ret;
416 }
417