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