OPeNDAP Hyrax Back End Server (BES) Updated for version 3.8.3
|
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 }