Field3D
SparseDataReader.h
Go to the documentation of this file.
1 //----------------------------------------------------------------------------//
2 
3 /*
4  * Copyright (c) 2009 Sony Pictures Imageworks Inc
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution. Neither the name of Sony Pictures Imageworks nor the
18  * names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior written
20  * permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 //----------------------------------------------------------------------------//
37 
42 //----------------------------------------------------------------------------//
43 
44 #ifndef _INCLUDED_Field3D_SparseDataReader_H_
45 #define _INCLUDED_Field3D_SparseDataReader_H_
46 
47 //----------------------------------------------------------------------------//
48 
49 #include <hdf5.h>
50 #include <string.h> // for memcpy
51 
52 #include "Hdf5Util.h"
53 
54 //----------------------------------------------------------------------------//
55 
56 #include "ns.h"
57 
59 
60 //----------------------------------------------------------------------------//
61 // SparseDataReader
62 //----------------------------------------------------------------------------//
63 
68 template <class Data_T>
70 {
71 public:
72 
73  // Constructors --------------------------------------------------------------
74 
77  SparseDataReader(hid_t location, int valuesPerBlock, int occupiedBlocks);
78 
79  // Main methods --------------------------------------------------------------
80 
83  void readBlock(int idx, Data_T &result);
84 
87  void readBlockList(int idx, const std::vector<Data_T*>& memoryList);
88 
89 private:
90 
91  // Data members --------------------------------------------------------------
92 
97 
99 
100  const std::string k_dataStr;
101 };
102 
103 //----------------------------------------------------------------------------//
104 // SparseDataReader implementations
105 //----------------------------------------------------------------------------//
106 
107 template <class Data_T>
108 SparseDataReader<Data_T>::SparseDataReader(hid_t location, int valuesPerBlock,
109  int occupiedBlocks)
110  : m_valuesPerBlock(valuesPerBlock),
111  k_dataStr("data")
112 {
113  using namespace Hdf5Util;
114  using namespace Exc;
115 
116  GlobalLock lock(g_hdf5Mutex);
117 
118  hsize_t dims[2];
119  hsize_t memDims[1];
120 
121  // Open the data set
122  m_dataSet.open(location, k_dataStr, H5P_DEFAULT);
123  if (m_dataSet.id() < 0)
124  throw OpenDataSetException("Couldn't open data set: " + k_dataStr);
125 
126  // Get the space and type
129  if (m_fileDataSpace.id() < 0)
130  throw GetDataSpaceException("Couldn't get data space");
131  if (m_dataType.id() < 0)
132  throw GetDataTypeException("Couldn't get data type");
133 
134  // Make the memory data space
135  memDims[0] = m_valuesPerBlock;
136  m_memDataSpace.create(H5S_SIMPLE);
137  H5Sset_extent_simple(m_memDataSpace.id(), 1, memDims, NULL);
138 
139  // Get the dimensions and check they match
140  H5Sget_simple_extent_dims(m_fileDataSpace.id(), dims, NULL);
141  if (dims[1] != static_cast<hsize_t>(m_valuesPerBlock)) {
142  throw FileIntegrityException("Block length mismatch in "
143  "SparseDataReader");
144  }
145  if (dims[0] != static_cast<hsize_t>(occupiedBlocks))
146  throw FileIntegrityException("Block count mismatch in "
147  "SparseDataReader");
148 }
149 
150 //----------------------------------------------------------------------------//
151 
152 template <class Data_T>
153 void SparseDataReader<Data_T>::readBlock(int idx, Data_T &result)
154 {
155  using namespace Hdf5Util;
156  using namespace Exc;
157 
158  GlobalLock lock(g_hdf5Mutex);
159 
160  hsize_t offset[2];
161  hsize_t count[2];
162  herr_t status;
163 
164  offset[0] = idx; // Index of block
165  offset[1] = 0; // Index of first data in block. Always 0
166  count[0] = 1; // Number of columns to read. Always 1
167  count[1] = m_valuesPerBlock; // Number of values in one column
168 
169  status = H5Sselect_hyperslab(m_fileDataSpace.id(), H5S_SELECT_SET,
170  offset, NULL, count, NULL);
171 
172  if (status < 0) {
173  throw ReadHyperSlabException("Couldn't select slab in readBlock(): " +
174  boost::lexical_cast<std::string>(idx));
175  }
176 
177  status = H5Dread(m_dataSet.id(), DataTypeTraits<Data_T>::h5type(),
179  H5P_DEFAULT, &result);
180 }
181 
182 //----------------------------------------------------------------------------//
183 
184 template <class Data_T>
186 (int idxLo, const std::vector<Data_T*>& memoryList)
187 {
188  using namespace Hdf5Util;
189  using namespace Exc;
190 
191  GlobalLock lock(g_hdf5Mutex);
192 
193  hsize_t offset[2];
194  hsize_t count[2];
195  herr_t status;
196 
197  offset[0] = idxLo; // Index of block
198  offset[1] = 0; // Index of first data in block. Always 0
199  count[0] = memoryList.size(); // Number of columns to read.
200  count[1] = m_valuesPerBlock; // Number of values in one column
201 
202  status = H5Sselect_hyperslab(m_fileDataSpace.id(), H5S_SELECT_SET,
203  offset, NULL, count, NULL);
204  if (status < 0) {
205  throw ReadHyperSlabException("Couldn't select slab in readBlockList():" +
206  boost::lexical_cast<std::string>(idxLo));
207  }
208 
209  // Make the memory data space ---
210 
211  Hdf5Util::H5ScopedScreate localMemDataSpace;
212  hsize_t memDims[2];
213  memDims[0] = memoryList.size();
214  memDims[1] = m_valuesPerBlock;
215  localMemDataSpace.create(H5S_SIMPLE);
216  H5Sset_extent_simple(localMemDataSpace.id(), 2, memDims, NULL);
217 
218  // Setup the temporary memory region ---
219 
220  int bytesPerValue = 0;
221  {
222  hid_t t = DataTypeTraits<Data_T>::h5type();
223  if (t == H5T_NATIVE_CHAR)
224  bytesPerValue = 1;
225  else if (t == H5T_NATIVE_SHORT)
226  bytesPerValue = 2;
227  else if (t == H5T_NATIVE_FLOAT)
228  bytesPerValue = 4;
229  else if (t == H5T_NATIVE_DOUBLE)
230  bytesPerValue = 8;
231  }
232 
233  int dim = sizeof(Data_T) / bytesPerValue;
234  std::vector<Data_T> bigblock(memoryList.size() * m_valuesPerBlock/dim);
235 
236  status = H5Dread(m_dataSet.id(),
238  localMemDataSpace.id(),
239  m_fileDataSpace.id(),
240  H5P_DEFAULT, &bigblock[0]);
241 
242  if (status < 0) {
243  throw Hdf5DataReadException("Couldn't read slab " +
244  boost::lexical_cast<std::string>(idxLo));
245  }
246 
247  // Distribute block data into memory slots ---
248  for (size_t i = 0; i < memoryList.size(); ++i) {
249  memcpy(memoryList[i],
250  &bigblock[i * m_valuesPerBlock / dim],
251  bytesPerValue * m_valuesPerBlock);
252  }
253 }
254 
255 //----------------------------------------------------------------------------//
256 
258 
259 //----------------------------------------------------------------------------//
260 
261 #endif
void open(hid_t dataset_id)
Definition: Hdf5Util.h:398
#define FIELD3D_NAMESPACE_HEADER_CLOSE
Definition: ns.h:58
Hdf5Util::H5ScopedScreate m_memDataSpace
Contains utility functions and classes for Hdf5 files.
Definition: Hdf5Util.h:86
Scoped object - opens a dataset on creation and closes it on destruction.
Definition: Hdf5Util.h:416
Namespace for Exception objects.
Definition: Exception.h:57
void readBlockList(int idx, const std::vector< Data_T * > &memoryList)
Reads a series of blocks, storing each block of data in memoryList, which is assumed to contain enoug...
SparseDataReader(hid_t location, int valuesPerBlock, int occupiedBlocks)
Constructor. Requires knowledge of the Hdf5 location where data is stored.
Scoped object - opens a dataset on creation and closes it on destruction.
Definition: Hdf5Util.h:356
boost::recursive_mutex::scoped_lock GlobalLock
Definition: Hdf5Util.h:78
Contains various utility functions for Hdf5.
Hdf5Util::H5ScopedDget_space m_fileDataSpace
void open(hid_t dataset_id)
Definition: Hdf5Util.h:428
void readBlock(int idx, Data_T &result)
Reads a block, storing the data in result, which is assumed to contain enough room for m_valuesPerBlo...
const std::string k_dataStr
This class gets used by SparseFieldIO and SparseFileManager to read the block data. On creation it will open the data set and not close it until the object is destroyed.
void open(hid_t parentLocation, const std::string &name, hid_t dapl_id)
Definition: Hdf5Util.h:368
static hid_t h5type()
Hdf5Util::H5ScopedDget_type m_dataType
Scoped object - creates a dataspace on creation and closes it on destruction.
Definition: Hdf5Util.h:234
FIELD3D_NAMESPACE_OPEN FIELD3D_API boost::recursive_mutex g_hdf5Mutex
Definition: Hdf5Util.cpp:67
Hdf5Util::H5ScopedDopen m_dataSet
void create(H5S_class_t type)
Definition: Hdf5Util.h:246
Scoped object - opens a dataset on creation and closes it on destruction.
Definition: Hdf5Util.h:386
hid_t id() const
Query the hid_t value.
Definition: Hdf5Util.h:100