]> SALOME platform Git repositories - modules/kernel.git/blob - src/Container/Component_i.cxx
Salome HOME
CCAR: revert the change because the problem is in NOTIFICATION (issue 20661)
[modules/kernel.git] / src / Container / Component_i.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  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 //  SALOME Container : implementation of container and engine for Kernel
23 //  File   : Component_i.cxx
24 //  Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA
25 //  Module : SALOME
26 //  $Header$
27 //#define private protected  // for pd_refCount trace
28 //
29 #include "SALOME_Component_i.hxx"
30 #include "SALOME_Container_i.hxx"
31 #include "RegistryConnexion.hxx"
32 #include "Basics_Utils.hxx"
33 #include <stdio.h>
34 #ifndef WIN32
35 #include <dlfcn.h>
36 #endif
37 #include <cstdlib>
38 #include "utilities.h"
39
40 #ifndef WIN32
41 #include <sys/time.h>
42 #include <sys/resource.h>
43 #include <unistd.h>
44 #else
45 #include <sys/timeb.h>
46 int SIGUSR11 = 1000;
47 #include <process.h>
48 #endif
49
50
51 using namespace std;
52
53 extern bool _Sleeping ;
54 static Engines_Component_i * theEngines_Component ;
55
56 bool Engines_Component_i::_isMultiStudy = true;
57 bool Engines_Component_i::_isMultiInstance = false;
58
59 /*! \class Engines_Component_i
60  *  \brief C++ implementation of Engines::Component interface
61  *
62  */
63
64 //=============================================================================
65 /*! 
66  *  Default constructor, not for use
67  */
68 //=============================================================================
69
70 Engines_Component_i::Engines_Component_i():_myConnexionToRegistry(0), _notifSupplier(0), _id(0)
71 {
72   //ASSERT(0);
73   MESSAGE("Default Constructor, not for normal use...");
74 }
75
76 //=============================================================================
77 /*!  \brief  Standard Constructor for generic Component, used in derived class
78  *
79  *  Connection to Registry and Notification
80  *  \param orb Object Request broker given by Container
81  *  \param poa Portable Object Adapter from Container (normally root_poa)
82  *  \param contId container CORBA id inside the server
83  *  \param instanceName unique instance name for this object (see Container_i)
84  *  \param interfaceName component class name
85  *  \param notif use of notification
86  *  \param regist (true or false) use of registry (default true)
87  */
88 //=============================================================================
89
90 Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb,
91                                          PortableServer::POA_ptr poa, 
92                                          PortableServer::ObjectId * contId, 
93                                          const char *instanceName,
94                                          const char *interfaceName,
95                                          bool notif,
96                                          bool regist ) :
97   _instanceName(instanceName),
98   _interfaceName(interfaceName),
99   _myConnexionToRegistry(0),
100   _notifSupplier(0),
101   _ThreadId(0) ,
102   _ThreadCpuUsed(0) ,
103   _Executed(false) ,
104   _graphName("") ,
105   _nodeName(""),
106   _studyId(-1),
107   _id(0),
108   _contId(0),
109   _CanceledThread(false)
110 {
111   MESSAGE("Component constructor with instanceName "<< _instanceName);
112   _orb = CORBA::ORB::_duplicate(orb);
113   _poa = PortableServer::POA::_duplicate(poa);
114   _contId = contId ;
115   CORBA::Object_var o = _poa->id_to_reference(*contId); // container ior...
116   _container=Engines::Container::_narrow(o);
117   setContainerName();
118
119   if(regist)
120     {
121       const CORBA::String_var ior = _orb->object_to_string(o);
122       _myConnexionToRegistry = new RegistryConnexion(0, 0, ior,"theSession",
123                                                      _instanceName.c_str());
124     }
125
126   _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
127 }
128
129 //=============================================================================
130 /*!  \brief  Standard Constructor for standalone Component, used in derived class
131  *
132  *  Connection to Registry and Notification
133  *  \param orb Object Request broker given by Container
134  *  \param poa Portable Object Adapter from Container (normally root_poa)
135  *  \param container container CORBA reference
136  *  \param instanceName unique instance name for this object (see Container_i)
137  *  \param interfaceName component class name
138  *  \param notif use of notification
139  *  \param regist (true or false) use of registry (default true)
140  */
141 //=============================================================================
142
143 Engines_Component_i::Engines_Component_i(CORBA::ORB_ptr orb,
144                                          PortableServer::POA_ptr poa,
145                                          Engines::Container_ptr container,
146                                          const char *instanceName,
147                                          const char *interfaceName,
148                                          bool notif,
149                                          bool regist) :
150   _instanceName(instanceName),
151   _interfaceName(interfaceName),
152   _myConnexionToRegistry(0),
153   _notifSupplier(0),
154   _ThreadId(0) ,
155   _ThreadCpuUsed(0) ,
156   _Executed(false) ,
157   _graphName("") ,
158   _nodeName(""),
159   _studyId(-1),
160   _id(0),
161   _contId(0),
162   _CanceledThread(false)
163 {
164   MESSAGE("Component constructor with instanceName "<< _instanceName);
165   _orb = CORBA::ORB::_duplicate(orb);
166   _poa = PortableServer::POA::_duplicate(poa);
167   _container=Engines::Container::_duplicate(container);
168   setContainerName();
169   const CORBA::String_var ior = _orb->object_to_string(_container);
170   if(regist)
171     _myConnexionToRegistry = new RegistryConnexion(0, 0, ior,"theSession", _instanceName.c_str());
172   _notifSupplier = new NOTIFICATION_Supplier(instanceName, notif);
173 }
174
175
176 //=============================================================================
177 /*! 
178  *  Destructor: call Container for decrement of instances count.
179  *  When instances count falls to 0, the container tries to remove the
180  *  component library (dlclose)
181  */
182 //=============================================================================
183
184 Engines_Component_i::~Engines_Component_i()
185 {
186   MESSAGE("Component destructor");
187   Engines_Container_i::decInstanceCnt(_interfaceName);
188   if(_myConnexionToRegistry)delete _myConnexionToRegistry;
189   _myConnexionToRegistry = 0 ;
190   if(_notifSupplier)delete _notifSupplier;
191   _notifSupplier = 0;
192   if(_id) delete _id;
193   _id=0;
194 }
195
196 //=============================================================================
197 /*! 
198  *  CORBA method: return name of the instance, unique in this Container
199  */
200 //=============================================================================
201
202 char* Engines_Component_i::instanceName()
203 {
204    return CORBA::string_dup(_instanceName.c_str()) ;
205 }
206
207 //=============================================================================
208 /*! 
209  *  CORBA method: return name of the component class
210  */
211 //=============================================================================
212
213 char* Engines_Component_i::interfaceName()
214 {
215   return CORBA::string_dup(_interfaceName.c_str()) ;
216 }
217
218 //=============================================================================
219 /*! 
220  *  CORBA method: Get study Id
221  *  \return -1: not initialised (Internal Error)
222  *           0: multistudy component instance
223  *          >0: study id associated to this instance
224  */
225 //=============================================================================
226
227 CORBA::Long Engines_Component_i::getStudyId()
228 {
229   return _studyId;
230 }
231
232 //=============================================================================
233 /*! 
234  *  CORBA method: Test if instance is alive and responds
235  */
236 //=============================================================================
237
238 void Engines_Component_i::ping()
239 {
240 #ifndef WIN32
241   MESSAGE("Engines_Component_i::ping() pid "<< getpid() << " threadid "
242           << pthread_self());
243 #else
244   MESSAGE("Engines_Component_i::ping() pid "<< _getpid()<< " threadid "
245           << pthread_self().p );
246 #endif
247 }
248
249 //=============================================================================
250 /*! 
251  *  CORBA method: Deactivate this instance. CORBA object is deactivated (do not
252  *  respond any more to CORBA calls), the connection to Regsitry is removed
253  *  (Registry informed of deactivation), internal server reference counter on
254  *  the derived servant class is decremented, to allow destruction of the class
255  *  (delete) by POA, when there are no more references.
256  *  -- TO BE USED BY CONTAINER ONLY (Container housekeeping) --
257  */
258 //=============================================================================
259
260 void Engines_Component_i::destroy()
261 {
262   MESSAGE("Engines_Component_i::destroy()");
263   //SCRUTE(_refcount_value());
264   _poa->deactivate_object(*_id);
265   //SCRUTE(_refcount_value());
266   _remove_ref();
267   //SCRUTE(_refcount_value());
268   MESSAGE("Engines_Component_i::destroyed") ;
269 }
270
271 //=============================================================================
272 /*! 
273  *  CORBA method: return CORBA reference of the Container
274  *
275  */
276 //=============================================================================
277
278 Engines::Container_ptr Engines_Component_i::GetContainerRef()
279 {
280   return Engines::Container::_duplicate(_container);
281 }
282
283 //=============================================================================
284 /*! 
285  *  CORBA method: 
286  *  Gives a sequence of (key=string,value=any) to the component. 
287  *  Base class component stores the sequence in a map.
288  *  The map is cleared before.
289  *  This map is for use by derived classes. 
290  *  \param dico sequence of (key=string,value=any)
291  */
292 //=============================================================================
293
294 void Engines_Component_i::setProperties(const Engines::FieldsDict& dico)
295 {
296   _fieldsDict.clear();
297   for (CORBA::ULong i=0; i<dico.length(); i++)
298     {
299       std::string cle(dico[i].key);
300       _fieldsDict[cle] = dico[i].value;
301     }
302 }
303
304 //=============================================================================
305 /*! 
306  *  CORBA method: 
307  *  returns a previously stored map (key=string,value=any) as a sequence.
308  *  (see setProperties)
309  */
310 //=============================================================================
311
312 Engines::FieldsDict* Engines_Component_i::getProperties()
313 {
314   Engines::FieldsDict_var copie = new Engines::FieldsDict;
315   copie->length(_fieldsDict.size());
316   map<std::string,CORBA::Any>::iterator it;
317   CORBA::ULong i = 0;
318   for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++, i++)
319     {
320       std::string cle((*it).first);
321       copie[i].key = CORBA::string_dup(cle.c_str());
322       copie[i].value = _fieldsDict[cle];
323     }
324   return copie._retn();
325 }
326
327 //=============================================================================
328 /*! 
329  *  CORBA method: used by Supervision to give names to this instance
330  */
331 //=============================================================================
332
333 void Engines_Component_i::Names( const char * graphName ,
334                                  const char * nodeName )
335 {
336   _graphName = graphName ;
337   _nodeName = nodeName ;
338   //  MESSAGE("Engines_Component_i::Names( '" << _graphName << "' , '"
339   //          << _nodeName << "' )");
340 }
341
342 //=============================================================================
343 /*! 
344  *  CORBA method: used in Supervision
345  */
346 //=============================================================================
347
348 bool Engines_Component_i::Kill_impl() 
349 {
350 //  MESSAGE("Engines_Component_i::Kill_i() pthread_t "<< pthread_self()
351 //          << " pid " << getpid() << " instanceName "
352 //          << _instanceName.c_str() << " interface " << _interfaceName.c_str()
353 //          << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
354 //          << dec << " _ThreadId " << _ThreadId << " this " << hex << this
355 //          << dec ) ;
356
357   bool RetVal = false ;
358 #ifndef WIN32
359   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
360     {
361       RetVal = Killer( _ThreadId , SIGUSR2 ) ;
362       _ThreadId = (pthread_t ) -1 ;
363     }
364
365 #else
366   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
367     {
368       RetVal = Killer( *_ThreadId , 0 ) ;
369       _ThreadId = (pthread_t* ) 0 ;
370     }
371
372 #endif
373   return RetVal ;
374 }
375
376 //=============================================================================
377 /*! 
378  *  CORBA method: used in Supervision
379  */
380 //=============================================================================
381
382 bool Engines_Component_i::Stop_impl()
383 {
384 #ifndef WIN32
385   MESSAGE("Engines_Component_i::Stop_i() pthread_t "<< pthread_self()
386           << " pid " << getpid() << " instanceName "
387           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
388           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
389           << dec << " _ThreadId " << _ThreadId );
390 #else
391   MESSAGE("Engines_Component_i::Stop_i() pthread_t "<< pthread_self().p
392           << " pid " << _getpid() << " instanceName "
393           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
394           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
395           << dec << " _ThreadId " << _ThreadId );
396 #endif
397   
398
399   bool RetVal = false ;
400 #ifndef WIN32
401   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
402     {
403       RetVal = Killer( _ThreadId , 0 ) ;
404       _ThreadId = (pthread_t ) -1 ;
405     }
406 #else
407   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
408     {
409       RetVal = Killer( *_ThreadId , 0 ) ;
410       _ThreadId = (pthread_t* ) 0 ;
411     }
412 #endif
413   return RetVal ;
414 }
415
416 //=============================================================================
417 /*! 
418  *  CORBA method: used in Supervision
419  */
420 //=============================================================================
421
422 bool Engines_Component_i::Suspend_impl()
423 {
424 #ifndef WIN32
425   MESSAGE("Engines_Component_i::Suspend_i() pthread_t "<< pthread_self()
426           << " pid " << getpid() << " instanceName "
427           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
428           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
429           << dec << " _ThreadId " << _ThreadId );
430 #else
431   MESSAGE("Engines_Component_i::Suspend_i() pthread_t "<< pthread_self().p
432           << " pid " << _getpid() << " instanceName "
433           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
434           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
435           << dec << " _ThreadId " << _ThreadId );
436 #endif
437
438   bool RetVal = false ;
439 #ifndef WIN32
440   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
441 #else
442   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
443 #endif
444     {
445       if ( _Sleeping )
446         {
447           return false ;
448         }
449     else 
450       {
451 #ifndef WIN32
452         RetVal = Killer( _ThreadId ,SIGINT ) ;
453 #else
454         RetVal = Killer( *_ThreadId ,SIGINT ) ;
455 #endif
456         //if ( RetVal ) _Sleeping = true;
457
458       }
459     }
460   return RetVal ;
461 }
462
463 //=============================================================================
464 /*! 
465  *  CORBA method: used in Supervision
466  */
467 //=============================================================================
468
469 bool Engines_Component_i::Resume_impl()
470 {
471 #ifndef WIN32
472   MESSAGE("Engines_Component_i::Resume_i() pthread_t "<< pthread_self()
473           << " pid " << getpid() << " instanceName "
474           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
475           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
476           << dec << " _ThreadId " << _ThreadId );
477 #else
478   MESSAGE("Engines_Component_i::Resume_i() pthread_t "<< pthread_self().p
479           << " pid " << _getpid() << " instanceName "
480           << _instanceName.c_str() << " interface " << _interfaceName.c_str()
481           << " machineName " << Kernel_Utils::GetHostname().c_str()<< " _id " << hex << _id
482           << dec << " _ThreadId " << _ThreadId );
483 #endif
484   bool RetVal = false ;
485 #ifndef WIN32
486   if ( _ThreadId > 0 && pthread_self() != _ThreadId )
487 #else
488   if ( _ThreadId > 0 && pthread_self().p != _ThreadId->p )
489 #endif
490     {
491     if ( _Sleeping ) 
492       {
493         _Sleeping = false ;
494         RetVal = true ;
495       }
496     else
497       {
498         RetVal = false ;
499       }
500     }
501   return RetVal ;
502 }
503
504 //=============================================================================
505 /*! 
506  *  CORBA method: 
507  */
508 //=============================================================================
509
510 CORBA::Long Engines_Component_i::CpuUsed_impl()
511 {
512   long cpu = 0 ;
513   if ( _ThreadId || _Executed )
514     {
515     if ( _ThreadId > 0 )
516       {
517 #ifndef WIN32
518       if ( pthread_self() != _ThreadId )
519 #else
520       if ( pthread_self().p != _ThreadId->p )
521 #endif
522         {
523         if ( _Sleeping )
524           {
525           }
526         else
527           {
528             // Get Cpu in the appropriate thread with that object !...
529             theEngines_Component = this ;
530 #ifndef WIN32
531             Killer( _ThreadId ,SIGUSR1 ) ;
532 #else
533             Killer( *_ThreadId ,SIGUSR11 ) ;
534 #endif
535           }
536         cpu = _ThreadCpuUsed ;
537         }
538       else
539         {
540           _ThreadCpuUsed = CpuUsed() ;
541           cpu = _ThreadCpuUsed ;
542           // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl "
543           //      << _serviceName << " " << cpu << endl ;
544       }
545     }
546     else 
547       {
548         cpu = _ThreadCpuUsed ;
549         // cout << pthread_self() << " Engines_Component_i::CpuUsed_impl "
550         //      << _serviceName << " " << cpu<< endl ;
551       }
552     }
553   else
554     {
555       // cout<< pthread_self()<<"Engines_Component_i::CpuUsed_impl _ThreadId "
556       //     <<_ThreadId <<" "<<_serviceName<<" _StartUsed "<<_StartUsed<<endl;
557     }
558   return cpu ;
559 }
560
561
562 //=============================================================================
563 /*! 
564  *  C++ method: return Container Servant
565  */
566 //=============================================================================
567
568 Engines_Container_i *Engines_Component_i::GetContainerPtr()
569 {
570   PortableServer::ObjectId_var  contId=_poa->reference_to_id(_container);
571   return dynamic_cast<Engines_Container_i*>(_poa->id_to_servant(contId)) ;
572 }
573
574 //=============================================================================
575 /*! 
576  *  C++ method: set study Id
577  *  \param studyId         0 if instance is not associated to a study, 
578  *                         >0 otherwise (== study id)
579  *  \return true if the set of study Id is OK
580  *  must be set once by Container, at instance creation,
581  *  and cannot be changed after.
582  */
583 //=============================================================================
584
585 CORBA::Boolean Engines_Component_i::setStudyId(CORBA::Long studyId)
586 {
587   ASSERT( studyId >= 0);
588   CORBA::Boolean ret = false;
589   if (_studyId < 0) // --- not yet initialized 
590     {
591       _studyId = studyId;
592       ret = true;
593     }
594   else
595     if ( _studyId == studyId) ret = true;
596   return ret;
597 }
598
599 //=============================================================================
600 /*! 
601  *  C++ method: return CORBA instance id, the id is set in derived class
602  *  constructor, when instance is activated.
603  */
604 //=============================================================================
605
606 PortableServer::ObjectId * Engines_Component_i::getId()
607 {
608 //  MESSAGE("PortableServer::ObjectId * Engines_Component_i::getId()");
609   return _id ;
610 }
611
612 //=============================================================================
613 /*! 
614  *  C++ method: used by derived classes for supervision
615  */
616 //=============================================================================
617
618 void Engines_Component_i::beginService(const char *serviceName)
619 {
620   std::cerr << "beginService for " << serviceName << " Component instance : " << _instanceName << std::endl;
621
622 #ifndef WIN32
623   _ThreadId = pthread_self() ;
624 #else
625   _ThreadId = new pthread_t;
626   _ThreadId->p = pthread_self().p ;
627   _ThreadId->x = pthread_self().x ;
628 #endif
629   _StartUsed = 0 ;
630   _StartUsed = CpuUsed_impl() ;
631   _ThreadCpuUsed = 0 ;
632   _Executed = true ;
633   _serviceName = serviceName ;
634   theEngines_Component = this ;
635   if ( pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS , NULL ) )
636     {
637       perror("pthread_setcanceltype ") ;
638       exit(0) ;
639     }
640   if ( pthread_setcancelstate( PTHREAD_CANCEL_ENABLE , NULL ) )
641     {
642       perror("pthread_setcancelstate ") ;
643       exit(0) ;
644     }
645
646   // --- all strings given with setProperties are set in environment
647   map<std::string,CORBA::Any>::iterator it;
648   for (it = _fieldsDict.begin(); it != _fieldsDict.end(); it++)
649     {
650       std::string cle((*it).first);
651       if ((*it).second.type()->kind() == CORBA::tk_string)
652         {
653           const char* value;
654           (*it).second >>= value;
655           std::string s(cle);
656           s+='=';
657           s+=value;
658           putenv((char *)s.c_str());
659           MESSAGE("--- setenv: "<<cle<<" = "<< value);
660         }
661     }
662 }
663
664 //=============================================================================
665 /*! 
666  *  C++ method: used by derived classes for supervision
667  */
668 //=============================================================================
669
670 void Engines_Component_i::endService(const char *serviceName)
671 {
672   if ( !_CanceledThread )
673     _ThreadCpuUsed = CpuUsed_impl() ;
674
675   float cpus=_ThreadCpuUsed/1000.;
676   std::cerr << "endService for " << serviceName << " Component instance : " << _instanceName ;
677   std::cerr << " Cpu Used: " << cpus << " (s) " << std::endl;
678   MESSAGE("Send EndService notification for " << serviceName
679           << endl << " Component instance : " << _instanceName << " StartUsed "
680           << _StartUsed << " _ThreadCpuUsed "<< _ThreadCpuUsed << endl <<endl);
681   _ThreadId = 0 ;
682 }
683
684 //=============================================================================
685 /*! 
686  *  C++ method: -- CHECK IF USED --
687  */
688 //=============================================================================
689
690 char* Engines_Component_i::graphName()
691 {
692   return CORBA::string_dup( _graphName.c_str() ) ;
693 }
694
695 //=============================================================================
696 /*! 
697  *  C++ method: -- CHECK IF USED --
698  */
699 //=============================================================================
700
701 char* Engines_Component_i::nodeName()
702 {
703   return CORBA::string_dup( _nodeName.c_str() ) ;
704 }
705
706 //=============================================================================
707 /*! 
708  *  C++ method: used in Supervision (see kill_impl)
709  */
710 //=============================================================================
711
712 bool Engines_Component_i::Killer( pthread_t ThreadId , int signum )
713 {
714 #ifndef WIN32
715   if ( ThreadId )
716 #else
717   if ( ThreadId.p )
718 #endif
719     {
720       if ( signum == 0 )
721         {
722           if ( pthread_cancel( ThreadId ) )
723             {
724               perror("Killer pthread_cancel error") ;
725               return false ;
726             }
727           else
728             {
729 #ifdef WNT
730               MESSAGE("Killer : ThreadId " << ThreadId.p << " pthread_canceled") ;
731 #else
732               MESSAGE("Killer : ThreadId " << ThreadId << " pthread_canceled") ;
733 #endif
734             }
735         }
736       else
737         {
738           if ( pthread_kill( ThreadId , signum ) == -1 )
739             {
740               perror("Killer pthread_kill error") ;
741               return false ;
742             }
743           else 
744             {
745 #ifdef WNT
746               MESSAGE("Killer : ThreadId " << ThreadId.p << " pthread_killed(" << signum << ")") ;
747 #else
748               MESSAGE("Killer : ThreadId " << ThreadId << " pthread_killed(" << signum << ")") ;
749 #endif
750             }
751         }
752     }
753   return true ;
754 }
755
756 //=============================================================================
757 /*! 
758  *  C++ method:
759  */ 
760 //=============================================================================
761
762 void SetCpuUsed()
763 {
764   if ( theEngines_Component )
765     theEngines_Component->SetCurCpu() ;
766 }
767
768 //=============================================================================
769 /*! 
770  *  C++ method:
771  */
772 //=============================================================================
773
774 void Engines_Component_i::SetCurCpu()
775 {
776   _ThreadCpuUsed =  CpuUsed() ;
777   //  MESSAGE(pthread_self() << 
778   //  " Engines_Component_i::SetCurCpu() _ThreadCpuUsed " << _ThreadCpuUsed) ;
779 }
780
781 //=============================================================================
782 /*! 
783  *  C++ method:
784  */
785 //=============================================================================
786
787 long Engines_Component_i::CpuUsed()
788 {
789   long cpu = 0 ;
790 #ifndef WIN32
791   struct rusage usage ;
792   if ( _ThreadId || _Executed )
793     {
794       if ( getrusage( RUSAGE_SELF , &usage ) == -1 )
795         {
796           perror("Engines_Component_i::CpuUsed") ;
797           return 0 ;
798         }
799       //cpu time is calculated in millisecond (user+system times)
800       cpu = usage.ru_utime.tv_sec*1000 +usage.ru_utime.tv_usec/1000;
801       cpu = cpu+ usage.ru_stime.tv_sec*1000 +usage.ru_stime.tv_usec/1000;
802       cpu=cpu-_StartUsed ;
803       // cout << pthread_self() << " Engines_Component_i::CpuUsed " << " "
804       //      << _serviceName   << usage.ru_utime.tv_sec << " - " << _StartUsed
805       //      << " = " << cpu << endl ;
806     }
807   else
808     {
809       // cout << pthread_self() << "Engines_Component_i::CpuUsed _ThreadId "
810       //      << _ThreadId << " " << _serviceName<< " _StartUsed " 
811       //      << _StartUsed << endl ;
812     }
813 #else
814         // NOT implementet yet
815 #endif
816
817
818   return cpu ;
819 }
820
821 void CallCancelThread()
822 {
823   if ( theEngines_Component )
824     theEngines_Component->CancelThread() ;
825 }
826
827 //=============================================================================
828 /*!
829  *  C++ method:
830  */
831 //=============================================================================
832
833 void Engines_Component_i::CancelThread()
834 {
835   _CanceledThread = true;
836 }
837
838 //=============================================================================
839 /*! 
840  *  C++ method: Send message to event channel
841  */
842 //=============================================================================
843
844 void Engines_Component_i::sendMessage(const char *event_type,
845                                       const char *message)
846 {
847     _notifSupplier->Send(_graphName.c_str(), _nodeName.c_str(), event_type, message);
848 }
849
850 //=============================================================================
851 /*! 
852  *  C++ method: return standard library name built on component name
853  */
854 //=============================================================================
855
856 string Engines_Component_i::GetDynLibraryName(const char *componentName)
857 {
858   string ret="lib";
859   ret+=componentName;
860   ret+="Engine.so";
861   return ret;
862 }
863
864 //=============================================================================
865 /*! 
866  *  C++ method: DumpPython default implementation
867  */
868 //=============================================================================
869
870 Engines::TMPFile* Engines_Component_i::DumpPython(CORBA::Object_ptr theStudy, 
871                                                   CORBA::Boolean isPublished, 
872                                                   CORBA::Boolean& isValidScript)
873 {
874   const char* aScript = "def RebuildData(theStudy): pass";
875   char* aBuffer = new char[strlen(aScript)+1];
876   strcpy(aBuffer, aScript);
877   CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
878   int aBufferSize = strlen(aBuffer)+1;
879   Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aBufferSize, aBufferSize, anOctetBuf, 1); 
880   isValidScript = true;
881   return aStreamFile._retn(); 
882 }
883
884 Engines::Salome_file_ptr 
885 Engines_Component_i::getInputFileToService(const char* service_name, 
886                                            const char* Salome_file_name) 
887 {
888   // Try to find the service, if it doesn't exist, we throw an exception.
889   _Service_file_map_it = _Input_Service_file_map.find(service_name);
890   if (_Service_file_map_it ==  _Input_Service_file_map.end()) {
891     SALOME::ExceptionStruct es;
892     es.type = SALOME::INTERNAL_ERROR;
893     es.text = "service doesn't have salome files";
894     throw SALOME::SALOME_Exception(es);
895   }
896   _t_Salome_file_map * _map = _Input_Service_file_map[service_name];
897
898   // Try to find the Salome_file ...
899   _Salome_file_map_it = _map->find(Salome_file_name);
900   if (_Salome_file_map_it ==  _map->end()) {
901     SALOME::ExceptionStruct es;
902     es.type = SALOME::INTERNAL_ERROR;
903     es.text = "service doesn't have this Salome_file";
904     throw SALOME::SALOME_Exception(es);
905   }
906   Salome_file_i * Sfile = (*_map)[Salome_file_name];
907
908   return Sfile->_this();
909 }
910
911 Engines::Salome_file_ptr 
912 Engines_Component_i::setInputFileToService(const char* service_name, 
913                                            const char* Salome_file_name) 
914 {
915   // Try to find the service, if it doesn't exist, we add it.
916   _Service_file_map_it = _Input_Service_file_map.find(service_name);
917   if (_Service_file_map_it ==  _Input_Service_file_map.end()) {
918     _t_Salome_file_map * _map = new _t_Salome_file_map();
919     _Input_Service_file_map[service_name] = _map;
920   }
921   _t_Salome_file_map * _map = _Input_Service_file_map[service_name];
922   
923   // Try to find the Salome_file ...
924   _Salome_file_map_it = _map->find(Salome_file_name);
925   if (_Salome_file_map_it ==  _map->end()) {
926     Salome_file_i * Sfile = new Salome_file_i();
927     Engines::Container_ptr container = this->GetContainerRef();
928     Sfile->setContainer(Engines::Container::_duplicate(container));
929     (*_map)[Salome_file_name] = Sfile;
930   }
931
932   Salome_file_i * Sfile = (*_map)[Salome_file_name];
933   return Sfile->_this();
934 }
935
936 void 
937 Engines_Component_i::checkInputFilesToService(const char* service_name) 
938 {
939   // Try to find the service, if it doesn't exist, nothing to do.
940   _Service_file_map_it = _Input_Service_file_map.find(service_name);
941   if (_Service_file_map_it !=  _Input_Service_file_map.end()) {
942     _t_Salome_file_map * _map = _Input_Service_file_map[service_name];
943     _t_Salome_file_map::iterator begin = _map->begin();
944     _t_Salome_file_map::iterator end = _map->end();
945
946     for(;begin!=end;begin++) {
947       Salome_file_i * file = begin->second;
948       std::string file_port_name = begin->first;
949       configureSalome_file(service_name, file_port_name, file);
950       file->recvFiles();
951     }
952   }
953 }
954
955 Engines::Salome_file_ptr 
956 Engines_Component_i::getOutputFileToService(const char* service_name, 
957                                             const char* Salome_file_name) 
958 {
959   // Try to find the service, if it doesn't exist, we throw an exception.
960   _Service_file_map_it = _Output_Service_file_map.find(service_name);
961   if (_Service_file_map_it ==  _Output_Service_file_map.end()) {
962     SALOME::ExceptionStruct es;
963     es.type = SALOME::INTERNAL_ERROR;
964     es.text = "service doesn't have salome files";
965     throw SALOME::SALOME_Exception(es);
966   }
967   _t_Salome_file_map * _map = _Output_Service_file_map[service_name];
968
969   // Try to find the Salome_file ...
970   _Salome_file_map_it = _map->find(Salome_file_name);
971   if (_Salome_file_map_it ==  _map->end()) {
972     SALOME::ExceptionStruct es;
973     es.type = SALOME::INTERNAL_ERROR;
974     es.text = "service doesn't have this Salome_file";
975     throw SALOME::SALOME_Exception(es);
976   }
977   Salome_file_i * Sfile = (*_map)[Salome_file_name];
978
979   return Sfile->_this();
980 }
981
982 Engines::Salome_file_ptr 
983 Engines_Component_i::setOutputFileToService(const char* service_name, 
984                                            const char* Salome_file_name) 
985 {
986   // Try to find the service, if it doesn't exist, we add it.
987   _Service_file_map_it = _Output_Service_file_map.find(service_name);
988   if (_Service_file_map_it ==  _Output_Service_file_map.end()) {
989     _t_Salome_file_map * _map = new _t_Salome_file_map();
990     _Output_Service_file_map[service_name] = _map;
991   }
992   _t_Salome_file_map * _map = _Output_Service_file_map[service_name];
993   
994   // Try to find the Salome_file ...
995   _Salome_file_map_it = _map->find(Salome_file_name);
996   if (_Salome_file_map_it ==  _map->end()) {
997     Salome_file_i * Sfile = new Salome_file_i();
998     Engines::Container_ptr container = this->GetContainerRef();
999     Sfile->setContainer(Engines::Container::_duplicate(container));
1000     (*_map)[Salome_file_name] = Sfile;
1001   }
1002
1003   Salome_file_i * Sfile = (*_map)[Salome_file_name];
1004   return Sfile->_this();
1005 }
1006
1007 void 
1008 Engines_Component_i::checkOutputFilesToService(const char* service_name) 
1009 {
1010   // Try to find the service, if it doesn't exist, nothing to do.
1011   _Service_file_map_it = _Output_Service_file_map.find(service_name);
1012   if (_Service_file_map_it !=  _Output_Service_file_map.end()) {
1013     _t_Salome_file_map * _map = _Output_Service_file_map[service_name];
1014     _t_Salome_file_map::iterator begin = _map->begin();
1015     _t_Salome_file_map::iterator end = _map->end();
1016
1017     for(;begin!=end;begin++) {
1018       Salome_file_i * file = begin->second;
1019       std::string file_port_name = begin->first;
1020       configureSalome_file(service_name, file_port_name, file);
1021       file->recvFiles();
1022     }
1023   }
1024
1025 }
1026
1027 //=============================================================================
1028 /*! 
1029  *  C++ method: used to configure the Salome_file into the runtime.
1030  *  \param service_name name of the service that use this Salome_file
1031  *  \param file_port_name name of the Salome_file
1032  *  \param file Salome_file C++ object
1033  */
1034 //=============================================================================
1035 void
1036 Engines_Component_i::configureSalome_file(std::string service_name,
1037                                           std::string file_port_name,
1038                                           Salome_file_i * file) 
1039 {
1040   // By default this method does nothing
1041 }
1042
1043 //=============================================================================
1044 /*! 
1045  *  C++ method: return the name of the container associated with this component
1046  *  This name does not contains the "/Containers" string and all "/" are replaced by "_"
1047  *  \return the container name (reformatted)
1048  */
1049 //=============================================================================
1050 std::string Engines_Component_i::getContainerName()
1051 {
1052   return _containerName;
1053 }
1054 //=============================================================================
1055 /*! 
1056  *  C++ method: set the name of the container associated with this component (attribute _containerName)
1057  *  This name does not contains the "/Containers" string and all "/" are replaced by "_"
1058  *  \return the container name (reformatted)
1059  */
1060 //=============================================================================
1061 void Engines_Component_i::setContainerName()
1062 {
1063   CORBA::String_var containerName=_container->name();
1064   std::string name(containerName);
1065   name.erase(0,12);
1066   string::size_type slash =name.find_first_of('/');
1067   if(slash != std::string::npos)
1068     name[slash]='_';
1069   _containerName=name;
1070 }