Salome HOME
Increment version number (2.2.3)
[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 #include "utilities.h"
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 using namespace std;
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 | WType_TopLevel | WStyle_StaysOnTop | WX11BypassWM  )
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   return 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],"PY")==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::SystemException&)
316             {
317               MESSAGE("CORBA::SystemException: 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
343
344       IsPassed = pingServer(iteration, errDescription);
345       if (!IsPassed)
346         *errMessage = new QString(errDescription);
347       break;
348     }
349 return IsPassed;
350 }
351
352 bool InquireServersQThread::pingServer(int iteration, QString& errMessage)
353 {
354   ASSERT(iteration<=myServersCount);
355   bool result = false;
356   QString errorDescr;
357   for (int i = myRepeat; i ; i--)
358     {
359       try
360         {
361           CORBA::ORB_var orb = CORBA::ORB_init(_argc,_argv) ;
362           SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance() ;
363           ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
364           NS.init_orb( orb ) ;
365           switch (iteration)
366             {
367             case 2:
368               {
369                 CORBA::Object_var obj = NS.Resolve("/Registry");
370                 Registry::Components_var registry = Registry::Components::_narrow(obj) ;
371                 if (!CORBA::is_nil(registry))
372                   {
373                     MESSAGE("/Registry is found");
374                     registry->ping();
375                     result = true;
376                     MESSAGE("Registry was activated");
377                     return result;
378                   }
379               }
380               break;
381             case 3:
382               {
383                 CORBA::Object_var obj = NS.Resolve("/myStudyManager");
384                 SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow(obj) ;
385                 if (!CORBA::is_nil(studyManager))
386
387
388
389
390
391                   {
392                     MESSAGE("/myStudyManager is found");
393                     studyManager->ping();
394                     result = true;
395                     MESSAGE("StudyManager was activated");
396                     return result;
397                   }
398               }
399               break;
400             case 4:
401               {
402                 CORBA::Object_var obj = NS.Resolve("/Kernel/ModulCatalog");
403                 SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
404                 if (!CORBA::is_nil(catalog))
405                   {
406                     MESSAGE("/Kernel/ModulCatalog is found");
407                     catalog->ping();
408                     result = true;
409                     MESSAGE("ModuleCatalog was activated");
410                     return result;
411                   }
412               }
413               break;
414             case 5:
415               {
416                 CORBA::Object_var obj = NS.Resolve("/Kernel/Session");
417                 SALOME::Session_var session = SALOME::Session::_narrow(obj) ;
418                 if (!CORBA::is_nil(session))
419                   {
420                     MESSAGE("/Kernel/Session is found");
421                     session->ping();
422                     result = true;
423                     MESSAGE("SALOME_Session was activated");
424                     return result;
425                   }
426               }
427               break;
428             case 6:
429               {
430                 string hostname = GetHostname();
431                 string containerName = "/Containers/";
432                 containerName += hostname;
433                 containerName += "/FactoryServer";
434
435                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
436                 Engines::Container_var FScontainer = Engines::Container::_narrow(obj) ;
437                 if (!CORBA::is_nil(FScontainer))
438                   {
439                     FScontainer->ping();
440                     result = true;
441                     MESSAGE("FactoryServer container was activated");
442                     return result;
443                   }
444               }
445               break;
446             case 7:
447               {
448                 string hostname = GetHostname();
449                 string containerName = "/Containers/";
450                 containerName += hostname;
451                 containerName += "/FactoryServerPy";
452                 
453                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
454                 Engines::Container_var FSPcontainer = Engines::Container::_narrow(obj) ;
455                 if (!CORBA::is_nil(FSPcontainer))
456                   {
457                     FSPcontainer->ping();
458                     result = true;
459                     MESSAGE("FactoryServerPy container was activated");
460                     return result;
461                   }
462               }
463               break;
464             case 8:
465               {
466                 string hostname = GetHostname();
467                 string containerName = "/Containers/";
468                 containerName += hostname;
469                 containerName += "/SuperVisionContainer";
470                 
471                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
472                 Engines::Container_var SVcontainer = Engines::Container::_narrow(obj) ;
473                 if (!CORBA::is_nil(SVcontainer))
474                   {
475                     SVcontainer->ping();
476
477                     result = true;
478                     MESSAGE("SuperVisionContainer container was activated");
479                     return result;
480                   }
481               }
482               break;
483             }
484          }
485       catch (ServiceUnreachable&)
486         {
487           MESSAGE("Caught exception: Naming Service Unreachable");
488           errorDescr = "Caught exception: Naming Service Unreachable";
489         }
490       catch (CORBA::COMM_FAILURE&)
491         {
492           MESSAGE("Caught CORBA::SystemException CommFailure.");
493           errorDescr = "Caught CORBA::SystemException CommFailure";
494         }
495       catch (CORBA::SystemException&)
496         {
497           MESSAGE("Caught CORBA::SystemException.");
498           errorDescr = "Caught CORBA::SystemException";
499         }
500       catch (CORBA::Exception&)
501         {
502           MESSAGE("Caught CORBA::Exception.");
503           errorDescr = "Caught CORBA::Exception";
504         }
505       catch (...)
506         {
507           MESSAGE("Caught unknown exception.");
508           errorDescr = "Caught unknown exception";
509         }
510       QThread::usleep(myDelay);
511     }
512   if (!result)
513     {
514       QString serverName;
515       switch (iteration)
516         {
517         case 2:
518           serverName = "SALOME_Registry_Server is not loaded. ";
519           break;
520         case 3:
521           serverName = "SALOMEDS_Server is not loaded. ";
522           break;
523         case 4:
524           serverName = "SALOME_ModuleCatalog_Server is not loaded. ";
525           break;
526         case 5:
527           serverName = "SALOME_Session_Server is not loaded. ";
528           break;
529         case 6:
530           serverName = "SALOME_Container FactoryServer is not loaded. ";
531           break;
532         case 7:
533           serverName = "SALOME_ContainerPy.py FactoryServerPy is not loaded. ";
534           break;
535         case 8:
536           serverName = "SALOME_Container SuperVisionContainer is not loaded. ";
537           break;
538         }
539       errMessage = serverName + errorDescr;
540     }
541   return result;
542 }
543
544 static const char* SEPARATOR    = ":";
545
546 QString findFile( QString filename )
547 {
548   QString dir;
549   char* cenv;
550   
551   // Try ${SALOME_SITE_DIR}/share/${SALOME_SITE_NAME}/resources directory
552   cenv = getenv( "SALOME_SITE_DIR" );
553   if ( cenv ) {
554     dir.sprintf( "%s", cenv );
555     if ( !dir.isEmpty() ) {
556       dir = addSlash(dir) ;
557       dir = dir + "share" ;
558       dir = addSlash(dir) ;
559       cenv = getenv( "SALOME_SITE_NAME" );
560       if ( cenv ) 
561         dir = dir + cenv ;
562       else
563         dir = dir + "salome" ;
564       dir = addSlash(dir) ;
565       dir = dir + "resources" ;
566       dir = addSlash(dir) ;
567       QFileInfo fileInfo( dir + filename );
568       if ( fileInfo.isFile() && fileInfo.exists() )
569         return fileInfo.filePath();
570     }
571   }
572   // Try ${KERNEL_ROOT_DIR}/share/salome/resources directory
573   cenv = getenv( "KERNEL_ROOT_DIR" );
574   if ( cenv ) {
575     dir.sprintf( "%s", cenv );
576     if ( !dir.isEmpty() ) {
577       dir = addSlash(dir) ;
578       dir = dir + "share" ;
579       dir = addSlash(dir) ;
580       dir = dir + "salome" ;
581       dir = addSlash(dir) ;
582       dir = dir + "resources" ;
583       dir = addSlash(dir) ;
584       QFileInfo fileInfo( dir + filename );
585       if ( fileInfo.isFile() && fileInfo.exists() )
586         return fileInfo.filePath();
587     }
588   }
589   // Try CSF_ResourcesDefaults env.var directory ( or directory list )
590   cenv = getenv( "CSF_ResourcesDefaults" );
591   if ( cenv ) {
592     dir.sprintf( "%s", cenv );
593     if ( !dir.isEmpty() ) {
594       QStringList dirList = QStringList::split( SEPARATOR, dir, false ); // skip empty entries
595       for ( int i = 0; i < dirList.count(); i++ ) {
596         QFileInfo fileInfo( addSlash( dirList[ i ] ) + filename );
597         if ( fileInfo.isFile() && fileInfo.exists() )
598           return fileInfo.filePath();
599       }
600     }
601   }
602   // Try ${HOME}/.salome/resources directory
603   cenv = getenv( "HOME" );
604   if ( cenv ) {
605     dir.sprintf( "%s", cenv );
606     if ( !dir.isEmpty() ) {
607       dir = addSlash(dir) ;
608       dir = dir + ".salome" ;
609       dir = addSlash(dir) ;
610       dir = dir + "resources" ;
611       dir = addSlash(dir) ;
612       QFileInfo fileInfo( dir + filename );
613       if ( fileInfo.isFile() && fileInfo.exists() )
614         return fileInfo.filePath();
615     }
616   }
617   return filename;
618 }
619 QString addSlash( const QString& path )
620 {
621   if (!path.isNull()) {
622 #ifdef WNT
623     QChar slash ('\\');
624 #else
625     QChar slash ('/');
626 #endif
627     if ( path.at(path.length()-1) != slash )
628       return path + slash;
629   }
630   return path;
631 }