Salome HOME
Update copyrights 2014.
[modules/gui.git] / src / Session / Session_ServerCheck.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File   : Session_ServerCheck.cxx
24 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
25 //
26 #include "Session_ServerCheck.hxx"
27
28 #include <SALOMEconfig.h>
29 #include CORBA_CLIENT_HEADER(SALOME_Session)
30 #include CORBA_CLIENT_HEADER(SALOME_Registry)
31 #include CORBA_CLIENT_HEADER(SALOMEDS)
32 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
33 #include CORBA_CLIENT_HEADER(SALOME_Component)
34
35 #include "Utils_ORB_INIT.hxx"
36 #include "Utils_SINGLETON.hxx"
37 #include "SALOME_NamingService.hxx"
38 #include "Basics_Utils.hxx"
39 #include "utilities.h"
40
41 #include <QApplication> 
42 #include <QWaitCondition>
43 #include <QMutexLocker>
44 #include <QStringList>
45
46 //
47 // Default settings
48 //
49
50 /*!
51   \brief Default number of attemtps to check SALOME server.
52
53   This value can be changed by setting the CSF_RepeatServerRequest
54   environment variable. For example, to set number of check attempts
55   for each server to 1000:
56   \code
57   setenv CSF_RepeatServerRequest 1000
58   \endcode
59 */
60 const int __DEFAULT__ATTEMPTS__ = 300;
61
62 /*!
63   \brief Default delay between attempts (in microseconds).
64
65   This value can be changed by setting the CSF_DelayServerRequest
66   environment variable. For example, to set delay between attemtps
67   to check SALOME servers to 100000 (0.1 second):
68   \code
69   setenv CSF_DelayServerRequest 100000
70   \endcode
71 */
72 const int __DEFAULT__DELAY__ = 50000;
73
74 /*!
75   \classSession_ServerCheck::Locker
76   \brief Automatic locker/unlocker.
77   \internal
78 */
79
80 class Session_ServerCheck::Locker
81 {
82 public:
83   /*!
84     \brief Constructor. Tries to aquire lock.
85   */
86   Locker( Session_ServerCheck* sc ) 
87     : myChecker( sc )
88   {
89     myChecker->myMutex->lock();
90     myChecker->myMutex->unlock();
91   }
92   /*!
93     \brief Destructor. Wakes the calling thread and goes sleeping.
94   */
95   ~Locker()
96   {
97     myChecker->myWC->wakeAll();
98     myChecker->usleep( myChecker->myDelay );
99   }
100 private:
101   Session_ServerCheck* myChecker;
102 };
103
104 /*!
105   \class Session_ServerCheck
106   \brief The class Session_ServerCheck is used to check SALOME
107   servers availability.
108   
109   It runs in the secondrary thread. The number of attemts to check
110   each SALOME server and the time delay between checks can be specified
111   via setting the CSF_RepeatServerRequest and CSF_DelayServerRequest
112   environment variables.
113
114   Total number of the check attempts can be retrieved via totalSteps()
115   method and current check step can be retrieved via currentStep() method.
116
117   The method currentMessage() can be used to get the information message
118   about what SALOME server is currently checked. If any error occured (some
119   server could not be found) the thread loop is stopped and error status
120   is set. Error message can be retrieved with the error() method.
121 */
122
123 /*!
124   \brief Constructor.
125   \param mutex a mutex used to serialize progress operations (splash)
126   \param wc a wait condition used in combination with \a mutex
127 */
128 Session_ServerCheck::Session_ServerCheck( QMutex* mutex, QWaitCondition* wc )
129 : QThread(),
130   myMutex( mutex ),
131   myWC( wc ),
132   myCheckCppContainer( false ),
133   myCheckPyContainer( false ),
134   myCheckSVContainer( false ),
135   myAttempts( __DEFAULT__ATTEMPTS__ ),
136   myDelay   ( __DEFAULT__DELAY__ ),
137   myCurrentStep( 0 )
138 {
139   char* cenv;
140   // try to get nb of attempts from environment variable
141   if ( ( cenv = getenv( "CSF_RepeatServerRequest" ) ) && atoi( cenv ) > 0 )
142     myAttempts = atoi( cenv );
143   // try to get delay between attempts from environment variable
144   if ( ( cenv = getenv( "CSF_DelayServerRequest" ) ) && atoi( cenv ) > 0 )
145     myDelay = atoi( cenv );
146
147   // parse command line check if it is necessary to wait SALOME containers
148   QStringList args = QApplication::arguments();
149   for ( int i = 1; i < args.count(); i++ ) {
150     myCheckCppContainer = myCheckCppContainer || args[i] == "CPP";
151     myCheckPyContainer  = myCheckPyContainer  || args[i] == "PY";
152     myCheckSVContainer  = myCheckSVContainer  || args[i] == "SUPERV";
153   }
154   
155   // start thread
156   start();
157 }
158
159 /*!
160   \brief Destructor
161 */
162 Session_ServerCheck::~Session_ServerCheck()
163 {
164   terminate();
165   while( isRunning() );
166 }
167
168 /*!
169   \brief Get current information message.
170   \return current message
171 */
172 QString Session_ServerCheck::currentMessage()
173 {
174   static QStringList messages;
175   if ( messages.isEmpty() ) {
176     messages << tr( "Waiting for naming service..." ); 
177     messages << tr( "Waiting for registry server..." );
178     messages << tr( "Waiting for study server..." );
179     messages << tr( "Waiting for module catalogue server..." );
180     messages << tr( "Waiting for session server..." );
181     messages << tr( "Waiting for C++ container..." );
182     messages << tr( "Waiting for Python container..." );
183     messages << tr( "Waiting for Supervision container..." );
184   }
185   QMutexLocker locker( &myDataMutex );
186   QString msg;
187   int idx = myCurrentStep / myAttempts;
188   if ( idx >= 0 && idx < messages.count() )
189     msg = messages[ idx ];
190   return msg;
191 }
192
193 /*!
194   \brief Get error message.
195   \return error message or null string of there was no any error
196 */
197 QString Session_ServerCheck::error()
198 {
199   QMutexLocker locker( &myDataMutex );
200   return myError;
201 }
202
203 /*!
204   \brief Get current step.
205   \return current step
206 */
207 int Session_ServerCheck::currentStep()
208 {
209   QMutexLocker locker( &myDataMutex );
210   return myCurrentStep;
211 }
212
213 /*!
214   \brief Get total number of check steps.
215   \return total number of steps
216 */
217 int Session_ServerCheck::totalSteps()
218 {
219   QMutexLocker locker( &myDataMutex );
220   int cnt = 5;                       // base servers
221   if ( myCheckCppContainer ) cnt++;  // + C++ container
222   if ( myCheckPyContainer )  cnt++;  // + Python container
223   if ( myCheckSVContainer )  cnt++;  // + supervision container
224   return cnt * myAttempts;
225 }
226
227 /*!
228   \brief Modify current step.
229   \param step new current step value
230 */
231 void Session_ServerCheck::setStep( const int step )
232 {
233   QMutexLocker locker( &myDataMutex );
234   myCurrentStep = step;
235 }
236
237 /*!
238   \brief Set error message.
239   \param msg error message
240 */
241 void Session_ServerCheck::setError( const QString& msg )
242 {
243   QMutexLocker locker( &myDataMutex );
244   myError = msg;
245 }
246
247 /*!
248   \brief Thread loop function. Performs SALOME servers check.
249 */
250 void Session_ServerCheck::run()
251 {
252   // start check servers
253   int current = 0;
254   QString error;
255   int    argc = QApplication::instance()->argc();
256   char** argv = QApplication::instance()->argv();
257
258   // 1. Check naming service
259   for ( int i = 0; i < myAttempts; i++ ) {
260     Locker locker( this );
261
262     setStep( current * myAttempts + i );
263
264     try {
265       CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
266       CORBA::Object_var obj = orb->resolve_initial_references( "NameService" );
267       CosNaming::NamingContext_var _root_context = CosNaming::NamingContext::_narrow( obj );
268       if ( !CORBA::is_nil( _root_context ) ) {
269         setStep( ++current * myAttempts );
270         break;
271       }
272     }
273     catch( CORBA::COMM_FAILURE& ) {
274       MESSAGE( "CORBA::COMM_FAILURE: unable to contact the naming service" );
275     }
276     catch( ... ) {
277       MESSAGE( "Unknown Exception: unable to contact the naming service" );
278     }
279
280     if ( i == myAttempts-1 ) {
281       setError( tr( "Unable to contact the naming service.\n" ) );
282       return;
283     }
284   }
285
286   // 2. Check registry server
287   for ( int i = 0; i < myAttempts ; i++ ) {
288     Locker locker( this );
289
290     setStep( current * myAttempts + i );
291
292     try {
293       CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
294       SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
295       ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
296       NS.init_orb( orb );
297       CORBA::Object_var obj = NS.Resolve( "/Registry" );
298       Registry::Components_var registry = Registry::Components::_narrow( obj );
299       if ( !CORBA::is_nil( registry ) ) {
300         MESSAGE( "/Registry is found" );
301         registry->ping();
302         MESSAGE( "Registry was activated" );
303         setStep( ++current * myAttempts );
304         break;
305       }
306     }
307     catch ( ServiceUnreachable& ) {
308       MESSAGE( "Caught exception: Naming Service unreachable." );
309       error = "Naming service unreachable";
310     }
311     catch ( CORBA::COMM_FAILURE& ) {
312       MESSAGE( "Caught CORBA::SystemException CommFailure." );
313       error = "Caught CORBA::SystemException CommFailure.";
314     }
315     catch ( CORBA::SystemException& ) {
316       MESSAGE( "Caught CORBA::SystemException." );
317       error = "Caught CORBA::SystemException.";
318     }
319     catch ( CORBA::Exception& ) {
320       MESSAGE( "Caught CORBA::Exception." );
321       error = "Caught CORBA::Exception.";
322     }
323     catch (...) {
324       MESSAGE( "Caught unknown exception." );
325       error = "Caught unknown exception.";
326     }
327
328     if ( i == myAttempts-1 ) {
329       setError( tr( "Registry server is not found.\n%1" ).arg ( error ) );
330       return;
331     }
332   }
333
334   // 3. Check data server
335   for ( int i = 0; i < myAttempts ; i++ ) {
336     Locker locker( this );
337
338     setStep( current * myAttempts + i );
339
340     try {
341       CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
342       SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
343       ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
344       NS.init_orb( orb );
345       CORBA::Object_var obj = NS.Resolve( "/myStudyManager" );
346       SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow( obj );
347       if ( !CORBA::is_nil( studyManager ) ) {
348         MESSAGE( "/myStudyManager is found" );
349         studyManager->ping();
350         MESSAGE( "StudyManager was activated" );
351         setStep( ++current * myAttempts );
352         break;
353       }
354     }
355     catch ( ServiceUnreachable& ) {
356       MESSAGE( "Caught exception: Naming Service unreachable." );
357       error = "Naming service unreachable";
358     }
359     catch ( CORBA::COMM_FAILURE& ) {
360       MESSAGE( "Caught CORBA::SystemException CommFailure." );
361       error = "Caught CORBA::SystemException CommFailure.";
362     }
363     catch ( CORBA::SystemException& ) {
364       MESSAGE( "Caught CORBA::SystemException." );
365       error = "Caught CORBA::SystemException.";
366     }
367     catch ( CORBA::Exception& ) {
368       MESSAGE( "Caught CORBA::Exception." );
369       error = "Caught CORBA::Exception.";
370     }
371     catch (...) {
372       MESSAGE( "Caught unknown exception." );
373       error = "Caught unknown exception.";
374     }
375
376     if ( i == myAttempts-1 ) {
377       setError( tr( "Study server is not found.\n%1" ).arg ( error ) );
378       return;
379     }
380   }
381   
382   // 4. Check module catalogue server
383   for ( int i = 0; i < myAttempts ; i++ ) {
384     Locker locker( this );
385
386     setStep( current * myAttempts + i );
387
388     try {
389       CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
390       SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
391       ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
392       NS.init_orb( orb );
393       CORBA::Object_var obj = NS.Resolve( "/Kernel/ModulCatalog" );
394       SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow( obj );
395       if ( !CORBA::is_nil( catalog ) ){
396         MESSAGE( "/Kernel/ModulCatalog is found" );
397         catalog->ping();
398         MESSAGE( "ModuleCatalog was activated" );
399         setStep( ++current * myAttempts );
400         break;
401       }
402     }
403     catch ( ServiceUnreachable& ) {
404       MESSAGE( "Caught exception: Naming Service unreachable." );
405       error = "Naming service unreachable";
406     }
407     catch ( CORBA::COMM_FAILURE& ) {
408       MESSAGE( "Caught CORBA::SystemException CommFailure." );
409       error = "Caught CORBA::SystemException CommFailure.";
410     }
411     catch ( CORBA::SystemException& ) {
412       MESSAGE( "Caught CORBA::SystemException." );
413       error = "Caught CORBA::SystemException.";
414     }
415     catch ( CORBA::Exception& ) {
416       MESSAGE( "Caught CORBA::Exception." );
417       error = "Caught CORBA::Exception.";
418     }
419     catch (...) {
420       MESSAGE( "Caught unknown exception." );
421       error = "Caught unknown exception.";
422     }
423
424     if ( i == myAttempts-1 ) {
425       setError( tr( "Module catalogue server is not found.\n%1" ).arg ( error ) );
426       return;
427     }
428   }
429
430   // 5. Check data server
431   for ( int i = 0; i < myAttempts ; i++ ) {
432     Locker locker( this );
433
434     setStep( current * myAttempts + i );
435
436     try {
437       CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
438       SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
439       ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
440       NS.init_orb( orb );
441       CORBA::Object_var obj = NS.Resolve( "/Kernel/Session" );
442       SALOME::Session_var session = SALOME::Session::_narrow( obj );
443       if ( !CORBA::is_nil( session ) ) {
444         MESSAGE( "/Kernel/Session is found" );
445         session->ping();
446         MESSAGE( "SALOME_Session was activated" );
447         setStep( ++current * myAttempts );
448         break;
449       }
450     }
451     catch ( ServiceUnreachable& ) {
452       MESSAGE( "Caught exception: Naming Service unreachable." );
453       error = "Naming service unreachable";
454     }
455     catch ( CORBA::COMM_FAILURE& ) {
456       MESSAGE( "Caught CORBA::SystemException CommFailure." );
457       error = "Caught CORBA::SystemException CommFailure.";
458     }
459     catch ( CORBA::SystemException& ) {
460       MESSAGE( "Caught CORBA::SystemException." );
461       error = "Caught CORBA::SystemException.";
462     }
463     catch ( CORBA::Exception& ) {
464       MESSAGE( "Caught CORBA::Exception." );
465       error = "Caught CORBA::Exception.";
466     }
467     catch (...) {
468       MESSAGE( "Caught unknown exception." );
469       error = "Caught unknown exception.";
470     }
471
472     if ( i == myAttempts-1 ) {
473       setError( tr( "Session server is not found.\n%1" ).arg ( error ) );
474       return;
475     }
476   }
477
478   // 6. Check C++ container
479   if ( myCheckCppContainer ) {
480     for ( int i = 0; i < myAttempts ; i++ ) {
481       Locker locker( this );
482       
483       setStep( current * myAttempts + i );
484
485       try {
486         CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
487         SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
488         ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
489         NS.init_orb( orb );
490         QString containerName = QString( "/Containers/%1/FactoryServer" ).arg( Kernel_Utils::GetHostname().c_str() );
491         CORBA::Object_var obj = NS.Resolve( containerName.toLatin1() );
492         Engines::Container_var FScontainer = Engines::Container::_narrow( obj );
493         if ( !CORBA::is_nil( FScontainer ) ) {
494           MESSAGE( containerName.toLatin1().constData() << " is found" );
495           FScontainer->ping();
496           MESSAGE( "FactoryServer container was activated" );
497           setStep( ++current * myAttempts );
498           break;
499         }
500       }
501       catch ( ServiceUnreachable& ) {
502         MESSAGE( "Caught exception: Naming Service unreachable." );
503         error = "Naming service unreachable";
504       }
505       catch ( CORBA::COMM_FAILURE& ) {
506         MESSAGE( "Caught CORBA::SystemException CommFailure." );
507         error = "Caught CORBA::SystemException CommFailure.";
508       }
509       catch ( CORBA::SystemException& ) {
510         MESSAGE( "Caught CORBA::SystemException." );
511         error = "Caught CORBA::SystemException.";
512       }
513       catch ( CORBA::Exception& ) {
514         MESSAGE( "Caught CORBA::Exception." );
515         error = "Caught CORBA::Exception.";
516       }
517       catch (...) {
518         MESSAGE( "Caught unknown exception." );
519         error = "Caught unknown exception.";
520       }
521       
522       if ( i == myAttempts-1 ) {
523         setError( tr( "C++ container is not found.\n%1" ).arg ( error ) );
524         return;
525       }
526     }
527   }
528
529   // 7. Check Python container
530   if ( myCheckPyContainer ) {
531     for ( int i = 0; i < myAttempts ; i++ ) {
532       Locker locker( this );
533       
534       setStep( current * myAttempts + i );
535
536       try {
537         CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
538         SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
539         ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
540         NS.init_orb( orb );
541         QString containerName = QString( "/Containers/%1/FactoryServerPy" ).arg( Kernel_Utils::GetHostname().c_str() );
542         CORBA::Object_var obj = NS.Resolve( containerName.toLatin1() );
543         Engines::Container_var FSPcontainer = Engines::Container::_narrow( obj );
544         if ( !CORBA::is_nil( FSPcontainer ) ) {
545           MESSAGE( containerName.toLatin1().constData() << " is found" );
546           FSPcontainer->ping();
547           MESSAGE("FactoryServerPy container was activated");
548           setStep( ++current * myAttempts );
549           break;
550         }
551       }
552       catch ( ServiceUnreachable& ) {
553         MESSAGE( "Caught exception: Naming Service unreachable." );
554         error = "Naming service unreachable";
555       }
556       catch ( CORBA::COMM_FAILURE& ) {
557         MESSAGE( "Caught CORBA::SystemException CommFailure." );
558         error = "Caught CORBA::SystemException CommFailure.";
559       }
560       catch ( CORBA::SystemException& ) {
561         MESSAGE( "Caught CORBA::SystemException." );
562         error = "Caught CORBA::SystemException.";
563       }
564       catch ( CORBA::Exception& ) {
565         MESSAGE( "Caught CORBA::Exception." );
566         error = "Caught CORBA::Exception.";
567       }
568       catch (...) {
569         MESSAGE( "Caught unknown exception." );
570         error = "Caught unknown exception.";
571       }
572
573       if ( i == myAttempts-1 ) {
574         setError( tr( "Python container is not found.\n%1" ).arg ( error ) );
575         return;
576       }
577     }
578   }
579
580   // 8. Check supervision container
581   if ( myCheckSVContainer ) {
582     for ( int i = 0; i < myAttempts ; i++ ) {
583       Locker locker( this );
584       
585       setStep( current * myAttempts + i );
586
587       try {
588         CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
589         SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
590         ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
591         NS.init_orb( orb );
592         QString containerName = QString( "/Containers/%1/SuperVisionContainer" ).arg( Kernel_Utils::GetHostname().c_str() );
593         CORBA::Object_var obj = NS.Resolve( containerName.toLatin1() );
594         Engines::Container_var SVcontainer = Engines::Container::_narrow( obj );
595         if ( !CORBA::is_nil( SVcontainer ) ) {
596           MESSAGE( containerName.toLatin1().constData() << " is found" );
597           SVcontainer->ping();
598           MESSAGE("SuperVisionContainer container was activated");
599           setStep( ++current * myAttempts );
600           break;
601         }
602       }
603       catch ( ServiceUnreachable& ) {
604         MESSAGE( "Caught exception: Naming Service unreachable." );
605         error = "Naming service unreachable";
606       }
607       catch ( CORBA::COMM_FAILURE& ) {
608         MESSAGE( "Caught CORBA::SystemException CommFailure." );
609         error = "Caught CORBA::SystemException CommFailure.";
610       }
611       catch ( CORBA::SystemException& ) {
612         MESSAGE( "Caught CORBA::SystemException." );
613         error = "Caught CORBA::SystemException.";
614       }
615       catch ( CORBA::Exception& ) {
616         MESSAGE( "Caught CORBA::Exception." );
617         error = "Caught CORBA::Exception.";
618       }
619       catch (...) {
620         MESSAGE( "Caught unknown exception." );
621         error = "Caught unknown exception.";
622       }
623     
624       if ( i == myAttempts-1 ) {
625         setError( tr( "Supervision container is not found.\n%1" ).arg ( error ) );
626         return;
627       }
628     }
629   }
630 }