bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
DmrppMetadataStore.cc
1// -*- mode: c++; c-basic-offset:4 -*-
2
3// This file is part of HYrax, A C++ implementation of the OPeNDAP Data
4// Access Protocol.
5
6// Copyright (c) 2018 OPeNDAP, Inc.
7// Author: James Gallagher <jgallagher@opendap.org>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22//
23// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24
25#include "config.h"
26
27#include <iostream>
28#include <string>
29#include <sstream>
30#include <memory>
31#include <typeinfo>
32
33#include <libdap/DMR.h>
34#include <libdap/XMLWriter.h>
35
36#include "BESDebug.h"
37
38#include "BESInternalFatalError.h"
39
40#include "DmrppParserSax2.h"
41#include "DmrppTypeFactory.h"
42#include "DmrppMetadataStore.h"
43
44#include "DMRpp.h"
45
46#define DEBUG_KEY "dmrpp_store"
47#define MAINTAIN_STORE_SIZE_EVEN_WHEN_UNLIMITED 0
48
49#ifdef HAVE_ATEXIT
50#define AT_EXIT(x) atexit((x))
51#else
52#define AT_EXIT(x)
53#endif
54
64#undef SYMETRIC_ADD_RESPONSES
65
66using namespace std;
67using namespace libdap;
68using namespace bes;
69
70using namespace dmrpp;
71
72DmrppMetadataStore *DmrppMetadataStore::d_instance = 0;
73bool DmrppMetadataStore::d_enabled = true;
74
89
106 // FIXME This code will not work correctly in a multi-thread situation. See http::EffectiveUrlCache();
108DmrppMetadataStore::get_instance(const string &cache_dir, const string &prefix, unsigned long long size)
109{
110 if (d_enabled && d_instance == 0) {
111 d_instance = new DmrppMetadataStore(cache_dir, prefix, size); // never returns null_ptr
112 d_enabled = d_instance->cache_enabled();
113 if (!d_enabled) {
114 delete d_instance;
115 d_instance = 0;
116
117 BESDEBUG(DEBUG_KEY, "DmrppMetadataStore::"<<__func__ << "() - " << "Cache is DISABLED"<< endl);
118 }
119 else {
120 AT_EXIT(delete_instance);
121
122 BESDEBUG(DEBUG_KEY, "DmrppMetadataStore::"<<__func__ << "() - " << "Cache is ENABLED"<< endl);
123 }
124 }
125
126 BESDEBUG(DEBUG_KEY, "DmrppMetadataStore::get_instance(dir,prefix,size) - d_instance: " << d_instance << endl);
127
128 return d_instance;
129}
130
139{
140 if (d_enabled && d_instance == 0) {
141 d_instance = new DmrppMetadataStore();
142 d_enabled = d_instance->cache_enabled();
143 if (!d_enabled) {
144 delete d_instance;
145 d_instance = NULL;
146 BESDEBUG(DEBUG_KEY, "DmrppMetadataStore::"<<__func__ << "() - " << "Cache is DISABLED"<< endl);
147 }
148 else {
149 AT_EXIT(delete_instance);
150
151 BESDEBUG(DEBUG_KEY, "DmrppMetadataStore::"<<__func__ << "() - " << "Cache is ENABLED"<< endl);
152 }
153 }
154
155 BESDEBUG(DEBUG_KEY, "DmrppMetadataStore::get_instance() - d_instance: " << (void *) d_instance << endl);
156
157 return d_instance;
158}
159
160
161void DmrppMetadataStore::StreamDMRpp::operator()(ostream &os)
162{
163 // Even though StreamDMRpp is-a StreamDAP and the latter has a d_dds
164 // field, we cannot use it for this version of the output operator.
165 // jhrg 5/17/18
166 if (d_dmr && typeid(*d_dmr) == typeid(dmrpp::DMRpp)) {
167 // FIXME This is where we will add the href that points toward the data file in S3. jhrg 5/17/18
168 DMRpp *dmrpp = static_cast<dmrpp::DMRpp*>(d_dmr);
169 dmrpp->set_print_chunks(true);
170 XMLWriter xml;
171 dmrpp->print_dap4(xml);
172
173 os << xml.get_doc();
174 }
175 else {
176 throw BESInternalFatalError("StreamDMRpp output operator call with non-DMRpp instance.", __FILE__, __LINE__);
177 }
178}
179
191bool
192DmrppMetadataStore::add_responses(DMR *dmr, const string &name)
193{
194 bool stored_dmr = GlobalMetadataStore::add_responses(dmr, name);
195
196 bool stored_dmrpp = false;
197 if (typeid(*dmr) == typeid(dmrpp::DMRpp)) {
198 d_ledger_entry = string("add DMR++ ").append(name);
199
200 StreamDMRpp write_the_dmrpp_response(dmr);
201 stored_dmrpp = store_dap_response(write_the_dmrpp_response, get_hash(name + "dmrpp_r"), name, "DMRpp");
202
203 write_ledger(); // write the index line
204 }
205 else {
206 stored_dmrpp = true; // if dmr is not a DMRpp, not writing the object is 'success.'
207 }
208
209 return(stored_dmr && stored_dmrpp);
210}
211
212bool
213DmrppMetadataStore::add_dmrpp_response(libdap::DMR *dmrpp, const std::string &name)
214{
215 bool stored_dmrpp = false;
216 if (typeid(*dmrpp) == typeid(dmrpp::DMRpp)) {
217 d_ledger_entry = string("add DMR++ ").append(name);
218
219 StreamDMRpp write_the_dmrpp_response(dmrpp);
220 stored_dmrpp = store_dap_response(write_the_dmrpp_response, get_hash(name + "dmrpp_r"), name, "DMRpp");
221
222 write_ledger(); // write the index line
223 }
224 else {
225 stored_dmrpp = true; // if dmr is not a DMRpp, not writing the object is 'success.'
226 }
227
228 return(stored_dmrpp);
229}
230
237DMR *
239{
240 // Get the DMR response, but then parse that so the resulting binary
241 // object is built with DMR++ types so that the chunk information can be
242 // stored in them.
243 stringstream oss;
244 write_dmr_response(name, oss); // throws BESInternalError if not found
245
246 DmrppTypeFactory dmrpp_btf;
247 unique_ptr<DMRpp> dmrpp(new DMRpp(&dmrpp_btf, "mds"));
248
249 DmrppParserSax2 parser;
250 parser.intern(oss.str(), dmrpp.get());
251
252 dmrpp->set_factory(0);
253
254 return dmrpp.release();
255}
256
269DMRpp *
271{
272 stringstream oss;
273 write_dmrpp_response(name, oss); // throws BESInternalError if not found
274
275 DmrppTypeFactory dmrpp_btf;
276 unique_ptr<DMRpp> dmrpp(new DMRpp(&dmrpp_btf, "mds"));
277
278 DmrppParserSax2 parser;
279 parser.intern(oss.str(), dmrpp.get());
280
281 dmrpp->set_factory(0);
282
283 return dmrpp.release();
284}
exception thrown if an internal error is found and is fatal to the BES
Store the DAP DMR++ metadata responses.
virtual bool add_responses(libdap::DMR *dmrpp, const std::string &name)
Add the DAP4 metadata responses using a DMR.
virtual libdap::DMR * get_dmr_object(const string &name)
Use the DMR response to build a DMR with Dmrpp Types.
static DmrppMetadataStore * get_instance()
virtual dmrpp::DMRpp * get_dmrpp_object(const std::string &name)
Build a DMR++ object from the cached Response.
virtual void write_dmr_response(const std::string &name, std::ostream &os)
Write the stored DMR response to a stream.
std::string get_hash(const std::string &name)
bool store_dap_response(StreamDAP &writer, const std::string &key, const std::string &name, const std::string &response_name)
virtual bool add_responses(libdap::DDS *dds, const std::string &name)
Add the DAP2 metadata responses using a DDS.
virtual void write_dmrpp_response(const std::string &name, std::ostream &os)
Write the stored DMR++ response to a stream.
Provide a way to print the DMR++ response.
Definition DMRpp.h:44
void intern(std::istream &f, libdap::DMR *dest_dmr)
Hack use a DMR to write a DMR++ response. WIP.