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             BESDEBUG( "bes", "  transmitting error info using transmitter ... " << endl ) ;
00408             _dhi->error_info->transmit( _transmitter, *_dhi ) ;
00409         }
00410         else if( _dhi->response_handler )
00411         {
00412             BESDEBUG( "bes", "  transmitting response using transmitter ...  " << endl ) ;
00413             _dhi->response_handler->transmit( _transmitter, *_dhi ) ;
00414         }
00415     }
00416     else
00417     {
00418         if( _dhi->error_info )
00419         {
00420             BESDEBUG( "bes", "  transmitting error info using cout ... " << endl ) ;
00421             _dhi->error_info->print( cout ) ;
00422         }
00423         else
00424         {
00425             BESDEBUG( "bes", "  Unable to transmit the response ... FAILED " << endl ) ;
00426             string err = "Unable to transmit the response, no transmitter" ;
00427             throw BESInternalError( err, __FILE__, __LINE__ ) ;
00428         }
00429     }
00430     BESDEBUG("bes", "OK" << endl) ;
00431 }
00432 
00435 void
00436 BESInterface::log_status()
00437 {
00438 }
00439 
00451 void
00452 BESInterface::report_request()
00453 {
00454     BESDEBUG( "bes", "Reporting on request: " << _dhi->data[DATA_REQUEST]
00455                      << " ... " << endl ) ;
00456 
00457     BESReporterList::TheList()->report( *_dhi ) ;
00458 
00459     BESDEBUG( "bes", "OK" << endl ) ;
00460 }
00461 
00462 void
00463 BESInterface::add_end_callback( p_bes_end end )
00464 {
00465     _end_list.push_back( end ) ;
00466 }
00467 
00473 void
00474 BESInterface::end_request()
00475 {
00476     BESDEBUG("bes", "Ending request: " << _dhi->data[DATA_REQUEST] << " ... " << endl ) ;
00477     end_iter i = _end_list.begin();
00478     for( ; i != _end_list.end(); i++ )
00479     {
00480         p_bes_end p = *i ;
00481         p( *_dhi ) ;
00482     }
00483 
00484     // now clean up any containers that were used in the request, release
00485     // the resource
00486     _dhi->first_container() ;
00487     while( _dhi->container )
00488     {
00489         _dhi->container->release() ;
00490         _dhi->next_container() ;
00491     }
00492 
00493     BESDEBUG("bes", "OK" << endl) ;
00494 }
00495 
00498 void
00499 BESInterface::clean()
00500 {
00501     if( _dhi )
00502         _dhi->clean() ;
00503 }
00504 
00517 int
00518 BESInterface::exception_manager( BESError &e )
00519 {
00520     return BESExceptionManager::TheEHM()->handle_exception( e, *_dhi ) ;
00521 }
00522 
00531 void
00532 BESInterface::dump(ostream & strm) const
00533 {
00534     strm << BESIndent::LMarg << "BESInterface::dump - ("
00535         << (void *) this << ")" << endl;
00536     BESIndent::Indent();
00537 
00538     if (_init_list.size()) {
00539         strm << BESIndent::LMarg << "termination functions:" << endl;
00540         BESIndent::Indent();
00541         init_iter i = _init_list.begin();
00542         for (; i != _init_list.end(); i++) {
00543             strm << BESIndent::LMarg << (void *) (*i) << endl;
00544         }
00545         BESIndent::UnIndent();
00546     } else {
00547         strm << BESIndent::LMarg << "termination functions: none" << endl;
00548     }
00549 
00550     if (_end_list.size()) {
00551         strm << BESIndent::LMarg << "termination functions:" << endl;
00552         BESIndent::Indent();
00553         end_iter i = _end_list.begin();
00554         for (; i != _end_list.end(); i++) {
00555             strm << BESIndent::LMarg << (void *) (*i) << endl;
00556         }
00557         BESIndent::UnIndent();
00558     } else {
00559         strm << BESIndent::LMarg << "termination functions: none" << endl;
00560     }
00561 
00562     strm << BESIndent::LMarg << "data handler interface:" << endl;
00563     BESIndent::Indent();
00564     _dhi->dump(strm);
00565     BESIndent::UnIndent();
00566 
00567     if (_transmitter) {
00568         strm << BESIndent::LMarg << "transmitter:" << endl;
00569         BESIndent::Indent();
00570         _transmitter->dump(strm);
00571         BESIndent::UnIndent();
00572     } else {
00573         strm << BESIndent::LMarg << "transmitter: not set" << endl;
00574     }
00575     BESIndent::UnIndent();
00576 }

Generated on Wed May 12 09:53:07 2010 for OPeNDAP Hyrax Back End Server (BES) by  doxygen 1.4.7