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