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