SheafSystem  0.0.0.0
file_data_type_map.cc
1 
2 //
3 // Copyright (c) 2014 Limit Point Systems, Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 
18 // Implementation for class file_data_type_map
19 
20 #include "SheafSystem/file_data_type_map.h"
21 
22 #include "SheafSystem/assert_contract.h"
23 #include "SheafSystem/data_converter.h"
24 #include "SheafSystem/namespace_relative_member_index.h"
25 #include "SheafSystem/namespace_relative_subposet_index.h"
26 #include "SheafSystem/primitive_attributes.h"
27 #include "SheafSystem/sheaf_file.h"
28 
29 using namespace std;
30 
31 // ===========================================================
32 // ANY FACET
33 // ===========================================================
34 
38 clone() const
39 {
40  file_data_type_map* result;
41 
42  // Preconditions:
43 
44  // Body:
45 
46  result = new file_data_type_map(*this);
47 
48  // Postconditions:
49 
50  ensure(result != 0);
51  ensure(is_same_type(result));
52 
53  // Exit:
54 
55  return result;
56 }
57 
58 
59 
60 
62 bool
64 invariant() const
65 {
66  bool result = true;
67 
68  // Preconditions:
69 
70  // Body:
71 
72  // Must satisfy base class invariant
73 
74  result = result && data_type_map::invariant();
75 
76  if(invariant_check())
77  {
78  // Prevent recursive calls to invariant
79 
80  disable_invariant_check();
81 
82  // Finished, turn invariant checking back on.
83 
84  enable_invariant_check();
85  }
86 
87  // Postconditions:
88 
89  // Exit
90 
91  return result;
92 }
93 
95 bool
97 is_ancestor_of(const any* other) const
98 {
99 
100  // Preconditions:
101 
102  require(other != 0);
103 
104  // Body:
105 
106  // True if other conforms to this
107 
108  bool result = dynamic_cast<const file_data_type_map*>(other) != 0;
109 
110  // Postconditions:
111 
112  return result;
113 
114 }
115 
116 
117 
118 // ===========================================================
119 // FILE_DATA_TYPE_MAP FACET
120 // ===========================================================
121 
122 
124 sheaf::file_data_type_map::
125 file_data_type_map(hid_t xfile, bool xcreate_ext_types)
126 {
127 
128  // Preconditions:
129 
130  // Body:
131 
132  _file = xfile;
133 
134  // Some of the internal HDF types are not predefined; must create them.
135 
136  hid_t linternal_hdf_types[PRIMITIVE_TYPE_END];
137  create_internal_hdf_types(linternal_hdf_types, PRIMITIVE_TYPE_END);
138 
139  // Get the external hdf types.
140 
141  hid_t lexternal_hdf_types[PRIMITIVE_TYPE_END];
142  if(xcreate_ext_types)
143  {
144  // Must create the external types.
145 
146  create_external_hdf_types(linternal_hdf_types,
147  PRIMITIVE_TYPE_END,
148  lexternal_hdf_types,
149  PRIMITIVE_TYPE_END);
150  }
151  else
152  {
153  // External types are already in the file.
154 
155  open_external_hdf_types(lexternal_hdf_types, PRIMITIVE_TYPE_END);
156  }
157 
158  // Create a data converter for each type.
159 
160  _max_internal_size = 0;
161  _max_external_size = 0;
162 
163  for(int i=PRIMITIVE_TYPE_BEGIN; i<PRIMITIVE_TYPE_END; i++)
164  {
165  _converters[i] =
166  new data_converter(lexternal_hdf_types[i], linternal_hdf_types[i], i);
167 
168  size_t lsize = _converters[i]->internal_size();
169  _max_internal_size = lsize > _max_internal_size ? lsize : _max_internal_size;
170 
171  lsize = _converters[i]->external_size();
172  _max_external_size = lsize > _max_external_size ? lsize : _max_external_size;
173  }
174 
175  // Postconditions:
176 
177  ensure(invariant());
178  ensure(max_internal_size() > 0);
179  ensure(max_external_size() > 0);
180 
181  // Exit:
182 
183  return;
184 }
185 
187 sheaf::file_data_type_map::
188 file_data_type_map(const file_data_type_map& xother)
189  : data_type_map(xother)
190 {
191 
192  // Preconditions:
193 
194  // Body:
195 
196  // Nothing to do.
197 
198  // Postconditions:
199 
200  ensure(invariant());
201 }
202 
203 
204 
208 {
209 
210  // Preconditions:
211 
212  // Body:
213 
214  // Terminate access to the hdf types.
215 
216  close_internal_hdf_types();
217  close_external_hdf_types();
218 
219  // Delete the converters.
220 
221  for(int i=PRIMITIVE_TYPE_BEGIN; i<PRIMITIVE_TYPE_END; i++)
222  {
223  delete _converters[i];
224  }
225 
226  // Postconditions:
227 
228  // Exit:
229 
230  return;
231 }
232 
233 // ===========================================================
234 // PROTECTED MEMBER FUNCTIONS
235 // ===========================================================
236 
237 sheaf::file_data_type_map::
238 file_data_type_map()
239 {
240 
241  // Preconditions:
242 
243 
244  // Body:
245 
246  // Postconditions:
247 
248  // Exit:
249 
250  return;
251 }
252 
253 
254 // ===========================================================
255 // PRIVATE MEMBER FUNCTIONS
256 // ===========================================================
257 
258 // ///
259 // const char*
260 // sheaf::file_data_type_map::
261 // external_hdf_type_name(int xi)
262 // {
263 // const char* result;
264 
265 // // Preconditions:
266 
267 
268 // // Body:
269 
270 // static const char* EXTERNAL_HDF_TYPE_NAMES[PRIMITIVE_TYPE_END] =
271 // {
272 // "__not_a_type_name", // placeholder top member
273 // "__not_a_type_name", // placeholder bottom member
274 // "SHF_PRIMITIVE_SIZE_T",
275 // "SHF_PRIMITIVE_INT",
276 // "SHF_PRIMITIVE_DOUBLE",
277 // "SHF_PRIMITIVE_CHAR_PTR",
278 // "SHF_PRIMITIVE_VOID_PTR",
279 // "SHF_PRIMITIVE_POSET_MEMBER_INDEX",
280 // "SHF_PRIMITIVE_SUBPOSET_INDEX",
281 // "SHF_PRIMITIVE_CLIENT_ID",
282 // "SHF_PRIMITIVE_CHAR",
283 // "SHF_PRIMITIVE_USHORT",
284 // "SHF_PRIMITIVE_NAMESPACE_RELATIVE_MEMBER_INDEX",
285 // "SHF_PRIMITIVE_NAMESPACE_RELATIVE_SUBPOSET_INDEX"
286 // };
287 
288 // result = EXTERNAL_HDF_TYPE_NAMES[xi];
289 
290 // // Postconditions:
291 
292 // ensure(result != 0);
293 
294 // // Exit:
295 
296 // return result;
297 // }
298 
299 // ///
300 // hid_t
301 // sheaf::file_data_type_map::
302 // predefined_internal_hdf_type(int xi)
303 // {
304 // hid_t result;
305 
306 // // Preconditions:
307 
308 
309 // // Body:
310 
311 // static const hid_t PREDEFINED_INTERNAL_HDF_TYPES[PRIMITIVE_TYPE_END] =
312 // {
313 // 0, // placeholder for top member
314 // 0, // placeholder for bottom member
315 // H5T_NATIVE_ULONG, // size_t
316 // H5T_NATIVE_INT, // int
317 // H5T_NATIVE_DOUBLE, // double
318 // H5T_C_S1, // char_ptr; treated specially, see Notes 1 and 3 below.
319 // H5T_NATIVE_ULONG, // void_ptr
320 // H5T_NATIVE_INT, // scoped_index
321 // H5T_NATIVE_INT, // subposet_index; treated specially, see Note 2 below.
322 // H5T_NATIVE_INT, // client_id
323 // H5T_C_S1, // char; see Note 3 below.
324 // H5T_NATIVE_USHORT, // ushort
325 // H5T_NATIVE_INT, // namespace_relative_member_index; treated specially, see Note 2 below.
326 // H5T_NATIVE_INT // namespace_relative_subposet_index; treated specially, see Note 2 below.
327 
328 // // Note 1: this is the type of an individual char,
329 // // see class data_converter for how it is used.
330 
331 // // Note 2: the sheaf_primitive type is a struct
332 // // with this type as the type of its members.
333 // // See create_internal_hdf_types(). Since the
334 // // internal member ids are converted to record ids
335 // // in the file, this type must be the same as the
336 // // type used by record_index_converter for record ids.
337 // // See classes dof_tuple_record and table_dof_tuple_record
338 // // for usage.
339 
340 // // Note 3: This system uses the null padding option
341 // // instead of the default null termination. See routine
342 // // create_internal_hdf_types. See also HDF User's Guide/Datatypes/Section 3.6
343 // // for a discussion of how HDF treats character data.
344 // };
345 
346 
347 // result = PREDEFINED_INTERNAL_HDF_TYPES[xi];
348 
349 // // Postconditions:
350 
351 
352 // // Exit:
353 
354 // return result;
355 // }
356 
358 void
359 sheaf::file_data_type_map::
360 create_internal_hdf_types(hid_t* xinternal_hdf_types, size_t xinternal_hdf_types_ub)
361 {
362  // Preconditions:
363 
364  require(xinternal_hdf_types != 0);
365  require(xinternal_hdf_types_ub >= PRIMITIVE_TYPE_END);
366 
367  // Body:
368 
369  // Set all the predefined types
370 
371  for(int i=PRIMITIVE_TYPE_BEGIN; i<PRIMITIVE_TYPE_END; i++)
372  {
373  xinternal_hdf_types[i] = primitive_attributes::hdf_type(i);
374  }
375 
376  hid_t lhdf_id, lmbr_type;
377  herr_t lstatus;
378 
379  // Create char_ptr type.
380  // Data type for char_ptr is special variable length C string.
381 
382  lhdf_id = H5Tcopy(H5T_C_S1);
383  if(lhdf_id < 0)
384  {
385  post_fatal_error_message("Unable to copy H5T_C_S1 datatype.");
386  }
387 
388  lstatus = H5Tset_size(lhdf_id, H5T_VARIABLE);
389  if(lstatus < 0)
390  {
391  post_fatal_error_message("Unable to set char_ptr datatype padding.");
392  }
393 
394  xinternal_hdf_types[C_STRING] = lhdf_id;
395 
396  // // Create char type; same as char_ptr type.
397 
398  // lsheaf_id = CHAR;
399  // lhdf_id = H5Tcopy(H5T_C_S1);
400  // if(lhdf_id < 0)
401  // {
402  // post_fatal_error_message("Unable to copy H5T_C_S1 datatype.");
403  // }
404 
405  // lstatus = H5Tset_strpad(lhdf_id, H5T_STR_NULLPAD);
406  // if(lstatus < 0)
407  // {
408  // post_fatal_error_message("Unable to set char datatype padding.");
409  // }
410  // xinternal_hdf_types[lsheaf_id] = lhdf_id;
411 
412 
413  // Create namespace_relative_member_index_type
414 
416 
417  lhdf_id = H5Tcreate (H5T_COMPOUND, sizeof(nrmi_type));
418  if(lhdf_id < 0)
419  {
420  post_fatal_error_message("unable to create internal HDF type");
421  }
422 
423  lmbr_type = primitive_attributes::hdf_type(NAMESPACE_RELATIVE_MEMBER_INDEX);
424 
425  lstatus = H5Tinsert (lhdf_id, "poset_id", HOFFSET(nrmi_type, poset_id), lmbr_type);
426  if(lstatus < 0)
427  {
428  post_fatal_error_message("unable to insert member in compound data type");
429  }
430 
431  lstatus = H5Tinsert (lhdf_id, "member_id", HOFFSET(nrmi_type, member_id), lmbr_type);
432  if(lstatus < 0)
433  {
434  post_fatal_error_message("unable to insert member in compound data type");
435  }
436 
437  xinternal_hdf_types[NAMESPACE_RELATIVE_MEMBER_INDEX] = lhdf_id;
438 
439  // Create namespace_relative_subposet_index_type
440 
442 
443  lhdf_id = H5Tcreate (H5T_COMPOUND, sizeof(nrsi_type));
444  if(lhdf_id < 0)
445  {
446  post_fatal_error_message("unable to create internal HDF type");
447  }
448 
449  lmbr_type = primitive_attributes::hdf_type(NAMESPACE_RELATIVE_SUBPOSET_INDEX);
450 
451  lstatus = H5Tinsert (lhdf_id, "poset_id", HOFFSET(nrsi_type, poset_id), lmbr_type);
452  if(lstatus < 0)
453  {
454  post_fatal_error_message("unable to insert member in compound data type");
455  }
456 
457  lstatus = H5Tinsert (lhdf_id, "subposet_id", HOFFSET(nrsi_type, subposet_id), lmbr_type);
458  if(lstatus < 0)
459  {
460  post_fatal_error_message("unable to insert member in compound data type");
461  }
462 
463  xinternal_hdf_types[NAMESPACE_RELATIVE_SUBPOSET_INDEX] = lhdf_id;
464 
465  // Postconditions:
466 
467  // Exit
468 
469  return;
470 }
471 
472 
474 void
475 sheaf::file_data_type_map::
476 close_internal_hdf_types()
477 {
478  // Preconditions:
479 
480  require(unexecutable("converters are valid."));
481 
482  // Body:
483 
484  // Only close the types we created, not the predefined types.
485 
486  static const int lcloseable_internal_types[3] =
487  {
488  C_STRING,
489  NAMESPACE_RELATIVE_MEMBER_INDEX,
490  NAMESPACE_RELATIVE_SUBPOSET_INDEX
491  };
492 
493  for(int i= 0; i<3; i++)
494  {
495  // Attempt to close the type.
496 
497  if(H5Tclose(_converters[lcloseable_internal_types[i]]->internal_type()) < 0)
498  {
499  // Close failed.
500 
501  post_fatal_error_message("Unable to close internal HDF datatype.");
502  }
503  }
504 
505  // Postconditions:
506 
507  // Exit
508 
509  return;
510 }
511 
512 
514 void
515 sheaf::file_data_type_map::
516 create_external_hdf_types(const hid_t* xinternal_hdf_types,
517  size_t xinternal_hdf_types_ub,
518  hid_t* xexternal_hdf_types,
519  size_t xexternal_hdf_types_ub)
520 {
521  // Preconditions:
522 
523  require(xinternal_hdf_types != 0);
524  require(xinternal_hdf_types_ub >= PRIMITIVE_TYPE_END);
525  require(xexternal_hdf_types != 0);
526  require(xexternal_hdf_types_ub >= PRIMITIVE_TYPE_END);
527 
528  // Body:
529 
530  for(int i=PRIMITIVE_TYPE_BEGIN; i<PRIMITIVE_TYPE_END; i++)
531  {
532  // Attempt to create the external type
533 
534  hid_t lhdf_id = H5Tcopy(xinternal_hdf_types[i]);
535  if(lhdf_id < 0)
536  {
537  post_fatal_error_message("can't create external type");
538  }
539 
540  // Commit external type to file.
541 
542  string lhdf_name = primitive_attributes::hdf_type_name(i);
543  // herr_t lstatus = H5Tcommit(_file, lhdf_name.c_str(), lhdf_id);
544  herr_t lstatus = H5Tcommit1(_file, lhdf_name.c_str(), lhdf_id);
545  if(lstatus < 0)
546  {
547  post_fatal_error_message("can't commit external data type to file");
548  }
549 
550  xexternal_hdf_types[i] = lhdf_id;
551  }
552 
553  // Postconditions:
554 
555  // Exit
556 
557  return;
558 }
559 
561 void
562 sheaf::file_data_type_map::
563 open_external_hdf_types(hid_t* xexternal_hdf_types, size_t xexternal_hdf_types_ub)
564 {
565  // Preconditions:
566 
567  require(xexternal_hdf_types != 0);
568  require(xexternal_hdf_types_ub >= PRIMITIVE_TYPE_END);
569 
570  // Body:
571 
572  hid_t lhdf_id;
573 
574  for(int i=PRIMITIVE_TYPE_BEGIN; i<PRIMITIVE_TYPE_END; i++)
575  {
576  // Attempt to open the external type
577 
578  string lhdf_name = primitive_attributes::prototype(i).hdf_type_name();
579  // lhdf_id = H5Topen(_file, lhdf_name.c_str());
580  lhdf_id = H5Topen1(_file, lhdf_name.c_str());
581  if(lhdf_id < 0)
582  {
583  post_fatal_error_message("external type doesn't exist");
584  }
585 
586  xexternal_hdf_types[i] = lhdf_id;
587  }
588 
589  // Postconditions:
590 
591  // Exit
592 
593  return;
594 }
595 
596 
598 void
599 sheaf::file_data_type_map::
600 close_external_hdf_types()
601 {
602  // Preconditions:
603 
604  require(unexecutable("converters are valid."));
605 
606  // Body:
607 
608  for(int i=PRIMITIVE_TYPE_BEGIN; i<PRIMITIVE_TYPE_END; i++)
609  {
610  // Attempt to close the external type
611 
612  if(H5Tclose(_converters[i]->external_type()) < 0)
613  {
614  // Close failed.
615 
616  post_fatal_error_message("can't close external type");
617  }
618  }
619 
620  // Postconditions:
621 
622  // Exit
623 
624  return;
625 }
626 
hid_t _file
The hdf file handle.
A collection of data converters that map data types between internal and external representations ass...
static const std::string & hdf_type_name(pod_index_type xid)
The name in the hdf file of primitive type with id xid.
STL namespace.
virtual file_data_type_map * clone() const
Virtual constructor; makes a new instance of the same type as this.
Abstract base class with useful features for all objects.
Definition: any.h:39
int hdf_type() const
The hdf type of the primitive type associated with this.
POD type associated with namespace_relative_subposet_index.
Definition: pod_types.h:111
POD type for namespace_relative_member_index.
Definition: pod_types.h:79
virtual ~file_data_type_map()
Destructor.
static const primitive_attributes & prototype(pod_index_type xid)
The prototype for the primitive value of the type associated with xid.
virtual bool is_ancestor_of(const any *other) const
Conformance test; true if other conforms to this.
Function object to convert between internal and external data formats.
data_converter * _converters[PRIMITIVE_TYPE_END]
Table of converters, one for each type defined in the file.
A collection of data converters that map data types between internal and external representations...
Definition: data_type_map.h:49
virtual bool invariant() const
Class invariant.
const std::string & hdf_type_name() const
The name in the hdf file of the primitive type associated with this.