Salome HOME
Corrected implementation of MESSAGE functionality on Windows
[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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //
23 //
24 //  File   : Component_i.cxx
25 //  Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA
26 //  Module : SALOME
27 //  $Header$
28
29 //#define private protected  // for pd_refCount trace
30 #include "SALOME_Component_i.hxx"
31 #include "SALOME_Container_i.hxx"
32 #include "RegistryConnexion.hxx"
33 #include "OpUtil.hxx"
34 #include <stdio.h>
35 #ifndef WNT
36 #include <dlfcn.h>
37 #endif
38 #include <cstdlib>
39 #include "utilities.h"
40
41 #ifndef WNT
42 #include <sys/time.h>
43 #include <sys/resource.h>
44 #include <unistd.h>
45 #else
46 #include <sys/timeb.h>
47 int SIGUSR11 = 1000;
48 #include <process.h>
49 #endif
50
51
52 using namespace std;
53
54 extern bool _Sleeping ;
55 static Engines_Component_i * theEngines_Component ;
56
57 bool Engines_Component_i::_isMultiStudy = true;
58 bool Engines_Component_i::_isMultiInstance = false;
59
60 //=============================================================================
61 /*! 
62  *  Default constructor, not for use
63  */
64 //=============================================================================
65
66 Engines_Component_i::Engines_Component_i()
67 {
68   //ASSERT(0);
69   MESSAGE("Default Constructor, not for normal use...");
70 }
71
72 //=============================================================================
73 /*! 
74  *  Standard Constructor for generic Component, used in derived class
75  *  Connection to Registry and Notification
76  *  \param orb Object Request broker given by Container
77  *  \param poa Portable Object Adapter from Container (normally root_poa)
78  *  \param contId container CORBA id inside the server
79  *  \param instanceName unique instance name for this object (see Container_i)
80  *  \param interfaceName component class name
81  *  \param notif use of notification
82  */
83 //=============================================================================
84
85 Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb,
86                                          PortableServer::POA_ptr poa, 
87                                          PortableServer::ObjectId * contId, 
88                                          const char *instanceName,
89                                          const char *interfaceName,
90                                          bool notif) :
91   _instanceName(instanceName),
92   _interfaceName(interfaceName),
93   _myConnexionToRegistry(0),
94   _ThreadId(0) ,
95   _ThreadCpuUsed(0) ,
96   _Executed(false) ,
97   _graphName("") ,
98   _nodeName(""),
99   _studyId(-1),
100   _CanceledThread(false)
101 {
102   MESSAGE("Component constructor with instanceName "<< _instanceName);
103   //SCRUTE(pd_refCount);
104   _orb = CORBA::ORB::_duplicate(orb);
105   _poa = PortableServer::POA::_duplicate(poa);
106   _contId = contId ;
107   CORBA::Object_var o = _poa->id_to_reference(*contId); // container ior...
108   const CORBA::String_var ior = _orb->object_to_string(o);
109   _myConnexionToRegistry = new RegistryConnexion(0, 0, ior,"theSession",
110                                                  _instanceName.c_str());
111
112   _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
113   //SCRUTE(pd_refCount);
114 }
115
116 //=============================================================================
117 /*! 
118  * Standard constructor for parallel component
119  *  Connection Notification (no connection to Registry !)
120  *  \param orb Object Request broker given by Container
121  *  \param poa Portable Object Adapter from Container (normally root_poa)
122  *  \param contId container CORBA id inside the server
123  *  \param instanceName unique instance name for this object (see Container_i)
124  *  \param interfaceName component class name
125  *  \param flag not used...
126  *  \param notif use of notification
127  */
128 //=============================================================================
129
130 Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb,
131                                          PortableServer::POA_ptr poa, 
132                                          PortableServer::ObjectId * contId, 
133                                          const char *instanceName,
134                                          const char *interfaceName,
135                                          int flag,
136                                          bool notif ) :
137  _instanceName(instanceName),
138  _interfaceName(interfaceName),
139  _myConnexionToRegistry(0),
140  _ThreadId(0) ,
141  _ThreadCpuUsed(0) ,
142  _Executed(false) ,
143  _graphName("") ,
144  _nodeName(""),
145  _studyId(-1),
146  _CanceledThread(false)
147 {
148   _orb = CORBA::ORB::_duplicate(orb);
149   _poa = PortableServer::POA::_duplicate(poa);
150   _contId = contId ;
151
152   _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
153 }
154
155 //=============================================================================
156 /*! 
157  *  Destructor: call Container for decrement of instances count.
158  *  When instances count falls to 0, the container tries to remove the
159  *  component library (dlclose)
160  */
161 //=============================================================================
162
163 Engines_Component_i::~Engines_Component_i()
164 {
165   MESSAGE("Component destructor");
166   Engines_Container_i::decInstanceCnt(_interfaceName);
167 }
168
169 //=============================================================================
170 /*! 
171  *  CORBA method: return name of the instance, unique in this Container
172  */
173 //=============================================================================
174
175 char* Engines_Component_i::instanceName()
176 {
177    return CORBA::string_dup(_instanceName.c_str()) ;
178 }
179
180 //=============================================================================
181 /*! 
182  *  CORBA method: return name of the component class
183  */
184 //=============================================================================
185
186 char* Engines_Component_i::interfaceName()
187 {
188   return CORBA::string_dup(_interfaceName.c_str()) ;
189 }
190
191 //=============================================================================
192 /*! 
193  *  CORBA method: Get study Id
194  *  \return -1: not initialised (Internal Error)
195  *           0: multistudy component instance
196  *          >0: study id associated to this instance
197  */
198 //=============================================================================
199
200 CORBA::Long Engines_Component_i::getStudyId()
201 {
202   return _studyId;
203 }
204
205 //=============================================================================
206 /*! 
207  *  CORBA method: Test if instance is alive and responds
208  */
209 //=============================================================================
210
211 void Engines_Component_i::ping()
212 {
213 #ifndef WNT
214   MESSAGE("Engines_Component_i::ping() pid "<< getpid() << " threadid "
215           << pthread_self());
216 #else
217   MESSAGE("Engines_Component_i::ping() pid "<< _getpid()<< " threadid "
218           << pthread_self().p );
219 #endif
220 }
221
222 //=============================================================================
223 /*! 
224  *  CORBA method: Deactivate this instance. CORBA object is deactivated (do not
225  *  respond any more to CORBA calls), the connection to Regsitry is removed
226  *  (Registry informed of deactivation), internal server reference counter on
227  *  the derived servant class is decremented, to allow destruction of the class
228  *  (delete) by POA, when there are no more references.
229  *  -- TO BE USED BY CONTAINER ONLY (Container housekeeping) --
230  */
231 //=============================================================================
232
233 void Engines_Component_i::destroy()
234 {
235   MESSAGE("Engines_Component_i::destroy()");
236   //SCRUTE(pd_refCount);
237
238   delete _notifSupplier;
239   _notifSupplier = 0;
240
241   delete _myConnexionToRegistry;
242   _myConnexionToRegistry = 0 ;
243   _poa->deactivate_object(*_id) ;
244   CORBA::release(_poa) ;
245   delete(_id) ;
246   //SCRUTE(pd_refCount);
247   _thisObj->_remove_ref();
248   //SCRUTE(pd_refCount);
249   MESSAGE("Engines_Component_i::destroyed") ;
250 }
251
252 //=============================================================================
253 /*! 
254  *  CORBA method: return CORBA reference of the Container
255  *
256  */
257 //=============================================================================
258
259 Engines::Container_ptr Engines_Component_i::GetContainerRef()
260 {
261   //  MESSAGE("Engines_Component_i::GetContainerRef");
262   CORBA::Object_ptr o = _poa->id_to_reference(*_contId) ;
263   return Engines::Container::_narrow(o);
264 }
265
266 //=============================================================================
267 /*! 
268  *  CORBA method: 
269  *  Gives a sequence of (key=string,value=any) to the component. 
270  *  Base class component stores the sequence in a map.
271  *  The map is cleared before.
272  *  This map is for use by derived classes. 
273  *  \param dico sequence of (key=string,value=any)
274  */
275 //=============================================================================
276
277 void Engines_Component_i::setProperties(const Engines::FieldsDict& dico)
278 {
279   _fieldsDict.clear();
280   for (CORBA::ULong i=0; i<dico.length(); i++)
281     {
282       std::string cle(dico[i].key);
283       _fieldsDict[cle] = dico[i].value;
284     }
285 }
286
287 //=============================================================================
288 /*! 
289  *  CORBA method: 
290  *  returns a previously stored map (key=string,value=any) as a sequence.
291  *  (see setProperties)
292  */
293 //=============================================================================
294
295 Engines::FieldsDict* Engines_Component_i::getProperties()
296 {
297   Engines::FieldsDict_var copie = new Engines::FieldsDict;
298   copie->length(_fieldsDict.size());
299   map<std::string,CORBA::Any>::iterator it;
300   CORBA::ULong i = 0;
301   for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++, i++)
302     {
303       std::string cle((*it).first);
304       copie[i].key = CORBA::string_dup(cle.c_str());
305       copie[i].value = _fieldsDict[cle];
306     }
307   return copie._retn();
308 }
309
310 //=============================================================================
311 /*! 
312  *  CORBA method: used by Supervision to give names to this instance
313  */
314 //=============================================================================
315
316 void Engines_Component_i::Names( const char * graphName ,
317                                  const char * nodeName )
318 {
319   _graphName = graphName ;
320   _nodeName = nodeName ;
321   //  MESSAGE("Engines_Component_i::Names( '" << _graphName << "' , '"
322   //          << _nodeName << "' )");
323 }
324
325 //=============================================================================
326 /*! 
327  *  CORBA method: used in Supervision
328  */
329 //=============================================================================
330
331 bool Engines_Component_i::Kill_impl() 
332 {
333 //  MESSAGE("Engines_Component_i::Kill_i() pthread_t "<< pthread_self()
334 //          << " pid " << getpid() << " instanceName "
335 //          << _instanceName.c_str() << " interface " << _interfaceName.c_str()
336 //          << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
337 //          << dec << " _ThreadId " << _ThreadId << " this " << hex << this
338 //          << dec ) ;
339
340   bool RetVal = false ;
341 #ifndef WNT
342   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
343     {
344       RetVal = Killer( _ThreadId , SIGUSR2 ) ;
345       _ThreadId = (pthread_t ) -1 ;
346     }
347
348 #else
349   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
350     {
351       RetVal = Killer( *_ThreadId , 0 ) ;
352       _ThreadId = (pthread_t* ) 0 ;
353     }
354
355 #endif
356   return RetVal ;
357 }
358
359 //=============================================================================
360 /*! 
361  *  CORBA method: used in Supervision
362  */
363 //=============================================================================
364
365 bool Engines_Component_i::Stop_impl()
366 {
367 #ifndef WNT
368   MESSAGE("Engines_Component_i::Stop_i() pthread_t "<< pthread_self()
369           << " pid " << getpid() << " instanceName "
370           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
371           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
372           << dec << " _ThreadId " << _ThreadId );
373 #else
374   MESSAGE("Engines_Component_i::Stop_i() pthread_t "<< pthread_self().p
375           << " pid " << _getpid() << " instanceName "
376           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
377           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
378           << dec << " _ThreadId " << _ThreadId );
379 #endif
380   
381
382   bool RetVal = false ;
383 #ifndef WNT
384   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
385     {
386       RetVal = Killer( _ThreadId , 0 ) ;
387       _ThreadId = (pthread_t ) -1 ;
388     }
389 #else
390   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
391     {
392       RetVal = Killer( *_ThreadId , 0 ) ;
393       _ThreadId = (pthread_t* ) 0 ;
394     }
395 #endif
396   return RetVal ;
397 }
398
399 //=============================================================================
400 /*! 
401  *  CORBA method: used in Supervision
402  */
403 //=============================================================================
404
405 bool Engines_Component_i::Suspend_impl()
406 {
407 #ifndef WNT
408   MESSAGE("Engines_Component_i::Suspend_i() pthread_t "<< pthread_self()
409           << " pid " << getpid() << " instanceName "
410           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
411           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
412           << dec << " _ThreadId " << _ThreadId );
413 #else
414   MESSAGE("Engines_Component_i::Suspend_i() pthread_t "<< pthread_self().p
415           << " pid " << _getpid() << " instanceName "
416           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
417           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
418           << dec << " _ThreadId " << _ThreadId );
419 #endif
420
421   bool RetVal = false ;
422 #ifndef WNT
423   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
424 #else
425   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
426 #endif
427     {
428       if ( _Sleeping )
429         {
430           return false ;
431         }
432     else 
433       {
434 #ifndef WNT
435         RetVal = Killer( _ThreadId ,SIGINT ) ;
436 #else
437         RetVal = Killer( *_ThreadId ,SIGINT ) ;
438 #endif
439         //if ( RetVal ) _Sleeping = true;
440
441       }
442     }
443   return RetVal ;
444 }
445
446 //=============================================================================
447 /*! 
448  *  CORBA method: used in Supervision
449  */
450 //=============================================================================
451
452 bool Engines_Component_i::Resume_impl()
453 {
454 #ifndef WNT
455   MESSAGE("Engines_Component_i::Resume_i() pthread_t "<< pthread_self()
456           << " pid " << getpid() << " instanceName "
457           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
458           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
459           << dec << " _ThreadId " << _ThreadId );
460 #else
461   MESSAGE("Engines_Component_i::Resume_i() pthread_t "<< pthread_self().p
462           << " pid " << _getpid() << " instanceName "
463           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
464           << " machineName " << GetHostname().c_str()<< " _id " << hex << _id
465           << dec << " _ThreadId " << _ThreadId );
466 #endif
467   bool RetVal = false ;
468 #ifndef WNT
469   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
470 #else
471   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
472 #endif
473     {
474     if ( _Sleeping ) 
475       {
476         _Sleeping = false ;
477         RetVal = true ;
478       }
479     else
480       {
481         RetVal = false ;
482       }
483     }
484   return RetVal ;
485 }
486
487 //=============================================================================
488 /*! 
489  *  CORBA method: 
490  */
491 //=============================================================================
492
493 CORBA::Long Engines_Component_i::CpuUsed_impl()
494 {
495   long cpu = 0 ;
496   if ( _ThreadId || _Executed )
497     {
498     if ( _ThreadId > 0 )
499       {
500 #ifndef WNT
501       if ( pthread_self() != _ThreadId )
502 #else
503       if ( pthread_self().p != _ThreadId->p )
504 #endif
505         {
506         if ( _Sleeping )
507           {
508           }
509         else
510           {
511             // Get Cpu in the appropriate thread with that object !...
512             theEngines_Component = this ;
513 #ifndef WNT
514             Killer( _ThreadId ,SIGUSR1 ) ;
515 #else
516             Killer( *_ThreadId ,SIGUSR11 ) ;
517 #endif
518           }
519         cpu = _ThreadCpuUsed ;
520         }
521       else
522         {
523           _ThreadCpuUsed = CpuUsed() ;
524           cpu = _ThreadCpuUsed ;
525           // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl "
526           //      << _serviceName << " " << cpu << endl ;
527       }
528     }
529     else 
530       {
531         cpu = _ThreadCpuUsed ;
532         // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl "
533         //      << _serviceName << " " << cpu<< endl ;
534       }
535     }
536   else
537     {
538       // cout<< pthread_self()<<"Engines_Component_i::CpuUsed_impl _ThreadId "
539       //     <<_ThreadId <<" "<<_serviceName<<" _StartUsed "<<_StartUsed<<endl;
540     }
541   return cpu ;
542 }
543
544
545 //=============================================================================
546 /*! 
547  *  C++ method: return Container Servant
548  */
549 //=============================================================================
550
551 Engines_Container_i *Engines_Component_i::GetContainerPtr()
552 {
553   return dynamic_cast<Engines_Container_i*>(_poa->id_to_servant(*_contId)) ;
554 }
555
556 //=============================================================================
557 /*! 
558  *  C++ method: set study Id
559  *  \param studyId         0 if instance is not associated to a study, 
560  *                         >0 otherwise (== study id)
561  *  \return true if the set of study Id is OK
562  *  must be set once by Container, at instance creation,
563  *  and cannot be changed after.
564  */
565 //=============================================================================
566
567 CORBA::Boolean Engines_Component_i::setStudyId(CORBA::Long studyId)
568 {
569   ASSERT( studyId >= 0);
570   CORBA::Boolean ret = false;
571   if (_studyId < 0) // --- not yet initialized 
572     {
573       _studyId = studyId;
574       ret = true;
575     }
576   else
577     if ( _studyId == studyId) ret = true;
578   return ret;
579 }
580
581 //=============================================================================
582 /*! 
583  *  C++ method: return CORBA instance id, the id is set in derived class
584  *  constructor, when instance is activated.
585  */
586 //=============================================================================
587
588 PortableServer::ObjectId * Engines_Component_i::getId()
589 {
590 //  MESSAGE("PortableServer::ObjectId * Engines_Component_i::getId()");
591   return _id ;
592 }
593
594 //=============================================================================
595 /*! 
596  *  C++ method: used by derived classes for supervision
597  */
598 //=============================================================================
599
600 void Engines_Component_i::beginService(const char *serviceName)
601 {
602 #ifndef WNT
603   MESSAGE(pthread_self() << "Send BeginService notification for " <<serviceName
604           << endl << "Component instance : " << _instanceName << endl << endl);
605 #else
606   MESSAGE(pthread_self().p << "Send BeginService notification for " <<serviceName
607           << endl << "Component instance : " << _instanceName << endl << endl);
608 #endif
609 #ifndef WNT
610   _ThreadId = pthread_self() ;
611 #else
612   _ThreadId = new pthread_t;
613   _ThreadId->p = pthread_self().p ;
614   _ThreadId->x = pthread_self().x ;
615 #endif
616   _StartUsed = 0 ;
617   _StartUsed = CpuUsed_impl() ;
618   _ThreadCpuUsed = 0 ;
619   _Executed = true ;
620   _serviceName = serviceName ;
621   theEngines_Component = this ;
622   if ( pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS , NULL ) )
623     {
624       perror("pthread_setcanceltype ") ;
625       exit(0) ;
626     }
627   if ( pthread_setcancelstate( PTHREAD_CANCEL_ENABLE , NULL ) )
628     {
629       perror("pthread_setcancelstate ") ;
630       exit(0) ;
631     }
632 //  MESSAGE(pthread_self() << " Return from BeginService for " << serviceName
633 //          << " ThreadId " << _ThreadId << " StartUsed " << _StartUsed
634 //          << " _graphName " << _graphName << " _nodeName " << _nodeName );
635
636   // --- for supervisor : all strings given with setProperties
637   //     are set in environment
638   bool overwrite = true;
639   map<std::string,CORBA::Any>::iterator it;
640   for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++)
641     {
642       std::string cle((*it).first);
643       if ((*it).second.type()->kind() == CORBA::tk_string)
644         {
645           const char* value;
646           (*it).second >>= value;
647           // ---todo: replace __GNUC__ test by an autoconf macro AC_CHECK_FUNC.
648 #if defined __GNUC__
649           int ret = setenv(cle.c_str(), value, overwrite);
650 #else
651           //CCRT porting : setenv not defined in stdlib.h
652           std::string s(cle);
653           s+='=';
654           s+=value;
655           // char* cast because 1st arg of linux putenv function
656           // is not a const char* !
657           int ret=putenv((char *)s.c_str());
658           //End of CCRT porting
659 #endif
660           MESSAGE("--- setenv: "<<cle<<" = "<< value);
661         }
662     }
663 }
664
665 //=============================================================================
666 /*! 
667  *  C++ method: used by derived classes for supervision
668  */
669 //=============================================================================
670
671 void Engines_Component_i::endService(const char *serviceName)
672 {
673   if ( !_CanceledThread )
674     _ThreadCpuUsed = CpuUsed_impl() ;
675
676 #ifndef WNT
677   MESSAGE(pthread_self() << " Send EndService notification for " << serviceName
678           << endl << " Component instance : " << _instanceName << " StartUsed "
679           << _StartUsed << " _ThreadCpuUsed "<< _ThreadCpuUsed << endl <<endl);
680 #else
681   MESSAGE(pthread_self().p << " Send EndService notification for " << serviceName
682           << endl << " Component instance : " << _instanceName << " StartUsed "
683     << _StartUsed << " _ThreadCpuUsed "<< _ThreadCpuUsed << endl <<endl);
684 #endif
685   _ThreadId = 0 ;
686 }
687
688 //=============================================================================
689 /*! 
690  *  C++ method: -- CHECK IF USED --
691  */
692 //=============================================================================
693
694 char* Engines_Component_i::graphName()
695 {
696   return CORBA::string_dup( _graphName.c_str() ) ;
697 }
698
699 //=============================================================================
700 /*! 
701  *  C++ method: -- CHECK IF USED --
702  */
703 //=============================================================================
704
705 char* Engines_Component_i::nodeName()
706 {
707   return CORBA::string_dup( _nodeName.c_str() ) ;
708 }
709
710 //=============================================================================
711 /*! 
712  *  C++ method: used in Supervision (see kill_impl)
713  */
714 //=============================================================================
715
716 bool Engines_Component_i::Killer( pthread_t ThreadId , int signum )
717 {
718 #ifndef WNT
719   if ( ThreadId )
720 #else
721   if ( ThreadId.p )
722 #endif
723     {
724       if ( signum == 0 )
725         {
726           if ( pthread_cancel( ThreadId ) )
727             {
728               perror("Killer pthread_cancel error") ;
729               return false ;
730             }
731           else
732             {
733 #ifndef WNT
734               MESSAGE(pthread_self() << "Killer : ThreadId " << ThreadId
735                       << " pthread_canceled") ;
736 #else
737         MESSAGE(pthread_self().p << "Killer : ThreadId " << ThreadId.p
738                       << " pthread_canceled") ;
739 #endif
740             }
741         }
742       else
743         {
744           if ( pthread_kill( ThreadId , signum ) == -1 )
745             {
746               perror("Killer pthread_kill error") ;
747               return false ;
748             }
749           else 
750             {
751 #ifndef WNT
752         MESSAGE(pthread_self() << "Killer : ThreadId " << ThreadId
753                       << " pthread_killed(" << signum << ")") ;
754 #else
755         MESSAGE(pthread_self().p << "Killer : ThreadId " << ThreadId.p
756                       << " pthread_killed(" << signum << ")") ;
757 #endif
758             }
759         }
760     }
761   return true ;
762 }
763
764 //=============================================================================
765 /*! 
766  *  C++ method:
767  */ 
768 //=============================================================================
769
770 void SetCpuUsed()
771 {
772   if ( theEngines_Component )
773     theEngines_Component->SetCurCpu() ;
774 }
775
776 //=============================================================================
777 /*! 
778  *  C++ method:
779  */
780 //=============================================================================
781
782 void Engines_Component_i::SetCurCpu()
783 {
784   _ThreadCpuUsed =  CpuUsed() ;
785   //  MESSAGE(pthread_self() << 
786   //  " Engines_Component_i::SetCurCpu() _ThreadCpuUsed " << _ThreadCpuUsed) ;
787 }
788
789 //=============================================================================
790 /*! 
791  *  C++ method:
792  */
793 //=============================================================================
794
795 long Engines_Component_i::CpuUsed()
796 {
797   long cpu = 0 ;
798 #ifndef WNT
799   struct rusage usage ;
800   if ( _ThreadId || _Executed )
801     {
802       if ( getrusage( RUSAGE_SELF , &usage ) == -1 )
803         {
804           perror("Engines_Component_i::CpuUsed") ;
805           return 0 ;
806         }
807       cpu = usage.ru_utime.tv_sec - _StartUsed ;
808       // cout << pthread_self() << " Engines_Component_i::CpuUsed " << " "
809       //      << _serviceName   << usage.ru_utime.tv_sec << " - " << _StartUsed
810       //      << " = " << cpu << endl ;
811     }
812   else
813     {
814       // cout << pthread_self() << "Engines_Component_i::CpuUsed _ThreadId "
815       //      << _ThreadId << " " << _serviceName<< " _StartUsed " 
816       //      << _StartUsed << endl ;
817     }
818 #else
819         // NOT implementet yet
820 #endif
821
822
823   return cpu ;
824 }
825
826 void CallCancelThread()
827 {
828   if ( theEngines_Component )
829     theEngines_Component->CancelThread() ;
830 }
831
832 //=============================================================================
833 /*!
834  *  C++ method:
835  */
836 //=============================================================================
837
838 void Engines_Component_i::CancelThread()
839 {
840   _CanceledThread = true;
841 }
842
843 //=============================================================================
844 /*! 
845  *  C++ method: Send message to event channel
846  */
847 //=============================================================================
848
849 void Engines_Component_i::sendMessage(const char *event_type,
850                                       const char *message)
851 {
852     _notifSupplier->Send(graphName(), nodeName(), event_type, message);
853 }
854
855 //=============================================================================
856 /*! 
857  *  C++ method: return standard library name built on component name
858  */
859 //=============================================================================
860
861 string Engines_Component_i::GetDynLibraryName(const char *componentName)
862 {
863   string ret="lib";
864   ret+=componentName;
865   ret+="Engine.so";
866   return ret;
867 }
868
869 //=============================================================================
870 /*! 
871  *  C++ method: DumpPython default implementation
872  */
873 //=============================================================================
874
875 Engines::TMPFile* Engines_Component_i::DumpPython(CORBA::Object_ptr theStudy, 
876                                                   CORBA::Boolean isPublished, 
877                                                   CORBA::Boolean& isValidScript)
878 {
879   char* aScript = "def RebuildData(theStudy): pass";
880   char* aBuffer = new char[strlen(aScript)+1];
881   strcpy(aBuffer, aScript);
882   CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
883   int aBufferSize = strlen(aBuffer)+1;
884   Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aBufferSize, aBufferSize, anOctetBuf, 1); 
885   isValidScript = true;
886   return aStreamFile._retn(); 
887 }