bes  Updated for version 3.20.10
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 #if 0
174  string href = "";
175  static_cast<dmrpp::DMRpp*>(d_dmr)->print_dmrpp(xml, href);
176 #endif
177 
178  os << xml.get_doc();
179  }
180  else {
181  throw BESInternalFatalError("StreamDMRpp output operator call with non-DMRpp instance.", __FILE__, __LINE__);
182  }
183 }
184 
196 bool
197 DmrppMetadataStore::add_responses(DMR *dmr, const string &name)
198 {
199  bool stored_dmr = GlobalMetadataStore::add_responses(dmr, name);
200 
201  bool stored_dmrpp = false;
202  if (typeid(*dmr) == typeid(dmrpp::DMRpp)) {
203  d_ledger_entry = string("add DMR++ ").append(name);
204 
205  StreamDMRpp write_the_dmrpp_response(dmr);
206  stored_dmrpp = store_dap_response(write_the_dmrpp_response, get_hash(name + "dmrpp_r"), name, "DMRpp");
207 
208  write_ledger(); // write the index line
209  }
210  else {
211  stored_dmrpp = true; // if dmr is not a DMRpp, not writing the object is 'success.'
212  }
213 
214  return(stored_dmr && stored_dmrpp);
215 }
216 
217 bool
218 DmrppMetadataStore::add_dmrpp_response(libdap::DMR *dmrpp, const std::string &name)
219 {
220  bool stored_dmrpp = false;
221  if (typeid(*dmrpp) == typeid(dmrpp::DMRpp)) {
222  d_ledger_entry = string("add DMR++ ").append(name);
223 
224  StreamDMRpp write_the_dmrpp_response(dmrpp);
225  stored_dmrpp = store_dap_response(write_the_dmrpp_response, get_hash(name + "dmrpp_r"), name, "DMRpp");
226 
227  write_ledger(); // write the index line
228  }
229  else {
230  stored_dmrpp = true; // if dmr is not a DMRpp, not writing the object is 'success.'
231  }
232 
233  return(stored_dmrpp);
234 }
235 
242 DMR *
243 DmrppMetadataStore::get_dmr_object(const string &name)
244 {
245  // Get the DMR response, but then parse that so the resulting binary
246  // object is built with DMR++ types so that the chunk information can be
247  // stored in them.
248  stringstream oss;
249  write_dmr_response(name, oss); // throws BESInternalError if not found
250 
251  DmrppTypeFactory dmrpp_btf;
252  unique_ptr<DMRpp> dmrpp(new DMRpp(&dmrpp_btf, "mds"));
253 
254  DmrppParserSax2 parser;
255  parser.intern(oss.str(), dmrpp.get());
256 
257  dmrpp->set_factory(0);
258 
259  return dmrpp.release();
260 }
261 
274 DMRpp *
275 DmrppMetadataStore::get_dmrpp_object(const string &name)
276 {
277  stringstream oss;
278  write_dmrpp_response(name, oss); // throws BESInternalError if not found
279 
280  DmrppTypeFactory dmrpp_btf;
281  unique_ptr<DMRpp> dmrpp(new DMRpp(&dmrpp_btf, "mds"));
282 
283  DmrppParserSax2 parser;
284  parser.intern(oss.str(), dmrpp.get());
285 
286  dmrpp->set_factory(0);
287 
288  return dmrpp.release();
289 }
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.