1 // Copyright (C) 2007-2023 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_SINGLETON.hxx"
36 #include "SALOME_NamingService.hxx"
37 #include "Basics_Utils.hxx"
38 #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 template<class MY_CLS>
90 class Session_ServerCheck<MY_CLS>::Locker
94 \brief Constructor. Tries to aquire lock.
96 Locker( Session_ServerCheck* sc )
99 myChecker->myMutex->lock();
100 myChecker->myMutex->unlock();
103 \brief Destructor. Wakes the calling thread and goes sleeping.
105 ~Locker() TYPE_NOEXCEPT
107 myChecker->myWC->wakeAll();
108 myChecker->usleep( myChecker->myDelay );
111 Session_ServerCheck* myChecker;
115 \class Session_ServerCheck
116 \brief The class Session_ServerCheck is used to check SALOME
117 servers availability.
119 It runs in the secondrary thread. The number of attemts to check
120 each SALOME server and the time delay between checks can be specified
121 via setting the CSF_RepeatServerRequest and CSF_DelayServerRequest
122 environment variables.
124 Total number of the check attempts can be retrieved via totalSteps()
125 method and current check step can be retrieved via currentStep() method.
127 The method currentMessage() can be used to get the information message
128 about what SALOME server is currently checked. If any error occured (some
129 server could not be found) the thread loop is stopped and error status
130 is set. Error message can be retrieved with the error() method.
135 \param mutex a mutex used to serialize progress operations (splash)
136 \param wc a wait condition used in combination with \a mutex
138 template<class MY_NS>
139 Session_ServerCheck<MY_NS>::Session_ServerCheck( QMutex* mutex, QWaitCondition* wc )
143 myCheckCppContainer( false ),
144 myCheckPyContainer( false ),
145 myCheckSVContainer( false ),
146 myAttempts( __DEFAULT__ATTEMPTS__ ),
147 myDelay ( __DEFAULT__DELAY__ ),
151 // try to get nb of attempts from environment variable
152 if ( ( cenv = getenv( "CSF_RepeatServerRequest" ) ) && atoi( cenv ) > 0 )
153 myAttempts = atoi( cenv );
154 // try to get delay between attempts from environment variable
155 if ( ( cenv = getenv( "CSF_DelayServerRequest" ) ) && atoi( cenv ) > 0 )
156 myDelay = atoi( cenv );
158 // parse command line check if it is necessary to wait SALOME containers
159 QStringList args = QApplication::arguments();
160 for ( int i = 1; i < args.count(); i++ ) {
161 myCheckCppContainer = myCheckCppContainer || args[i] == "CPP";
162 myCheckPyContainer = myCheckPyContainer || args[i] == "PY";
163 myCheckSVContainer = myCheckSVContainer || args[i] == "SUPERV";
173 template<class MY_NS>
174 Session_ServerCheck<MY_NS>::~Session_ServerCheck()
177 while( isRunning() );
181 \brief Get current information message.
182 \return current message
184 template<class MY_NS>
185 QString Session_ServerCheck<MY_NS>::currentMessage()
187 static QStringList messages;
188 if ( messages.isEmpty() ) {
189 messages << tr( "Waiting for naming service..." );
190 messages << tr( "Waiting for registry server..." );
191 messages << tr( "Waiting for study server..." );
192 messages << tr( "Waiting for module catalogue server..." );
193 messages << tr( "Waiting for session server..." );
194 messages << tr( "Waiting for C++ container..." );
195 messages << tr( "Waiting for Python container..." );
196 messages << tr( "Waiting for Supervision container..." );
198 QMutexLocker locker( &myDataMutex );
200 int idx = myCurrentStep / myAttempts;
201 if ( idx >= 0 && idx < messages.count() )
202 msg = messages[ idx ];
207 \brief Get error message.
208 \return error message or null string of there was no any error
210 template<class MY_NS>
211 QString Session_ServerCheck<MY_NS>::error()
213 QMutexLocker locker( &myDataMutex );
218 \brief Get current step.
221 template<class MY_NS>
222 int Session_ServerCheck<MY_NS>::currentStep()
224 QMutexLocker locker( &myDataMutex );
225 return myCurrentStep;
229 \brief Get total number of check steps.
230 \return total number of steps
232 template<class MY_NS>
233 int Session_ServerCheck<MY_NS>::totalSteps()
235 QMutexLocker locker( &myDataMutex );
236 int cnt = 5; // base servers
237 if ( myCheckCppContainer ) cnt++; // + C++ container
238 if ( myCheckPyContainer ) cnt++; // + Python container
239 if ( myCheckSVContainer ) cnt++; // + supervision container
240 return cnt * myAttempts;
244 \brief Modify current step.
245 \param step new current step value
247 template<class MY_NS>
248 void Session_ServerCheck<MY_NS>::setStep( const int step )
250 QMutexLocker locker( &myDataMutex );
251 myCurrentStep = step;
255 \brief Set error message.
256 \param msg error message
258 template<class MY_NS>
259 void Session_ServerCheck<MY_NS>::setError( const QString& msg )
261 QMutexLocker locker( &myDataMutex );
266 \brief Thread loop function. Performs SALOME servers check.
268 template<class MY_NS>
269 void Session_ServerCheck<MY_NS>::run()
271 // start check servers
274 Qtx::CmdLineArgs args;
276 // 1. Check naming service
277 for ( int i = 0; i < myAttempts; i++ ) {
278 Locker locker( this );
280 setStep( current * myAttempts + i );
283 bool forceOK = false;
284 CosNaming::NamingContext_var _root_context = MY_NS::checkTrueNamingServiceIfExpected(args.argc(), args.argv(),forceOK);
285 if ( forceOK || !CORBA::is_nil( _root_context ) ) {
286 setStep( ++current * myAttempts );
290 catch( CORBA::COMM_FAILURE& ) {
291 MESSAGE( "CORBA::COMM_FAILURE: unable to contact the naming service" );
294 MESSAGE( "Unknown Exception: unable to contact the naming service" );
297 if ( i == myAttempts-1 ) {
298 setError( tr( "Unable to contact the naming service." ) + "\n" );
303 QString errfmt = "\n%1";
305 // 2. Check registry server
306 for ( int i = 0; i < myAttempts ; i++ ) {
307 Locker locker( this );
309 setStep( current * myAttempts + i );
312 CORBA::Object_var obj = MY_NS::forServerChecker("/Registry", args.argc(), args.argv());
313 Registry::Components_var registry = Registry::Components::_narrow( obj );
314 if ( !CORBA::is_nil( registry ) ) {
315 MESSAGE( "/Registry is found" );
317 MESSAGE( "Registry was activated" );
318 setStep( ++current * myAttempts );
322 catch ( ServiceUnreachable& ) {
323 MESSAGE( "Caught exception: Naming Service unreachable." );
324 error = "Naming service unreachable";
326 catch ( CORBA::COMM_FAILURE& ) {
327 MESSAGE( "Caught CORBA::SystemException CommFailure." );
328 error = "Caught CORBA::SystemException CommFailure.";
330 catch ( CORBA::SystemException& ) {
331 MESSAGE( "Caught CORBA::SystemException." );
332 error = "Caught CORBA::SystemException.";
334 catch ( CORBA::Exception& ) {
335 MESSAGE( "Caught CORBA::Exception." );
336 error = "Caught CORBA::Exception.";
339 MESSAGE( "Caught unknown exception." );
340 error = "Caught unknown exception.";
343 if ( i == myAttempts-1 ) {
344 setError( tr( "Registry server is not found." ) + errfmt.arg( error ) );
349 // 3. Check data server
350 for ( int i = 0; i < myAttempts ; i++ ) {
351 Locker locker( this );
353 setStep( current * myAttempts + i );
356 CORBA::Object_var obj = MY_NS::forServerChecker("/Study", args.argc(), args.argv());
357 SALOMEDS::Study_var study = SALOMEDS::Study::_narrow( obj );
358 if ( !CORBA::is_nil( study ) ) {
359 MESSAGE( "/Study is found" );
361 MESSAGE( "Study was activated" );
362 setStep( ++current * myAttempts );
366 catch ( ServiceUnreachable& ) {
367 MESSAGE( "Caught exception: Naming Service unreachable." );
368 error = "Naming service unreachable";
370 catch ( CORBA::COMM_FAILURE& ) {
371 MESSAGE( "Caught CORBA::SystemException CommFailure." );
372 error = "Caught CORBA::SystemException CommFailure.";
374 catch ( CORBA::SystemException& ) {
375 MESSAGE( "Caught CORBA::SystemException." );
376 error = "Caught CORBA::SystemException.";
378 catch ( CORBA::Exception& ) {
379 MESSAGE( "Caught CORBA::Exception." );
380 error = "Caught CORBA::Exception.";
383 MESSAGE( "Caught unknown exception." );
384 error = "Caught unknown exception.";
387 if ( i == myAttempts-1 ) {
388 setError( tr( "Study server is not found." ) + errfmt.arg( error ) );
393 // 4. Check module catalogue server
394 for ( int i = 0; i < myAttempts ; i++ ) {
395 Locker locker( this );
397 setStep( current * myAttempts + i );
400 CORBA::Object_var obj = MY_NS::forServerChecker("/Kernel/ModulCatalog", args.argc(), args.argv());
401 SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow( obj );
402 if ( !CORBA::is_nil( catalog ) ){
403 MESSAGE( "/Kernel/ModulCatalog is found" );
405 MESSAGE( "ModuleCatalog was activated" );
406 setStep( ++current * myAttempts );
410 catch ( ServiceUnreachable& ) {
411 MESSAGE( "Caught exception: Naming Service unreachable." );
412 error = "Naming service unreachable";
414 catch ( CORBA::COMM_FAILURE& ) {
415 MESSAGE( "Caught CORBA::SystemException CommFailure." );
416 error = "Caught CORBA::SystemException CommFailure.";
418 catch ( CORBA::SystemException& ) {
419 MESSAGE( "Caught CORBA::SystemException." );
420 error = "Caught CORBA::SystemException.";
422 catch ( CORBA::Exception& ) {
423 MESSAGE( "Caught CORBA::Exception." );
424 error = "Caught CORBA::Exception.";
427 MESSAGE( "Caught unknown exception." );
428 error = "Caught unknown exception.";
431 if ( i == myAttempts-1 ) {
432 setError( tr( "Module catalogue server is not found." ) + errfmt.arg( error ) );
437 // 5. Check data server
438 for ( int i = 0; i < myAttempts ; i++ ) {
439 Locker locker( this );
441 setStep( current * myAttempts + i );
444 CORBA::Object_var obj = MY_NS::forServerChecker("/Kernel/Session", args.argc(), args.argv());
445 SALOME::Session_var session = SALOME::Session::_narrow( obj );
446 if ( !CORBA::is_nil( session ) ) {
447 MESSAGE( "/Kernel/Session is found" );
449 MESSAGE( "SALOME_Session was activated" );
450 setStep( ++current * myAttempts );
454 catch ( ServiceUnreachable& ) {
455 MESSAGE( "Caught exception: Naming Service unreachable." );
456 error = "Naming service unreachable";
458 catch ( CORBA::COMM_FAILURE& ) {
459 MESSAGE( "Caught CORBA::SystemException CommFailure." );
460 error = "Caught CORBA::SystemException CommFailure.";
462 catch ( CORBA::SystemException& ) {
463 MESSAGE( "Caught CORBA::SystemException." );
464 error = "Caught CORBA::SystemException.";
466 catch ( CORBA::Exception& ) {
467 MESSAGE( "Caught CORBA::Exception." );
468 error = "Caught CORBA::Exception.";
471 MESSAGE( "Caught unknown exception." );
472 error = "Caught unknown exception.";
475 if ( i == myAttempts-1 ) {
476 setError( tr( "Session server is not found." ) + errfmt.arg( error ) );
481 // 6. Check C++ container
482 if ( myCheckCppContainer ) {
483 for ( int i = 0; i < myAttempts ; i++ ) {
484 Locker locker( this );
486 setStep( current * myAttempts + i );
489 QString containerName = QString( "/Containers/%1/FactoryServer" ).arg( Kernel_Utils::GetHostname().c_str() );
490 CORBA::Object_var obj = MY_NS::forServerChecker(containerName.toLatin1(), args.argc(), args.argv());
491 Engines::Container_var FScontainer = Engines::Container::_narrow( obj );
492 if ( !CORBA::is_nil( FScontainer ) ) {
493 MESSAGE( containerName.toLatin1().constData() << " is found" );
495 MESSAGE( "FactoryServer container was activated" );
496 setStep( ++current * myAttempts );
500 catch ( ServiceUnreachable& ) {
501 MESSAGE( "Caught exception: Naming Service unreachable." );
502 error = "Naming service unreachable";
504 catch ( CORBA::COMM_FAILURE& ) {
505 MESSAGE( "Caught CORBA::SystemException CommFailure." );
506 error = "Caught CORBA::SystemException CommFailure.";
508 catch ( CORBA::SystemException& ) {
509 MESSAGE( "Caught CORBA::SystemException." );
510 error = "Caught CORBA::SystemException.";
512 catch ( CORBA::Exception& ) {
513 MESSAGE( "Caught CORBA::Exception." );
514 error = "Caught CORBA::Exception.";
517 MESSAGE( "Caught unknown exception." );
518 error = "Caught unknown exception.";
521 if ( i == myAttempts-1 ) {
522 setError( tr( "C++ container is not found." ) + errfmt.arg( error ) );
528 // 7. Check Python container
529 if ( myCheckPyContainer ) {
530 for ( int i = 0; i < myAttempts ; i++ ) {
531 Locker locker( this );
533 setStep( current * myAttempts + i );
536 QString containerName = QString( "/Containers/%1/FactoryServerPy" ).arg( Kernel_Utils::GetHostname().c_str() );
537 CORBA::Object_var obj = MY_NS::forServerChecker(containerName.toLatin1(), args.argc(), args.argv());
538 Engines::Container_var FSPcontainer = Engines::Container::_narrow( obj );
539 if ( !CORBA::is_nil( FSPcontainer ) ) {
540 MESSAGE( containerName.toLatin1().constData() << " is found" );
541 FSPcontainer->ping();
542 MESSAGE("FactoryServerPy container was activated");
543 setStep( ++current * myAttempts );
547 catch ( ServiceUnreachable& ) {
548 MESSAGE( "Caught exception: Naming Service unreachable." );
549 error = "Naming service unreachable";
551 catch ( CORBA::COMM_FAILURE& ) {
552 MESSAGE( "Caught CORBA::SystemException CommFailure." );
553 error = "Caught CORBA::SystemException CommFailure.";
555 catch ( CORBA::SystemException& ) {
556 MESSAGE( "Caught CORBA::SystemException." );
557 error = "Caught CORBA::SystemException.";
559 catch ( CORBA::Exception& ) {
560 MESSAGE( "Caught CORBA::Exception." );
561 error = "Caught CORBA::Exception.";
564 MESSAGE( "Caught unknown exception." );
565 error = "Caught unknown exception.";
568 if ( i == myAttempts-1 ) {
569 setError( tr( "Python container is not found." ) + errfmt.arg( error ) );
575 // 8. Check supervision container
576 if ( myCheckSVContainer ) {
577 for ( int i = 0; i < myAttempts ; i++ ) {
578 Locker locker( this );
580 setStep( current * myAttempts + i );
583 QString containerName = QString( "/Containers/%1/SuperVisionContainer" ).arg( Kernel_Utils::GetHostname().c_str() );
584 CORBA::Object_var obj = MY_NS::forServerChecker(containerName.toLatin1(), args.argc(), args.argv());
585 Engines::Container_var SVcontainer = Engines::Container::_narrow( obj );
586 if ( !CORBA::is_nil( SVcontainer ) ) {
587 MESSAGE( containerName.toLatin1().constData() << " is found" );
589 MESSAGE("SuperVisionContainer container was activated");
590 setStep( ++current * myAttempts );
594 catch ( ServiceUnreachable& ) {
595 MESSAGE( "Caught exception: Naming Service unreachable." );
596 error = "Naming service unreachable";
598 catch ( CORBA::COMM_FAILURE& ) {
599 MESSAGE( "Caught CORBA::SystemException CommFailure." );
600 error = "Caught CORBA::SystemException CommFailure.";
602 catch ( CORBA::SystemException& ) {
603 MESSAGE( "Caught CORBA::SystemException." );
604 error = "Caught CORBA::SystemException.";
606 catch ( CORBA::Exception& ) {
607 MESSAGE( "Caught CORBA::Exception." );
608 error = "Caught CORBA::Exception.";
611 MESSAGE( "Caught unknown exception." );
612 error = "Caught unknown exception.";
615 if ( i == myAttempts-1 ) {
616 setError( tr( "Supervision container is not found." ) + errfmt.arg( error ) );
623 #include "Session_NS_wrapper.hxx"
625 template class Session_ServerCheck<OldStyleNS>;
626 template class Session_ServerCheck<NewStyleNS>;