bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
HDFArray.cc
1// This file is part of the hdf4 data handler for the OPeNDAP data server.
2
3// Copyright (c) 2005 OPeNDAP, Inc.
4// Author: James Gallagher <jgallagher@opendap.org>
5//
6// This is free software; you can redistribute it and/or modify it under the
7// terms of the GNU Lesser General Public License as published by the Free
8// Software Foundation; either version 2.1 of the License, or (at your
9// option) any later version.
10//
11// This software is distributed in the hope that it will be useful, but
12// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14// License for more details.
15//
16// You should have received a copy of the GNU Lesser General Public License
17// along with this software; if not, write to the Free Software Foundation,
18// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19//
20// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
21
23// Copyright 1996, by the California Institute of Technology.
24// ALL RIGHTS RESERVED. United States Government Sponsorship
25// acknowledged. Any commercial use must be negotiated with the
26// Office of Technology Transfer at the California Institute of
27// Technology. This software may be subject to U.S. export control
28// laws and regulations. By accepting this software, the user
29// agrees to comply with all applicable U.S. export laws and
30// regulations. User has the responsibility to obtain export
31// licenses, or other export authority as may be required before
32// exporting such information to foreign countries or providing
33// access to foreign persons.
34
35// Author: Todd Karakashian, NASA/Jet Propulsion Laboratory
36// Todd.K.Karakashian@jpl.nasa.gov
37//
39
40#include "config_hdf.h"
41//#define DODS_DEBUG 1
42
43#include <vector>
44
45// Include this on linux to suppress an annoying warning about multiple
46// definitions of MIN and MAX.
47#ifdef HAVE_SYS_PARAM_H
48#include <sys/param.h>
49#endif
50#include <mfhdf.h>
51
52#include <hdfclass.h>
53#include <hcstream.h>
54
55#include <libdap/escaping.h>
56#include <libdap/Error.h>
57#include <libdap/debug.h>
58#include <BESDebug.h>
59
60#include "HDFArray.h"
61#include "dhdferr.h"
62
63using namespace libdap;
64using namespace std;
65
66HDFArray::HDFArray(const string &n, const string &d, BaseType * v) :
67 Array(n, d, v) {
68}
69
70HDFArray::~HDFArray() = default;
71
72
73BaseType *HDFArray::ptr_duplicate() {
74 return new HDFArray(*this);
75}
76void LoadArrayFromSDS(HDFArray * ar, const hdf_sds & sds);
77void LoadArrayFromGR(HDFArray * ar, const hdf_gri & gr);
78
79// Read in an Array from either an SDS or a GR in an HDF file.
80bool HDFArray::read() {
81 int err = 0;
82 int status = read_tagref(-1, -1, err);
83
84 if (err)
85 throw Error(unknown_error, "Could not read from dataset.");
86
87 return status;
88}
89
90// todo: refactor: get rid of the err value-result parameter; throw from
91// within this method.
92bool HDFArray::read_tagref(int32 tag, int32 ref, int &err) {
93 if (read_p())
94 return true;
95
96 // get the HDF dataset name, SDS name
97 string hdf_file = dataset();
98 string hdf_name = this->name();
99
100 // get slab constraint
101 vector<int> start;
102 vector<int> edge;
103 vector<int> stride;
104 bool isslab = GetSlabConstraint(start, edge, stride);
105
106 bool foundsds = false;
107 hdf_sds sds;
108 if (tag == -1 || tag == DFTAG_NDG) {
109 if (SDSExists(hdf_file.c_str(), hdf_name.c_str())) {
110 hdfistream_sds sdsin(hdf_file.c_str());
111 if (ref != -1) {
112 BESDEBUG("h4", "sds seek with ref = " << ref << endl);
113 sdsin.seek_ref(ref);
114 } else {
115 BESDEBUG("h4", "sds seek with name = '" << hdf_name << "'" << endl);
116 sdsin.seek(hdf_name.c_str());
117 }
118 if (isslab)
119 sdsin.setslab(start, edge, stride, false);
120 sdsin >> sds;
121 sdsin.close();
122 foundsds = true;
123 }
124 }
125
126 bool foundgr = false;
127 hdf_gri gr;
128 if (!foundsds && (tag == -1 || tag == DFTAG_VG)) {
129 if (GRExists(hdf_file.c_str(), hdf_name.c_str())) {
130 hdfistream_gri grin(hdf_file.c_str());
131 if (ref != -1)
132 grin.seek_ref(ref);
133 else
134 grin.seek(hdf_name.c_str());
135 if (isslab)
136 grin.setslab(start, edge, stride, false);
137 grin >> gr;
138 grin.close();
139 foundgr = true;
140 }
141 }
142
143 // Todo: refactor: move this stuff up into the above if stmts.
144 if (foundsds)
145 LoadArrayFromSDS(this, sds);
146 else if (foundgr)
147 LoadArrayFromGR(this, gr);
148
149 if (foundgr || foundsds) {
150 set_read_p(true); // Moved here; see bug 136
151 err = 0; // no error
152 return true;
153 } else {
154 err = 1;
155 return false;
156 }
157}
158
159// Read the slab constraint parameters; the arrays start_array, edge_array,
160// stride_array. Returns true if there is a slab constraint, false otherwise.
161bool HDFArray::GetSlabConstraint(vector<int>&start_array,
162 vector<int>&edge_array, vector<int>&stride_array) {
163 int start = 0;
164 int stop = 0;
165 int stride = 0;
166 int edge = 0;
167
168 start_array = vector<int> (0);
169 edge_array = vector<int> (0);
170 stride_array = vector<int> (0);
171
172 for (Array::Dim_iter p = dim_begin(); p != dim_end(); ++p) {
173 start = dimension_start(p, true);
174 stride = dimension_stride(p, true);
175 stop = dimension_stop(p, true);
176 if (start == 0 && stop == 0 && stride == 0)
177 return false; // no slab constraint
178 if (start > stop)
179 THROW(dhdferr_arrcons);
180 edge = ((stop - start) / stride) + 1;
181 if (start + edge > dimension_size(p))
182 THROW(dhdferr_arrcons);
183
184 start_array.push_back(start);
185 edge_array.push_back(edge);
186 stride_array.push_back(stride);
187 }
188 return true;
189}
190
212void HDFArray::transfer_attributes(AttrTable *at) {
213 BESDEBUG("h4","Transferring attributes for " << name() << endl);
214
215 BaseType::transfer_attributes(at);
216
217 BESDEBUG("h4","...Now looking for the " << name() << " _dim_n containers." << endl);
218
219 // Here we should look for the *_dim_n where '*' is name() and n is 0, 1, ...
220 string dim_name_base = name() + "_dim_";
221
222 AttrTable::Attr_iter a_p = at->attr_begin();
223 while (a_p != at->attr_end()) {
224 string::size_type i = at->get_name(a_p).find(dim_name_base);
225 // Found a matching container?
226 // To avoid matching both Month_dim_0 and DayOfMonth_dim_0, et c.,
227 // check that i == 0 and not just i != string::npos. jhrg 8/17/11
228 if (i == 0 && at->get_attr_type(a_p) == Attr_container) {
229 AttrTable *dim = at->get_attr_table(a_p);
230 try {
231 BESDEBUG("h4","Found a dimension container for " << name() << endl);
232 transfer_dimension_attribute(dim);
233 }
234 catch (Error &e) {
235 BESDEBUG("h4","Caught an error transferring dimension attribute " << dim->get_name() << " for variable " << name() << endl);
236 throw e;
237 }
238 }
239
240 a_p++;
241 }
242}
243
244void HDFArray::transfer_dimension_attribute(AttrTable *dim) {
245 // Mark the table as not global
246 dim->set_is_global_attribute(false);
247 // copy the table
248 auto at = new AttrTable(*dim);
249 // add it to this variable using just the 'dim_<digit>' part of the name
250 string name = at->get_name().substr(at->get_name().find("dim"));
251 get_attr_table().append_container(at, name);
252}
253
void transfer_attributes(libdap::AttrTable *at_container) override
Definition HDFArray.cc:212