1 // SALOME Container : implementation of container and engine for Kernel
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : Component_i.cxx
25 // Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA
29 #include "SALOME_Component_i.hxx"
30 #include "SALOME_Container_i.hxx"
31 #include "RegistryConnexion.hxx"
36 #include "utilities.h"
39 extern bool _Sleeping ;
40 static Engines_Component_i * theEngines_Component ;
42 Engines_Component_i::Engines_Component_i()
44 // MESSAGE("Component constructor");
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,
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);
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());
65 _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
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,
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);
84 // CORBA::Object_var myself = this->_this(); //appel a _this = increment reference
86 _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
89 Engines_Component_i::~Engines_Component_i()
91 MESSAGE("Component destructor");
92 // delete _myConnexionToRegistry;
93 // _myConnexionToRegistry = 0 ;
96 char* Engines_Component_i::instanceName() {
97 return CORBA::string_dup(_instanceName.c_str()) ;
100 char* Engines_Component_i::interfaceName() {
101 return CORBA::string_dup(_interfaceName.c_str()) ;
104 void Engines_Component_i::ping()
106 MESSAGE("Engines_Component_i::ping() pid "<< getpid() << " threadid "
110 void Engines_Component_i::destroy()
112 MESSAGE("Engines_Component_i::destroy()");
114 delete _notifSupplier;
117 delete _myConnexionToRegistry;
118 _myConnexionToRegistry = 0 ;
119 _poa->deactivate_object(*_id) ;
120 CORBA::release(_poa) ;
122 _thisObj->_remove_ref();
123 MESSAGE("Engines_Component_i::destroyed") ;
126 Engines::Container_ptr Engines_Component_i::GetContainerRef()
128 MESSAGE("Engines_Component_i::GetContainerRef");
129 CORBA::Object_ptr o = _poa->id_to_reference(*_contId) ;
130 return Engines::Container::_narrow(o);
133 PortableServer::ObjectId * Engines_Component_i::getId()
135 // MESSAGE("PortableServer::ObjectId * Engines_Component_i::getId()");
139 void Engines_Component_i::setProperties(const Engines::FieldsDict& dico)
142 for (CORBA::ULong i=0; i<dico.length(); i++)
144 std::string cle(dico[i].key);
145 _fieldsDict[cle] = dico[i].value;
149 Engines::FieldsDict* Engines_Component_i::getProperties()
151 Engines::FieldsDict_var copie = new Engines::FieldsDict;
152 copie->length(_fieldsDict.size());
153 map<std::string,CORBA::Any>::iterator it;
155 for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++, i++)
157 std::string cle((*it).first);
158 copie[i].key = CORBA::string_dup(cle.c_str());
159 copie[i].value = _fieldsDict[cle];
161 return copie._retn();
164 void Engines_Component_i::beginService(const char *serviceName)
166 MESSAGE(pthread_self() << "Send BeginService notification for " << serviceName << endl
167 << "Component instance : " << _instanceName << endl << endl);
168 _ThreadId = pthread_self() ;
170 _StartUsed = CpuUsed_impl() ;
173 _serviceName = serviceName ;
174 if ( pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS , NULL ) ) {
175 perror("pthread_setcanceltype ") ;
178 if ( pthread_setcancelstate( PTHREAD_CANCEL_ENABLE , NULL ) ) {
179 perror("pthread_setcancelstate ") ;
182 // MESSAGE(pthread_self() << " Return from BeginService for " << serviceName
183 // << " ThreadId " << _ThreadId << " StartUsed " << _StartUsed
184 // << " _graphName " << _graphName << " _nodeName " << _nodeName );
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++)
192 std::string cle((*it).first);
193 if ((*it).second.type()->kind() == CORBA::tk_string)
196 (*it).second >>= value;
197 // --- todo: replace __GNUC__ test by an autoconf macro AC_CHECK_FUNC...
199 int ret = setenv(cle.c_str(), value, overwrite);
201 //CCRT porting : setenv not defined in stdlib.h
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
209 MESSAGE("--- setenv: "<<cle<<" = "<< value);
214 void Engines_Component_i::endService(const char *serviceName)
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);
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 << "' )");
231 char* Engines_Component_i::graphName() {
232 return CORBA::string_dup( _graphName.c_str() ) ;
235 char* Engines_Component_i::nodeName() {
236 return CORBA::string_dup( _nodeName.c_str() ) ;
239 bool Engines_Component_i::Killer( pthread_t ThreadId , int signum ) {
242 if ( pthread_cancel( ThreadId ) ) {
243 perror("Killer pthread_cancel error") ;
247 MESSAGE(pthread_self() << "Killer : ThreadId " << ThreadId << " pthread_canceled") ;
251 if ( pthread_kill( ThreadId , signum ) == -1 ) {
252 perror("Killer pthread_kill error") ;
256 MESSAGE(pthread_self() << "Killer : ThreadId " << ThreadId << " pthread_killed("
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
271 bool RetVal = false ;
272 if ( _ThreadId > 0 && pthread_self() != _ThreadId ) {
273 RetVal = Killer( _ThreadId , 0 ) ;
274 _ThreadId = (pthread_t ) -1 ;
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 ;
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 ) {
305 RetVal = Killer( _ThreadId ,SIGINT ) ;
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 ) {
332 theEngines_Component->SetCurCpu() ;
334 void Engines_Component_i::SetCurCpu() {
335 _ThreadCpuUsed = CpuUsed() ;
336 // MESSAGE(pthread_self() << " Engines_Component_i::SetCurCpu() _ThreadCpuUsed " << _ThreadCpuUsed) ;
339 #include <sys/time.h>
340 #include <sys/resource.h>
343 long Engines_Component_i::CpuUsed() {
345 struct rusage usage ;
346 if ( _ThreadId || _Executed ) {
347 if ( getrusage( RUSAGE_SELF , &usage ) == -1 ) {
348 perror("Engines_Component_i::CpuUsed") ;
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 ;
356 // cout << pthread_self() << "Engines_Component_i::CpuUsed _ThreadId " << _ThreadId << " " << _serviceName
357 // << " _StartUsed " << _StartUsed << endl ;
362 CORBA::Long Engines_Component_i::CpuUsed_impl() {
364 if ( _ThreadId || _Executed ) {
365 if ( _ThreadId > 0 ) {
366 if ( pthread_self() != _ThreadId ) {
370 // Get Cpu in the appropriate thread with that object !...
371 theEngines_Component = this ;
372 Killer( _ThreadId ,SIGUSR1 ) ;
374 cpu = _ThreadCpuUsed ;
377 _ThreadCpuUsed = CpuUsed() ;
378 cpu = _ThreadCpuUsed ;
379 // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl " << _serviceName << " " << cpu
384 cpu = _ThreadCpuUsed ;
385 // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl " << _serviceName << " " << cpu
390 // cout << pthread_self() << "Engines_Component_i::CpuUsed_impl _ThreadId " << _ThreadId << " "
391 // << _serviceName << " _StartUsed " << _StartUsed << endl ;
396 // Send message to event channel
398 void Engines_Component_i::sendMessage(const char *event_type, const char *message) {
399 _notifSupplier->Send(graphName(), nodeName(), event_type, message);
402 string Engines_Component_i::GetDynLibraryName(const char *componentName)
410 string Engines_Component_i::BuildComponentNameForNS(const char *ComponentName, const char *ContainerName, const char *hostname)
412 string ret=Engines_Container_i::BuildContainerNameForNS(ContainerName,hostname);