1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : Session_ServerCheck.cxx
24 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
26 #include "Session_ServerCheck.hxx"
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)
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"
41 #include <QApplication>
42 #include <QWaitCondition>
43 #include <QMutexLocker>
44 #include <QStringList>
51 \brief Default number of attemtps to check SALOME server.
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:
57 setenv CSF_RepeatServerRequest 1000
60 const int __DEFAULT__ATTEMPTS__ = 300;
63 \brief Default delay between attempts (in microseconds).
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):
69 setenv CSF_DelayServerRequest 100000
72 const int __DEFAULT__DELAY__ = 50000;
74 // The exception being thrown out of a destructor,
75 // that is not allowed by default in C++11.
77 #if __cplusplus >= 201103L
78 # define TYPE_NOEXCEPT noexcept(false)
80 # define TYPE_NOEXCEPT
84 \classSession_ServerCheck::Locker
85 \brief Automatic locker/unlocker.
89 class Session_ServerCheck::Locker
93 \brief Constructor. Tries to aquire lock.
95 Locker( Session_ServerCheck* sc )
98 myChecker->myMutex->lock();
99 myChecker->myMutex->unlock();
102 \brief Destructor. Wakes the calling thread and goes sleeping.
104 ~Locker() TYPE_NOEXCEPT
106 myChecker->myWC->wakeAll();
107 myChecker->usleep( myChecker->myDelay );
110 Session_ServerCheck* myChecker;
114 \class Session_ServerCheck
115 \brief The class Session_ServerCheck is used to check SALOME
116 servers availability.
118 It runs in the secondrary thread. The number of attemts to check
119 each SALOME server and the time delay between checks can be specified
120 via setting the CSF_RepeatServerRequest and CSF_DelayServerRequest
121 environment variables.
123 Total number of the check attempts can be retrieved via totalSteps()
124 method and current check step can be retrieved via currentStep() method.
126 The method currentMessage() can be used to get the information message
127 about what SALOME server is currently checked. If any error occured (some
128 server could not be found) the thread loop is stopped and error status
129 is set. Error message can be retrieved with the error() method.
134 \param mutex a mutex used to serialize progress operations (splash)
135 \param wc a wait condition used in combination with \a mutex
137 Session_ServerCheck::Session_ServerCheck( QMutex* mutex, QWaitCondition* wc )
141 myCheckCppContainer( false ),
142 myCheckPyContainer( false ),
143 myCheckSVContainer( false ),
144 myAttempts( __DEFAULT__ATTEMPTS__ ),
145 myDelay ( __DEFAULT__DELAY__ ),
149 // try to get nb of attempts from environment variable
150 if ( ( cenv = getenv( "CSF_RepeatServerRequest" ) ) && atoi( cenv ) > 0 )
151 myAttempts = atoi( cenv );
152 // try to get delay between attempts from environment variable
153 if ( ( cenv = getenv( "CSF_DelayServerRequest" ) ) && atoi( cenv ) > 0 )
154 myDelay = atoi( cenv );
156 // parse command line check if it is necessary to wait SALOME containers
157 QStringList args = QApplication::arguments();
158 for ( int i = 1; i < args.count(); i++ ) {
159 myCheckCppContainer = myCheckCppContainer || args[i] == "CPP";
160 myCheckPyContainer = myCheckPyContainer || args[i] == "PY";
161 myCheckSVContainer = myCheckSVContainer || args[i] == "SUPERV";
171 Session_ServerCheck::~Session_ServerCheck()
174 while( isRunning() );
178 \brief Get current information message.
179 \return current message
181 QString Session_ServerCheck::currentMessage()
183 static QStringList messages;
184 if ( messages.isEmpty() ) {
185 messages << tr( "Waiting for naming service..." );
186 messages << tr( "Waiting for registry server..." );
187 messages << tr( "Waiting for study server..." );
188 messages << tr( "Waiting for module catalogue server..." );
189 messages << tr( "Waiting for session server..." );
190 messages << tr( "Waiting for C++ container..." );
191 messages << tr( "Waiting for Python container..." );
192 messages << tr( "Waiting for Supervision container..." );
194 QMutexLocker locker( &myDataMutex );
196 int idx = myCurrentStep / myAttempts;
197 if ( idx >= 0 && idx < messages.count() )
198 msg = messages[ idx ];
203 \brief Get error message.
204 \return error message or null string of there was no any error
206 QString Session_ServerCheck::error()
208 QMutexLocker locker( &myDataMutex );
213 \brief Get current step.
216 int Session_ServerCheck::currentStep()
218 QMutexLocker locker( &myDataMutex );
219 return myCurrentStep;
223 \brief Get total number of check steps.
224 \return total number of steps
226 int Session_ServerCheck::totalSteps()
228 QMutexLocker locker( &myDataMutex );
229 int cnt = 5; // base servers
230 if ( myCheckCppContainer ) cnt++; // + C++ container
231 if ( myCheckPyContainer ) cnt++; // + Python container
232 if ( myCheckSVContainer ) cnt++; // + supervision container
233 return cnt * myAttempts;
237 \brief Modify current step.
238 \param step new current step value
240 void Session_ServerCheck::setStep( const int step )
242 QMutexLocker locker( &myDataMutex );
243 myCurrentStep = step;
247 \brief Set error message.
248 \param msg error message
250 void Session_ServerCheck::setError( const QString& msg )
252 QMutexLocker locker( &myDataMutex );
257 \brief Thread loop function. Performs SALOME servers check.
259 void Session_ServerCheck::run()
261 // start check servers
264 int argc = QApplication::instance()->argc();
265 char** argv = QApplication::instance()->argv();
267 // 1. Check naming service
268 for ( int i = 0; i < myAttempts; i++ ) {
269 Locker locker( this );
271 setStep( current * myAttempts + i );
274 CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
275 CORBA::Object_var obj = orb->resolve_initial_references( "NameService" );
276 CosNaming::NamingContext_var _root_context = CosNaming::NamingContext::_narrow( obj );
277 if ( !CORBA::is_nil( _root_context ) ) {
278 setStep( ++current * myAttempts );
282 catch( CORBA::COMM_FAILURE& ) {
283 MESSAGE( "CORBA::COMM_FAILURE: unable to contact the naming service" );
286 MESSAGE( "Unknown Exception: unable to contact the naming service" );
289 if ( i == myAttempts-1 ) {
290 setError( tr( "Unable to contact the naming service.\n" ) );
295 // 2. Check registry server
296 for ( int i = 0; i < myAttempts ; i++ ) {
297 Locker locker( this );
299 setStep( current * myAttempts + i );
302 CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
303 SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
304 ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
306 CORBA::Object_var obj = NS.Resolve( "/Registry" );
307 Registry::Components_var registry = Registry::Components::_narrow( obj );
308 if ( !CORBA::is_nil( registry ) ) {
309 MESSAGE( "/Registry is found" );
311 MESSAGE( "Registry was activated" );
312 setStep( ++current * myAttempts );
316 catch ( ServiceUnreachable& ) {
317 MESSAGE( "Caught exception: Naming Service unreachable." );
318 error = "Naming service unreachable";
320 catch ( CORBA::COMM_FAILURE& ) {
321 MESSAGE( "Caught CORBA::SystemException CommFailure." );
322 error = "Caught CORBA::SystemException CommFailure.";
324 catch ( CORBA::SystemException& ) {
325 MESSAGE( "Caught CORBA::SystemException." );
326 error = "Caught CORBA::SystemException.";
328 catch ( CORBA::Exception& ) {
329 MESSAGE( "Caught CORBA::Exception." );
330 error = "Caught CORBA::Exception.";
333 MESSAGE( "Caught unknown exception." );
334 error = "Caught unknown exception.";
337 if ( i == myAttempts-1 ) {
338 setError( tr( "Registry server is not found.\n%1" ).arg ( error ) );
343 // 3. Check data server
344 for ( int i = 0; i < myAttempts ; i++ ) {
345 Locker locker( this );
347 setStep( current * myAttempts + i );
350 CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
351 SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
352 ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
354 CORBA::Object_var obj = NS.Resolve( "/myStudyManager" );
355 SALOMEDS::StudyManager_var studyManager = SALOMEDS::StudyManager::_narrow( obj );
356 if ( !CORBA::is_nil( studyManager ) ) {
357 MESSAGE( "/myStudyManager is found" );
358 studyManager->ping();
359 MESSAGE( "StudyManager was activated" );
360 setStep( ++current * myAttempts );
364 catch ( ServiceUnreachable& ) {
365 MESSAGE( "Caught exception: Naming Service unreachable." );
366 error = "Naming service unreachable";
368 catch ( CORBA::COMM_FAILURE& ) {
369 MESSAGE( "Caught CORBA::SystemException CommFailure." );
370 error = "Caught CORBA::SystemException CommFailure.";
372 catch ( CORBA::SystemException& ) {
373 MESSAGE( "Caught CORBA::SystemException." );
374 error = "Caught CORBA::SystemException.";
376 catch ( CORBA::Exception& ) {
377 MESSAGE( "Caught CORBA::Exception." );
378 error = "Caught CORBA::Exception.";
381 MESSAGE( "Caught unknown exception." );
382 error = "Caught unknown exception.";
385 if ( i == myAttempts-1 ) {
386 setError( tr( "Study server is not found.\n%1" ).arg ( error ) );
391 // 4. Check module catalogue server
392 for ( int i = 0; i < myAttempts ; i++ ) {
393 Locker locker( this );
395 setStep( current * myAttempts + i );
398 CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
399 SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
400 ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
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 MESSAGE( "/Kernel/ModulCatalog is found" );
407 MESSAGE( "ModuleCatalog was activated" );
408 setStep( ++current * myAttempts );
412 catch ( ServiceUnreachable& ) {
413 MESSAGE( "Caught exception: Naming Service unreachable." );
414 error = "Naming service unreachable";
416 catch ( CORBA::COMM_FAILURE& ) {
417 MESSAGE( "Caught CORBA::SystemException CommFailure." );
418 error = "Caught CORBA::SystemException CommFailure.";
420 catch ( CORBA::SystemException& ) {
421 MESSAGE( "Caught CORBA::SystemException." );
422 error = "Caught CORBA::SystemException.";
424 catch ( CORBA::Exception& ) {
425 MESSAGE( "Caught CORBA::Exception." );
426 error = "Caught CORBA::Exception.";
429 MESSAGE( "Caught unknown exception." );
430 error = "Caught unknown exception.";
433 if ( i == myAttempts-1 ) {
434 setError( tr( "Module catalogue server is not found.\n%1" ).arg ( error ) );
439 // 5. Check data server
440 for ( int i = 0; i < myAttempts ; i++ ) {
441 Locker locker( this );
443 setStep( current * myAttempts + i );
446 CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
447 SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
448 ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
450 CORBA::Object_var obj = NS.Resolve( "/Kernel/Session" );
451 SALOME::Session_var session = SALOME::Session::_narrow( obj );
452 if ( !CORBA::is_nil( session ) ) {
453 MESSAGE( "/Kernel/Session is found" );
455 MESSAGE( "SALOME_Session was activated" );
456 setStep( ++current * myAttempts );
460 catch ( ServiceUnreachable& ) {
461 MESSAGE( "Caught exception: Naming Service unreachable." );
462 error = "Naming service unreachable";
464 catch ( CORBA::COMM_FAILURE& ) {
465 MESSAGE( "Caught CORBA::SystemException CommFailure." );
466 error = "Caught CORBA::SystemException CommFailure.";
468 catch ( CORBA::SystemException& ) {
469 MESSAGE( "Caught CORBA::SystemException." );
470 error = "Caught CORBA::SystemException.";
472 catch ( CORBA::Exception& ) {
473 MESSAGE( "Caught CORBA::Exception." );
474 error = "Caught CORBA::Exception.";
477 MESSAGE( "Caught unknown exception." );
478 error = "Caught unknown exception.";
481 if ( i == myAttempts-1 ) {
482 setError( tr( "Session server is not found.\n%1" ).arg ( error ) );
487 // 6. Check C++ container
488 if ( myCheckCppContainer ) {
489 for ( int i = 0; i < myAttempts ; i++ ) {
490 Locker locker( this );
492 setStep( current * myAttempts + i );
495 CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
496 SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
497 ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
499 QString containerName = QString( "/Containers/%1/FactoryServer" ).arg( Kernel_Utils::GetHostname().c_str() );
500 CORBA::Object_var obj = NS.Resolve( containerName.toLatin1() );
501 Engines::Container_var FScontainer = Engines::Container::_narrow( obj );
502 if ( !CORBA::is_nil( FScontainer ) ) {
503 MESSAGE( containerName.toLatin1().constData() << " is found" );
505 MESSAGE( "FactoryServer container was activated" );
506 setStep( ++current * myAttempts );
510 catch ( ServiceUnreachable& ) {
511 MESSAGE( "Caught exception: Naming Service unreachable." );
512 error = "Naming service unreachable";
514 catch ( CORBA::COMM_FAILURE& ) {
515 MESSAGE( "Caught CORBA::SystemException CommFailure." );
516 error = "Caught CORBA::SystemException CommFailure.";
518 catch ( CORBA::SystemException& ) {
519 MESSAGE( "Caught CORBA::SystemException." );
520 error = "Caught CORBA::SystemException.";
522 catch ( CORBA::Exception& ) {
523 MESSAGE( "Caught CORBA::Exception." );
524 error = "Caught CORBA::Exception.";
527 MESSAGE( "Caught unknown exception." );
528 error = "Caught unknown exception.";
531 if ( i == myAttempts-1 ) {
532 setError( tr( "C++ container is not found.\n%1" ).arg ( error ) );
538 // 7. Check Python container
539 if ( myCheckPyContainer ) {
540 for ( int i = 0; i < myAttempts ; i++ ) {
541 Locker locker( this );
543 setStep( current * myAttempts + i );
546 CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
547 SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
548 ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
550 QString containerName = QString( "/Containers/%1/FactoryServerPy" ).arg( Kernel_Utils::GetHostname().c_str() );
551 CORBA::Object_var obj = NS.Resolve( containerName.toLatin1() );
552 Engines::Container_var FSPcontainer = Engines::Container::_narrow( obj );
553 if ( !CORBA::is_nil( FSPcontainer ) ) {
554 MESSAGE( containerName.toLatin1().constData() << " is found" );
555 FSPcontainer->ping();
556 MESSAGE("FactoryServerPy container was activated");
557 setStep( ++current * myAttempts );
561 catch ( ServiceUnreachable& ) {
562 MESSAGE( "Caught exception: Naming Service unreachable." );
563 error = "Naming service unreachable";
565 catch ( CORBA::COMM_FAILURE& ) {
566 MESSAGE( "Caught CORBA::SystemException CommFailure." );
567 error = "Caught CORBA::SystemException CommFailure.";
569 catch ( CORBA::SystemException& ) {
570 MESSAGE( "Caught CORBA::SystemException." );
571 error = "Caught CORBA::SystemException.";
573 catch ( CORBA::Exception& ) {
574 MESSAGE( "Caught CORBA::Exception." );
575 error = "Caught CORBA::Exception.";
578 MESSAGE( "Caught unknown exception." );
579 error = "Caught unknown exception.";
582 if ( i == myAttempts-1 ) {
583 setError( tr( "Python container is not found.\n%1" ).arg ( error ) );
589 // 8. Check supervision container
590 if ( myCheckSVContainer ) {
591 for ( int i = 0; i < myAttempts ; i++ ) {
592 Locker locker( this );
594 setStep( current * myAttempts + i );
597 CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
598 SALOME_NamingService &NS = *SINGLETON_<SALOME_NamingService>::Instance();
599 ASSERT( SINGLETON_<SALOME_NamingService>::IsAlreadyExisting() );
601 QString containerName = QString( "/Containers/%1/SuperVisionContainer" ).arg( Kernel_Utils::GetHostname().c_str() );
602 CORBA::Object_var obj = NS.Resolve( containerName.toLatin1() );
603 Engines::Container_var SVcontainer = Engines::Container::_narrow( obj );
604 if ( !CORBA::is_nil( SVcontainer ) ) {
605 MESSAGE( containerName.toLatin1().constData() << " is found" );
607 MESSAGE("SuperVisionContainer container was activated");
608 setStep( ++current * myAttempts );
612 catch ( ServiceUnreachable& ) {
613 MESSAGE( "Caught exception: Naming Service unreachable." );
614 error = "Naming service unreachable";
616 catch ( CORBA::COMM_FAILURE& ) {
617 MESSAGE( "Caught CORBA::SystemException CommFailure." );
618 error = "Caught CORBA::SystemException CommFailure.";
620 catch ( CORBA::SystemException& ) {
621 MESSAGE( "Caught CORBA::SystemException." );
622 error = "Caught CORBA::SystemException.";
624 catch ( CORBA::Exception& ) {
625 MESSAGE( "Caught CORBA::Exception." );
626 error = "Caught CORBA::Exception.";
629 MESSAGE( "Caught unknown exception." );
630 error = "Caught unknown exception.";
633 if ( i == myAttempts-1 ) {
634 setError( tr( "Supervision container is not found.\n%1" ).arg ( error ) );