00001 // BESCmdInterface.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 <iostream> 00035 #include <sstream> 00036 00037 using std::endl ; 00038 using std::stringstream ; 00039 00040 #include "BESCmdInterface.h" 00041 #include "BESCmdParser.h" 00042 #include "BESInterface.h" 00043 #include "BESLog.h" 00044 #include "BESDebug.h" 00045 #include "BESBasicHttpTransmitter.h" 00046 #include "BESReturnManager.h" 00047 #include "BESTransmitException.h" 00048 #include "BESAggFactory.h" 00049 #include "BESAggregationServer.h" 00050 #include "BESTransmitterNames.h" 00051 #include "BESDataNames.h" 00052 00060 BESCmdInterface::BESCmdInterface() 00061 : BESInterface() 00062 { 00063 } 00064 00065 BESCmdInterface::BESCmdInterface( const string &cmd ) 00066 { 00067 _dhi.data[DATA_REQUEST] = cmd ; 00068 } 00069 00070 BESCmdInterface::~BESCmdInterface() 00071 { 00072 clean() ; 00073 } 00074 00083 int 00084 BESCmdInterface::execute_request() 00085 { 00086 return BESInterface::execute_request() ; 00087 } 00088 00098 void 00099 BESCmdInterface::initialize() 00100 { 00101 // dhi has already been filled in at this point, so let's set a default 00102 // transmitter given the protocol. The transmitter might change after 00103 // parsing a request and given a return manager to use. This is done in 00104 // build_data_plan. 00105 // 00106 // The reason I moved this from the build_data_plan method is because a 00107 // registered initialization routine might throw an exception and we 00108 // will need to transmit the exception info, which needs a transmitter. 00109 // If an exception happens before this then the exception info is just 00110 // printed to stdout (see BESInterface::transmit_data()). -- pcw 09/05/06 00111 string protocol = _dhi.transmit_protocol ; 00112 if( protocol != "HTTP" ) 00113 { 00114 BESDEBUG( "Finding " << BASIC_TRANSMITTER << " transmitter ... " ) 00115 _transmitter = BESReturnManager::TheManager()->find_transmitter( BASIC_TRANSMITTER ) ; 00116 if( !_transmitter ) 00117 { 00118 string s = (string)"Unable to find transmitter " 00119 + BASIC_TRANSMITTER ; 00120 throw BESTransmitException( s, __FILE__, __LINE__ ) ; 00121 } 00122 BESDEBUG( "OK" << endl ) 00123 } 00124 else 00125 { 00126 BESDEBUG( "Finding " << HTTP_TRANSMITTER << " transmitter ... " ) 00127 _transmitter = BESReturnManager::TheManager()->find_transmitter( HTTP_TRANSMITTER ) ; 00128 if( !_transmitter ) 00129 { 00130 string s = (string)"Unable to find transmitter " 00131 + HTTP_TRANSMITTER ; 00132 throw BESTransmitException( s, __FILE__, __LINE__ ) ; 00133 } 00134 BESDEBUG( "OK" << endl ) 00135 } 00136 pid_t thepid = getpid() ; 00137 stringstream ss ; 00138 ss << thepid ; 00139 _dhi.data[SERVER_PID] = ss.str() ; 00140 00141 BESInterface::initialize() ; 00142 } 00143 00146 void 00147 BESCmdInterface::validate_data_request() 00148 { 00149 BESInterface::validate_data_request() ; 00150 } 00151 00156 void 00157 BESCmdInterface::build_data_request_plan() 00158 { 00159 BESDEBUG( "building request plan for: "<< _dhi.data[DATA_REQUEST] << " ...") 00160 if( BESLog::TheLog()->is_verbose() ) 00161 { 00162 *(BESLog::TheLog()) << _dhi.data[SERVER_PID] 00163 << " [" << _dhi.data[DATA_REQUEST] << "] building" 00164 << endl ; 00165 } 00166 BESCmdParser::parse( _dhi.data[DATA_REQUEST], _dhi ) ; 00167 BESDEBUG( " OK" << endl ) 00168 00169 // The default _transmitter (either basic or http depending on the 00170 // protocol passed) has been set in initialize. If the parsed command 00171 // sets a RETURN_CMD (a different transmitter) then look it up here. If 00172 // it's set but not found then this is an error. If it's not set then 00173 // just use the defaults. 00174 if( _dhi.data[RETURN_CMD] != "" ) 00175 { 00176 BESDEBUG( "Finding transmitter: " << _dhi.data[RETURN_CMD] << " ... " ) 00177 _transmitter = BESReturnManager::TheManager()->find_transmitter( _dhi.data[RETURN_CMD] ) ; 00178 if( !_transmitter ) 00179 { 00180 string s = (string)"Unable to find transmitter " 00181 + _dhi.data[RETURN_CMD] ; 00182 throw BESTransmitException( s, __FILE__, __LINE__ ) ; 00183 } 00184 BESDEBUG( "OK" << endl ) 00185 } 00186 00187 if( BESDebug::Debug() ) _dhi.dump( *(BESDebug::Get_strm()) ) ; 00188 } 00189 00197 void 00198 BESCmdInterface::execute_data_request_plan() 00199 { 00200 *(BESLog::TheLog()) << _dhi.data[SERVER_PID] 00201 << " [" << _dhi.data[DATA_REQUEST] << "] executing" 00202 << endl ; 00203 BESInterface::execute_data_request_plan() ; 00204 } 00205 00213 void 00214 BESCmdInterface::invoke_aggregation() 00215 { 00216 if( _dhi.data[AGG_CMD] == "" ) 00217 { 00218 *(BESLog::TheLog()) << _dhi.data[SERVER_PID] 00219 << " [" << _dhi.data[DATA_REQUEST] << "]" 00220 << " not aggregating, aggregation command empty" 00221 << endl ; 00222 } 00223 else 00224 { 00225 BESAggregationServer *agg = BESAggFactory::TheFactory()->find_handler( _dhi.data[AGG_HANDLER] ) ; 00226 if( !agg ) 00227 { 00228 if( BESLog::TheLog()->is_verbose() ) 00229 { 00230 *(BESLog::TheLog()) << _dhi.data[SERVER_PID] 00231 << " [" << _dhi.data[DATA_REQUEST] << "]" 00232 << " not aggregating, no handler" 00233 << endl ; 00234 } 00235 } 00236 else 00237 { 00238 if( BESLog::TheLog()->is_verbose() ) 00239 { 00240 *(BESLog::TheLog()) << _dhi.data[SERVER_PID] 00241 << " [" << _dhi.data[DATA_REQUEST] 00242 << "] aggregating" << endl ; 00243 } 00244 //This is done in BESInterface::invoke_aggregation 00245 //agg->aggregate( _dhi ) ; 00246 } 00247 } 00248 BESInterface::invoke_aggregation() ; 00249 } 00250 00258 void 00259 BESCmdInterface::transmit_data() 00260 { 00261 if( BESLog::TheLog()->is_verbose() ) 00262 { 00263 *(BESLog::TheLog()) << _dhi.data[SERVER_PID] 00264 << " [" << _dhi.data[DATA_REQUEST] 00265 << "] transmitting" << endl ; 00266 } 00267 BESInterface::transmit_data() ; 00268 } 00269 00274 void 00275 BESCmdInterface::log_status() 00276 { 00277 string result = "completed" ; 00278 if( _dhi.error_info ) 00279 result = "failed" ; 00280 *(BESLog::TheLog()) << _dhi.data[SERVER_PID] 00281 << " [" << _dhi.data[DATA_REQUEST] << "] " 00282 << result << endl ; 00283 } 00284 00293 void 00294 BESCmdInterface::clean() 00295 { 00296 BESInterface::clean() ; 00297 *(BESLog::TheLog()) << _dhi.data[SERVER_PID] 00298 << " [" << _dhi.data[DATA_REQUEST] << "] cleaning" 00299 << endl ; 00300 } 00301 00308 void 00309 BESCmdInterface::dump( ostream &strm ) const 00310 { 00311 strm << BESIndent::LMarg << "BESCmdInterface::dump - (" 00312 << (void *)this << ")" << endl ; 00313 BESIndent::Indent() ; 00314 BESInterface::dump( strm ) ; 00315 BESIndent::UnIndent() ; 00316 00317 00318 } 00319