ServerApp.cc

Go to the documentation of this file.
00001 // ServerApp.cc
00002 
00003 // This file is part of bes, A C++ back-end server implementation framework
00004 // for the OPeNDAP Data Access Protocol.
00005 
00006 // Copyright (c) 2004,2005 University Corporation for Atmospheric Research
00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 // 
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact University Corporation for Atmospheric Research at
00024 // 3080 Center Green Drive, Boulder, CO 80301
00025  
00026 // (c) COPYRIGHT University Corporation for Atmostpheric Research 2004-2005
00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
00028 //
00029 // Authors:
00030 //      pwest       Patrick West <pwest@ucar.edu>
00031 //      jgarcia     Jose Garcia <jgarcia@ucar.edu>
00032 
00033 #include <signal.h>
00034 #include <unistd.h>
00035 
00036 #include <iostream>
00037 #include <fstream>
00038 
00039 using std::cout ;
00040 using std::cerr ;
00041 using std::endl ;
00042 using std::ofstream ;
00043 
00044 #include "config.h"
00045 
00046 #include "ServerApp.h"
00047 #include "ServerExitConditions.h"
00048 #include "TheBESKeys.h"
00049 #include "SocketListener.h"
00050 #include "TcpSocket.h"
00051 #include "UnixSocket.h"
00052 #include "BESServerHandler.h"
00053 #include "BESException.h"
00054 #include "PPTException.h"
00055 #include "PPTServer.h"
00056 #include "PPTException.h"
00057 #include "SocketException.h"
00058 #include "BESMemoryManager.h"
00059 #include "BESDebug.h"
00060 #include "BESServerUtils.h"
00061 
00062 #include "BESDefaultModule.h"
00063 #include "BESDefaultCommands.h"
00064 
00065 ServerApp::ServerApp()
00066     : BESModuleApp(),
00067       _portVal( 0 ),
00068       _gotPort( false ),
00069       _unixSocket( "" ),
00070       _secure( false ),
00071       _mypid( 0 ),
00072       _ts( 0 ),
00073       _us( 0 ),
00074       _ps( 0 )
00075 {
00076     _mypid = getpid() ;
00077 }
00078 
00079 ServerApp::~ServerApp()
00080 {
00081 }
00082 
00083 void
00084 ServerApp::signalTerminate( int sig )
00085 {
00086     if( sig == SIGTERM )
00087     {
00088         BESApp::TheApplication()->terminate( sig ) ;
00089         exit( SERVER_EXIT_NORMAL_SHUTDOWN ) ;
00090     }
00091 }
00092 
00093 void
00094 ServerApp::signalInterrupt( int sig )
00095 {
00096     if( sig == SIGINT )
00097     {
00098         BESApp::TheApplication()->terminate( sig ) ;
00099         exit( SERVER_EXIT_NORMAL_SHUTDOWN ) ;
00100     }
00101 }
00102 
00103 void
00104 ServerApp::signalRestart( int sig )
00105 {
00106     if( sig == SIGUSR1 )
00107     {
00108         BESApp::TheApplication()->terminate( sig ) ;
00109         exit( SERVER_EXIT_RESTART ) ;
00110     }
00111 }
00112 
00113 int
00114 ServerApp::initialize( int argc, char **argv )
00115 {
00116     int c = 0 ;
00117 
00118     // If you change the getopt statement below, be sure to make the
00119     // corresponding change in daemon.cc
00120     while( ( c = getopt( argc, argv, "hvsd:c:p:u:" ) ) != EOF )
00121     {
00122         switch( c )
00123         {
00124             case 'c':
00125                 TheBESKeys::ConfigFile = optarg ;
00126                 break ;
00127             case 'p':
00128                 _portVal = atoi( optarg ) ;
00129                 _gotPort = true ;
00130                 break ;
00131             case 'u':
00132                 _unixSocket = optarg ;
00133                 break ;
00134             case 'd':
00135                 {
00136                     string dbgstrm = optarg ;
00137                     if( dbgstrm[0] == '-' )
00138                     {
00139                         cout << "Debug filename or stream can not start "
00140                              << "with a -" << endl << endl ;
00141                         BESServerUtils::show_usage( BESApp::TheApplication()->appName() ) ;
00142                     }
00143                     if( dbgstrm == "cerr" )
00144                     {
00145                         BESDebug::Set_debugger( new BESDebug( &cerr ) ) ;
00146                     }
00147                     else
00148                     {
00149                         ostream *fstrm = new ofstream( dbgstrm.c_str() ) ;
00150                         if( !(*fstrm) )
00151                         {
00152                             cerr << "Unable to open debug file" << endl ;
00153                             BESServerUtils::show_usage( BESApp::TheApplication()->appName() ) ;
00154                         }
00155                         BESDebug::Set_debugger( new BESDebug( fstrm ) ) ;
00156                     }
00157                     BESDebug::Begin_debug() ;
00158                 }
00159                 break ;
00160             case 'v':
00161                 BESServerUtils::show_version( BESApp::TheApplication()->appName() ) ;
00162                 break ;
00163             case 's':
00164                 _secure = true ;
00165                 break ;
00166             case 'h':
00167             case '?':
00168             default:
00169                 BESServerUtils::show_usage( BESApp::TheApplication()->appName() ) ;
00170                 break ;
00171         }
00172     }
00173 
00174     bool found = false ;
00175     string port_key = "BES.ServerPort" ;
00176     if( !_gotPort )
00177     {
00178         string sPort = TheBESKeys::TheKeys()->get_key( port_key, found ) ;
00179         if( found )
00180         {
00181             _portVal = atoi( sPort.c_str() ) ;
00182             if( _portVal != 0 )
00183             {
00184                 _gotPort = true ;
00185             }
00186         }
00187     }
00188 
00189     found = false ;
00190     string socket_key = "BES.ServerUnixSocket" ;
00191     if( _unixSocket == "" )
00192     {
00193         _unixSocket = TheBESKeys::TheKeys()->get_key( socket_key, found ) ;
00194     }
00195 
00196     if( !_gotPort && _unixSocket == "" )
00197     {
00198         cout << endl << "Must specify either a tcp port"
00199              << " or a unix socket or both" << endl ;
00200         cout << "Please specify on the command line with"
00201              << " -p <port> -u <unix_socket> "
00202              << endl
00203              << "Or specify in the bes configuration file with "
00204              << port_key << " and/or " << socket_key
00205              << endl << endl ;
00206         BESServerUtils::show_usage( BESApp::TheApplication()->appName() ) ;
00207     }
00208 
00209     found = false ;
00210     if( _secure == false )
00211     {
00212         string key = "BES.ServerSecure" ;
00213         string isSecure = TheBESKeys::TheKeys()->get_key( key, found ) ;
00214         if( isSecure == "Yes" || isSecure == "YES" || isSecure == "yes" )
00215         {
00216             _secure = true ;
00217         }
00218     }
00219 
00220     BESDEBUG( "ServerApp: Registering signal SIGTERM ... " )
00221     if( signal( SIGTERM, signalTerminate ) == SIG_ERR )
00222     {
00223         BESDEBUG( "FAILED" << endl ) ;
00224         cerr << "FAILED: Can not register SIGTERM signal handler" << endl ;
00225         exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00226     }
00227     BESDEBUG( "OK" << endl ) ;
00228 
00229     BESDEBUG( "ServerApp: Registering signal SIGINT ... " )
00230     if( signal( SIGINT, signalInterrupt ) == SIG_ERR )
00231     {
00232         BESDEBUG( "FAILED" << endl ) ;
00233         cerr << "FAILED: Can not register SIGINT signal handler" << endl ;
00234         exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00235     }
00236     BESDEBUG( "OK" << endl ) ;
00237 
00238     BESDEBUG( "ServerApp: Registering signal SIGUSR1 ... " )
00239     if( signal( SIGUSR1, signalRestart ) == SIG_ERR )
00240     {
00241         BESDEBUG( "FAILED" << endl ) ;
00242         cerr << "FAILED: Can not register SIGUSR1 signal handler" << endl ;
00243         exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00244     }
00245     BESDEBUG( "OK" << endl ) ;
00246 
00247     BESDEBUG( "ServerApp: initializing default module ... " )
00248     BESDefaultModule::initialize( argc, argv ) ;
00249     BESDEBUG( "OK" << endl ) ;
00250 
00251     BESDEBUG( "ServerApp: initializing default commands ... " )
00252     BESDefaultCommands::initialize( argc, argv ) ;
00253     BESDEBUG( "OK" << endl ) ;
00254 
00255     int ret = BESModuleApp::initialize( argc, argv ) ;
00256 
00257     BESDEBUG( "ServerApp: initialized settings:" << *this ) ;
00258 
00259     return ret ;
00260 }
00261 
00262 int
00263 ServerApp::run()
00264 {
00265     try
00266     {
00267         BESDEBUG( "ServerApp: initializing memory pool ... " )
00268         BESMemoryManager::initialize_memory_pool() ;
00269         BESDEBUG( "OK" << endl ) ;
00270 
00271         SocketListener listener ;
00272 
00273         if( _portVal )
00274         {
00275             _ts = new TcpSocket( _portVal ) ;
00276             listener.listen( _ts ) ;
00277             BESDEBUG( "ServerApp: listening on port (" << _portVal << ")" << endl )
00278         }
00279 
00280         if( !_unixSocket.empty() )
00281         {
00282             _us = new UnixSocket( _unixSocket ) ;
00283             listener.listen( _us ) ;
00284             BESDEBUG( "ServerApp: listening on unix socket (" << _unixSocket << ")" << endl )
00285         }
00286 
00287         BESServerHandler handler ;
00288 
00289         _ps = new PPTServer( &handler, &listener, _secure ) ;
00290         _ps->initConnection() ;
00291     }
00292     catch( SocketException &se )
00293     {
00294         cerr << "caught SocketException" << endl ;
00295         cerr << se.getMessage() << endl ;
00296         return 1 ;
00297     }
00298     catch( PPTException &pe )
00299     {
00300         cerr << "caught PPTException" << endl ;
00301         cerr << pe.getMessage() << endl ;
00302         return 1 ;
00303     }
00304     catch( ... )
00305     {
00306         cerr << "caught unknown exception" << endl ;
00307         return 1 ;
00308     }
00309 
00310     return 0 ;
00311 }
00312 
00313 int
00314 ServerApp::terminate( int sig )
00315 {
00316     pid_t apppid = getpid() ;
00317     if( apppid == _mypid )
00318     {
00319         if( _ps )
00320         {
00321             _ps->closeConnection() ;
00322             delete _ps ;
00323         }
00324         if( _ts )
00325         {
00326             _ts->close() ;
00327             delete _ts ;
00328         }
00329         if( _us )
00330         {
00331             _us->close() ;
00332             delete _us ;
00333         }
00334 
00335         BESDEBUG( "ServerApp: terminating default module ... " )
00336         BESDefaultModule::terminate( ) ;
00337         BESDEBUG( "OK" << endl ) ;
00338 
00339         BESDEBUG( "ServerApp: terminating default commands ... " )
00340         BESDefaultCommands::terminate( ) ;
00341         BESDEBUG( "OK" << endl ) ;
00342 
00343         BESModuleApp::terminate( sig ) ;
00344     }
00345     return sig ;
00346 }
00347 
00354 void
00355 ServerApp::dump( ostream &strm ) const
00356 {
00357     strm << BESIndent::LMarg << "ServerApp::dump - ("
00358                              << (void *)this << ")" << endl ;
00359     BESIndent::Indent() ;
00360     strm << BESIndent::LMarg << "got port? " << _gotPort << endl ;
00361     strm << BESIndent::LMarg << "port: " << _portVal << endl ;
00362     strm << BESIndent::LMarg << "unix socket: " << _unixSocket << endl ;
00363     strm << BESIndent::LMarg << "is secure? " << _secure << endl ;
00364     strm << BESIndent::LMarg << "pid: " << _mypid << endl ;
00365     if( _ts )
00366     {
00367         strm << BESIndent::LMarg << "tcp socket:" << endl ;
00368         BESIndent::Indent() ;
00369         _ts->dump( strm ) ;
00370         BESIndent::UnIndent() ;
00371     }
00372     else
00373     {
00374         strm << BESIndent::LMarg << "tcp socket: null" << endl ;
00375     }
00376     if( _us )
00377     {
00378         strm << BESIndent::LMarg << "unix socket:" << endl ;
00379         BESIndent::Indent() ;
00380         _us->dump( strm ) ;
00381         BESIndent::UnIndent() ;
00382     }
00383     else
00384     {
00385         strm << BESIndent::LMarg << "unix socket: null" << endl ;
00386     }
00387     if( _ps )
00388     {
00389         strm << BESIndent::LMarg << "ppt server:" << endl ;
00390         BESIndent::Indent() ;
00391         _ps->dump( strm ) ;
00392         BESIndent::UnIndent() ;
00393     }
00394     else
00395     {
00396         strm << BESIndent::LMarg << "ppt server: null" << endl ;
00397     }
00398     BESModuleApp::dump( strm ) ;
00399     BESIndent::UnIndent() ;
00400 }
00401 
00402 int
00403 main( int argc, char **argv )
00404 {
00405     try
00406     {
00407         ServerApp app ;
00408         return app.main( argc, argv ) ;
00409     }
00410     catch( BESException &e )
00411     {
00412         cerr << "Caught unhandled exception: " << endl ;
00413         cerr << e.get_message() << endl ;
00414         return 1 ;
00415     }
00416     catch( ... )
00417     {
00418         cerr << "Caught unhandled, unknown exception" << endl ;
00419         return 1 ;
00420     }
00421     return 0 ;
00422 }
00423 

Generated on Wed Aug 29 03:20:59 2007 for OPeNDAP Back End Server (BES) by  doxygen 1.5.2