Salome HOME
NRI : Update launch.
[modules/kernel.git] / src / Loader / InquireServersQThread.cxx
1 //=============================================================================
2 // File      : InquireServersQThread.cxx
3 // Created   : Mon Oct 21 17:26:42 2002
4 // Author    : Vasily RUSYAEV
5 // Project   : SALOME
6 // Copyright : EDF 2001
7 // $Header$
8 //=============================================================================
9
10 using namespace std;
11
12 #include "InquireServersQThread.h"
13
14 #include <qlabel.h>
15 #include <qpushbutton.h>
16 #include <qabstractlayout.h> 
17 #include <qlayout.h>
18 #include <qevent.h> 
19 #include <qfont.h> 
20 #include <qmessagebox.h> 
21 #include <qdir.h>
22 #include <qfileinfo.h>
23 #include <qstringlist.h>
24
25 //VRV: porting on Qt 3.0.5
26 #if QT_VERSION >= 0x030005
27 #include <qdesktopwidget.h> 
28 #endif
29 //VRV: porting on Qt 3.0.5
30
31 #include <qsize.h> 
32
33 #include <SALOMEconfig.h>
34
35 #include "Utils_ORB_INIT.hxx"
36 #include "Utils_SINGLETON.hxx"
37 #include "SALOME_NamingService.hxx"
38 #include "utilities.h"
39 #include "OpUtil.hxx"
40
41 #include CORBA_CLIENT_HEADER(SALOME_Session)
42 #include CORBA_CLIENT_HEADER(SALOME_Registry)
43 #include CORBA_CLIENT_HEADER(SALOMEDS)
44 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
45 #include CORBA_CLIENT_HEADER(SALOME_Component)
46
47 #define MARGIN_SIZE  5
48 #define SPACING_SIZE 3
49
50 static QString findFile( QString filename );
51 static QString addSlash( const QString& path );
52
53 InquireServersGUI::InquireServersGUI()
54      : QVBox(0, "SFA splash", Qt::WDestructiveClose | Qt::WStyle_Customize | Qt::WStyle_NoBorder )
55 {
56   myGUI = false;
57   myThread = new InquireServersQThread(this);
58
59   // 1. Polish the appearance
60   setMargin( MARGIN_SIZE );
61   setSpacing( SPACING_SIZE );
62   setFrameStyle( QFrame::Plain | QFrame::Box );
63   setLineWidth( 2 );
64   setMinimumSize( 200, 150 );
65
66   // 2. Splash image
67   QFrame* frm = new QFrame( this );
68   frm->setFrameStyle( QFrame::Box | QFrame::Raised );
69   QHBoxLayout* frmLayout = new QHBoxLayout( frm );
70   frmLayout->setMargin( MARGIN_SIZE );
71   QLabel* splash = 0;
72   splash = new QLabel( frm, "splash" );
73   frmLayout->addWidget( splash );
74   // setting pixmap
75   QString path = findFile( "Application-Splash.png" );
76   splash->setPixmap( QPixmap( path )  );
77   
78   // 3. Progress bar
79   myPrgBar = new QProgressBar( this, "QProgressBar" );
80   myPrgBar->setFixedWidth( splash->pixmap()->isNull() ? 180 : splash->sizeHint().width() );
81   //Sets the total number of steps . 
82   myPrgBar->setTotalSteps ( myThread->getInquiredServers() );
83   myPrgBar->setProgress( 0 );
84
85   // 4. Info label
86   QWidget* aWgt1 = new QWidget( this );
87   QHBoxLayout* aHBoxLayout1 = new QHBoxLayout( aWgt1 );
88   myLabel = new QLabel( tr( "Loading:" ), aWgt1 );
89   myLabel->setFixedWidth( splash->pixmap()->isNull() ? 180 : splash->sizeHint().width() );
90   myLabel->setAlignment( AlignLeft );
91   QFont theFont = myLabel->font();
92   theFont.setBold(true);
93   myLabel->setFont( theFont );
94   aHBoxLayout1->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ) );
95   aHBoxLayout1->addWidget( myLabel );
96   aHBoxLayout1->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ) );
97
98   // 5. <Cancel> button
99   QWidget* aWgt = new QWidget( this );
100   QHBoxLayout* aHBoxLayout = new QHBoxLayout( aWgt );
101   QPushButton* myCancelBtn = new QPushButton( tr( "Cancel" ), aWgt );
102   connect( myCancelBtn, SIGNAL( clicked() ), this, SLOT( ClickOnCancel() ) ) ;
103   aHBoxLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum )  );
104   aHBoxLayout->addWidget( myCancelBtn );
105   aHBoxLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum )  );
106
107   //Center widget
108 #if QT_VERSION >= 0x030005
109   QDesktopWidget *d = QApplication::desktop();
110 #else
111   QWidget *d = QApplication::desktop();
112 #endif
113 //VRV: porting on Qt 3.0.5
114
115   int w = d->width();         // returns desktop width
116   int h = d->height();        // returns desktop height
117   QSize mySize = sizeHint (); // returns widget size
118   int Xc = ( w - mySize.width() )  / 2;
119   int Yc = ( h - mySize.height() ) / 2;
120   move( Xc, Yc );
121
122   myThread->start();
123 }
124
125 InquireServersGUI::~InquireServersGUI()
126 {
127   delete myThread;
128 }
129
130 void InquireServersGUI::getArgs( int& _argc, char *** _argv)
131 {
132   _argc = qApp->argc();
133   *_argv = qApp->argv();
134 }
135
136 //=================================================================================
137 // function : ClickOnCancel()
138 // purpose  : cancel loading of SALOME
139 //=================================================================================
140 void InquireServersGUI::ClickOnCancel()
141 {
142   //it's necessary to stop asking servers
143   myThread->stop();
144   myGUI = false;
145   //Also we should send QCloseEvent in order to close this widget (and remove from screen) 
146   //QThread::postEvent ( this, new QCloseEvent() );
147   qApp->exit(1);
148 }
149
150 void InquireServersGUI::closeEvent ( QCloseEvent * pe)
151 {
152   //default implementation calls e->accept(), which hides this widget. 
153   //See the QCloseEvent documentation for more details.
154   pe->accept();
155   QApplication::flushX ();
156   QApplication::syncX ();
157   qApp->exit();
158 }
159
160 void InquireServersGUI::customEvent( QCustomEvent* pe )
161 {
162   switch( pe->type() )
163     {
164         case InquireEvent::ProgressEvent:
165         {
166             int* value = ( int* )(( InquireEvent*)pe)->data();
167             myPrgBar->setProgress( *value );
168             break;
169         }
170         case InquireEvent::ProgressEventLabel:
171         {
172             QString* myString = ( QString* )(( InquireEvent*)pe)->data();
173             myLabel->setText( *myString );
174             break;
175         }
176         case InquireEvent::ProgressEventError:
177         {
178             QString* myErrDesc = ( QString* )(( InquireEvent*)pe)->data();
179             QString  appName = "SALOME Professional";
180             QString  error = "An internal error occurred.\n"+ *myErrDesc + "\n";
181             QMessageBox myMsgBox(appName,error,QMessageBox::Critical,QMessageBox::Ok,QMessageBox::NoButton,
182                                         QMessageBox::NoButton,0,"MY",TRUE,WStyle_DialogBorder|WStyle_StaysOnTop);
183             myMsgBox.exec();
184             ClickOnCancel();
185             break;
186         }
187       default:
188         {
189           ;
190         }
191     }
192 }
193
194 int InquireServersGUI::getExitStatus()
195 {
196   myThread->getExitStatus();
197 }
198
199 InquireServersQThread::InquireServersQThread( InquireServersGUI* r )
200      : receiver(r),  myExitStatus(0)
201 {
202   char* cenv;
203
204   IsChecking = true;
205   myServersCount = 5;
206   //how many times we should repeat attempts to get response from all needed for launching SALOME servers
207   myRepeat = 30; // default value, user can change it by setting CSF_RepeatServerRequest env.variable
208   cenv = getenv( "CSF_RepeatServerRequest" );
209   if ( cenv ) {
210     int val = atoi( cenv );
211     if ( val > 0 )
212       myRepeat = val;
213   }
214   //define delay time between two attempts
215   myDelay = 1000000; // 1 second
216   QString str = "Loading: ";
217   myMessages[0] = "Checking naming service...";
218   myMessages[1] = str + "SALOME_Registry_Server" + "...";
219   myMessages[2] = str + "SALOMEDS_Server" + "...";
220   myMessages[3] = str + "SALOME_ModuleCatalog_Server" + "...";
221   myMessages[4] = str + "SALOME_Session_Server" + "...";
222   myMessages[5] = "";
223   myMessages[6] = "";
224   myMessages[7] = "";
225
226   r->getArgs( _argc, &_argv);
227
228   // NRI : Temporary solution for SuperVisionContainer
229   for ( int i=1; i<=(_argc-1); i++) {
230     if (strcmp(_argv[i],"CPP")==0) {
231       myMessages[5] = str + "SALOME_Container FactoryServer" + "...";
232       myServersCount++;
233     }
234     if (strcmp(_argv[i],"PYTHON")==0) {
235       myMessages[6] = str + "SALOME_ContainerPy.py FactoryServerPy" + "...";
236       myServersCount++;
237     }
238     if (strcmp(_argv[i],"SUPERV")==0) {
239       myMessages[7] = str + "SALOME_Container SuperVisionContainer" + "...";
240       myServersCount++;
241     }
242     if (strcmp(_argv[i],"GUI")==0) {
243       r->withGUI(true);
244     }
245   }
246 }
247
248 void InquireServersQThread::run()
249 {
250 while (IsChecking)
251   {
252     for (int i=1; i<=8; i++)
253       {
254         if ( myMessages[i-1].isEmpty() ) {
255           if (i==8) {
256             IsChecking = false;
257             //myExitStatus should be 0 because all servers exist and work
258             myExitStatus = 0;
259             //we should send QCloseEvent in order to close this widget (and remove from screen) 
260             QThread::postEvent ( receiver , new QCloseEvent() );
261           } else
262             continue;
263         }
264         QString *message = new QString(myMessages[i-1]);
265         QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEventLabel, message ) );
266         QThread::usleep(200000);
267         QString *errMsg;
268         bool result = AskServer(i,&errMsg);
269         if (result)
270           {
271             QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEvent, new int( i ) ) );
272             if (i==8)
273               {
274                 IsChecking = false;
275                 //myExitStatus should be 0 because all servers exist and work
276                 myExitStatus = 0;
277                 //we should send QCloseEvent in order to close this widget (and remove from screen) 
278                 QThread::postEvent ( receiver , new QCloseEvent() );
279               }
280           }
281         else
282           {
283             QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEventError, errMsg ) );
284             //myExitStatus should be 1 because we didn't receive response from server
285             myExitStatus = 1;
286             return;
287           }
288       }
289   }
290 }
291
292 bool InquireServersQThread::AskServer(int iteration, QString ** errMessage)
293 {
294   ASSERT(iteration<=myServersCount);
295   //will be set true if we get response from server
296   bool IsPassed = false;
297   QString errDescription;
298   switch (iteration)
299     {
300     case 1:
301       //First checking - existence of Naming Service
302       for (int i = myRepeat; i ; i--)
303         {
304           try
305             {
306               CORBA::ORB_var orb = CORBA::ORB_init(_argc,_argv) ;
307               CORBA::Object_var obj = orb->resolve_initial_references("NameService");
308               CosNaming::NamingContext_var _root_context = CosNaming::NamingContext::_narrow(obj);
309               if (CORBA::is_nil(_root_context))
310                 continue;
311               else
312                 IsPassed = true;
313               break;
314             }
315           catch(CORBA::COMM_FAILURE&)
316             {
317               MESSAGE("CORBA::COMM_FAILURE: unable to contact the naming service");
318             }
319           catch(...)
320             {
321               MESSAGE("Unknown Exception: unable to contact the naming service");
322             }
323           QThread::usleep(myDelay);
324         }
325       if (!IsPassed)
326         *errMessage = new QString("unable to contact the naming service");
327       break;
328     case 2:
329       //checking - existence of SALOME_Registry_Server
330     case 3:
331       //checking - existence of SALOMEDS_Server
332     case 4:
333       //checking - existence of SALOME_ModuleCatalog_Server
334     case 5:
335       //checking - existence of SALOME_Session_Server
336     case 6:
337       //checking - existence of SALOME_Container FactoryServer
338     case 7:
339       //checking - existence of SALOME_ContainerPy.py FactoryServerPy
340     case 8:
341       //checking - existence of SALOME_Container SuperVisionContainer
342       IsPassed = pingServer(iteration, errDescription);
343       if (!IsPassed)
344         *errMessage = new QString(errDescription);
345       break;
346     }
347 return IsPassed;
348 }
349
350 bool InquireServersQThread::pingServer(int iteration, QString& errMessage)
351 {
352   ASSERT(iteration<=myServersCount);
353   bool result = false;
354   QString errorDescr;
355   for (int i = myRepeat; i ; i--)
356     {
357       try
358         {
359           CORBA::ORB_var orb = CORBA::ORB_init(_argc,_argv) ;
360           SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance() ;
361           ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
362           NS.init_orb( orb ) ;
363           switch (iteration)
364             {
365             case 2:
366               {
367                 CORBA::Object_var obj = NS.Resolve("/Registry");
368                 Registry::Components_var registry = Registry::Components::_narrow(obj) ;
369                 if (!CORBA::is_nil(registry))
370                   {
371                     MESSAGE("/Registry is found");
372                     registry->ping();
373                     result = true;
374                     MESSAGE("Registry was activated");
375                     return result;
376                   }
377               }
378               break;
379             case 3:
380               {
381                 CORBA::Object_var obj = NS.Resolve("/myStudyManager");
382                 SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow(obj) ;
383                 if (!CORBA::is_nil(studyManager))
384                   {
385                     MESSAGE("/myStudyManager is found");
386                     studyManager->ping();
387                     result = true;
388                     MESSAGE("StudyManager was activated");
389                     return result;
390                   }
391               }
392               break;
393             case 4:
394               {
395                 CORBA::Object_var obj = NS.Resolve("Kernel/ModulCatalog");
396                 SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
397                 if (!CORBA::is_nil(catalog))
398                   {
399                     MESSAGE("/Kernel/ModulCatalog is found");
400                     catalog->ping();
401                     result = true;
402                     MESSAGE("ModuleCatalog was activated");
403                     return result;
404                   }
405               }
406               break;
407             case 5:
408               {
409                 CORBA::Object_var obj = NS.Resolve("Kernel/Session");
410                 SALOME::Session_var session = SALOME::Session::_narrow(obj) ;
411                 if (!CORBA::is_nil(session))
412                   {
413                     MESSAGE("/Kernel/Session is found");
414                     session->ping();
415                     result = true;
416                     MESSAGE("SALOME_Session was activated");
417                     return result;
418                   }
419               }
420               break;
421             case 6:
422               {
423                 string hostname = GetHostname();
424                 string containerName = "/Containers/";
425                 containerName += hostname;
426                 containerName += "/FactoryServer";
427
428                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
429                 Engines::Container_var FScontainer = Engines::Container::_narrow(obj) ;
430                 if (!CORBA::is_nil(FScontainer))
431                   {
432                     FScontainer->ping();
433                     result = true;
434                     MESSAGE("FactoryServer container was activated");
435                     return result;
436                   }
437               }
438               break;
439             case 7:
440               {
441                 string hostname = GetHostname();
442                 string containerName = "/Containers/";
443                 containerName += hostname;
444                 containerName += "/FactoryServerPy";
445                 
446                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
447                 Engines::Container_var FSPcontainer = Engines::Container::_narrow(obj) ;
448                 if (!CORBA::is_nil(FSPcontainer))
449                   {
450                     FSPcontainer->ping();
451                     result = true;
452                     MESSAGE("FactoryServerPy container was activated");
453                     return result;
454                   }
455               }
456               break;
457             case 8:
458               {
459                 string hostname = GetHostname();
460                 string containerName = "/Containers/";
461                 containerName += hostname;
462                 containerName += "/SuperVisionContainer";
463                 
464                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
465                 Engines::Container_var SVcontainer = Engines::Container::_narrow(obj) ;
466                 if (!CORBA::is_nil(SVcontainer))
467                   {
468                     SVcontainer->ping();
469                     result = true;
470                     MESSAGE("SuperVisionContainer container was activated");
471                     return result;
472                   }
473               }
474               break;
475             }
476          }
477       catch (ServiceUnreachable&)
478         {
479           MESSAGE("Caught exception: Naming Service Unreachable");
480           errorDescr = "Caught exception: Naming Service Unreachable";
481         }
482       catch (CORBA::COMM_FAILURE&)
483         {
484           MESSAGE("Caught CORBA::SystemException CommFailure.");
485           errorDescr = "Caught CORBA::SystemException CommFailure";
486         }
487       catch (CORBA::SystemException&)
488         {
489           MESSAGE("Caught CORBA::SystemException.");
490           errorDescr = "Caught CORBA::SystemException";
491         }
492       catch (CORBA::Exception&)
493         {
494           MESSAGE("Caught CORBA::Exception.");
495           errorDescr = "Caught CORBA::Exception";
496         }
497       catch (...)
498         {
499           MESSAGE("Caught unknown exception.");
500           errorDescr = "Caught unknown exception";
501         }
502       QThread::usleep(myDelay);
503     }
504   if (!result)
505     {
506       QString serverName;
507       switch (iteration)
508         {
509         case 2:
510           serverName = "SALOME_Registry_Server is not loaded. ";
511           break;
512         case 3:
513           serverName = "SALOMEDS_Server is not loaded. ";
514           break;
515         case 4:
516           serverName = "SALOME_ModuleCatalog_Server is not loaded. ";
517           break;
518         case 5:
519           serverName = "SALOME_Session_Server is not loaded. ";
520           break;
521         case 6:
522           serverName = "SALOME_Container FactoryServer is not loaded. ";
523           break;
524         case 7:
525           serverName = "SALOME_ContainerPy.py FactoryServerPy is not loaded. ";
526           break;
527         case 8:
528           serverName = "SALOME_Container SuperVisionContainer is not loaded. ";
529           break;
530         }
531       errMessage = serverName + errorDescr;
532     }
533   return result;
534 }
535
536 static const char* SEPARATOR    = ":";
537
538 QString findFile( QString filename )
539 {
540   QString dir;
541   char* cenv;
542   
543   // Try ${SALOME_ROOT_DIR}/share/salome/resources directory
544   cenv = getenv( "KERNEL_ROOT_DIR" );
545   if ( cenv ) {
546     dir.sprintf( "%s", cenv );
547     if ( !dir.isEmpty() ) {
548       dir = addSlash(dir) ;
549       dir = dir + "share" ;
550       dir = addSlash(dir) ;
551       dir = dir + "salome" ;
552       dir = addSlash(dir) ;
553       dir = dir + "resources" ;
554       dir = addSlash(dir) ;
555       QFileInfo fileInfo( dir + filename );
556       if ( fileInfo.isFile() && fileInfo.exists() )
557         return fileInfo.filePath();
558     }
559   }
560   // Try CSF_ResourcesDefaults env.var directory ( or directory list )
561   cenv = getenv( "CSF_ResourcesDefaults" );
562   if ( cenv ) {
563     dir.sprintf( "%s", cenv );
564     if ( !dir.isEmpty() ) {
565       QStringList dirList = QStringList::split( SEPARATOR, dir, false ); // skip empty entries
566       for ( int i = 0; i < dirList.count(); i++ ) {
567         QFileInfo fileInfo( addSlash( dirList[ i ] ) + filename );
568         if ( fileInfo.isFile() && fileInfo.exists() )
569           return fileInfo.filePath();
570       }
571     }
572   }
573   // Try ${HOME}/.salome/resources directory
574   cenv = getenv( "HOME" );
575   if ( cenv ) {
576     dir.sprintf( "%s", cenv );
577     if ( !dir.isEmpty() ) {
578       dir = addSlash(dir) ;
579       dir = dir + ".salome" ;
580       dir = addSlash(dir) ;
581       dir = dir + "resources" ;
582       dir = addSlash(dir) ;
583       QFileInfo fileInfo( dir + filename );
584       if ( fileInfo.isFile() && fileInfo.exists() )
585         return fileInfo.filePath();
586     }
587   }
588   // Try ${SALOME_SITE_DIR}/share/salome/resources directory
589   cenv = getenv( "SALOME_SITE_DIR" );
590   if ( cenv ) {
591     dir.sprintf( "%s", cenv );
592     if ( !dir.isEmpty() ) {
593       dir = addSlash(dir) ;
594       dir = dir + "share" ;
595       dir = addSlash(dir) ;
596       dir = dir + "salome" ;
597       dir = addSlash(dir) ;
598       dir = dir + "resources" ;
599       dir = addSlash(dir) ;
600       QFileInfo fileInfo( dir + filename );
601       if ( fileInfo.isFile() && fileInfo.exists() )
602         return fileInfo.filePath();
603     }
604   }
605   // Try ${SALOME_ROOT_DIR}/share/salome/resources directory
606   cenv = getenv( "SALOME_ROOT_DIR" );
607   if ( cenv ) {
608     dir.sprintf( "%s", cenv );
609     if ( !dir.isEmpty() ) {
610       dir = addSlash(dir) ;
611       dir = dir + "share" ;
612       dir = addSlash(dir) ;
613       dir = dir + "salome" ;
614       dir = addSlash(dir) ;
615       dir = dir + "resources" ;
616       dir = addSlash(dir) ;
617       QFileInfo fileInfo( dir + filename );
618       if ( fileInfo.isFile() && fileInfo.exists() )
619         return fileInfo.filePath();
620     }
621   }
622   return filename;
623 }
624 QString addSlash( const QString& path )
625 {
626   if (!path.isNull()) {
627 #ifdef WNT
628     QChar slash ('\\');
629 #else
630     QChar slash ('/');
631 #endif
632     if ( path.at(path.length()-1) != slash )
633       return path + slash;
634   }
635   return path;
636 }