BESServerHandler.cc

Go to the documentation of this file.
00001 // BESServerHandler.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 <unistd.h>
00034 #include <sys/types.h>
00035 #include <signal.h>
00036 #include <sys/wait.h>
00037 #include <errno.h>
00038 
00039 #include <sstream>
00040 #include <iostream>
00041 
00042 using std::ostringstream ;
00043 using std::cout ;
00044 using std::endl ;
00045 using std::cerr ;
00046 
00047 #include "BESServerHandler.h"
00048 #include "Connection.h"
00049 #include "Socket.h"
00050 #include "BESCmdInterface.h"
00051 #include "TheBESKeys.h"
00052 #include "BESException.h"
00053 #include "ServerExitConditions.h"
00054 #include "BESStatusReturn.h"
00055 #include "BESUtil.h"
00056 
00057 BESServerHandler::BESServerHandler()
00058 {
00059     bool found = false ;
00060     _method = TheBESKeys::TheKeys()->get_key( "BES.ProcessManagerMethod", found ) ;
00061     if( _method != "multiple" && _method != "single" )
00062     {
00063         cerr << "Unable to determine method to handle clients, "
00064              << "single or multiple as defined by BES.ProcessManagerMethod"
00065              << endl ;
00066         exit( SERVER_EXIT_FATAL_CAN_NOT_START ) ;
00067     }
00068 }
00069 
00070 // *** I'm not sure that we need to fork twice. jhrg 11/14/05
00071 // The reason that we fork twice is explained in Advanced Programming in the
00072 // Unit Environment by W. Richard Stevens. In the 'multiple' case we don't
00073 // want to leave any zombie processes.
00074 void
00075 BESServerHandler::handle( Connection *c )
00076 {
00077     if(_method=="single")
00078     {
00079         execute( c ) ;
00080     }
00081     else
00082     {
00083         int main_process = getpid() ;
00084         pid_t pid ;
00085         if( ( pid = fork() ) < 0 )
00086         {
00087             string error( "fork error" ) ;
00088             const char* error_info = strerror( errno ) ;
00089             if( error_info )
00090                 error += " " + (string)error_info ;
00091             throw BESException( error, __FILE__, __LINE__ ) ;
00092         }
00093         else if( pid == 0 ) /* child process */
00094         {
00095             pid_t pid1 ;
00096             // we fork twice so we do not have zombie children
00097             if( ( pid1 = fork() ) < 0 )
00098             {
00099                 // we must send a signal of inmediate termination to the
00100                 // main server 
00101                 kill( main_process, 9 ) ;
00102                 perror( "fork error" ) ;
00103                 exit( SERVER_EXIT_CHILD_SUBPROCESS_ABNORMAL_TERMINATION ) ;
00104             } 
00105             else if( pid1 == 0 ) /* child of the child */
00106             {
00107                 execute( c ) ;
00108             }
00109             sleep( 1 ) ;
00110             c->closeConnection() ;
00111             exit( SERVER_EXIT_CHILD_SUBPROCESS_NORMAL_TERMINATION ) ;
00112         }
00113         if( waitpid( pid, NULL, 0 ) != pid )
00114         {
00115             string error( "waitpid error" ) ;
00116             const char *error_info = strerror( errno ) ;
00117             if( error_info )
00118                 error += " " + (string)error_info ;
00119             throw BESException( error, __FILE__, __LINE__ ) ;
00120         } 
00121         c->closeConnection() ;
00122     }
00123 }
00124 
00125 void
00126 BESServerHandler::execute( Connection *c )
00127 {
00128     for(;;)
00129     {
00130         ostringstream ss ;
00131 
00132         bool isDone = c->receive( &ss ) ;
00133 
00134         if( isDone )
00135         {
00136             c->closeConnection() ;
00137             exit( CHILD_SUBPROCESS_READY ) ;
00138         }
00139 
00140         int holder = dup( STDOUT_FILENO ) ;
00141         dup2( c->getSocket()->getSocketDescriptor(), STDOUT_FILENO ) ;
00142         
00143         BESCmdInterface cmd( BESUtil::www2id( ss.str(), "%", "%20" ) ) ;
00144         int status = cmd.execute_request() ;
00145 
00146         fflush( stdout ) ;
00147         dup2( holder, STDOUT_FILENO ) ;
00148         close( holder ) ;
00149 
00150         if( status == BES_EXECUTED_OK )
00151         {
00152             c->send( "" ) ;
00153         }
00154         else
00155         {
00156             switch (status)
00157             {
00158                 case BES_TERMINATE_IMMEDIATE:
00159                     {
00160                         cout << "BES server " << getpid()
00161                              << ": Status not OK, dispatcher returned value "
00162                              << status << endl ;
00163                         //string toSend = "FATAL ERROR: server must exit!" ;
00164                         //c->send( toSend ) ;
00165                         c->send( "" ) ;
00166                         c->sendExit() ;
00167                         c->closeConnection() ;
00168                         exit( CHILD_SUBPROCESS_READY ) ;
00169                     }
00170                     break;
00171                 case BES_DATA_HANDLER_FAILURE:
00172                     {
00173                         cout << "BES server " << getpid()
00174                              << ": Status not OK, dispatcher returned value "
00175                              << status << endl ;
00176                         //string toSend = "Data Handler Error: server my exit!" ;
00177                         //c->send( toSend ) ;
00178                         c->send( "" ) ;
00179                         c->sendExit() ;
00180                         c->closeConnection() ;
00181                         exit( CHILD_SUBPROCESS_READY ) ;
00182                     }
00183                     break;
00184                 case BES_REQUEST_INCORRECT: 
00185                 case BES_MEMORY_EXCEPTION:
00186                 case BES_CONTAINER_PERSISTENCE_ERROR:
00187                 case BES_INITIALIZATION_FILE_PROBLEM:
00188                 case BES_LOG_FILE_PROBLEM:
00189                 case BES_AGGREGATION_EXCEPTION:
00190                 case BES_FAILED_TO_EXECUTE_COMMIT_COMMAND:
00191                 default:
00192                     {
00193                         c->send( "" ) ;
00194                     }
00195                     break;
00196             }
00197         }
00198     }
00199 }
00200 
00207 void
00208 BESServerHandler::dump( ostream &strm ) const
00209 {
00210     strm << BESIndent::LMarg << "BESServerHandler::dump - ("
00211                              << (void *)this << ")" << endl ;
00212     BESIndent::Indent() ;
00213     strm << BESIndent::LMarg << "server method: " << _method << endl ;
00214     BESIndent::UnIndent() ;
00215 }
00216 

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