BESInterface.cc

Go to the documentation of this file.
00001 // BESInterface.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-2009 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 Atmospheric 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 "config.h"
00034 
00035 #include <string>
00036 #include <sstream>
00037 #include <iostream>
00038 
00039 #if HAVE_UNISTD_H
00040 #include <unistd.h>
00041 #endif
00042 
00043 using std::string;
00044 using std::ostringstream;
00045 using std::bad_alloc;
00046 using std::cout;
00047 
00048 #include "BESInterface.h"
00049 
00050 #include "TheBESKeys.h"
00051 #include "BESResponseHandler.h"
00052 #include "BESAggFactory.h"
00053 #include "BESAggregationServer.h"
00054 #include "BESReporterList.h"
00055 
00056 #include "BESExceptionManager.h"
00057 
00058 #include "BESDataNames.h"
00059 
00060 #include "BESDebug.h"
00061 #include "BESInternalError.h"
00062 #include "BESInternalFatalError.h"
00063 
00064 #include "BESLog.h"
00065 
00066 list < p_bes_init > BESInterface::_init_list;
00067 list < p_bes_end > BESInterface::_end_list;
00068 
00069 BESInterface::BESInterface( ostream *output_stream )
00070     : _strm( output_stream ),
00071       _transmitter( 0 )
00072 {
00073     if( !output_stream )
00074     {
00075         string err = "output stream must be set in order to output responses" ;
00076         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00077     }
00078 }
00079 
00080 BESInterface::~BESInterface()
00081 {
00082 }
00083 
00116 int
00117 BESInterface::execute_request( const string &from )
00118 {
00119     if( !_dhi )
00120     {
00121         string err = "DataHandlerInterface can not be null" ;
00122         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00123     }
00124     _dhi->set_output_stream( _strm ) ;
00125     _dhi->data[REQUEST_FROM] = from ;
00126 
00127     pid_t thepid = getpid() ;
00128     ostringstream ss ;
00129     ss << thepid ;
00130     _dhi->data[SERVER_PID] = ss.str() ;
00131 
00132     int status = 0;
00133 
00134     // We split up the calls for the reason that if we catch an
00135     // exception during the initialization, building, execution, or response
00136     // transmit of the request then we can transmit the exception/error
00137     // information.
00138     try {
00139         initialize();
00140 
00141         *(BESLog::TheLog()) << _dhi->data[SERVER_PID]
00142                             << " from " << _dhi->data[REQUEST_FROM]
00143                             << " request received" << endl ;
00144 
00145         validate_data_request();
00146         build_data_request_plan() ;
00147         execute_data_request_plan();
00148         /* These two functions are now being called inside
00149          * execute_data_request_plan as they are really a part of executing
00150          * the request and not separate.
00151         invoke_aggregation();
00152         transmit_data();
00153         */
00154         _dhi->executed = true ;
00155     }
00156     catch( BESError & ex )
00157     {
00158         return exception_manager( ex ) ;
00159     }
00160     catch( bad_alloc & )
00161     {
00162         string serr = "BES out of memory" ;
00163         BESInternalFatalError ex( serr, __FILE__, __LINE__ ) ;
00164         return exception_manager( ex ) ;
00165     }
00166     catch(...) {
00167         string serr = "An undefined exception has been thrown" ;
00168         BESInternalError ex( serr, __FILE__, __LINE__ ) ;
00169         return exception_manager( ex ) ;
00170     }
00171 
00172     return finish( status ) ;
00173 }
00174 
00175 int
00176 BESInterface::finish( int status )
00177 {
00178     try
00179     {
00180         // if there was an error duriing initialization, validation,
00181         // execution or transmit of the response then we need to transmit
00182         // the error information. Once printed, delete the error
00183         // information since we are done with it.
00184         if( _dhi->error_info )
00185         {
00186             transmit_data();
00187             delete _dhi->error_info ;
00188             _dhi->error_info = 0 ;
00189         }
00190     }
00191     catch( BESError &ex )
00192     {
00193         status = exception_manager( ex ) ;
00194     }
00195     catch( bad_alloc & )
00196     {
00197         string serr = "BES out of memory" ;
00198         BESInternalFatalError ex( serr, __FILE__, __LINE__ ) ;
00199         status = exception_manager( ex ) ;
00200     }
00201     catch(...)
00202     {
00203         string serr = "An undefined exception has been thrown" ;
00204         BESInternalError ex( serr, __FILE__, __LINE__ ) ;
00205         status = exception_manager( ex ) ;
00206     }
00207 
00208     // If there is error information then the transmit of the error failed,
00209     // print it to standard out. Once printed, delete the error
00210     // information since we are done with it.
00211     if( _dhi->error_info )
00212     {
00213         _dhi->error_info->print( cout ) ;
00214         delete _dhi->error_info ;
00215         _dhi->error_info = 0 ;
00216     }
00217 
00218     // if there is a problem with the rest of these steps then all we will
00219     // do is log it to the BES log file and not handle the exception with
00220     // the exception manager.
00221     try
00222     {
00223         log_status();
00224     }
00225     catch( BESError &ex )
00226     {
00227         (*BESLog::TheLog()) << "Problem logging status: " << ex.get_message()
00228                             << endl ;
00229     }
00230     catch( ... )
00231     {
00232         (*BESLog::TheLog()) << "Unknown problem logging status" << endl ;
00233     }
00234 
00235     try
00236     {
00237         report_request();
00238     }
00239     catch( BESError &ex )
00240     {
00241         (*BESLog::TheLog()) << "Problem reporting request: " << ex.get_message()
00242                             << endl ;
00243     }
00244     catch( ... )
00245     {
00246         (*BESLog::TheLog()) << "Unknown problem reporting request" << endl ;
00247     }
00248 
00249     try
00250     {
00251         end_request();
00252     }
00253     catch( BESError &ex )
00254     {
00255         (*BESLog::TheLog()) << "Problem ending request: " << ex.get_message()
00256                             << endl ;
00257     }
00258     catch( ... )
00259     {
00260         (*BESLog::TheLog()) << "Unknown problem ending request" << endl ;
00261     }
00262 
00263     return status ;
00264 }
00265 
00266 int
00267 BESInterface::finish_with_error( int status )
00268 {
00269     if( !_dhi->error_info )
00270     {
00271         // there wasn't an error ... so now what?
00272         string serr = "Finish_with_error called with no error object" ;
00273         BESInternalError ex( serr, __FILE__, __LINE__ ) ;
00274         status = exception_manager( ex ) ;
00275     }
00276 
00277     return finish( status ) ;
00278 }
00279 
00280 void
00281 BESInterface::add_init_callback(p_bes_init init)
00282 {
00283     _init_list.push_back(init);
00284 }
00285 
00291 void
00292 BESInterface::initialize()
00293 {
00294     BESDEBUG("bes", "Initializing request: " << _dhi->data[DATA_REQUEST] << " ... " << endl ) ;
00295     bool do_continue = true;
00296     init_iter i = _init_list.begin();
00297     
00298     for( ; i != _init_list.end() && do_continue == true; i++ )
00299     {
00300         p_bes_init p = *i ;
00301         do_continue = p( *_dhi ) ;
00302     }
00303     
00304     if( !do_continue )
00305     {
00306         BESDEBUG("bes", "FAILED" << endl) ;
00307         string se = "Initialization callback failed, exiting";
00308         throw BESInternalError( se, __FILE__, __LINE__ ) ;
00309     }
00310     else
00311     {
00312         BESDEBUG("bes", "OK" << endl) ;
00313     }
00314 }
00315 
00318 void
00319 BESInterface::validate_data_request()
00320 {
00321 }
00322 
00336 void
00337 BESInterface::execute_data_request_plan()
00338 {
00339     BESDEBUG("bes", "Executing request: " << _dhi->data[DATA_REQUEST] << " ... " << endl ) ;
00340     BESResponseHandler *rh = _dhi->response_handler ;
00341     if( rh )
00342     {
00343         rh->execute( *_dhi ) ;
00344     }
00345     else
00346     {
00347         BESDEBUG("bes", "FAILED" << endl) ;
00348         string se = "The response handler \"" + _dhi->action
00349                     + "\" does not exist" ;
00350         throw BESInternalError( se, __FILE__, __LINE__ ) ;
00351     }
00352     BESDEBUG("bes", "OK" << endl) ;
00353 
00354     // Now we need to do the post processing piece of executing the request
00355     invoke_aggregation();
00356 
00357     // And finally, transmit the response of this request
00358     transmit_data();
00359 }
00360 
00363 void
00364 BESInterface::invoke_aggregation()
00365 {
00366     if( _dhi->data[AGG_CMD] != "" )
00367     {
00368         BESDEBUG("bes", "aggregating with: " << _dhi->data[AGG_CMD] << " ...  "<< endl ) ;
00369         BESAggregationServer *agg =
00370             BESAggFactory::TheFactory()->find_handler( _dhi->data[AGG_HANDLER] );
00371         if( agg )
00372         {
00373             agg->aggregate( *_dhi ) ;
00374         }
00375         else
00376         {
00377             BESDEBUG("bes", "FAILED" << endl) ;
00378             string se = "The aggregation handler " + _dhi->data[AGG_HANDLER]
00379                 + "does not exist" ;
00380             throw BESInternalError( se, __FILE__, __LINE__ ) ;
00381         }
00382         BESDEBUG("bes", "OK" << endl) ;
00383     }
00384 }
00385 
00399 void
00400 BESInterface::transmit_data()
00401 {
00402     BESDEBUG("bes", "Transmitting request: " << _dhi->data[DATA_REQUEST] << endl) ;
00403     if (_transmitter)
00404     {
00405         if( _dhi->error_info )
00406         {
00407             ostringstream strm ;
00408             _dhi->error_info->print( strm ) ;
00409             (*BESLog::TheLog()) << strm.str() << endl ;
00410             BESDEBUG( "bes", "  transmitting error info using transmitter ... "
00411                              << endl << strm.str() << endl ) ;
00412             _dhi->error_info->transmit( _transmitter, *_dhi ) ;
00413         }
00414         else if( _dhi->response_handler )
00415         {
00416             BESDEBUG( "bes", "  transmitting response using transmitter ...  " << endl ) ;
00417             _dhi->response_handler->transmit( _transmitter, *_dhi ) ;
00418         }
00419     }
00420     else
00421     {
00422         if( _dhi->error_info )
00423         {
00424             BESDEBUG( "bes", "  transmitting error info using cout ... " << endl ) ;
00425             _dhi->error_info->print( cout ) ;
00426         }
00427         else
00428         {
00429             BESDEBUG( "bes", "  Unable to transmit the response ... FAILED " << endl ) ;
00430             string err = "Unable to transmit the response, no transmitter" ;
00431             throw BESInternalError( err, __FILE__, __LINE__ ) ;
00432         }
00433     }
00434     BESDEBUG("bes", "OK" << endl) ;
00435 }
00436 
00439 void
00440 BESInterface::log_status()
00441 {
00442 }
00443 
00455 void
00456 BESInterface::report_request()
00457 {
00458     BESDEBUG( "bes", "Reporting on request: " << _dhi->data[DATA_REQUEST]
00459                      << " ... " << endl ) ;
00460 
00461     BESReporterList::TheList()->report( *_dhi ) ;
00462 
00463     BESDEBUG( "bes", "OK" << endl ) ;
00464 }
00465 
00466 void
00467 BESInterface::add_end_callback( p_bes_end end )
00468 {
00469     _end_list.push_back( end ) ;
00470 }
00471 
00477 void
00478 BESInterface::end_request()
00479 {
00480     BESDEBUG("bes", "Ending request: " << _dhi->data[DATA_REQUEST] << " ... " << endl ) ;
00481     end_iter i = _end_list.begin();
00482     for( ; i != _end_list.end(); i++ )
00483     {
00484         p_bes_end p = *i ;
00485         p( *_dhi ) ;
00486     }
00487 
00488     // now clean up any containers that were used in the request, release
00489     // the resource
00490     _dhi->first_container() ;
00491     while( _dhi->container )
00492     {
00493         _dhi->container->release() ;
00494         _dhi->next_container() ;
00495     }
00496 
00497     BESDEBUG("bes", "OK" << endl) ;
00498 }
00499 
00502 void
00503 BESInterface::clean()
00504 {
00505     if( _dhi )
00506         _dhi->clean() ;
00507 }
00508 
00521 int
00522 BESInterface::exception_manager( BESError &e )
00523 {
00524     return BESExceptionManager::TheEHM()->handle_exception( e, *_dhi ) ;
00525 }
00526 
00535 void
00536 BESInterface::dump(ostream & strm) const
00537 {
00538     strm << BESIndent::LMarg << "BESInterface::dump - ("
00539         << (void *) this << ")" << endl;
00540     BESIndent::Indent();
00541 
00542     if (_init_list.size()) {
00543         strm << BESIndent::LMarg << "termination functions:" << endl;
00544         BESIndent::Indent();
00545         init_iter i = _init_list.begin();
00546         for (; i != _init_list.end(); i++) {
00547             strm << BESIndent::LMarg << (void *) (*i) << endl;
00548         }
00549         BESIndent::UnIndent();
00550     } else {
00551         strm << BESIndent::LMarg << "termination functions: none" << endl;
00552     }
00553 
00554     if (_end_list.size()) {
00555         strm << BESIndent::LMarg << "termination functions:" << endl;
00556         BESIndent::Indent();
00557         end_iter i = _end_list.begin();
00558         for (; i != _end_list.end(); i++) {
00559             strm << BESIndent::LMarg << (void *) (*i) << endl;
00560         }
00561         BESIndent::UnIndent();
00562     } else {
00563         strm << BESIndent::LMarg << "termination functions: none" << endl;
00564     }
00565 
00566     strm << BESIndent::LMarg << "data handler interface:" << endl;
00567     BESIndent::Indent();
00568     _dhi->dump(strm);
00569     BESIndent::UnIndent();
00570 
00571     if (_transmitter) {
00572         strm << BESIndent::LMarg << "transmitter:" << endl;
00573         BESIndent::Indent();
00574         _transmitter->dump(strm);
00575         BESIndent::UnIndent();
00576     } else {
00577         strm << BESIndent::LMarg << "transmitter: not set" << endl;
00578     }
00579     BESIndent::UnIndent();
00580 }
Generated by  doxygen 1.6.2-20100208