OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
NCMLArray.h
Go to the documentation of this file.
1 // This file is part of the "NcML Module" project, a BES module designed
3 // to allow NcML files to be used to be used as a wrapper to add
4 // AIS to existing datasets of any format.
5 //
6 // Copyright (c) 2009 OPeNDAP, Inc.
7 // Author: Michael Johnson <m.johnson@opendap.org>
8 //
9 // For more information, please also see the main website: http://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 // Please see the files COPYING and COPYRIGHT for more information on the GLPL.
26 //
27 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
29 #ifndef __NCML_MODULE__NCMLARRAY_H__
30 #define __NCML_MODULE__NCMLARRAY_H__
31 
32 #include <dods-datatypes.h>
33 #include <Array.h>
34 #include <BaseType.h>
35 #include <Vector.h>
36 #include <memory>
37 #include "MyBaseTypeFactory.h"
38 #include "NCMLBaseArray.h"
39 #include "NCMLDebug.h"
40 #include "Shape.h"
41 #include <sstream>
42 #include <string>
43 #include <typeinfo>
44 #include <vector>
45 
46 using libdap::Array;
47 using libdap::dods_byte;
48 using libdap::dods_int16;
49 using libdap::dods_uint16;
50 using libdap::dods_int32;
51 using libdap::dods_uint32;
52 using libdap::dods_float32;
53 using libdap::dods_float64;
54 
55 using std::string;
56 using std::vector;
57 
58 namespace ncml_module
59 {
60  class Shape;
61 
82 template <typename T>
83 class NCMLArray : public NCMLBaseArray
84 {
85 public: // Class methods
86 
87 public: // Instance methods
89  : NCMLBaseArray("")
90  , _allValues(0)
91  {
92  }
93 
94  explicit NCMLArray(const string& name)
95  : NCMLBaseArray(name)
96  , _allValues(0)
97  {
98  }
99 
100  explicit NCMLArray(const NCMLArray<T>& proto)
101  : NCMLBaseArray(proto)
102  , _allValues(0)
103  {
104  copyLocalRepFrom(proto);
105  }
106 
108  virtual ~NCMLArray()
109  {
110  destroy(); // helper
111  }
112 
113  NCMLArray<T>&
115  {
116  if (&rhs == this)
117  {
118  return *this;
119  }
120 
121  // Call the super assignment
123 
124  // Copy local private rep
125  copyLocalRepFrom(rhs);
126 
127  return *this;
128  }
129 
132  {
133  return new NCMLArray(*this);
134  }
135 
143  virtual void copyDataFrom(libdap::Array& from)
144  {
145  // We both better have a valid template class.
146  VALID_PTR(from.var());
147 
148  // clear out any current local values
149  destroy();
150 
151  // OK, now that we have it, we need to copy the attribute table and the prototype variable
152  set_attr_table(from.get_attr_table());
153  add_var(from.var()->ptr_duplicate()); // TODO This may leak memory
154 
155  // add all the dimensions
156  Array::Dim_iter endIt = from.dim_end();
157  Array::Dim_iter it;
158  for (it = from.dim_begin(); it != endIt; ++it)
159  {
160  Array::dimension& dim = *it;
161  append_dim(dim.size, dim.name);
162  }
163 
164  // Finally, copy the data.
165  // Initialize with length() values so the storage and size of _allValues is correct.
166  _allValues = new std::vector<T>(from.length());
167  NCML_ASSERT(_allValues->size() == static_cast<unsigned int>(from.length()));
168 
169  // Copy the values in from._buf into our cache!
170  T* pFirst = &((*_allValues)[0]);
171  from.buf2val(reinterpret_cast<void**>(&pFirst));
172  }
173 
174  virtual bool isDataCached() const
175  {
176  return _allValues;
177  }
178 
180  // We have to override these to make a copy in this subclass as well since constraints added before read().
181  // TODO Consider instead allowing add_constraint() in Array to be virtual so we can catch it and cache at that point rather than
182  // all the time!!
183 
184  // Helper macros to avoid a bunch of cut & paste
185 
186 #define NCMLARRAY_CHECK_ARRAY_TYPE_THEN_CALL_SUPER(arrayValue, sz) \
187  if (typeid(arrayValue) != typeid(T*)) \
188  { \
189  THROW_NCML_INTERNAL_ERROR("NCMLArray<T>::set_value(): got wrong type of value array, doesn't match type T!"); \
190  } \
191  bool ret = Vector::set_value((arrayValue), (sz)); \
192  cacheSuperclassStateIfNeeded(); \
193  return ret;
194 
195 #define NCMLARRAY_CHECK_VECTOR_TYPE_THEN_CALL_SUPER(vecValue, sz) \
196  if (typeid(vecValue) != typeid(vector<T>&)) \
197  { \
198  THROW_NCML_INTERNAL_ERROR("NCMLArray<T>::setValue(): got wrong type of value vector, doesn't match type T!"); \
199  } \
200  bool ret = Vector::set_value((vecValue), (sz)); \
201  cacheSuperclassStateIfNeeded(); \
202  return ret;
203 
204  virtual bool set_value(dods_byte *val, int sz)
205  {
207  }
208 
209  virtual bool set_value(vector<dods_byte> &val, int sz)
210  {
212  }
213 
214  virtual bool set_value(dods_int16 *val, int sz)
215  {
217  }
218 
219  virtual bool set_value(vector<dods_int16> &val, int sz)
220  {
222  }
223 
224  virtual bool set_value(dods_uint16 *val, int sz)
225  {
227  }
228 
229  virtual bool set_value(vector<dods_uint16> &val, int sz)
230  {
232  }
233 
234  virtual bool set_value(dods_int32 *val, int sz)
235  {
237  }
238 
239  virtual bool set_value(vector<dods_int32> &val, int sz)
240  {
242  }
243 
244  virtual bool set_value(dods_uint32 *val, int sz)
245  {
247  }
248 
249  virtual bool set_value(vector<dods_uint32> &val, int sz)
250  {
252  }
253 
254  virtual bool set_value(dods_float32 *val, int sz)
255  {
257  }
258 
259  virtual bool set_value(vector<dods_float32> &val, int sz)
260  {
262  }
263 
264  virtual bool set_value(dods_float64 *val, int sz)
265  {
267  }
268 
269  virtual bool set_value(vector<dods_float64> &val, int sz)
270  {
272  }
273 
274  virtual bool set_value(string *val, int sz)
275  {
277  }
278 
279  virtual bool set_value(vector<string> &val, int sz)
280  {
282  }
283 
284 #undef NCMLARRAY_CHECK_ARRAY_TYPE_THEN_CALL_SUPER
285 #undef NCMLARRAY_CHECK_VECTOR_TYPE_THEN_CALL_SUPER
286 
287 protected:
288 
298  virtual void cacheValuesIfNeeded()
299  {
300  // If the super Vector has no capacity, it's not set up correctly, so don't call this or we get exception.
301  if (get_value_capacity() == 0)
302  {
303  BESDEBUG("ncml", "cacheValuesIfNeeded: the superclass Vector has no data so not copying...");
304  }
305 
306  // If we haven't gotten this yet, go get it,
307  // assuming the super Vector contains all values
308  if (!_allValues)
309  {
310  BESDEBUG("ncml", "NCMLArray<T>:: we don't have unconstrained values cached, caching from Vector now..." << endl);
311  unsigned int spaceSize = _noConstraints->getUnconstrainedSpaceSize();
312  // These must match or we're not getting all the data and the caller messed up.
313  NCML_ASSERT_MSG(static_cast<unsigned int>(length()) == spaceSize,
314  "NCMLArray expected superclass Vector length() to be the same as unconstrained space size, but it wasn't!");
315  // Make new default storage with enough space for all the data.
316  _allValues = new vector<T>(spaceSize);
317  NCML_ASSERT(_allValues->size() == spaceSize); // the values should all be default for T().
318  // Grab the address of the start of the vector memory block.
319  // This is safe since vector memory is required to be contiguous
320  T* pFirstElt = &((*_allValues)[0]);
321  // Now overwrite the defaults in from the buffer.
322  unsigned int stored = buf2val(reinterpret_cast<void**>(&pFirstElt));
323  NCML_ASSERT((stored/sizeof(T)) == spaceSize); // make sure it did what it was supposed to do.
324  // OK, we have our copy now!
325  }
326 
327  // We ignore the current constraints since we don't worry about them until later in read().
328  }
329 
339  {
340  BESDEBUG("ncml", "NCMLArray<T>::createAndSetConstrainedValueBuffer() called!" << endl);
341 
342  // Whether to validate, depending on debug build or not.
343  #ifdef NDEBUG
344  const bool validateBounds = false;
345  #else
346  const bool validateBounds = true;
347  #endif
348 
349  // These need to exist or caller goofed.
351  VALID_PTR(_allValues);
352 
353  // This reflects the current constraints, so is what we want.
354  unsigned int numVals = length();
355  vector<T> values; // Exceptions may wind through and I want this storage cleaned, so vector<T> rather than T*.
356  values.reserve(numVals);
357 
358  // Our current space, with constraints
359  const Shape shape = getSuperShape();
362  unsigned int count=0; // just a counter for number of points for sanity checking
363  for (it = shape.beginSpaceEnumeration(); it != endIt; ++it, ++count)
364  {
365  // Take the current point in constrained space, look it up in cached 3values, set it as next elt in output
366  values.push_back( (*_allValues)[_noConstraints->getRowMajorIndex(*it, validateBounds)] );
367  }
368 
369  // Sanity check the number of points we added. They need to match or something is wrong.
370  if (count != static_cast<unsigned int>(length()))
371  {
372  stringstream msg;
373  msg << "While adding points to hyperslab buffer we got differing number of points "
374  "from Shape space enumeration as expected from the constraints! "
375  "Shape::IndexIterator produced " << count << " points but we expected " << length();
376  THROW_NCML_INTERNAL_ERROR(msg.str());
377  }
378 
379  if (count != shape.getConstrainedSpaceSize())
380  {
381  stringstream msg;
382  msg << "While adding points to hyperslab buffer we got differing number of points "
383  "from Shape space enumeration as expected from the shape.getConstrainedSpaceSize()! "
384  "Shape::IndexIterator produced " << count << " points but we expected " << shape.getConstrainedSpaceSize();
385  THROW_NCML_INTERNAL_ERROR(msg.str());
386  }
387 
388  // Otherwise, we're good, so blast the values into the valuebuffer.
389  // tell it to reuse the current buffer since by definition is has enough room since it holds all points to start.
390  val2buf(static_cast<void*>(&(values[0])), true);
391  }
392 
393 private: // This class ONLY methods
394 
397  void copyLocalRepFrom(const NCMLArray<T>& proto)
398  {
399  // Avoid unnecessary finagling
400  if (&proto == this)
401  {
402  return;
403  }
404 
405  // Blow away any old data before copying new
406  destroy();
407 
408  // If there are values, make a copy of the vector.
409  if (proto._allValues)
410  {
411  _allValues = new vector<T>(*(proto._allValues));
412  }
413  }
414 
416  void destroy() throw ()
417  {
418  delete _allValues; _allValues=0;
419  }
420 
421 private:
422 
423  // The unconstrained data set, cached from super in first call to cacheSuperclassStateIfNeeded()
424  // if it is null.
425  std::vector<T>* _allValues;
426 
427 }; // class NCMLArray<T>
428 
429 } // namespace ncml_module
430 
431 #endif /* __NCML_MODULE__NCMLARRAY_H__ */
virtual Shape getSuperShape() const
Get the current dimensions of our superclass Array as a Shape object.
Shape::IndexIterator endSpaceEnumeration() const
The end of the enumeration for testing end conditions.
Definition: Shape.cc:178
virtual void createAndSetConstrainedValueBuffer()
If we have constraints that are not the same as the constraints on the last read() call (or if this i...
Definition: NCMLArray.h:338
virtual bool set_value(string *val, int sz)
Definition: NCMLArray.h:274
A custom iterator that enumerates all the points in the space defined by a Shape in row major order...
Definition: Shape.h:72
A parameterized subclass of libdap::Array that allows us to apply constraints on NcML-specified data ...
Definition: NCMLArray.h:83
unsigned int getUnconstrainedSpaceSize() const
Get the product of all the dimension sizes.
Definition: Shape.h:163
#define NCML_ASSERT(cond)
Definition: NCMLDebug.h:80
virtual void cacheValuesIfNeeded()
The first time we get a read(), we want to grab the current state of the superclass Array and Vector ...
Definition: NCMLArray.h:298
An abstract superclass for NCMLArray that handles the non-parameterized functionality and allows u...
virtual void copyDataFrom(libdap::Array &from)
Copy the rep from the given Array.
Definition: NCMLArray.h:143
#define NCML_ASSERT_MSG(cond, msg)
Definition: NCMLDebug.h:83
virtual bool set_value(dods_uint32 *val, int sz)
Definition: NCMLArray.h:244
virtual bool set_value(dods_float32 *val, int sz)
Definition: NCMLArray.h:254
virtual bool set_value(vector< dods_uint32 > &val, int sz)
Definition: NCMLArray.h:249
#define NCMLARRAY_CHECK_ARRAY_TYPE_THEN_CALL_SUPER(arrayValue, sz)
Definition: NCMLArray.h:186
NCMLArray(const string &name)
Definition: NCMLArray.h:94
A wrapper class for a vector of Array::dimension structs.
Definition: Shape.h:59
virtual bool set_value(dods_byte *val, int sz)
Definition: NCMLArray.h:204
virtual bool set_value(vector< dods_int16 > &val, int sz)
Definition: NCMLArray.h:219
NCMLBaseArray & operator=(const NCMLBaseArray &rhs)
virtual bool set_value(dods_uint16 *val, int sz)
Definition: NCMLArray.h:224
virtual bool set_value(vector< dods_int32 > &val, int sz)
Definition: NCMLArray.h:239
Shape::IndexIterator beginSpaceEnumeration() const
Create a forward iterator that returns IndexTuple's in a row major order (leftmost dimension slowest ...
Definition: Shape.cc:172
virtual bool set_value(vector< string > &val, int sz)
Definition: NCMLArray.h:279
virtual bool set_value(vector< dods_byte > &val, int sz)
Definition: NCMLArray.h:209
virtual NCMLArray< T > * ptr_duplicate()
Override virtual constructor, deep clone.
Definition: NCMLArray.h:131
#define THROW_NCML_INTERNAL_ERROR(msg)
Definition: NCMLDebug.h:61
virtual bool set_value(vector< dods_float32 > &val, int sz)
Definition: NCMLArray.h:259
virtual bool set_value(vector< dods_float64 > &val, int sz)
Definition: NCMLArray.h:269
virtual bool isDataCached() const
Definition: NCMLArray.h:174
NCMLArray< T > & operator=(const NCMLArray< T > &rhs)
Definition: NCMLArray.h:114
virtual bool set_value(dods_int32 *val, int sz)
Definition: NCMLArray.h:234
virtual bool set_value(dods_int16 *val, int sz)
Definition: NCMLArray.h:214
virtual ~NCMLArray()
Destroy any locally cached data.
Definition: NCMLArray.h:108
#define VALID_PTR(ptr)
Definition: NCMLDebug.h:88
#define NCMLARRAY_CHECK_VECTOR_TYPE_THEN_CALL_SUPER(vecValue, sz)
Definition: NCMLArray.h:195
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
unsigned int getRowMajorIndex(const IndexTuple &indices, bool validate=true) const
Return the row major linear index into a slowest varying dimension first flattening of the given UNCO...
Definition: Shape.cc:155
NCMLArray(const NCMLArray< T > &proto)
Definition: NCMLArray.h:100
virtual bool set_value(dods_float64 *val, int sz)
Definition: NCMLArray.h:264
unsigned int getConstrainedSpaceSize() const
Get the production of all dimension c_sizes.
Definition: Shape.h:174
virtual bool set_value(vector< dods_uint16 > &val, int sz)
Definition: NCMLArray.h:229