43 #include <sys/types.h>
55 #include <ConstraintEvaluator.h>
57 #include <TheBESKeys.h>
58 #include <BESContextManager.h>
59 #include <BESDataDDSResponse.h>
60 #include <BESDapNames.h>
61 #include <BESDataNames.h>
66 #include <BESDapResponseBuilder.h>
69 #include <BESDapError.h>
70 #include <BESForbiddenError.h>
71 #include <BESInternalFatalError.h>
72 #include <DapFunctionUtils.h>
74 #include "FONcBaseType.h"
75 #include "FONcRequestHandler.h"
76 #include "FONcTransmitter.h"
77 #include "FONcTransform.h"
84 #define OUTPUT_FILE_BLOCK_SIZE 4096
107 struct wrap_temp_descriptor {
109 wrap_temp_descriptor(
int fd) : d_fd(fd) {}
110 ~wrap_temp_descriptor() { close(d_fd); }
120 struct wrap_temp_name {
122 wrap_temp_name(vector<char> &name) : d_name(name) {}
123 ~wrap_temp_name() { unlink(&d_name[0]); }
137 void updateHistoryAttribute(DDS *dds,
const string ce)
139 bool foundIt =
false;
140 string cf_history_entry = BESContextManager::TheManager()->
get_context(
"cf_history_entry", foundIt);
150 string request_url = dds->filename();
152 request_url = request_url.substr(request_url.find_last_of(
'/')+1);
154 request_url = request_url.substr(request_url.find_last_of(
'#')+1);
155 request_url +=
"?" + ce;
157 std::stringstream ss;
160 struct tm * timeinfo;
162 timeinfo = localtime(&raw_now);
166 strftime(time_str, 100,
"%Y-%m-%d %H:%M:%S", timeinfo);
168 ss << time_str <<
" " <<
"Hyrax" <<
" " << request_url;
169 cf_history_entry = ss.str();
173 "FONcTransmitter::updateHistoryAttribute() - Adding cf_history_entry context. '" << cf_history_entry <<
"'" << endl);
175 vector<string> hist_entry_vec;
176 hist_entry_vec.push_back(cf_history_entry);
178 "FONcTransmitter::updateHistoryAttribute() - hist_entry_vec.size(): " << hist_entry_vec.size() << endl);
182 AttrTable &globals = dds->get_attr_table();
187 unsigned int num_attrs = globals.get_size();
191 AttrTable::Attr_iter i = globals.attr_begin();
192 AttrTable::Attr_iter e = globals.attr_end();
193 for (; i != e && !done; i++) {
194 AttrType attrType = globals.get_attr_type(i);
195 string attr_name = globals.get_name(i);
199 AttrTable *source_file_globals = globals.get_attr_table(i);
200 AttrTable::Attr_iter history_attrItr = source_file_globals->simple_find(
"history");
201 if (history_attrItr != source_file_globals->attr_end()) {
204 "FONcTransmitter::updateHistoryAttribute() - Adding history entry to " << attr_name << endl);
205 source_file_globals->append_attr(
"history",
"string", &hist_entry_vec);
215 "FONcTransmitter::updateHistoryAttribute() - Adding history entry to top level AttrTable" << endl);
216 globals.append_attr(
"history",
"string", &hist_entry_vec);
232 void update_Dap4_HistoryAttribute(DMR *dmr,
const string ce)
234 bool foundIt =
false;
235 string cf_history_entry = BESContextManager::TheManager()->
get_context(
"cf_history_entry", foundIt);
245 string request_url = dds->filename();
247 request_url = request_url.substr(request_url.find_last_of(
'/')+1);
249 request_url = request_url.substr(request_url.find_last_of(
'#')+1);
250 request_url +=
"?" + ce;
252 std::stringstream ss;
255 struct tm * timeinfo;
257 timeinfo = localtime(&raw_now);
261 strftime(time_str, 100,
"%Y-%m-%d %H:%M:%S", timeinfo);
263 ss << time_str <<
" " <<
"Hyrax" <<
" " << request_url;
264 cf_history_entry = ss.str();
268 "FONcTransmitter::update_Dap4_HistoryAttribute() - Adding cf_history_entry context. '" << cf_history_entry <<
"'" << endl);
270 vector<string> hist_entry_vec;
271 hist_entry_vec.push_back(cf_history_entry);
273 "FONcTransmitter::update_Dap4_HistoryAttribute() - hist_entry_vec.size(): " << hist_entry_vec.size() << endl);
278 D4Group* root_grp = dmr->root();
284 unsigned int num_attrs = globals.get_size();
288 AttrTable::Attr_iter i = globals.attr_begin();
289 AttrTable::Attr_iter e = globals.attr_end();
290 for (; i != e && !done; i++) {
291 AttrType attrType = globals.get_attr_type(i);
292 string attr_name = globals.get_name(i);
296 AttrTable *source_file_globals = globals.get_attr_table(i);
297 AttrTable::Attr_iter history_attrItr = source_file_globals->simple_find(
"history");
298 if (history_attrItr != source_file_globals->attr_end()) {
301 "FONcTransmitter::updateHistoryAttribute() - Adding history entry to " << attr_name << endl);
302 source_file_globals->append_attr(
"history",
"string", &hist_entry_vec);
312 "FONcTransmitter::updateHistoryAttribute() - Adding history entry to top level AttrTable" << endl);
313 globals.append_attr(
"history",
"string", &hist_entry_vec);
338 BESDEBUG(
"fonc",
"FONcTransmitter::send_data() - BEGIN" << endl);
351 BESDEBUG(
"fonc",
"FONcTransmitter::send_data() - Reading data into DataDDS" << endl);
357 updateHistoryAttribute(loaded_dds, dhi.
data[POST_CONSTRAINT]);
363 string temp_file_name = FONcRequestHandler::temp_dir +
"/ncXXXXXX";
364 vector<char> temp_file(temp_file_name.length() + 1);
365 string::size_type len = temp_file_name.copy(&temp_file[0], temp_file_name.length());
366 temp_file[len] =
'\0';
369 mode_t original_mode = umask(077);
370 int fd = mkstemp(&temp_file[0]);
371 umask(original_mode);
376 wrap_temp_name w_temp_file(temp_file);
377 wrap_temp_descriptor w_fd(fd);
379 if (fd == -1)
throw BESInternalError(
"Failed to open the temporary file.", __FILE__, __LINE__);
382 bes::TempFile temp_file(FONcRequestHandler::temp_dir +
"/ncXXXXXX");
384 BESDEBUG(
"fonc",
"FONcTransmitter::send_data - Building response file " << temp_file.get_name() << endl);
390 ostream &strm = dhi.get_output_stream();
391 if (!strm)
throw BESInternalError(
"Output stream is not set, can not return as", __FILE__, __LINE__);
393 BESDEBUG(
"fonc",
"FONcTransmitter::send_data - Transmitting temp file " << temp_file.get_name() << endl);
395 FONcTransmitter::write_temp_file_to_stream(temp_file.get_fd(), strm);
398 throw BESDapError(
"Failed to read data: " + e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
403 catch (std::exception &e) {
404 throw BESInternalError(
"Failed to read data: STL Error: " +
string(e.what()), __FILE__, __LINE__);
407 throw BESInternalError(
"Failed to get read data: Unknown exception caught", __FILE__, __LINE__);
410 BESDEBUG(
"fonc",
"FONcTransmitter::send_data - done transmitting to netcdf" << endl);
432 BESDEBUG(
"fonc",
"FONcTransmitter::send_dap4_data() - BEGIN" << endl);
445 BESDEBUG(
"fonc",
"FONcTransmitter::send_dap4_data() - Reading data into DMR" << endl);
453 D4Group* root_grp = loaded_dmr->root();
454 Constructor::Vars_iter v = root_grp->var_begin();
455 for (D4Group::Vars_iter i = root_grp->var_begin(), e = root_grp->var_end(); i != e; ++i) {
456 BESDEBUG(
"fonc",
"BESDapResponseBuilder::send_dap4_data() - "<< (*i)->name() <<endl);
457 if ((*i)->send_p()) {
472 string temp_file_name = FONcRequestHandler::temp_dir +
"/ncXXXXXX";
473 vector<char> temp_file(temp_file_name.length() + 1);
474 string::size_type len = temp_file_name.copy(&temp_file[0], temp_file_name.length());
475 temp_file[len] =
'\0';
478 mode_t original_mode = umask(077);
479 int fd = mkstemp(&temp_file[0]);
480 umask(original_mode);
485 wrap_temp_name w_temp_file(temp_file);
486 wrap_temp_descriptor w_fd(fd);
488 if (fd == -1)
throw BESInternalError(
"Failed to open the temporary file.", __FILE__, __LINE__);
491 bes::TempFile temp_file(FONcRequestHandler::temp_dir +
"/ncXXXXXX");
493 BESDEBUG(
"fonc",
"FONcTransmitter::send_dap4_data - Building response file " << temp_file.get_name() << endl);
501 ostream &strm = dhi.get_output_stream();
502 if (!strm)
throw BESInternalError(
"Output stream is not set, can not return as", __FILE__, __LINE__);
504 BESDEBUG(
"fonc",
"FONcTransmitter::send_dap4_data - Transmitting temp file " << temp_file.get_name() << endl);
506 FONcTransmitter::write_temp_file_to_stream(temp_file.get_fd(), strm);
509 throw BESDapError(
"Failed to read data: " + e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
514 catch (std::exception &e) {
515 throw BESInternalError(
"Failed to read data: STL Error: " +
string(e.what()), __FILE__, __LINE__);
518 throw BESInternalError(
"Failed to get read data: Unknown exception caught", __FILE__, __LINE__);
521 BESDEBUG(
"fonc",
"FONcTransmitter::send_dap4_data - done transmitting to netcdf" << endl);
534 void FONcTransmitter::write_temp_file_to_stream(
int fd, ostream &strm)
536 char block[OUTPUT_FILE_BLOCK_SIZE];
538 int nbytes = read(fd, block,
sizeof block);
540 strm.write(block, nbytes );
541 nbytes = read(fd, block,
sizeof block);
virtual std::string get_context(const std::string &name, bool &found)
retrieve the value of the specified context from the BES
error object created from libdap error objects and can handle those errors
virtual libdap::DMR * intern_dap4_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
virtual libdap::DDS * intern_dap2_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
Structure storing information used by the BES to handle the request.
std::map< std::string, std::string > data
the map of string data that will be required for the current request.
Abstract exception class for the BES with basic string message.
exception thrown if internal error encountered
Abstract base class representing a specific set of information in response to a request to the BES.
static bool endsWith(std::string const &fullString, std::string const &ending)
static void conditional_timeout_cancel()
static void send_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
The static method registered to transmit OPeNDAP data objects as a netcdf file.
static void send_dap4_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
The static method registered to transmit OPeNDAP data objects as a netcdf file.
FONcTransmitter()
Construct the FONcTransmitter, adding it with name netcdf to be able to transmit a data response.
Get a new temporary file.