Salome HOME
This commit was generated by cvs2git to track changes on a CVS vendor
[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   myGUI = false;
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   myGUI = false;
144   //Also we should send QCloseEvent in order to close this widget (and remove from screen) 
145   //QThread::postEvent ( this, new QCloseEvent() );
146   qApp->exit(1);
147 }
148
149 void InquireServersGUI::closeEvent ( QCloseEvent * pe)
150 {
151   //default implementation calls e->accept(), which hides this widget. 
152   //See the QCloseEvent documentation for more details.
153   pe->accept();
154   QApplication::flushX ();
155   QApplication::syncX ();
156   qApp->exit();
157 }
158
159 void InquireServersGUI::customEvent( QCustomEvent* pe )
160 {
161   switch( pe->type() )
162     {
163         case InquireEvent::ProgressEvent:
164         {
165             int* value = ( int* )(( InquireEvent*)pe)->data();
166             myPrgBar->setProgress( *value );
167             break;
168         }
169         case InquireEvent::ProgressEventLabel:
170         {
171             QString* myString = ( QString* )(( InquireEvent*)pe)->data();
172             myLabel->setText( *myString );
173             break;
174         }
175         case InquireEvent::ProgressEventError:
176         {
177             QString* myErrDesc = ( QString* )(( InquireEvent*)pe)->data();
178             QString  appName = "SALOME Professional";
179             QString  error = "An internal error occurred.\n"+ *myErrDesc + "\n";
180             QMessageBox myMsgBox(appName,error,QMessageBox::Critical,QMessageBox::Ok,QMessageBox::NoButton,
181                                         QMessageBox::NoButton,0,"MY",TRUE,WStyle_DialogBorder|WStyle_StaysOnTop);
182             myMsgBox.exec();
183             ClickOnCancel();
184             break;
185         }
186       default:
187         {
188           ;
189         }
190     }
191 }
192
193 int InquireServersGUI::getExitStatus()
194 {
195   myThread->getExitStatus();
196 }
197
198 InquireServersQThread::InquireServersQThread( InquireServersGUI* r )
199      : receiver(r),  myExitStatus(0)
200 {
201   char* cenv;
202
203   IsChecking = true;
204   myServersCount = 5;
205   //how many times we should repeat attempts to get response from all needed for launching SALOME servers
206   myRepeat = 30; // default value, user can change it by setting CSF_RepeatServerRequest env.variable
207   cenv = getenv( "CSF_RepeatServerRequest" );
208   if ( cenv ) {
209     int val = atoi( cenv );
210     if ( val > 0 )
211       myRepeat = val;
212   }
213   //define delay time between two attempts
214   myDelay = 1000000; // 1 second
215   QString str = "Loading: ";
216   myMessages[0] = "Checking naming service...";
217   myMessages[1] = str + "SALOME_Registry_Server" + "...";
218   myMessages[2] = str + "SALOME_Container SuperVisionContainer" + "...";
219   myMessages[3] = str + "SALOME_ModuleCatalog_Server" + "...";
220   myMessages[4] = str + "SALOME_ContainerPy.py FactoryServerPy" + "...";
221   myMessages[5] = str + "SALOME_Container FactoryServer" + "...";
222   myMessages[6] = str + "SALOMEDS_Server" + "...";
223   myMessages[7] = str + "SALOME_Session_Server" + "...";
224
225   r->getArgs( _argc, &_argv);
226
227   // NRI : Temporary solution for SuperVisionContainer
228   for ( int i=1; i<=(_argc-1); i++) {
229     if (strcmp(_argv[i],"CPP")==0) {
230       myMessages[5] = str + "SALOME_Container FactoryServer" + "...";
231       myServersCount++;
232     }
233     if (strcmp(_argv[i],"PYTHON")==0) {
234       myMessages[6] = str + "SALOME_ContainerPy.py FactoryServerPy" + "...";
235       myServersCount++;
236     }
237     if (strcmp(_argv[i],"SUPERV")==0) {
238       myMessages[7] = str + "SALOME_Container SuperVisionContainer" + "...";
239       myServersCount++;
240     }
241     if (strcmp(_argv[i],"GUI")==0) {
242       r->withGUI(true);
243     }
244   }
245 }
246
247 void InquireServersQThread::run()
248 {
249 while (IsChecking)
250   {
251     for (int i=1; i<=8; i++)
252       {
253         if ( myMessages[i-1].isEmpty() ) {
254           if (i==8) {
255             IsChecking = false;
256             //myExitStatus should be 0 because all servers exist and work
257             myExitStatus = 0;
258             //we should send QCloseEvent in order to close this widget (and remove from screen) 
259             QThread::postEvent ( receiver , new QCloseEvent() );
260           } else
261             continue;
262         }
263         QString *message = new QString(myMessages[i-1]);
264         QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEventLabel, message ) );
265         QThread::usleep(200000);
266         QString *errMsg;
267         bool result = AskServer(i,&errMsg);
268         if (result)
269           {
270             QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEvent, new int( i ) ) );
271             if (i==8)
272               {
273                 IsChecking = false;
274                 //myExitStatus should be 0 because all servers exist and work
275                 myExitStatus = 0;
276                 //we should send QCloseEvent in order to close this widget (and remove from screen) 
277                 QThread::postEvent ( receiver , new QCloseEvent() );
278               }
279           }
280         else
281           {
282             QThread::postEvent( receiver, new InquireEvent( ( QEvent::Type )InquireEvent::ProgressEventError, errMsg ) );
283             //myExitStatus should be 1 because we didn't receive response from server
284             myExitStatus = 1;
285             return;
286           }
287       }
288   }
289 }
290
291 bool InquireServersQThread::AskServer(int iteration, QString ** errMessage)
292 {
293   ASSERT(iteration<=myServersCount);
294   //will be set true if we get response from server
295   bool IsPassed = false;
296   QString errDescription;
297   switch (iteration)
298     {
299     case 1:
300       //First checking - existence of Naming Service
301       for (int i = myRepeat; i ; i--)
302         {
303           try
304             {
305               CORBA::ORB_var orb = CORBA::ORB_init(_argc,_argv) ;
306               CORBA::Object_var obj = orb->resolve_initial_references("NameService");
307               CosNaming::NamingContext_var _root_context = CosNaming::NamingContext::_narrow(obj);
308               if (CORBA::is_nil(_root_context))
309                 continue;
310               else
311                 IsPassed = true;
312               break;
313             }
314           catch(CORBA::COMM_FAILURE&)
315             {
316               MESSAGE("CORBA::COMM_FAILURE: unable to contact the naming service");
317             }
318           catch(...)
319             {
320               MESSAGE("Unknown Exception: unable to contact the naming service");
321             }
322           QThread::usleep(myDelay);
323         }
324       if (!IsPassed)
325         *errMessage = new QString("unable to contact the naming service");
326       break;
327     case 2:
328       //checking - existence of SALOME_Registry_Server
329     case 3:
330       //checking - existence of SALOME_Container SuperVisionContainer
331     case 4:
332       //checking - existence of SALOME_ModuleCatalog_Server
333     case 5:
334       //checking - existence of SALOME_ContainerPy.py FactoryServerPy
335     case 6:
336       //checking - existence of SALOME_Container FactoryServer
337     case 7:
338       //checking - existence of SALOMEDS_Server
339     case 8:
340       //checking - existence of SALOME_Session_Server
341       
342
343       IsPassed = pingServer(iteration, errDescription);
344       if (!IsPassed)
345         *errMessage = new QString(errDescription);
346       break;
347     }
348 return IsPassed;
349 }
350
351 bool InquireServersQThread::pingServer(int iteration, QString& errMessage)
352 {
353   ASSERT(iteration<=myServersCount);
354   bool result = false;
355   QString errorDescr;
356   for (int i = myRepeat; i ; i--)
357     {
358       try
359         {
360           CORBA::ORB_var orb = CORBA::ORB_init(_argc,_argv) ;
361           SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance() ;
362           ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
363           NS.init_orb( orb ) ;
364           switch (iteration)
365             {
366             case 2:
367               {
368                 CORBA::Object_var obj = NS.Resolve("/Registry");
369                 Registry::Components_var registry = Registry::Components::_narrow(obj) ;
370                 if (!CORBA::is_nil(registry))
371                   {
372                     MESSAGE("/Registry is found");
373                     registry->ping();
374                     result = true;
375                     MESSAGE("Registry was activated");
376                     return result;
377                   }
378               }
379               break;
380             case 3:     
381               {
382                 string hostname = GetHostname();
383                 string containerName = "/Containers/";
384                 containerName += hostname;
385                 containerName += "/SuperVisionContainer";
386                 
387                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
388                 Engines::Container_var SVcontainer = Engines::Container::_narrow(obj) ;
389                 if (!CORBA::is_nil(SVcontainer))
390                   {
391                     SVcontainer->ping();
392                     result = true;
393                     MESSAGE("SuperVisionContainer container was activated");
394                     return result;
395                   }
396               }
397               break;
398             case 4:
399               {
400                 CORBA::Object_var obj = NS.Resolve("Kernel/ModulCatalog");
401                 SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj) ;
402                 if (!CORBA::is_nil(catalog))
403                   {
404                     MESSAGE("/Kernel/ModulCatalog is found");
405                     catalog->ping();
406                     result = true;
407                     MESSAGE("ModuleCatalog was activated");
408                     return result;
409                   }
410               }
411               break;
412             case 8:
413               {
414                 CORBA::Object_var obj = NS.Resolve("Kernel/Session");
415                 SALOME::Session_var session = SALOME::Session::_narrow(obj) ;
416                 if (!CORBA::is_nil(session))
417                   {
418                     MESSAGE("/Kernel/Session is found");
419                     session->ping();
420                     result = true;
421                     MESSAGE("SALOME_Session was activated");
422                     return result;
423                   }
424               }
425               break;
426             case 6:
427               {
428                 string hostname = GetHostname();
429                 string containerName = "/Containers/";
430                 containerName += hostname;
431                 containerName += "/FactoryServer";
432
433                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
434                 Engines::Container_var FScontainer = Engines::Container::_narrow(obj) ;
435                 if (!CORBA::is_nil(FScontainer))
436                   {
437                     FScontainer->ping();
438                     result = true;
439                     MESSAGE("FactoryServer container was activated");
440                     return result;
441                   }
442               }
443               break;
444             case 5:
445               {
446                 string hostname = GetHostname();
447                 string containerName = "/Containers/";
448                 containerName += hostname;
449                 containerName += "/FactoryServerPy";
450                 
451                 CORBA::Object_var obj = NS.Resolve(containerName.c_str());
452                 Engines::Container_var FSPcontainer = Engines::Container::_narrow(obj) ;
453                 if (!CORBA::is_nil(FSPcontainer))
454                   {
455                     FSPcontainer->ping();
456                     result = true;
457                     MESSAGE("FactoryServerPy container was activated");
458                     return result;
459                   }
460               }
461               break;
462             case 7:
463               {
464                 CORBA::Object_var obj = NS.Resolve("/myStudyManager");
465                 SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow(obj) ;
466                 if (!CORBA::is_nil(studyManager))
467                   {
468                     MESSAGE("/myStudyManager is found");
469                     studyManager->ping();
470                     result = true;
471                     MESSAGE("StudyManager was activated");
472                     return result;
473                   }
474               }
475               break;
476             }
477          }
478       catch (ServiceUnreachable&)
479         {
480           MESSAGE("Caught exception: Naming Service Unreachable");
481           errorDescr = "Caught exception: Naming Service Unreachable";
482         }
483       catch (CORBA::COMM_FAILURE&)
484         {
485           MESSAGE("Caught CORBA::SystemException CommFailure.");
486           errorDescr = "Caught CORBA::SystemException CommFailure";
487         }
488       catch (CORBA::SystemException&)
489         {
490           MESSAGE("Caught CORBA::SystemException.");
491           errorDescr = "Caught CORBA::SystemException";
492         }
493       catch (CORBA::Exception&)
494         {
495           MESSAGE("Caught CORBA::Exception.");
496           errorDescr = "Caught CORBA::Exception";
497         }
498       catch (...)
499         {
500           MESSAGE("Caught unknown exception.");
501           errorDescr = "Caught unknown exception";
502         }
503       QThread::usleep(myDelay);
504     }
505   if (!result)
506     {
507       QString serverName;
508       switch (iteration)
509         {
510         case 2:
511           serverName = "SALOME_Registry_Server is not loaded. ";
512           break;
513         case 7:
514           serverName = "SALOMEDS_Server is not loaded. ";
515           break;
516         case 4:
517           serverName = "SALOME_ModuleCatalog_Server is not loaded. ";
518           break;
519         case 8:
520           serverName = "SALOME_Session_Server is not loaded. ";
521           break;
522         case 6:
523           serverName = "SALOME_Container FactoryServer is not loaded. ";
524           break;
525         case 5:
526           serverName = "SALOME_ContainerPy.py FactoryServerPy is not loaded. ";
527           break;
528         case 3:
529           serverName = "SALOME_Container SuperVisionContainer is not loaded. ";
530           break;
531         }
532       errMessage = serverName + errorDescr;
533     }
534   return result;
535 }
536
537 static const char* SEPARATOR    = ":";
538
539 QString findFile( QString filename )
540 {
541   QString dir;
542   char* cenv;
543   
544   // Try CSF_ResourcesDefaults env.var directory ( or directory list )
545   cenv = getenv( "CSF_ResourcesDefaults" );
546   if ( cenv ) {
547     dir.sprintf( "%s", cenv );
548     if ( !dir.isEmpty() ) {
549       QStringList dirList = QStringList::split( SEPARATOR, dir, false ); // skip empty entries
550       for ( int i = 0; i < dirList.count(); i++ ) {
551         QFileInfo fileInfo( addSlash( dirList[ i ] ) + filename );
552         if ( fileInfo.isFile() && fileInfo.exists() )
553           return fileInfo.filePath();
554       }
555     }
556   }
557   // Try ${HOME}/.salome/resources directory
558   cenv = getenv( "HOME" );
559   if ( cenv ) {
560     dir.sprintf( "%s", cenv );
561     if ( !dir.isEmpty() ) {
562       dir = addSlash(dir) ;
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 ${SALOME_SITE_DIR}/share/salome/resources directory
573   cenv = getenv( "SALOME_SITE_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 ${SALOME_ROOT_DIR}/share/salome/resources directory
590   cenv = getenv( "SALOME_ROOT_DIR" );
591   if ( cenv ) {
592     dir.sprintf( "%s", cenv );
593     if ( !dir.isEmpty() ) {
594       dir = addSlash(dir) ;
595       dir = dir + "share" ;
596       dir = addSlash(dir) ;
597       dir = dir + "salome" ;
598       dir = addSlash(dir) ;
599       dir = dir + "resources" ;
600       dir = addSlash(dir) ;
601       QFileInfo fileInfo( dir + filename );
602       if ( fileInfo.isFile() && fileInfo.exists() )
603         return fileInfo.filePath();
604     }
605   }
606   return filename;
607 }
608 QString addSlash( const QString& path )
609 {
610   if (!path.isNull()) {
611 #ifdef WNT
612     QChar slash ('\\');
613 #else
614     QChar slash ('/');
615 #endif
616     if ( path.at(path.length()-1) != slash )
617       return path + slash;
618   }
619   return path;
620 }