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