Salome HOME
DCQ : Merge with Ecole_ete_a6.
[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 using namespace std;
30 #include "SALOME_Component_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
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           int ret = setenv(cle.c_str(), value, overwrite);
197           MESSAGE("--- setenv: "<<cle<<" = "<< value);
198         }
199     }
200 }
201
202 void Engines_Component_i::endService(const char *serviceName)
203 {
204   _ThreadCpuUsed = CpuUsed_impl() ;
205   MESSAGE(pthread_self() << " Send EndService notification for " << serviceName << endl
206           << " Component instance : " << _instanceName << " StartUsed " << _StartUsed << " _ThreadCpuUsed "
207           << _ThreadCpuUsed << endl << endl);
208   _ThreadId = 0 ;
209 }
210
211 void Engines_Component_i::Names( const char * graphName ,
212                                  const char * nodeName ) {
213   _graphName = graphName ;
214   _nodeName = nodeName ;
215 //  MESSAGE("Engines_Component_i::Names( '" << _graphName << "' , '"
216 //          << _nodeName << "' )");
217 }
218
219 char* Engines_Component_i::graphName() {
220   return CORBA::string_dup( _graphName.c_str() ) ;
221 }
222
223 char* Engines_Component_i::nodeName() {
224   return CORBA::string_dup( _nodeName.c_str() ) ;
225 }
226
227 bool Engines_Component_i::Killer( int ThreadId , int signum ) {
228   if ( ThreadId ) {
229     if ( signum == 0 ) {
230       if ( pthread_cancel( ThreadId ) ) {
231         perror("Killer pthread_cancel error") ;
232         return false ;
233       }
234       else {
235         MESSAGE(pthread_self() << "Killer : ThreadId " << ThreadId << " pthread_canceled") ;
236       }
237     }
238     else {
239       if ( pthread_kill( ThreadId , signum ) == -1 ) {
240         perror("Killer pthread_kill error") ;
241         return false ;
242       }
243       else {
244         MESSAGE(pthread_self() << "Killer : ThreadId " << ThreadId << " pthread_killed("
245                 << signum << ")") ;
246       }
247     }
248   }
249   return true ;
250 }
251
252 bool Engines_Component_i::Kill_impl() {
253 //  MESSAGE("Engines_Component_i::Kill_i() pthread_t "<< pthread_self()
254 //          << " pid " << getpid() << " instanceName "
255 //          << _instanceName.c_str() << " interface " << _interfaceName.c_str()
256 //          << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
257 //          << dec << " _ThreadId " << _ThreadId << " this " << hex << this
258 //          << dec ) ;
259   bool RetVal = false ;
260   if ( _ThreadId > 0 && pthread_self() != _ThreadId ) {
261     RetVal = Killer( _ThreadId , 0 ) ;
262     _ThreadId = (pthread_t ) -1 ;
263   }
264   return RetVal ;
265 }
266
267 bool Engines_Component_i::Stop_impl() {
268   MESSAGE("Engines_Component_i::Stop_i() pthread_t "<< pthread_self()
269           << " pid " << getpid() << " instanceName "
270           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
271           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
272           << dec << " _ThreadId " << _ThreadId );
273   bool RetVal = false ;
274   if ( _ThreadId > 0 && pthread_self() != _ThreadId ) {
275     RetVal = Killer( _ThreadId , 0 ) ;
276     _ThreadId = (pthread_t ) -1 ;
277   }
278   return RetVal ;
279 }
280
281 bool Engines_Component_i::Suspend_impl() {
282   MESSAGE("Engines_Component_i::Suspend_i() pthread_t "<< pthread_self()
283           << " pid " << getpid() << " instanceName "
284           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
285           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
286           << dec << " _ThreadId " << _ThreadId );
287   bool RetVal = false ;
288   if ( _ThreadId > 0 && pthread_self() != _ThreadId ) {
289     if ( _Sleeping ) {
290       return false ;
291     }
292     else {
293       RetVal = Killer( _ThreadId ,SIGINT ) ;
294     }
295   }
296   return RetVal ;
297 }
298
299 bool Engines_Component_i::Resume_impl() {
300   MESSAGE("Engines_Component_i::Resume_i() pthread_t "<< pthread_self()
301           << " pid " << getpid() << " instanceName "
302           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
303           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
304           << dec << " _ThreadId " << _ThreadId );
305   bool RetVal = false ;
306   if ( _ThreadId > 0 && pthread_self() != _ThreadId ) {
307     if ( _Sleeping ) {
308       _Sleeping = false ;
309       RetVal = true ;
310     }
311     else {
312       RetVal = false ;
313     }
314   }
315   return RetVal ;
316
317 }
318
319 void SetCpuUsed() {
320   theEngines_Component->SetCurCpu() ;
321 }
322 void Engines_Component_i::SetCurCpu() {
323   _ThreadCpuUsed =  CpuUsed() ;
324 //  MESSAGE(pthread_self() << " Engines_Component_i::SetCurCpu() _ThreadCpuUsed " << _ThreadCpuUsed) ;
325 }
326
327 #include <sys/time.h>
328 #include <sys/resource.h>
329 #include <unistd.h>
330
331 long Engines_Component_i::CpuUsed() {
332   long cpu = 0 ;
333   struct rusage usage ;
334   if ( _ThreadId || _Executed ) {
335     if ( getrusage( RUSAGE_SELF , &usage ) == -1 ) {
336       perror("Engines_Component_i::CpuUsed") ;
337       return 0 ;
338     }
339     cpu = usage.ru_utime.tv_sec - _StartUsed ;
340 //    cout << pthread_self() << " Engines_Component_i::CpuUsed " << " " << _serviceName
341 //         << usage.ru_utime.tv_sec << " - " << _StartUsed << " = " << cpu << endl ;
342   }
343   else {
344 //    cout << pthread_self() << "Engines_Component_i::CpuUsed _ThreadId " << _ThreadId << " " << _serviceName
345 //         << " _StartUsed " << _StartUsed << endl ;
346   }
347   return cpu ;
348 }
349
350 long Engines_Component_i::CpuUsed_impl() {
351   long cpu = 0 ;
352   if ( _ThreadId || _Executed ) {
353     if ( _ThreadId > 0 ) {
354       if ( pthread_self() != _ThreadId ) {
355         if ( _Sleeping ) {
356         }
357         else {
358 // Get Cpu in the appropriate thread with that object !...
359           theEngines_Component = this ;
360           Killer( _ThreadId ,SIGUSR1 ) ;
361         }
362         cpu = _ThreadCpuUsed ;
363       }
364       else {
365         _ThreadCpuUsed = CpuUsed() ;
366         cpu = _ThreadCpuUsed ;
367 //        cout << pthread_self() << " Engines_Component_i::CpuUsed_impl " << _serviceName << " " << cpu
368 //             << endl ;
369       }
370     }
371     else {
372       cpu = _ThreadCpuUsed ;
373 //      cout << pthread_self() << " Engines_Component_i::CpuUsed_impl " << _serviceName << " " << cpu
374 //           << endl ;
375     }
376   }
377   else {
378 //    cout << pthread_self() << "Engines_Component_i::CpuUsed_impl _ThreadId " << _ThreadId << " "
379 //         << _serviceName << " _StartUsed " << _StartUsed << endl ;
380   }
381   return cpu ;
382 }
383
384 // Send message to event channel
385
386 void Engines_Component_i::sendMessage(const char *event_type, const char *message) {
387     _notifSupplier->Send(graphName(), nodeName(), event_type, message);
388 }