bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
CmrContainer.cc
1// CmrContainer.cc
2
3// -*- mode: c++; c-basic-offset:4 -*-
4
5// This file is part of cnr_module, A C++ module that can be loaded in to
6// the OPeNDAP Back-End Server (BES) and is able to handle remote requests.
7
8// Copyright (c) 2018 OPeNDAP, Inc.
9// Author: Nathan Potter <ndp@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
27// Authors:
28// ndp Nathan Potter <ndp@opendap.org>
29# include "config.h"
30
31#include <sstream>
32
33#include <BESSyntaxUserError.h>
34#include <BESInternalError.h>
35#include <BESNotFoundError.h>
36#include <BESDebug.h>
37#include <BESUtil.h>
38#include <TheBESKeys.h>
39#include <AllowedHosts.h>
40#include "RemoteResource.h"
41
42#include "CmrContainer.h"
43#include "CmrNames.h"
44#include "CmrApi.h"
45
46using namespace std;
47using namespace bes;
48
49#define prolog std::string("CmrContainer::").append(__func__).append("() - ")
50
51namespace cmr {
52
63CmrContainer::CmrContainer(const string &sym_name,
64 const string &real_name, const string &type) :
65 BESContainer(sym_name, real_name, type), d_remoteResource(0) {
66
67 BESDEBUG(MODULE, prolog << "BEGIN sym_name: " << sym_name
68 << " real_name: " << real_name << " type: " << type << endl);
69
70
71 string path = BESUtil::normalize_path(real_name, true, false);
72 vector<string> path_elements = BESUtil::split(path);
73 BESDEBUG(MODULE, prolog << "path: '" << path << "' path_elements.size(): " << path_elements.size() << endl);
74
75
77
78 if (type == "") {
79 // @TODO FIX Dynamically determine the type from the Granule information (type-match to name, mime-type, etc)
80 this->set_container_type("nc");
81 }
82
83
84 BESDEBUG( MODULE, prolog << "END" << endl);
85
86}
87
91CmrContainer::CmrContainer(const CmrContainer &copy_from) :
92 BESContainer(copy_from), d_remoteResource(copy_from.d_remoteResource) {
93 // we can not make a copy of this container once the request has
94 // been made
95 if (d_remoteResource) {
96 string err = (string) "The Container has already been accessed, "
97 + "can not create a copy of this container.";
98 throw BESInternalError(err, __FILE__, __LINE__);
99 }
100}
101
102void CmrContainer::_duplicate(CmrContainer &copy_to) {
103 if (copy_to.d_remoteResource) {
104 string err = (string) "The Container has already been accessed, "
105 + "can not duplicate this resource.";
106 throw BESInternalError(err, __FILE__, __LINE__);
107 }
108 copy_to.d_remoteResource = d_remoteResource;
110}
111
112BESContainer *
114 CmrContainer *container = new CmrContainer;
115 _duplicate(*container);
116 return container;
117}
118
119CmrContainer::~CmrContainer() {
120 if (d_remoteResource) {
121 release();
122 }
123}
124
131
132 BESDEBUG( MODULE, prolog << "BEGIN" << endl);
133
134 // Since this the CMR thang we know that the real_name is a path of facets and such.
135 string path = get_real_name();
136 BESDEBUG( MODULE, prolog << "path: " << path << endl);
137
138 auto granule = getTemporalFacetGranule(path);
139 if (!granule) {
140 throw BESNotFoundError("Failed to locate a granule associated with the path " + path, __FILE__, __LINE__);
141 }
142 string granule_url = granule->getDataGranuleUrl();
143
144 if(!d_remoteResource) {
145 BESDEBUG( MODULE, prolog << "Building new RemoteResource." << endl );
146 shared_ptr<http::url> target_url(new http::url(granule_url,true));
147 d_remoteResource = new http::RemoteResource(target_url);
148 d_remoteResource->retrieve_resource();
149 }
150 BESDEBUG( MODULE, prolog << "Retrieved RemoteResource." << endl );
151
152 string cachedResource = d_remoteResource->get_filename();
153 BESDEBUG( MODULE, prolog << "Using local cache file: " << cachedResource << endl );
154
155 string type = d_remoteResource->get_type();
156 set_container_type(type);
157 BESDEBUG( MODULE, prolog << "Type: " << type << endl );
158
159 BESDEBUG( MODULE, prolog << "Done accessing " << get_real_name() << " returning cached file " << cachedResource << endl);
160 BESDEBUG( MODULE, prolog << "Done accessing " << *this << endl);
161 BESDEBUG( MODULE, prolog << "END" << endl);
162
163 return cachedResource; // this should return the file name from the CmrCache
164}
165
166
167
175 BESDEBUG( MODULE, prolog << "BEGIN" << endl);
176 if (d_remoteResource) {
177 BESDEBUG( MODULE, prolog << "Releasing RemoteResource" << endl);
178 delete d_remoteResource;
179 d_remoteResource = nullptr;
180 }
181 BESDEBUG( MODULE, prolog << "END" << endl);
182 return true;
183}
184
192void CmrContainer::dump(ostream &strm) const {
193 strm << BESIndent::LMarg << prolog << "(" << (void *) this
194 << ")" << endl;
195 BESIndent::Indent();
196 BESContainer::dump(strm);
197 if (d_remoteResource) {
198 strm << BESIndent::LMarg << "RemoteResource.get_filename(): " << d_remoteResource->get_filename()
199 << endl;
200 } else {
201 strm << BESIndent::LMarg << "response not yet obtained" << endl;
202 }
203 BESIndent::UnIndent();
204}
205
211unique_ptr<Granule> CmrContainer::getTemporalFacetGranule(const std::string &granule_path)
212{
213 const unsigned int PATH_SIZE = 7;
214
215 BESDEBUG(MODULE, prolog << "BEGIN (granule_path: '" << granule_path << ")" << endl);
216
217 string path = BESUtil::normalize_path(granule_path,false, false);
218 vector<string> path_elements = BESUtil::split(path);
219 BESDEBUG(MODULE, prolog << "path: '" << path << "' path_elements.size(): " << path_elements.size() << endl);
220
221 if(path_elements.size() != PATH_SIZE){
222 stringstream msg;
223 msg << "The path component: '" << granule_path << "' of your request has ";
224 msg << (path_elements.size()<PATH_SIZE?"too few components. ":"too many components. ");
225 msg << "I was expecting " << PATH_SIZE << " elements but I found " << path_elements.size() << ". ";
226 msg << "I was unable to locate a granule from what you provided.";
227 throw BESNotFoundError(msg.str(),__FILE__,__LINE__);
228 }
229
230 // We don't need the provider_id for this operation, so commented out.
231 // string provider = path_elements[0];
232 // BESDEBUG(MODULE, prolog << " provider: '" << provider << endl);
233
234 string collection = path_elements[1];
235 BESDEBUG(MODULE, prolog << "collection: '" << collection << endl);
236 string facet = path_elements[2];
237 BESDEBUG(MODULE, prolog << " facet: '" << facet << endl);
238 string year = path_elements[3];
239 BESDEBUG(MODULE, prolog << " year: '" << year << endl);
240 string month = path_elements[4];
241 BESDEBUG(MODULE, prolog << " month: '" << month << endl);
242 string day = path_elements[5];
243 BESDEBUG(MODULE, prolog << " day: '" << day << endl);
244 string granule_id = path_elements[6];
245 BESDEBUG(MODULE, prolog << "granule_id: '" << granule_id << endl);
246
247 CmrApi cmrApi;
248 return cmrApi.get_granule( collection, year, month, day, granule_id);
249}
250
251
252
253} // namespace cmr
void set_container_type(const std::string &type)
set the type of data that this container represents, such as cedar or netcdf.
void dump(std::ostream &strm) const override
dumps information about this object
void set_relative_name(const std::string &relative)
Set the relative name of the object in this container.
void _duplicate(BESContainer &copy_to)
duplicate this instance into the passed container
std::string get_real_name() const
retrieve the real name for this container, such as a file name.
exception thrown if internal error encountered
error thrown if the resource requested cannot be found
static std::vector< std::string > split(const std::string &s, char delim='/', bool skip_empty=true)
Splits the string s into the return vector of tokens using the delimiter delim and skipping empty val...
Definition BESUtil.cc:1068
static std::string normalize_path(const std::string &path, bool leading_separator, bool trailing_separator, std::string separator="/")
Removes duplicate separators and provides leading and trailing separators as directed.
Definition BESUtil.cc:949
Container representing a remote request.
virtual bool release()
release the resources
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual BESContainer * ptr_duplicate()
pure abstract method to duplicate this instances of BESContainer
static std::unique_ptr< Granule > getTemporalFacetGranule(const std::string &granule_path)
virtual std::string access()
access the remote target response by making the remote request
Parse a URL into the protocol, host, path and query parts.
Definition url_impl.h:44