bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
FODmrppTransmitter.cc
1// -*- mode: c++; c-basic-offset:4 -*-
2//
3// FoDapJsonTransmitter.cc
4//
5// This file is part of BES DMRPP Module
6//
7// Copyright (c) 2023 OPeNDAP, Inc.
8// Author: Nathan Potter <ndp@opendap.org>
9// Author: Daniel Holloway <dholloway@opendap.org>
10//
11// This library is free software; you can redistribute it and/or
12// modify it under the terms of the GNU Lesser General Public
13// License as published by the Free Software Foundation; either
14// version 2.1 of the License, or (at your option) any later version.
15//
16// This library is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19// Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public
22// License along with this library; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24//
25// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26// (c) COPYRIGHT URI/MIT 1995-1999
27// Please read the full copyright statement in the file COPYRIGHT_URI.
28//
29
30#include "config.h"
31
32#ifdef HAVE_UNISTD_H
33#include <unistd.h>
34#endif
35
36#include <exception>
37#include <sstream> // std::stringstream
38#include <thread>
39#include <future>
40
41#include <libdap/util.h>
42#include <libdap/D4Attributes.h>
43#include <libdap/D4ParserSax2.h>
44
45#include <BESContextManager.h>
46#include <BESDapNames.h>
47#include <BESDebug.h>
48#include <BESUtil.h>
49#include <RequestServiceTimer.h>
50
51#include <BESLog.h>
52#include <BESError.h>
53#include <BESInternalFatalError.h>
54#include <BESDapError.h>
55
56#include "BESDMRResponse.h"
57
58#include "DMRpp.h"
59#include "DmrppTypeFactory.h"
60#include "DmrppD4Group.h"
61
62#include "build_dmrpp_util.h"
63#include "FODmrppTransmitter.h"
64
65#include "DapUtils.h"
66
67using namespace libdap;
68using namespace std;
69
70#define MODULE "dmrpp"
71#define prolog string("FODmrppTransmitter::").append(__func__).append("() - ")
72
82 BESTransmitter()
83{
84 add_method(DAP4DATA_SERVICE, FODmrppTransmitter::send_dmrpp);
85}
86
104{
105 BESDEBUG(MODULE, prolog << "BEGIN" << endl);
106
107 bool add_production_metadata = true;
108
109 auto bdmr = dynamic_cast<BESDMRResponse *>(obj);
110 if (!bdmr) throw BESInternalFatalError("Expected a BESDMRResponse instance", __FILE__, __LINE__);
111 auto dmr = bdmr->get_dmr();
112
113 try {
114 dmrpp::DMRpp dmrpp;
116 dmrpp.set_factory(&dtf);
117
118 XMLWriter dmr_writer;
119 dmr->print_dap4(dmr_writer, false);
120
121 // WORKAROUND: Need to write DMR to stringstream to strip HDF5 specific content
122 // for subsequent parsing by D4ParserSax3 parser.
123 ostringstream oss;
124 oss << dmr_writer.get_doc();
125
126 istringstream iss(oss.str());
127
128 D4ParserSax2 parser;
129 parser.intern(iss, &dmrpp, false);
130
131 // WORKAROUND: Because this Transmitter is called after the H5 ResponseHandler building
132 // the DMR, dhi.container is set to null by BESDap4ResponseHandler::execute_each().
133 // BUT we need access to the container::d_real_name so we use an iterator to the dhi.containers
134 // to get the first container.
135 string dataset_name = (*(dhi.containers.begin()))->access();
136 string href_url = (*(dhi.containers.begin()))->get_real_name();
137
138 // Currently the disable_dio flag is always false.
139 // One cannot pass a different value of the disable_dio flag for this build_dmrpp module.
140 // The build_dmrpp module will not generate a dmrpp file that turns off the direct IO feature.
141 // One has to use the build_dmrpp utility to do this. KY 2024-07-17
142 build_dmrpp_util::add_chunk_information(dataset_name, &dmrpp, false);
143
144 if (add_production_metadata) {
145 build_dmrpp_util::inject_build_dmrpp_metadata(&dmrpp);
146 }
147
148 XMLWriter dmrpp_writer;
149 dmrpp.print_dmrpp(dmrpp_writer, href_url);
150
151 dap_utils::log_response_and_memory_size(prolog, dmrpp_writer);
152
153 auto &strm = dhi.get_output_stream();
154 strm << dmrpp_writer.get_doc() << flush;
155
156#if !NDEBUG
157 stringstream msg;
158 msg << prolog << "Using ostream: " << (void *) &strm << endl;
159 BESDEBUG(MODULE, msg.str());
160 INFO_LOG(msg.str());
161#endif
162
163 if (!strm) throw BESInternalError("Output stream is not set, can not return as", __FILE__, __LINE__);
164
165 // Verify the request hasn't exceeded bes_timeout, and disable timeout if allowed.
166 RequestServiceTimer::TheTimer()->throw_if_timeout_expired("ERROR: bes-timeout expired before transmit",
167 __FILE__, __LINE__);
169
170 // FONcTransmitter::write_temp_file_to_stream(temp_file.get_fd(), strm); //, loaded_dds->filename(), ncVersion);
171// BESUtil::file_to_stream(temp_file_name,strm);
172 }
173 catch (Error &e) {
174 throw BESDapError("Failed to read data: " + e.get_error_message(), false, e.get_error_code(), __FILE__, __LINE__);
175 }
176 catch (BESError &e) {
177 throw;
178 }
179 catch (std::exception &e) {
180 throw BESInternalError("Failed to read data: STL Error: " + string(e.what()), __FILE__, __LINE__);
181 }
182 catch (...) {
183 throw BESInternalError("Failed to get read data: Unknown exception caught", __FILE__, __LINE__);
184 }
185
186 BESDEBUG(MODULE, prolog << "END Transmitted DMRPP XML" << endl);
187}
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
Structure storing information used by the BES to handle the 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
FODmrppTransmitter()
BESTransmitter class named "dmrpp" that transmits an OPeNDAP data object as a DMRPP file.
static void send_dmrpp(BESResponseObject *obj, BESDataHandlerInterface &dhi)
The static method registered to transmit OPeNDAP DMRPP XML metadata.
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...
Provide a way to print the DMR++ response.
Definition DMRpp.h:44