bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
FONcTransmitter.cc
1// FONcTransmitter.cc
2
3// This file is part of BES Netcdf File Out Module
4
5// Copyright (c) 2004,2005 University Corporation for Atmospheric Research
6// Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
7//
8// This library is free software; you can redistribute it and/or
9// modify it under the terms of the GNU Lesser General Public
10// License as published by the Free Software Foundation; either
11// version 2.1 of the License, or (at your option) any later version.
12//
13// This library is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// Lesser General Public License for more details.
17//
18// You should have received a copy of the GNU Lesser General Public
19// License along with this library; if not, write to the Free Software
20// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21//
22// You can contact University Corporation for Atmospheric Research at
23// 3080 Center Green Drive, Boulder, CO 80301
24
25// (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
26// Please read the full copyright statement in the file COPYRIGHT_UCAR.
27//
28// Authors:
29// pwest Patrick West <pwest@ucar.edu>
30// jgarcia Jose Garcia <jgarcia@ucar.edu>
31// kyang Kent Yang <myang6@hdfgroup.org> (for DAP4/netCDF-4 enhancement)
32
33#include "config.h"
34
35
36#ifdef HAVE_UNISTD_H
37#include <unistd.h>
38#endif
39
40#include <exception>
41#include <sstream> // std::stringstream
42#include <thread>
43#include <future>
44
45#include <libdap/D4Group.h>
46#include <libdap/D4Attributes.h>
47#include <libdap/BaseType.h>
48#include <libdap/escaping.h>
49
50#include <BESContextManager.h>
51#include <BESDataDDSResponse.h>
52#include <BESDapNames.h>
53#include <BESDataNames.h>
54#include <BESDebug.h>
55#include <BESUtil.h>
56#include <TempFile.h>
57#include <RequestServiceTimer.h>
58
59#include <BESLog.h>
60#include <BESError.h>
61#include <BESInternalFatalError.h>
62#include <BESDapError.h>
63#include "BESDMRResponse.h"
64#include <stringbuffer.h>
65
66#include "FONcBaseType.h"
67#include "FONcRequestHandler.h"
68#include "FONcTransmitter.h"
69#include "FONcTransform.h"
70
71using namespace libdap;
72using namespace std;
73using namespace rapidjson;
74
75#define MODULE "fonc"
76#define prolog string("FONcTransmitter::").append(__func__).append("() - ")
77
78
91 BESTransmitter()
92{
93 add_method(DATA_SERVICE, FONcTransmitter::send_dap2_data);
94 add_method(DAP4DATA_SERVICE, FONcTransmitter::send_dap4_data);
95}
96
97
115{
116 BESDEBUG(MODULE, prolog << "BEGIN" << endl);
117
118 uint64_t bytes_sent = 0;
119
120 try { // Expanded try block so all DAP errors are caught. ndp 12/23/2015
121 auto bdds = dynamic_cast<BESDataDDSResponse *>(obj);
122 if (!bdds) throw BESInternalFatalError("Expected a BESDataDDSResponse instance", __FILE__, __LINE__);
123 auto dds = bdds->get_dds();
124
125 string base_name = dds->filename().substr(dds->filename().find_last_of("/\\") + 1);
126
127 // This object closes the file when it goes out of scope.
128 bes::TempFile temp_file;
129 string temp_file_name = temp_file.create(FONcRequestHandler::temp_dir, "dap2_nc_"+base_name);
130
131 BESDEBUG(MODULE, prolog << "Building response file " << temp_file_name << endl);
132
133 // Note that 'RETURN_CMD' is the same as the string that determines the file type:
134 // netcdf 3 or netcdf 4. Hack. jhrg 9/7/16
135 FONcTransform ft(obj, &dhi, temp_file_name, dhi.data[RETURN_CMD]);
136
137 ft.transform_dap2();
138 ostream &strm = dhi.get_output_stream();
139 if (!strm) throw BESInternalError("Output stream is not set, can not return as", __FILE__, __LINE__);
140
141 // Verify the request hasn't exceeded bes_timeout, and disable timeout if allowed.
142 RequestServiceTimer::TheTimer()->throw_if_timeout_expired("ERROR: bes-timeout expired before transmit", __FILE__, __LINE__);
144
145 BESDEBUG(MODULE, prolog << "Transmitting temp file " << temp_file_name << endl);
146
147 bytes_sent = BESUtil::file_to_stream(temp_file_name,strm);
148
149 }
150 // This series of catch blocks is used to convert other errors into BESErrors.
151 // Thus, we do not need to catch BESError here because it's already what we want.
152 catch (const Error &e) {
153 throw BESDapError(prolog + "Failed to read data: " + e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
154 }
155 catch (const BESError &e) {
156 BESDEBUG(MODULE, prolog << "Caught BESError. Message " << e.get_verbose_message() << endl);
157 throw;
158 }
159 catch (const std::exception &e) {
160 throw BESInternalError(prolog + "Failed to read data! Caught std::exception. Message; " + string(e.what()), __FILE__, __LINE__);
161 }
162 catch (...) {
163 throw BESInternalError(prolog + "Failed to get read data: Unknown exception caught", __FILE__, __LINE__);
164 }
165 BESDEBUG(MODULE, prolog << "END Transmitted as netcdf. bytes_sent: " << bytes_sent<<endl);
166}
167
186{
187 BESDEBUG(MODULE, prolog << "BEGIN" << endl);
188 uint64_t bytes_sent = 0;
189 try { // Expanded try block so all DAP errors are caught. ndp 12/23/2015
190
191 auto bdmr = dynamic_cast<BESDMRResponse *>(obj);
192 if (!bdmr) throw BESInternalFatalError("Expected a BESDMRResponse instance", __FILE__, __LINE__);
193 auto dmr = bdmr->get_dmr();
194
195 string base_name = dmr->filename().substr(dmr->filename().find_last_of("/\\") + 1);
196
197 // This object closes the file when it goes out of scope.
198 bes::TempFile temp_file;
199 string temp_file_name = temp_file.create(FONcRequestHandler::temp_dir, "dap4_nc_"+base_name);
200
201 BESDEBUG(MODULE, prolog << "Building response file " << temp_file_name << endl);
202 // Note that 'RETURN_CMD' is the same as the string that determines the file type:
203 // netcdf 3 or netcdf 4. Hack. jhrg 9/7/16
204 // FONcTransform ft(loaded_dmr, dhi, temp_file.get_name(), dhi.data[RETURN_CMD]);
205 FONcTransform ft(obj, &dhi, temp_file_name, dhi.data[RETURN_CMD]);
206
207 // Call the transform function for DAP4.
208 ft.transform_dap4();
209
210 ostream &strm = dhi.get_output_stream();
211
212#if !NDEBUG
213 stringstream msg;
214 msg << prolog << "Using ostream: " << (void *) &strm << endl;
215 BESDEBUG(MODULE, msg.str());
216 INFO_LOG( msg.str());
217#endif
218
219 if (!strm) throw BESInternalError("Output stream is not set, can not return as", __FILE__, __LINE__);
220
221 // Verify the request hasn't exceeded bes_timeout, and disable timeout if allowed.
222 RequestServiceTimer::TheTimer()->throw_if_timeout_expired("ERROR: bes-timeout expired before transmit", __FILE__, __LINE__);
224
225 BESDEBUG(MODULE, prolog << "Transmitting temp file " << temp_file_name << endl);
226
227 bytes_sent = BESUtil::file_to_stream(temp_file_name,strm);
228 }
229 // This series of catch blocks is used to convert other errors into BESErrors.
230 // Thus, we do not need to catch BESError here because it's already what we want.
231 catch (const Error &e) {
232 throw BESDapError(prolog + "Failed to read data: " + e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
233 }
234 catch (const BESError &e) {
235 BESDEBUG(MODULE, prolog << "Caught BESError. Message " << e.get_verbose_message() << endl);
236 throw;
237 }
238 catch (const std::exception &e) {
239 throw BESInternalError(prolog + "Failed to read data! Caught std::exception. Message: " + string(e.what()), __FILE__, __LINE__);
240 }
241 catch (...) {
242 throw BESInternalError(prolog + "Failed to get read data: Unknown exception caught", __FILE__, __LINE__);
243 }
244
245 BESDEBUG(MODULE, prolog << "END Transmitted as netcdf. bytes_sent: " << bytes_sent << endl);
246}
247
248
249
250
251
252
Represents an OPeNDAP DMR DAP4 data object within the BES.
error object created from libdap error objects and can handle those errors
Definition BESDapError.h:50
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
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.
Base exception class for the BES with basic string message.
Definition BESError.h:66
exception thrown if internal error encountered
exception thrown if an internal error is found and is fatal to the BES
Abstract base class representing a specific set of information in response to a request to the BES.
static void conditional_timeout_cancel()
Checks if the timeout alarm should be canceled based on the value of the BES key BES....
Definition BESUtil.cc:898
static uint64_t file_to_stream(const std::string &file_name, std::ostream &o_strm, uint64_t read_start_position=0)
Copies the contents of the file identified by file_name to the stream o_strm.
Definition BESUtil.cc:1136
Transformation object that converts an OPeNDAP DataDDS to a netcdf file.
virtual void transform_dap2()
Transforms each of the variables of the DataDDS to the NetCDF file.
virtual void transform_dap4()
Transforms each of the variables of the DMR to the NetCDF file.
static void send_dap4_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
The static method registered to transmit OPeNDAP data objects as a netcdf file.
static void send_dap2_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.
static RequestServiceTimer * TheTimer()
Return a pointer to a singleton timer instance. If an instance does not exist it will create and init...
void throw_if_timeout_expired(const std::string &message, const std::string &file, const int line)
Checks the RequestServiceTimer to determine if the time spent servicing the request at this point has...
Get a new temporary file.
Definition TempFile.h:43
std::string create(const std::string &dir_name="/tmp/hyrax_tmp", const std::string &path_template="opendap")
Create a new temporary file.
Definition TempFile.cc:164
main RapidJSON namespace