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