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