bes Updated for version 3.20.10
h5das.cc
Go to the documentation of this file.
1// This file is part of hdf5_handler a HDF5 file handler for the OPeNDAP
2// data server.
3
4// Copyright (c) 2007-2016 The HDF Group, Inc. and OPeNDAP, Inc.
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
17// License along with this library; if not, write to the Free Software
18// Foundation, 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// You can contact The HDF Group, Inc. at 1800 South Oak Street,
22// Suite 203, Champaign, IL 61820
23
38#include "hdf5_handler.h"
39#include <BESDebug.h>
40
41using namespace std;
42using namespace libdap;
43
46
62void depth_first(hid_t pid, const char *gname, DAS & das)
63{
65 int slinkindex = 0;
66
67 // Although HDF5 comments are rarely used, we still keep this
68 // function.
69 read_comments(das, gname, pid);
70
71 H5G_info_t g_info;
72 hsize_t nelems;
73
74 if (H5Gget_info(pid, &g_info) < 0) {
75 string msg = "h5_das handler: unable to obtain the HDF5 group info. for ";
76 msg += gname;
77 throw InternalErr(__FILE__, __LINE__, msg);
78 }
79 nelems = g_info.nlinks;
80
81 ssize_t oname_size = 0;
82 for (hsize_t i = 0; i < nelems; i++) {
83
84 // Query the length of object name.
85 oname_size = H5Lget_name_by_idx(pid, ".", H5_INDEX_NAME, H5_ITER_NATIVE, i, NULL, (size_t) DODS_NAMELEN,
86 H5P_DEFAULT);
87
88 if (oname_size <= 0) {
89 string msg = "hdf5 object name error from: ";
90 msg += gname;
91 throw InternalErr(__FILE__, __LINE__, msg);
92 }
93 // Obtain the name of the object.
94 vector<char> oname(oname_size + 1);
95 if (H5Lget_name_by_idx(pid, ".", H5_INDEX_NAME, H5_ITER_NATIVE, i, &oname[0], (size_t) (oname_size + 1),
96 H5P_DEFAULT) < 0) {
97 string msg = "hdf5 object name error from: ";
98 msg += gname;
99 throw InternalErr(__FILE__, __LINE__, msg);
100 }
101
102 // Check if it is the hard link or the soft link
103 H5L_info_t linfo;
104 if (H5Lget_info(pid, &oname[0], &linfo, H5P_DEFAULT) < 0) {
105 string msg = "hdf5 link name error from: ";
106 msg += gname;
107 throw InternalErr(__FILE__, __LINE__, msg);
108 }
109
110 // This is the soft link.
111 if (linfo.type == H5L_TYPE_SOFT) {
112 slinkindex++;
113 size_t val_size = linfo.u.val_size;
114 get_softlink(das, pid, gname, &oname[0], slinkindex, val_size);
115 continue;
116 }
117
118 // Obtain the object type
119 H5O_info_t oinfo;
120 if (H5OGET_INFO_BY_IDX(pid, ".", H5_INDEX_NAME, H5_ITER_NATIVE, i, &oinfo, H5P_DEFAULT) < 0) {
121 string msg = "Cannot obtain the object info ";
122 msg += gname;
123 throw InternalErr(__FILE__, __LINE__, msg);
124 }
125 H5O_type_t obj_type = oinfo.type;
126
127 switch (obj_type) {
128
129 case H5O_TYPE_GROUP: {
130
131 BESDEBUG("h5", "=depth_first():H5G_GROUP " << &oname[0] << endl);
132
133 // This function will store the HDF5 group hierarchy into an DAP attribute.
134 add_group_structure_info(das, gname, &oname[0], true);
135
136 string full_path_name = string(gname) + string(&oname[0]) + "/";
137
138 hid_t cgroup = H5Gopen(pid, full_path_name.c_str(), H5P_DEFAULT);
139 if (cgroup < 0) {
140 string msg = "opening hdf5 group failed for ";
141 msg += full_path_name;
142 throw InternalErr(__FILE__, __LINE__, msg);
143 }
144
145 // Get the object info
146 H5O_info_t obj_info;
147 if (H5OGET_INFO(cgroup, &obj_info) < 0) {
148 H5Gclose(cgroup);
149 string msg = "Obtaining the hdf5 group info. failed for ";
150 msg += full_path_name;
151 throw InternalErr(__FILE__, __LINE__, msg);
152 }
153
154 // Obtain the number of attributes
155 int num_attr = obj_info.num_attrs;
156 if (num_attr < 0) {
157 H5Gclose(cgroup);
158 string msg = "Fail to get the number of attributes for group ";
159 msg += full_path_name;
160 throw InternalErr(__FILE__, __LINE__, msg);
161 }
162
163 // Read all attributes in this group and map to DAS.
164 try {
165 read_objects(das, full_path_name.c_str(), cgroup, num_attr);
166 }
167 catch (...) {
168 H5Gclose(cgroup);
169 throw;
170 }
171
172 // Check if this group has been visited by using the hardlink
173 string oid = get_hardlink(cgroup, full_path_name.c_str());
174
175 // Break the cyclic loop created by hard links.
176 if (oid.empty()) { // The group has never been visited, go to the next level.
177 depth_first(cgroup, full_path_name.c_str(), das);
178 }
179 else {
180
181 // This group has been visited.
182 // Add the attribute table with the attribute name as HDF5_HARDLINK.
183 // The attribute value is the name of the group when it is first visited.
184 AttrTable *at = das.get_table(full_path_name);
185 if (!at) {
186 at = das.add_table(full_path_name, new AttrTable);
187 }
188
189 // Note that "paths" is a global object to find the visited path.
190 // It is defined at the beginning of this source code file.
191 at->append_attr("HDF5_HARDLINK", STRING, paths.get_name(oid));
192 }
193
194 if (H5Gclose(cgroup) < 0) {
195 throw InternalErr(__FILE__, __LINE__, "H5Gclose() failed.");
196 }
197 break;
198 } // case H5G_GROUP
199
200 case H5O_TYPE_DATASET: {
201
202 BESDEBUG("h5", "=depth_first():H5G_DATASET " << &oname[0] << endl);
203
204 // This function will store the HDF5 group hierarchy into an DAP attribute.
205 add_group_structure_info(das, gname, &oname[0], false);
206
207 string full_path_name = string(gname) + string(&oname[0]);
208 hid_t dset = -1;
209
210 // Open the dataset
211 if ((dset = H5Dopen(pid, full_path_name.c_str(), H5P_DEFAULT)) < 0) {
212 string msg = "unable to open the hdf5 dataset of the group ";
213 msg += gname;
214 throw InternalErr(__FILE__, __LINE__, msg);
215 }
216
217 // Get the object info
218 H5O_info_t obj_info;
219 if (H5OGET_INFO(dset, &obj_info) < 0) {
220 H5Dclose(dset);
221 string msg = "Obtaining the info. failed for the dataset ";
222 msg += full_path_name;
223 throw InternalErr(__FILE__, __LINE__, msg);
224 }
225
226 // Obtain the number of attributes
227 int num_attr = obj_info.num_attrs;
228 if (num_attr < 0) {
229 H5Dclose(dset);
230 string msg = "Fail to get the number of attributes for dataset ";
231 msg += full_path_name;
232 throw InternalErr(__FILE__, __LINE__, msg);
233 }
234
235 // Read all attributes in this dataset and map to DAS.
236 try {
237 read_objects(das, full_path_name, dset, num_attr);
238 }
239 catch (...) {
240 H5Dclose(dset);
241 throw;
242 }
243
244 string oid = get_hardlink(dset, full_path_name);
245
246 // Break the cyclic loop created by hard links
247
248 // If this HDF5 dataset has been visited,
249 // Add the DAS table with the attribute name as HDF5_HARDLINK.
250 // The attribute value is the name of the HDF5 dataset when it is first visited.
251 if (!oid.empty()) {
252 // Add attribute table with HARDLINK
253 AttrTable *at = das.get_table(full_path_name);
254 if (!at) {
255 at = das.add_table(full_path_name, new AttrTable);
256 }
257
258 // Note that "paths" is a global object to find the visited path.
259 // It is defined at the beginning of this source code file.
260 at->append_attr("HDF5_HARDLINK", STRING, paths.get_name(oid));
261 }
262
263 if (H5Dclose(dset) < 0) {
264 throw InternalErr(__FILE__, __LINE__, "Could not close the dataset.");
265 }
266 break;
267 } // case H5G_DATASET
268
269 case H5O_TYPE_NAMED_DATATYPE:
270 // ignore the named datatype
271 break;
272
273 default:
274 break;
275 }
276 } // end for
277
278 BESDEBUG("h5", "<depth_first():" << gname << endl);
279}
280
281
283// \fn read_objects(DAS & das, const string & varname, hid_t oid, int num_attr)
295void read_objects(DAS & das, const string & varname, hid_t oid, int num_attr)
296{
297
298 BESDEBUG("h5", ">read_objects():" << "varname=" << varname << " id=" << oid << endl);
299
300 // Prepare a variable for full path attribute.
301 string hdf5_path = HDF5_OBJ_FULLPATH;
302
303 // Obtain the DAS table of which the name is the variable name.
304 // If not finding the table, add a table of which the name is the variable name.
305 AttrTable *attr_table_ptr = das.get_table(varname);
306 if (!attr_table_ptr) {
307 BESDEBUG("h5", "=read_objects(): adding a table with name " << varname << endl);
308 attr_table_ptr = das.add_table(varname, new AttrTable);
309 }
310
311 // Add a DAP attribute that stores the HDF5 absolute path
312 attr_table_ptr->append_attr(hdf5_path.c_str(), STRING, varname);
313
314 // Check the number of attributes in this HDF5 object and
315 // put HDF5 attribute information into the DAS table.
316 string print_rep;
317 vector<char> temp_buf;
318
319 bool ignore_attr = false;
320 hid_t attr_id = -1;
321 for (int j = 0; j < num_attr; j++) {
322
323 // Obtain attribute information.
324 DSattr_t attr_inst;
325
326 // Ignore the attributes of which the HDF5 datatype
327 // cannot be mapped to DAP2. The ignored attribute datatypes can be found
328 // at function get_attr_info in h5get.cc.
329 attr_id = get_attr_info(oid, j, false, &attr_inst, &ignore_attr);
330 if (true == ignore_attr) {
331 H5Aclose(attr_id);
332 continue;
333 }
334
335 // Since HDF5 attribute may be in string datatype, it must be dealt
336 // properly. Get data type.
337 hid_t ty_id = H5Aget_type(attr_id);
338 string dap_type = get_dap_type(ty_id, false);
339 string attr_name = attr_inst.name;
340
341 // We have to handle variable length string differently.
342 if (H5Tis_variable_str(ty_id)) {
343
344 write_vlen_str_attrs(attr_id,ty_id,&attr_inst,NULL,attr_table_ptr,false);
345
346#if 0
347 BESDEBUG("h5", "attribute name " << attr_name <<endl);
348 BESDEBUG("h5", "attribute size " <<attr_inst.need <<endl);
349 BESDEBUG("h5", "attribute type size " <<(int)(H5Tget_size(ty_id))<<endl);
350
351 hid_t temp_space_id = H5Aget_space(attr_id);
352 BESDEBUG("h5",
353 "attribute calculated size "<<(int)(H5Tget_size(ty_id)) *(int)(H5Sget_simple_extent_npoints(temp_space_id)) <<endl);
354 if (temp_space_id < 0) {
355 H5Tclose(ty_id);
356 H5Aclose(attr_id);
357 throw InternalErr(__FILE__, __LINE__, "unable to read HDF5 attribute data");
358
359 }
360
361 // Variable length string attribute values only store pointers of the actual string value.
362 temp_buf.resize((size_t) attr_inst.need);
363
364 if (H5Aread(attr_id, ty_id, &temp_buf[0]) < 0) {
365 H5Sclose(temp_space_id);
366 H5Tclose(ty_id);
367 H5Aclose(attr_id);
368 throw InternalErr(__FILE__, __LINE__, "unable to read HDF5 attribute data");
369 }
370
371 char *temp_bp;
372 temp_bp = &temp_buf[0];
373 char* onestring;
374 for (unsigned int temp_i = 0; temp_i < attr_inst.nelmts; temp_i++) {
375
376 // This line will assure that we get the real variable length string value.
377 onestring = *(char **) temp_bp;
378
379 // Change the C-style string to C++ STD string just for easy appending the attributes in DAP.
380 if (onestring != NULL) {
381 string tempstring(onestring);
382 attr_table_ptr->append_attr(attr_name, dap_type, tempstring);
383 }
384
385 // going to the next value.
386 temp_bp += H5Tget_size(ty_id);
387 }
388 if (temp_buf.empty() != true) {
389 // Reclaim any VL memory if necessary.
390 herr_t ret_vlen_claim;
391 ret_vlen_claim = H5Dvlen_reclaim(ty_id, temp_space_id, H5P_DEFAULT, &temp_buf[0]);
392 if(ret_vlen_claim < 0) {
393 H5Sclose(temp_space_id);
394 throw InternalErr(__FILE__, __LINE__, "Cannot reclaim the memory buffer of the HDF5 variable length string.");
395 }
396 temp_buf.clear();
397 }
398 H5Sclose(temp_space_id);
399#endif
400 }
401 else {
402 vector<char> value;
403 // TODO: I think the second line is right. Will check this later.
404 value.resize(attr_inst.need + sizeof(char));
405 //value.resize(attr_inst.need);
406 BESDEBUG("h5", "arttr_inst.need=" << attr_inst.need << endl);
407
408 hid_t memtype = H5Tget_native_type(ty_id, H5T_DIR_ASCEND);
409 // Read HDF5 attribute data.
410 //if (H5Aread(attr_id, ty_id, (void *) (&value[0])) < 0) {
411 if (H5Aread(attr_id, memtype, (void *) (&value[0])) < 0) {
412 // value is deleted in the catch block below so
413 // shouldn't be deleted here. pwest Mar 18, 2009
414 throw InternalErr(__FILE__, __LINE__, "unable to read HDF5 attribute data");
415 }
416 H5Aclose(memtype);
417
418 // For scalar data, just read data once.
419 if (attr_inst.ndims == 0) {
420 for (int loc = 0; loc < (int) attr_inst.nelmts; loc++) {
421 print_rep = print_attr(ty_id, loc, &value[0]);
422 if (print_rep.c_str() != NULL) {
423 attr_table_ptr->append_attr(attr_name, dap_type, print_rep.c_str());
424 }
425 }
426
427 }
428 else {
429 // If the hdf5 data type is HDF5 string or number of dimension is positive;
430 // handle this differently.
431 BESDEBUG("h5", "=read_objects(): ndims=" << (int) attr_inst. ndims << endl);
432
433 // Get the attribute datatype size
434 int elesize = (int) H5Tget_size(ty_id);
435 if (elesize == 0) {
436 BESDEBUG("h5", "=read_objects(): elesize=0" << endl);
437 H5Tclose(ty_id);
438 H5Aclose(attr_id);
439 throw InternalErr(__FILE__, __LINE__, "unable to get attibute size");
440 }
441
442 // Due to the implementation of print_attr, the attribute value will be
443 // written one by one.
444 char *tempvalue = &value[0];
445
446 // Write this value. the "loc" can always be set to 0 since
447 // tempvalue will be moved to the next value.
448 for (hsize_t temp_index = 0; temp_index < attr_inst.nelmts; temp_index++) {
449 print_rep = print_attr(ty_id, 0/*loc*/, tempvalue);
450 if (print_rep.c_str() != NULL) {
451 attr_table_ptr->append_attr(attr_name, dap_type, print_rep.c_str());
452 tempvalue = tempvalue + elesize;
453
454 BESDEBUG("h5", "tempvalue=" << tempvalue << "elesize=" << elesize << endl);
455
456 }
457 else {
458 H5Tclose(ty_id);
459 H5Aclose(attr_id);
460 throw InternalErr(__FILE__, __LINE__, "unable to convert attibute value to DAP");
461 }
462 }
463 } // end if
464 }
465 if (H5Tclose(ty_id) < 0) {
466 H5Aclose(attr_id);
467 throw InternalErr(__FILE__, __LINE__, "unable to close HDF5 type id");
468 }
469 if (H5Aclose(attr_id) < 0) {
470 throw InternalErr(__FILE__, __LINE__, "unable to close attibute id");
471 }
472 } // end for
473 BESDEBUG("h5", "<read_objects()" << endl);
474}
475
487void find_gloattr(hid_t file, DAS & das)
488{
489 BESDEBUG("h5", ">find_gloattr()" << endl);
490
491 hid_t root = H5Gopen(file, "/", H5P_DEFAULT);
492 try {
493 if (root < 0) throw InternalErr(__FILE__, __LINE__, "unable to open the HDF5 root group");
494
495 // In the default option of the HDF5 handler, the
496 // HDF5 file structure(group hierarchy) will be mapped to
497 // a DAP attribute HDF5_ROOT_GROUP. In a sense, this created
498 // attribute can be treated as an HDF5 attribute under the root group,
499 // so to say, a global attribute.
500 das.add_table("HDF5_ROOT_GROUP", new AttrTable);
501
502 // Since the root group is the first HDF5 object to visit(in HDF5RequestHandler.cc, find_gloattr()
503 // is before the depth_first()), it will always be not visited. However, to find the cyclic groups
504 // to root, we still need to add the object name to the global variable name list "paths" defined at
505 // the beginning of the h5das.cc file.
506 get_hardlink(root, "/");
507
508 // Obtain the number of "real" attributes of the root group.
509 int num_attrs;
510 H5O_info_t obj_info;
511 if (H5OGET_INFO(root, &obj_info) < 0) {
512 H5Gclose(root);
513 string msg = "Obtaining the info. failed for the root group ";
514 throw InternalErr(__FILE__, __LINE__, msg);
515 }
516
517 // Obtain the number of attributes
518 num_attrs = obj_info.num_attrs;
519 if (num_attrs < 0) {
520 H5Gclose(root);
521 throw InternalErr(__FILE__, __LINE__, "unable to get the number of attributes for the HDF root group ");
522
523 }
524 if (num_attrs == 0) {
525 if (H5Gclose(root) < 0) {
526 throw InternalErr(__FILE__, __LINE__, "Could not close the group.");
527 }
528 BESDEBUG("h5", "<find_gloattr():no attributes" << endl);
529 return;
530 }
531
532 // Map the HDF5 root attributes to DAP and save it in a DAS table "H5_GLOBAL".
533 // In theory, we can just "/" as the table name. To help clients better understand,
534 // we use "H5_GLOBAL" which is a more meaningful name.
535 read_objects(das, "H5_GLOBAL", root, num_attrs);
536
537 BESDEBUG("h5", "=find_gloattr(): H5Gclose()" << endl);
538 if (H5Gclose(root) < 0) {
539 throw InternalErr(__FILE__, __LINE__, "Could not close the group.");
540 }
541 BESDEBUG("h5", "<find_gloattr()" << endl);
542 }
543 catch (...) {
544 if (H5Gclose(root) < 0) {
545 throw InternalErr(__FILE__, __LINE__, "Could not close the group.");
546 }
547 throw;
548 }
549}
550
565void get_softlink(DAS & das, hid_t pgroup, const char *gname, const string & oname, int index, size_t val_size)
566{
567 BESDEBUG("h5", ">get_softlink():" << oname << endl);
568
569 ostringstream oss;
570 oss << string("HDF5_SOFTLINK");
571 oss << "_";
572 oss << index;
573 string temp_varname = oss.str();
574
575
576 BESDEBUG("h5", "=get_softlink():" << temp_varname << endl);
577 AttrTable *attr_table_ptr = das.get_table(gname);
578 if (!attr_table_ptr) attr_table_ptr = das.add_table(gname, new AttrTable);
579
580 AttrTable *attr_softlink_ptr;
581 attr_softlink_ptr = attr_table_ptr->append_container(temp_varname);
582
583 string softlink_name = "linkname";
584 attr_softlink_ptr->append_attr(softlink_name, STRING, oname);
585 string softlink_value_name = "LINKTARGET";
586
587 // Get the link target information. We always return the link value in a string format.
588
589 char *buf = 0;
590 try {
591 buf = new char[(val_size + 1) * sizeof(char)];
592 // get link target name
593 if (H5Lget_val(pgroup, oname.c_str(), (void*) buf, val_size + 1, H5P_DEFAULT) < 0) {
594 delete[] buf;
595 throw InternalErr(__FILE__, __LINE__, "unable to get link value");
596 }
597 attr_softlink_ptr->append_attr(softlink_value_name, STRING, buf);
598 delete[] buf;
599 }
600 catch (...) {
601 delete[] buf;
602 throw;
603 }
604}
605
619string get_hardlink(hid_t pgroup, const string & oname)
620{
621
622 BESDEBUG("h5", ">get_hardlink():" << oname << endl);
623
624 // Get the object info
625 H5O_info_t obj_info;
626 if (H5OGET_INFO(pgroup, &obj_info) < 0) {
627 throw InternalErr(__FILE__, __LINE__, "H5OGET_INFO() failed.");
628 }
629
630 // If the reference count is greater than 1,that means
631 // hard links are found. return the original object name this
632 // hard link points to.
633
634 if (obj_info.rc > 1) {
635 string objno;
636
637#if (H5_VERS_MAJOR == 1 && ((H5_VERS_MINOR == 12) || (H5_VERS_MINOR == 13)))
638 char *obj_tok_str = NULL;
639 if(H5Otoken_to_str(pgroup, &(obj_info.token), &obj_tok_str) <0) {
640 throw InternalErr(__FILE__, __LINE__, "H5Otoken_to_str failed.");
641 }
642 objno.assign(obj_tok_str,obj_tok_str+strlen(obj_tok_str));
643 H5free_memory(obj_tok_str);
644#else
645 ostringstream oss;
646 oss << hex << obj_info.addr;
647 objno = oss.str();
648#endif
649
650
651 BESDEBUG("h5", "=get_hardlink() objno=" << objno << endl);
652
653 if (!paths.add(objno, oname)) {
654 return objno;
655 }
656 else {
657 return "";
658 }
659 }
660 else {
661 return "";
662 }
663
664}
665
675void read_comments(DAS & das, const string & varname, hid_t oid)
676{
677
678 // Obtain the comment size
679 int comment_size;
680 comment_size = (int) (H5Oget_comment(oid, NULL, 0));
681 if (comment_size < 0) {
682 throw InternalErr(__FILE__, __LINE__, "Could not retrieve the comment size.");
683 }
684
685 if (comment_size > 0) {
686 vector<char> comment;
687 comment.resize(comment_size + 1);
688 if (H5Oget_comment(oid, &comment[0], comment_size + 1) < 0) {
689 throw InternalErr(__FILE__, __LINE__, "Could not retrieve the comment.");
690 }
691
692 // Insert this comment into the das table.
693 AttrTable *at = das.get_table(varname);
694 if (!at) at = das.add_table(varname, new AttrTable);
695 at->append_attr("HDF5_COMMENT", STRING, &comment[0]);
696
697 }
698}
699
719void add_group_structure_info(DAS & das, const char *gname, char *oname, bool is_group)
720{
721
722 string h5_spec_char("/");
723 string dap_notion(".");
724 string::size_type pos = 1;
725
726 if (gname == NULL) {
727 throw InternalErr(__FILE__, __LINE__, "The wrong HDF5 group name.");
728 }
729
730 string full_path = string(gname);
731
732 // Change the HDF5 special character '/' with DAP notion '.'
733 // to make sure the group structure can be handled by DAP properly.
734 while ((pos = full_path.find(h5_spec_char, pos)) != string::npos) {
735 full_path.replace(pos, h5_spec_char.size(), dap_notion);
736 pos++;
737 }
738
739 // If the HDF5 file includes only the root group, replacing
740 // the "/" with the string "HDF5_ROOT_GROUP".
741 // Otherwise, replacing the first "/" with the string "HDF5_ROOT_GROUP.",
742 // (note the . after "HDF5_ROOT_GROUP." . Then cutting the last "/".
743
744 if (strncmp(gname, "/", strlen(gname)) == 0) {
745 full_path.replace(0, 1, "HDF5_ROOT_GROUP");
746 }
747 else {
748 full_path.replace(0, 1, "HDF5_ROOT_GROUP.");
749 full_path = full_path.substr(0, full_path.length() - 1);
750 }
751
752 BESDEBUG("h5", full_path << endl);
753 // TODO: Not sure if we need to create a table for each group. KY 2015-07-08
754 AttrTable *at = das.get_table(full_path);
755 if (at == NULL) {
756 throw InternalErr(__FILE__, __LINE__,
757 "Failed to add group structure information for " + full_path + " attribute table."
758 + "This happens when a group name has . character.");
759 }
760
761 // group will be mapped to a container
762 if (is_group) {
763 at->append_container(oname);
764 }
765 else {
766 at->append_attr("Dataset", "String", oname);
767 }
768}
769
std::string get_name(std::string id)
bool add(std::string id, const std::string name)
string get_hardlink(hid_t pgroup, const string &oname)
Definition: h5das.cc:619
void depth_first(hid_t pid, const char *gname, DAS &das)
Definition: h5das.cc:62
HDF5PathFinder paths
A variable for remembering visited paths to break cyclic HDF5 groups.
Definition: h5das.cc:45
void find_gloattr(hid_t file, DAS &das)
Definition: h5das.cc:487
void read_objects(DAS &das, const string &varname, hid_t oid, int num_attr)
Definition: h5das.cc:295
void read_comments(DAS &das, const string &varname, hid_t oid)
Definition: h5das.cc:675
void add_group_structure_info(DAS &das, const char *gname, char *oname, bool is_group)
Definition: h5das.cc:719
string print_attr(hid_t type, int loc, void *sm_buf)
Definition: h5get.cc:863
string get_dap_type(hid_t type, bool is_dap4)
Definition: h5get.cc:291
hid_t get_attr_info(hid_t dset, int index, bool is_dap4, DSattr_t *attr_inst_ptr, bool *ignore_attr_ptr)
Definition: h5get.cc:90
The main header of the HDF5 OPeNDAP handler.
const int DODS_NAMELEN
Maximum length of variable or attribute name(default option only).
Definition: hdf5_handler.h:65
const std::string HDF5_OBJ_FULLPATH
The special DAS attribute name for HDF5 path information from the top(root) group.
Definition: hdf5_handler.h:67
A structure for DAS generation.
Definition: hdf5_handler.h:94
char name[DODS_NAMELEN]
Name of HDF5 group or dataset.
Definition: hdf5_handler.h:96
int ndims
Number of dimensions.
Definition: hdf5_handler.h:100
hsize_t nelmts
Number of elements.
Definition: hdf5_handler.h:104
hsize_t need
Memory space needed to hold nelmts type.
Definition: hdf5_handler.h:106