1 // Copyright (C) 2007-2020 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"
42 #include <QApplication>
43 #include <QWaitCondition>
44 #include <QMutexLocker>
45 #include <QStringList>
52 \brief Default number of attemtps to check SALOME server.
54 This value can be changed by setting the CSF_RepeatServerRequest
55 environment variable. For example, to set number of check attempts
56 for each server to 1000:
58 setenv CSF_RepeatServerRequest 1000
61 const int __DEFAULT__ATTEMPTS__ = 300;
64 \brief Default delay between attempts (in microseconds).
66 This value can be changed by setting the CSF_DelayServerRequest
67 environment variable. For example, to set delay between attemtps
68 to check SALOME servers to 100000 (0.1 second):
70 setenv CSF_DelayServerRequest 100000
73 const int __DEFAULT__DELAY__ = 50000;
75 // The exception being thrown out of a destructor,
76 // that is not allowed by default in C++11.
78 #if __cplusplus >= 201103L
79 # define TYPE_NOEXCEPT noexcept(false)
81 # define TYPE_NOEXCEPT
85 \classSession_ServerCheck::Locker
86 \brief Automatic locker/unlocker.
90 template<class MY_CLS>
91 class Session_ServerCheck<MY_CLS>::Locker
95 \brief Constructor. Tries to aquire lock.
97 Locker( Session_ServerCheck* sc )
100 myChecker->myMutex->lock();
101 myChecker->myMutex->unlock();
104 \brief Destructor. Wakes the calling thread and goes sleeping.
106 ~Locker() TYPE_NOEXCEPT
108 myChecker->myWC->wakeAll();
109 myChecker->usleep( myChecker->myDelay );
112 Session_ServerCheck* myChecker;
116 \class Session_ServerCheck
117 \brief The class Session_ServerCheck is used to check SALOME
118 servers availability.
120 It runs in the secondrary thread. The number of attemts to check
121 each SALOME server and the time delay between checks can be specified
122 via setting the CSF_RepeatServerRequest and CSF_DelayServerRequest
123 environment variables.
125 Total number of the check attempts can be retrieved via totalSteps()
126 method and current check step can be retrieved via currentStep() method.
128 The method currentMessage() can be used to get the information message
129 about what SALOME server is currently checked. If any error occured (some
130 server could not be found) the thread loop is stopped and error status
131 is set. Error message can be retrieved with the error() method.
136 \param mutex a mutex used to serialize progress operations (splash)
137 \param wc a wait condition used in combination with \a mutex
139 template<class MY_NS>
140 Session_ServerCheck<MY_NS>::Session_ServerCheck( QMutex* mutex, QWaitCondition* wc )
144 myCheckCppContainer( false ),
145 myCheckPyContainer( false ),
146 myCheckSVContainer( false ),
147 myAttempts( __DEFAULT__ATTEMPTS__ ),
148 myDelay ( __DEFAULT__DELAY__ ),
152 // try to get nb of attempts from environment variable
153 if ( ( cenv = getenv( "CSF_RepeatServerRequest" ) ) && atoi( cenv ) > 0 )
154 myAttempts = atoi( cenv );
155 // try to get delay between attempts from environment variable
156 if ( ( cenv = getenv( "CSF_DelayServerRequest" ) ) && atoi( cenv ) > 0 )
157 myDelay = atoi( cenv );
159 // parse command line check if it is necessary to wait SALOME containers
160 QStringList args = QApplication::arguments();
161 for ( int i = 1; i < args.count(); i++ ) {
162 myCheckCppContainer = myCheckCppContainer || args[i] == "CPP";
163 myCheckPyContainer = myCheckPyContainer || args[i] == "PY";
164 myCheckSVContainer = myCheckSVContainer || args[i] == "SUPERV";
174 template<class MY_NS>
175 Session_ServerCheck<MY_NS>::~Session_ServerCheck()
178 while( isRunning() );
182 \brief Get current information message.
183 \return current message
185 template<class MY_NS>
186 QString Session_ServerCheck<MY_NS>::currentMessage()
188 static QStringList messages;
189 if ( messages.isEmpty() ) {
190 messages << tr( "Waiting for naming service..." );
191 messages << tr( "Waiting for registry server..." );
192 messages << tr( "Waiting for study server..." );
193 messages << tr( "Waiting for module catalogue server..." );
194 messages << tr( "Waiting for session server..." );
195 messages << tr( "Waiting for C++ container..." );
196 messages << tr( "Waiting for Python container..." );
197 messages << tr( "Waiting for Supervision container..." );
199 QMutexLocker locker( &myDataMutex );
201 int idx = myCurrentStep / myAttempts;
202 if ( idx >= 0 && idx < messages.count() )
203 msg = messages[ idx ];
208 \brief Get error message.
209 \return error message or null string of there was no any error
211 template<class MY_NS>
212 QString Session_ServerCheck<MY_NS>::error()
214 QMutexLocker locker( &myDataMutex );
219 \brief Get current step.
222 template<class MY_NS>
223 int Session_ServerCheck<MY_NS>::currentStep()
225 QMutexLocker locker( &myDataMutex );
226 return myCurrentStep;
230 \brief Get total number of check steps.
231 \return total number of steps
233 template<class MY_NS>
234 int Session_ServerCheck<MY_NS>::totalSteps()
236 QMutexLocker locker( &myDataMutex );
237 int cnt = 5; // base servers
238 if ( myCheckCppContainer ) cnt++; // + C++ container
239 if ( myCheckPyContainer ) cnt++; // + Python container
240 if ( myCheckSVContainer ) cnt++; // + supervision container
241 return cnt * myAttempts;
245 \brief Modify current step.
246 \param step new current step value
248 template<class MY_NS>
249 void Session_ServerCheck<MY_NS>::setStep( const int step )
251 QMutexLocker locker( &myDataMutex );
252 myCurrentStep = step;
256 \brief Set error message.
257 \param msg error message
259 template<class MY_NS>
260 void Session_ServerCheck<MY_NS>::setError( const QString& msg )
262 QMutexLocker locker( &myDataMutex );
267 \brief Thread loop function. Performs SALOME servers check.
269 template<class MY_NS>
270 void Session_ServerCheck<MY_NS>::run()
272 // start check servers
275 Qtx::CmdLineArgs args;
277 // 1. Check naming service
278 for ( int i = 0; i < myAttempts; i++ ) {
279 Locker locker( this );
281 setStep( current * myAttempts + i );
284 bool forceOK = false;
285 CosNaming::NamingContext_var _root_context = MY_NS::checkTrueNamingServiceIfExpected(args.argc(), args.argv(),forceOK);
286 if ( forceOK || !CORBA::is_nil( _root_context ) ) {
287 setStep( ++current * myAttempts );
291 catch( CORBA::COMM_FAILURE& ) {
292 MESSAGE( "CORBA::COMM_FAILURE: unable to contact the naming service" );
295 MESSAGE( "Unknown Exception: unable to contact the naming service" );
298 if ( i == myAttempts-1 ) {
299 setError( tr( "Unable to contact the naming service." ) + "\n" );
304 QString errfmt = "\n%1";
306 // 2. Check registry server
307 for ( int i = 0; i < myAttempts ; i++ ) {
308 Locker locker( this );
310 setStep( current * myAttempts + i );
313 CORBA::Object_var obj = MY_NS::forServerChecker("/Registry", args.argc(), args.argv());
314 Registry::Components_var registry = Registry::Components::_narrow( obj );
315 if ( !CORBA::is_nil( registry ) ) {
316 MESSAGE( "/Registry is found" );
318 MESSAGE( "Registry was activated" );
319 setStep( ++current * myAttempts );
323 catch ( ServiceUnreachable& ) {
324 MESSAGE( "Caught exception: Naming Service unreachable." );
325 error = "Naming service unreachable";
327 catch ( CORBA::COMM_FAILURE& ) {
328 MESSAGE( "Caught CORBA::SystemException CommFailure." );
329 error = "Caught CORBA::SystemException CommFailure.";
331 catch ( CORBA::SystemException& ) {
332 MESSAGE( "Caught CORBA::SystemException." );
333 error = "Caught CORBA::SystemException.";
335 catch ( CORBA::Exception& ) {
336 MESSAGE( "Caught CORBA::Exception." );
337 error = "Caught CORBA::Exception.";
340 MESSAGE( "Caught unknown exception." );
341 error = "Caught unknown exception.";
344 if ( i == myAttempts-1 ) {
345 setError( tr( "Registry server is not found." ) + errfmt.arg( error ) );
350 // 3. Check data server
351 for ( int i = 0; i < myAttempts ; i++ ) {
352 Locker locker( this );
354 setStep( current * myAttempts + i );
357 CORBA::Object_var obj = MY_NS::forServerChecker("/Study", args.argc(), args.argv());
358 SALOMEDS::Study_var study = SALOMEDS::Study::_narrow( obj );
359 if ( !CORBA::is_nil( study ) ) {
360 MESSAGE( "/Study is found" );
362 MESSAGE( "Study was activated" );
363 setStep( ++current * myAttempts );
367 catch ( ServiceUnreachable& ) {
368 MESSAGE( "Caught exception: Naming Service unreachable." );
369 error = "Naming service unreachable";
371 catch ( CORBA::COMM_FAILURE& ) {
372 MESSAGE( "Caught CORBA::SystemException CommFailure." );
373 error = "Caught CORBA::SystemException CommFailure.";
375 catch ( CORBA::SystemException& ) {
376 MESSAGE( "Caught CORBA::SystemException." );
377 error = "Caught CORBA::SystemException.";
379 catch ( CORBA::Exception& ) {
380 MESSAGE( "Caught CORBA::Exception." );
381 error = "Caught CORBA::Exception.";
384 MESSAGE( "Caught unknown exception." );
385 error = "Caught unknown exception.";
388 if ( i == myAttempts-1 ) {
389 setError( tr( "Study server is not found." ) + errfmt.arg( error ) );
394 // 4. Check module catalogue server
395 for ( int i = 0; i < myAttempts ; i++ ) {
396 Locker locker( this );
398 setStep( current * myAttempts + i );
401 CORBA::Object_var obj = MY_NS::forServerChecker("/Kernel/ModulCatalog", args.argc(), args.argv());
402 SALOME_ModuleCatalog::ModuleCatalog_var catalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow( obj );
403 if ( !CORBA::is_nil( catalog ) ){
404 MESSAGE( "/Kernel/ModulCatalog is found" );
406 MESSAGE( "ModuleCatalog was activated" );
407 setStep( ++current * myAttempts );
411 catch ( ServiceUnreachable& ) {
412 MESSAGE( "Caught exception: Naming Service unreachable." );
413 error = "Naming service unreachable";
415 catch ( CORBA::COMM_FAILURE& ) {
416 MESSAGE( "Caught CORBA::SystemException CommFailure." );
417 error = "Caught CORBA::SystemException CommFailure.";
419 catch ( CORBA::SystemException& ) {
420 MESSAGE( "Caught CORBA::SystemException." );
421 error = "Caught CORBA::SystemException.";
423 catch ( CORBA::Exception& ) {
424 MESSAGE( "Caught CORBA::Exception." );
425 error = "Caught CORBA::Exception.";
428 MESSAGE( "Caught unknown exception." );
429 error = "Caught unknown exception.";
432 if ( i == myAttempts-1 ) {
433 setError( tr( "Module catalogue server is not found." ) + errfmt.arg( error ) );
438 // 5. Check data server
439 for ( int i = 0; i < myAttempts ; i++ ) {
440 Locker locker( this );
442 setStep( current * myAttempts + i );
445 CORBA::Object_var obj = MY_NS::forServerChecker("/Kernel/Session", args.argc(), args.argv());
446 SALOME::Session_var session = SALOME::Session::_narrow( obj );
447 if ( !CORBA::is_nil( session ) ) {
448 MESSAGE( "/Kernel/Session is found" );
450 MESSAGE( "SALOME_Session was activated" );
451 setStep( ++current * myAttempts );
455 catch ( ServiceUnreachable& ) {
456 MESSAGE( "Caught exception: Naming Service unreachable." );
457 error = "Naming service unreachable";
459 catch ( CORBA::COMM_FAILURE& ) {
460 MESSAGE( "Caught CORBA::SystemException CommFailure." );
461 error = "Caught CORBA::SystemException CommFailure.";
463 catch ( CORBA::SystemException& ) {
464 MESSAGE( "Caught CORBA::SystemException." );
465 error = "Caught CORBA::SystemException.";
467 catch ( CORBA::Exception& ) {
468 MESSAGE( "Caught CORBA::Exception." );
469 error = "Caught CORBA::Exception.";
472 MESSAGE( "Caught unknown exception." );
473 error = "Caught unknown exception.";
476 if ( i == myAttempts-1 ) {
477 setError( tr( "Session server is not found." ) + errfmt.arg( error ) );
482 // 6. Check C++ container
483 if ( myCheckCppContainer ) {
484 for ( int i = 0; i < myAttempts ; i++ ) {
485 Locker locker( this );
487 setStep( current * myAttempts + i );
490 QString containerName = QString( "/Containers/%1/FactoryServer" ).arg( Kernel_Utils::GetHostname().c_str() );
491 CORBA::Object_var obj = MY_NS::forServerChecker(containerName.toLatin1(), args.argc(), args.argv());
492 Engines::Container_var FScontainer = Engines::Container::_narrow( obj );
493 if ( !CORBA::is_nil( FScontainer ) ) {
494 MESSAGE( containerName.toLatin1().constData() << " is found" );
496 MESSAGE( "FactoryServer container was activated" );
497 setStep( ++current * myAttempts );
501 catch ( ServiceUnreachable& ) {
502 MESSAGE( "Caught exception: Naming Service unreachable." );
503 error = "Naming service unreachable";
505 catch ( CORBA::COMM_FAILURE& ) {
506 MESSAGE( "Caught CORBA::SystemException CommFailure." );
507 error = "Caught CORBA::SystemException CommFailure.";
509 catch ( CORBA::SystemException& ) {
510 MESSAGE( "Caught CORBA::SystemException." );
511 error = "Caught CORBA::SystemException.";
513 catch ( CORBA::Exception& ) {
514 MESSAGE( "Caught CORBA::Exception." );
515 error = "Caught CORBA::Exception.";
518 MESSAGE( "Caught unknown exception." );
519 error = "Caught unknown exception.";
522 if ( i == myAttempts-1 ) {
523 setError( tr( "C++ container is not found." ) + errfmt.arg( error ) );
529 // 7. Check Python container
530 if ( myCheckPyContainer ) {
531 for ( int i = 0; i < myAttempts ; i++ ) {
532 Locker locker( this );
534 setStep( current * myAttempts + i );
537 QString containerName = QString( "/Containers/%1/FactoryServerPy" ).arg( Kernel_Utils::GetHostname().c_str() );
538 CORBA::Object_var obj = MY_NS::forServerChecker(containerName.toLatin1(), args.argc(), args.argv());
539 Engines::Container_var FSPcontainer = Engines::Container::_narrow( obj );
540 if ( !CORBA::is_nil( FSPcontainer ) ) {
541 MESSAGE( containerName.toLatin1().constData() << " is found" );
542 FSPcontainer->ping();
543 MESSAGE("FactoryServerPy container was activated");
544 setStep( ++current * myAttempts );
548 catch ( ServiceUnreachable& ) {
549 MESSAGE( "Caught exception: Naming Service unreachable." );
550 error = "Naming service unreachable";
552 catch ( CORBA::COMM_FAILURE& ) {
553 MESSAGE( "Caught CORBA::SystemException CommFailure." );
554 error = "Caught CORBA::SystemException CommFailure.";
556 catch ( CORBA::SystemException& ) {
557 MESSAGE( "Caught CORBA::SystemException." );
558 error = "Caught CORBA::SystemException.";
560 catch ( CORBA::Exception& ) {
561 MESSAGE( "Caught CORBA::Exception." );
562 error = "Caught CORBA::Exception.";
565 MESSAGE( "Caught unknown exception." );
566 error = "Caught unknown exception.";
569 if ( i == myAttempts-1 ) {
570 setError( tr( "Python container is not found." ) + errfmt.arg( error ) );
576 // 8. Check supervision container
577 if ( myCheckSVContainer ) {
578 for ( int i = 0; i < myAttempts ; i++ ) {
579 Locker locker( this );
581 setStep( current * myAttempts + i );
584 QString containerName = QString( "/Containers/%1/SuperVisionContainer" ).arg( Kernel_Utils::GetHostname().c_str() );
585 CORBA::Object_var obj = MY_NS::forServerChecker(containerName.toLatin1(), args.argc(), args.argv());
586 Engines::Container_var SVcontainer = Engines::Container::_narrow( obj );
587 if ( !CORBA::is_nil( SVcontainer ) ) {
588 MESSAGE( containerName.toLatin1().constData() << " is found" );
590 MESSAGE("SuperVisionContainer container was activated");
591 setStep( ++current * myAttempts );
595 catch ( ServiceUnreachable& ) {
596 MESSAGE( "Caught exception: Naming Service unreachable." );
597 error = "Naming service unreachable";
599 catch ( CORBA::COMM_FAILURE& ) {
600 MESSAGE( "Caught CORBA::SystemException CommFailure." );
601 error = "Caught CORBA::SystemException CommFailure.";
603 catch ( CORBA::SystemException& ) {
604 MESSAGE( "Caught CORBA::SystemException." );
605 error = "Caught CORBA::SystemException.";
607 catch ( CORBA::Exception& ) {
608 MESSAGE( "Caught CORBA::Exception." );
609 error = "Caught CORBA::Exception.";
612 MESSAGE( "Caught unknown exception." );
613 error = "Caught unknown exception.";
616 if ( i == myAttempts-1 ) {
617 setError( tr( "Supervision container is not found." ) + errfmt.arg( error ) );
624 #include "Session_NS_wrapper.hxx"
626 template class Session_ServerCheck<OldStyleNS>;
627 template class Session_ServerCheck<NewStyleNS>;