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