bes  Updated for version 3.20.13
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 
66 using namespace std;
67 using namespace libdap;
68 using namespace bes;
69 
70 using namespace dmrpp;
71 
72 DmrppMetadataStore *DmrppMetadataStore::d_instance = 0;
73 bool DmrppMetadataStore::d_enabled = true;
74 
89 
106  // FIXME This code will not work correctly in a multi-thread situation. See http::EffectiveUrlCache();
108 DmrppMetadataStore::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 
138 DmrppMetadataStore::get_instance()
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 }
160 
161 void 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 
191 bool
192 DmrppMetadataStore::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 
212 bool
213 DmrppMetadataStore::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 
237 DMR *
238 DmrppMetadataStore::get_dmr_object(const string &name)
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 
269 DMRpp *
270 DmrppMetadataStore::get_dmrpp_object(const string &name)
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.
Provide a way to print the DMR++ response.
Definition: DMRpp.h:44
void print_dap4(libdap::XMLWriter &xml, bool constrained=false)
override DMR::print_dap4() so the chunk info will print too.
Definition: DMRpp.cc:140
void intern(std::istream &f, libdap::DMR *dest_dmr)
Hack use a DMR to write a DMR++ response. WIP.