42 #include <sys/types.h> 54 #include <ConstraintEvaluator.h> 56 #include <TheBESKeys.h> 57 #include <BESContextManager.h> 58 #include <BESDataDDSResponse.h> 59 #include <BESDapNames.h> 60 #include <BESDataNames.h> 65 #include <BESDapResponseBuilder.h> 68 #include <BESDapError.h> 69 #include <BESForbiddenError.h> 70 #include <BESInternalFatalError.h> 71 #include <DapFunctionUtils.h> 73 #include "FONcBaseType.h" 74 #include "FONcRequestHandler.h" 75 #include "FONcTransmitter.h" 76 #include "FONcTransform.h" 83 #define OUTPUT_FILE_BLOCK_SIZE 4096 105 struct wrap_temp_descriptor {
107 wrap_temp_descriptor(
int fd) : d_fd(fd) {}
108 ~wrap_temp_descriptor() { close(d_fd); }
118 struct wrap_temp_name {
120 wrap_temp_name(vector<char> &name) : d_name(name) {}
121 ~wrap_temp_name() { unlink(&d_name[0]); }
135 void updateHistoryAttribute(DDS *dds,
const string ce)
137 bool foundIt =
false;
138 string cf_history_entry = BESContextManager::TheManager()->
get_context(
"cf_history_entry", foundIt);
148 string request_url = dds->filename();
150 request_url = request_url.substr(request_url.find_last_of(
'/')+1);
152 request_url = request_url.substr(request_url.find_last_of(
'#')+1);
153 request_url +=
"?" + ce;
155 std::stringstream ss;
158 struct tm * timeinfo;
160 timeinfo = localtime(&raw_now);
164 strftime(time_str, 100,
"%Y-%m-%d %H:%M:%S", timeinfo);
166 ss << time_str <<
" " <<
"Hyrax" <<
" " << request_url;
167 cf_history_entry = ss.str();
171 "FONcTransmitter::updateHistoryAttribute() - Adding cf_history_entry context. '" << cf_history_entry <<
"'" << endl);
173 vector<string> hist_entry_vec;
174 hist_entry_vec.push_back(cf_history_entry);
176 "FONcTransmitter::updateHistoryAttribute() - hist_entry_vec.size(): " << hist_entry_vec.size() << endl);
180 AttrTable &globals = dds->get_attr_table();
185 unsigned int num_attrs = globals.get_size();
189 AttrTable::Attr_iter i = globals.attr_begin();
190 AttrTable::Attr_iter e = globals.attr_end();
191 for (; i != e && !done; i++) {
192 AttrType attrType = globals.get_attr_type(i);
193 string attr_name = globals.get_name(i);
197 AttrTable *source_file_globals = globals.get_attr_table(i);
198 AttrTable::Attr_iter history_attrItr = source_file_globals->simple_find(
"history");
199 if (history_attrItr != source_file_globals->attr_end()) {
202 "FONcTransmitter::updateHistoryAttribute() - Adding history entry to " << attr_name << endl);
203 source_file_globals->append_attr(
"history",
"string", &hist_entry_vec);
213 "FONcTransmitter::updateHistoryAttribute() - Adding history entry to top level AttrTable" << endl);
214 globals.append_attr(
"history",
"string", &hist_entry_vec);
237 BESDEBUG(
"fonc",
"FONcTransmitter::send_data() - BEGIN" << endl);
250 BESDEBUG(
"fonc",
"FONcTransmitter::send_data() - Reading data into DataDDS" << endl);
256 updateHistoryAttribute(loaded_dds, dhi.
data[POST_CONSTRAINT]);
262 string temp_file_name = FONcRequestHandler::temp_dir +
"/ncXXXXXX";
263 vector<char> temp_file(temp_file_name.length() + 1);
264 string::size_type len = temp_file_name.copy(&temp_file[0], temp_file_name.length());
265 temp_file[len] =
'\0';
268 mode_t original_mode = umask(077);
269 int fd = mkstemp(&temp_file[0]);
270 umask(original_mode);
275 wrap_temp_name w_temp_file(temp_file);
276 wrap_temp_descriptor w_fd(fd);
278 if (fd == -1)
throw BESInternalError(
"Failed to open the temporary file.", __FILE__, __LINE__);
281 bes::TempFile temp_file(FONcRequestHandler::temp_dir +
"/ncXXXXXX");
283 BESDEBUG(
"fonc",
"FONcTransmitter::send_data - Building response file " << temp_file.
get_name() << endl);
289 ostream &strm = dhi.get_output_stream();
290 if (!strm)
throw BESInternalError(
"Output stream is not set, can not return as", __FILE__, __LINE__);
292 BESDEBUG(
"fonc",
"FONcTransmitter::send_data - Transmitting temp file " << temp_file.
get_name() << endl);
294 FONcTransmitter::write_temp_file_to_stream(temp_file.
get_fd(), strm);
297 throw BESDapError(
"Failed to read data: " + e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
302 catch (std::exception &e) {
303 throw BESInternalError(
"Failed to read data: STL Error: " +
string(e.what()), __FILE__, __LINE__);
306 throw BESInternalError(
"Failed to get read data: Unknown exception caught", __FILE__, __LINE__);
309 BESDEBUG(
"fonc",
"FONcTransmitter::send_data - done transmitting to netcdf" << endl);
321 void FONcTransmitter::write_temp_file_to_stream(
int fd, ostream &strm)
323 char block[OUTPUT_FILE_BLOCK_SIZE];
325 int nbytes = read(fd, block,
sizeof block);
327 strm.write(block, nbytes );
328 nbytes = read(fd, block,
sizeof block);
virtual libdap::DDS * intern_dap2_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
exception thrown if inernal error encountered
std::string get_name() const
static void conditional_timeout_cancel()
FONcTransmitter()
Construct the FONcTransmitter, adding it with name netcdf to be able to transmit a data response.
static void send_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
The static method registered to transmit OPeNDAP data objects as a netcdf file.
virtual string get_context(const string &name, bool &found)
retrieve the value of the specified context from the BES
Abstract exception class for the BES with basic string message.
error object created from libdap error objects and can handle those errors
static bool endsWith(std::string const &fullString, std::string const &ending)
Structure storing information used by the BES to handle the request.
map< string, string > data
the map of string data that will be required for the current request.
Abstract base class representing a specific set of information in response to a request to the BES.
Get a new temporary file.