bes  Updated for version 3.20.6
build_dmrpp.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of the Hyrax data server.
4 
5 // Copyright (c) 2018 OPeNDAP, Inc.
6 // Author: James Gallagher <jgallagher@opendap.org>
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 //
22 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
23 
24 #include <iostream>
25 #include <fstream>
26 #include <sstream>
27 #include <memory>
28 #include <iterator>
29 #include <algorithm>
30 
31 #include <cstdlib>
32 
33 //#define H5D_FRIEND // Workaround, needed to use H5D_chunk_rec_t
34 //#include <H5Dpkg.h>
35 #define H5S_MAX_RANK 32
36 #define H5O_LAYOUT_NDIMS (H5S_MAX_RANK+1)
37 #include <H5Ppublic.h>
38 #include <H5Dpublic.h>
39 #include <H5Epublic.h>
40 #include <H5Zpublic.h> // Constants for compression filters
41 #include <H5Spublic.h>
42 
43 /*
44  * "Generic" chunk record. Each chunk is keyed by the minimum logical
45  * N-dimensional coordinates and the datatype size of the chunk.
46  * The fastest-varying dimension is assumed to reference individual bytes of
47  * the array, so a 100-element 1-D array of 4-byte integers would really be a
48  * 2-D array with the slow varying dimension of size 100 and the fast varying
49  * dimension of size 4 (the storage dimensionality has very little to do with
50  * the real dimensionality).
51  *
52  * The chunk's file address, filter mask and size on disk are not key values.
53  */
54 typedef struct H5D_chunk_rec_t {
55  hsize_t scaled[H5O_LAYOUT_NDIMS]; /* Logical offset to start */
56  uint32_t nbytes; /* Size of stored data */
57  uint32_t filter_mask; /* Excluded filters */
58  haddr_t chunk_addr; /* Address of chunk in file */
59 } H5D_chunk_rec_t;
60 
61 #include <DMRpp.h>
62 #include <D4Attributes.h>
63 #include <BaseType.h>
64 #include <D4ParserSax2.h>
65 #include <GetOpt.h>
66 
67 #include <TheBESKeys.h>
68 #include <BESUtil.h>
69 #include <BESDebug.h>
70 
71 #include <BESError.h>
72 #include <BESNotFoundError.h>
73 #include <BESInternalError.h>
74 #include <BESDataHandlerInterface.h>
75 
76 #include "DmrppTypeFactory.h"
77 #include "DmrppD4Group.h"
78 #include "DmrppMetadataStore.h"
79 #include "BESDapNames.h"
80 
81 using namespace std;
82 using namespace libdap;
83 using namespace dmrpp;
84 
85 static bool verbose = false;
86 #define VERBOSE(x) do { if (verbose) x; } while(false)
87 
88 #define DEBUG_KEY "metadata_store,dmrpp_store,dmrpp"
89 #define ROOT_DIRECTORY "BES.Catalog.catalog.RootDirectory"
90 
101 static void print_dataset_type_info(hid_t dataset, uint8_t layout_type)
102 {
103  hid_t dtype_id = H5Dget_type(dataset);
104  if (dtype_id < 0) {
105  throw BESInternalError("Cannot obtain the correct HDF5 datatype.", __FILE__, __LINE__);
106  }
107 
108  if (H5Tget_class(dtype_id) == H5T_INTEGER || H5Tget_class(dtype_id) == H5T_FLOAT) {
109  hid_t dcpl_id = H5Dget_create_plist(dataset);
110  if (dcpl_id < 0) {
111  throw BESInternalError("Cannot obtain the HDF5 dataset creation property list.", __FILE__, __LINE__);
112  }
113 
114  try {
115  // Wrap the resources like dcpl_id in try/catch blocks so that the
116  // calls to H5Pclose(dcpl_id) for each error can be removed. jhrg 5/7/18
117  H5D_fill_value_t fvalue_status;
118  if (H5Pfill_value_defined(dcpl_id, &fvalue_status) < 0) {
119  H5Pclose(dcpl_id);
120  throw BESInternalError("Cannot obtain the fill value status.", __FILE__, __LINE__);
121  }
122  if (fvalue_status == H5D_FILL_VALUE_UNDEFINED) {
123  // Replace with switch(), here and elsewhere. jhrg 5/7/18
124  if (layout_type == 1)
125  cerr << " The storage size is 0 and the storage type is contiguous." << endl;
126  else if (layout_type == 2)
127  cerr << " The storage size is 0 and the storage type is chunking." << endl;
128  else if (layout_type == 3) cerr << " The storage size is 0 and the storage type is compact." << endl;
129 
130  cerr << " The Fillvalue is undefined ." << endl;
131  }
132  else {
133  if (layout_type == 1)
134  cerr << " The storage size is 0 and the storage type is contiguous." << endl;
135  else if (layout_type == 2)
136  cerr << " The storage size is 0 and the storage type is chunking." << endl;
137  else if (layout_type == 3) cerr << " The storage size is 0 and the storage type is compact." << endl;
138 
139  char* fvalue = NULL;
140  size_t fv_size = H5Tget_size(dtype_id);
141  if (fv_size == 1)
142  fvalue = (char*) (malloc(1));
143  else if (fv_size == 2)
144  fvalue = (char*) (malloc(2));
145  else if (fv_size == 4)
146  fvalue = (char*) (malloc(4));
147  else if (fv_size == 8) fvalue = (char*) (malloc(8));
148 
149  if (fv_size <= 8) {
150  if (H5Pget_fill_value(dcpl_id, dtype_id, (void*) (fvalue)) < 0) {
151  H5Pclose(dcpl_id);
152  throw BESInternalError("Cannot obtain the fill value status.", __FILE__, __LINE__);
153  }
154  if (H5Tget_class(dtype_id) == H5T_INTEGER) {
155  H5T_sign_t fv_sign = H5Tget_sign(dtype_id);
156  if (fv_size == 1) {
157  if (fv_sign == H5T_SGN_NONE) {
158  cerr << "This dataset's datatype is unsigned char " << endl;
159  cerr << "and the fillvalue is " << *fvalue << endl;
160  }
161  else {
162  cerr << "This dataset's datatype is char and the fillvalue is " << *fvalue << endl;
163  }
164  }
165  else if (fv_size == 2) {
166  if (fv_sign == H5T_SGN_NONE) {
167  cerr << "This dataset's datatype is unsigned short and the fillvalue is " << *fvalue << endl;
168  }
169  else {
170  cerr << "This dataset's datatype is short and the fillvalue is " << *fvalue << endl;
171  }
172  }
173  else if (fv_size == 4) {
174  if (fv_sign == H5T_SGN_NONE) {
175  cerr << "This dataset's datatype is unsigned int and the fillvalue is " << *fvalue << endl;
176  }
177  else {
178  cerr << "This dataset's datatype is int and the fillvalue is " << *fvalue << endl;
179  }
180  }
181  else if (fv_size == 8) {
182  if (fv_sign == H5T_SGN_NONE) {
183  cerr << "This dataset's datatype is unsigned long long and the fillvalue is " << *fvalue << endl;
184  }
185  else {
186  cerr << "This dataset's datatype is long long and the fillvalue is " << *fvalue << endl;
187  }
188  }
189  }
190  if (H5Tget_class(dtype_id) == H5T_FLOAT) {
191  if (fv_size == 4) {
192  cerr << "This dataset's datatype is float and the fillvalue is " << *fvalue << endl;
193  }
194  else if (fv_size == 8) {
195  cerr << "This dataset's datatype is double and the fillvalue is " << *fvalue << endl;
196  }
197  }
198 
199  if (fvalue != NULL) free(fvalue);
200  }
201  else
202  cerr
203  << "The size of the datatype is greater than 8 bytes, Use HDF5 API H5Pget_fill_value() to retrieve the fill value of this dataset."
204  << endl;
205  }
206  }
207  catch (...) {
208  H5Pclose(dcpl_id);
209  throw;
210  }
211  H5Pclose(dcpl_id);
212  }
213  else {
214  if (layout_type == 1)
215  cerr << " The storage size is 0 and the storage type is contiguous." << endl;
216  else if (layout_type == 2)
217  cerr << " The storage size is 0 and the storage type is chunking." << endl;
218  else if (layout_type == 3) cerr << " The storage size is 0 and the storage type is compact." << endl;
219 
220  cerr << "The datatype is neither float nor integer,use HDF5 API H5Pget_fill_value() to retrieve the fill value of this dataset." << endl;
221  }
222 }
223 
224 // FYI: Filter IDs
225 // H5Z_FILTER_ERROR (-1) no filter
226 // H5Z_FILTER_NONE 0 reserved indefinitely
227 // H5Z_FILTER_DEFLATE 1 deflation like gzip
228 // H5Z_FILTER_SHUFFLE 2 shuffle the data
229 // H5Z_FILTER_FLETCHER32 3 fletcher32 checksum of EDC
230 // H5Z_FILTER_SZIP 4 szip compression
231 // H5Z_FILTER_NBIT 5 nbit compression
232 // H5Z_FILTER_SCALEOFFSET 6 scale+offset compression
233 // H5Z_FILTER_RESERVED 256 filter ids below this value are reserved for library use
234 
241 static void set_filter_information(hid_t dataset_id, DmrppCommon *dc)
242 {
243  hid_t plist_id = H5Dget_create_plist(dataset_id);
244 
245  try {
246  int numfilt = H5Pget_nfilters(plist_id);
247  VERBOSE(cerr << "Number of filters associated with dataset: " << numfilt << endl);
248 
249  for (int filter = 0; filter < numfilt; filter++) {
250  size_t nelmts = 0;
251  unsigned int flags, filter_info;
252  H5Z_filter_t filter_type = H5Pget_filter2(plist_id, filter, &flags, &nelmts, NULL, 0, NULL, &filter_info);
253  VERBOSE(cerr << "Filter Type: ");
254 
255  switch (filter_type) {
256  case H5Z_FILTER_DEFLATE:
257  VERBOSE(cerr << "H5Z_FILTER_DEFLATE" << endl);
258  dc->set_deflate(true);
259  break;
260  case H5Z_FILTER_SHUFFLE:
261  VERBOSE(cerr << "H5Z_FILTER_SHUFFLE" << endl);
262  dc->set_shuffle(true);
263  break;
264  default: {
265  ostringstream oss("Unsupported HDF5 filter: ", std::ios::ate);
266  oss << filter_type;
267  throw BESInternalError(oss.str(), __FILE__, __LINE__);
268  }
269  }
270  }
271  }
272  catch (...) {
273  H5Pclose(plist_id);
274  throw;
275  }
276 
277  H5Pclose(plist_id);
278 }
279 
290 static void get_variable_chunk_info(hid_t dataset, DmrppCommon *dc)
291 {
292  try {
293  hid_t dcpl = H5Dget_create_plist(dataset);
294  uint8_t layout_type = H5Pget_layout(dcpl);
295 
296  hid_t fspace_id = H5Dget_space(dataset);
297 
298  unsigned int dataset_rank = H5Sget_simple_extent_ndims(fspace_id);
299 
300  /* layout_type: 1 contiguous 2 chunk 3 compact */
301  switch (layout_type) {
302 
303  case H5D_CONTIGUOUS: { /* Contiguous storage */
304  haddr_t cont_addr = 0;
305  hsize_t cont_size = 0;
306  VERBOSE(cerr << "Storage: contiguous" << endl);
307 
308  cont_addr = H5Dget_offset(dataset);
309  if (cont_addr < 0) {
310  throw BESInternalError("Cannot obtain the offset.", __FILE__, __LINE__);
311  }
312  cont_size = H5Dget_storage_size(dataset);
313  if (cont_size < 0) {
314  throw BESInternalError("Cannot obtain the storage size.", __FILE__, __LINE__);
315  }
316  VERBOSE(cerr << " Addr: " << cont_addr << endl);
317  VERBOSE(cerr << " Size: " << cont_size << endl);
318 
319  if (dc) dc->add_chunk("", cont_size, cont_addr, "" /*pos in array*/);
320 
321  break;
322  }
323 
324  case H5D_CHUNKED: { /*chunking storage */
325  hsize_t num_chunks = 0;
326  herr_t status = H5Dget_num_chunks(dataset, fspace_id, &num_chunks);
327  if (status < 0) {
328  throw BESInternalError("Could not get the number of chunks",
329  __FILE__, __LINE__);
330  }
331 
332  VERBOSE(cerr << "storage: chunked." << endl);
333  VERBOSE(cerr << "Number of chunks is " << num_chunks << endl);
334 
335  if (dc)
336  set_filter_information(dataset, dc);
337 
338  // Get chunking information: rank and dimensions
339  vector<size_t> chunk_dims(dataset_rank);
340  unsigned int chunk_rank = H5Pget_chunk(dcpl, dataset_rank, (hsize_t*) &chunk_dims[0]);
341  if (chunk_rank != dataset_rank)
342  throw BESNotFoundError("Found a chunk with rank different than the dataset's (aka variables's) rank", __FILE__, __LINE__);
343 
344  if (dc) dc->set_chunk_dimension_sizes(chunk_dims);
345 
346  for (unsigned int i = 0; i < num_chunks; ++i) {
347 
348  vector<hsize_t> temp_coords(dataset_rank);
349  vector<unsigned int> chunk_coords(dataset_rank); //FIXME - see below
350 
351  haddr_t addr = 0;
352  hsize_t size = 0;
353 
354  //H5_DLL herr_t H5Dget_chunk_info(hid_t dset_id, hid_t fspace_id, hsize_t chk_idx, hsize_t *coord, unsigned *filter_mask, haddr_t *addr, hsize_t *size);
355  status = H5Dget_chunk_info(dataset, fspace_id, i, &temp_coords[0], NULL, &addr, &size);
356  if (status < 0) {
357  VERBOSE(cerr << "ERROR" << endl);
358  throw BESInternalError("Cannot get HDF5 dataset storage info.", __FILE__, __LINE__);
359  }
360 
361  VERBOSE(cerr << "chk_idk: " << i << ", addr: " << addr << ", size: " << size << endl);
362 
363  //The coords need to be of type 'unsigned int' when passed into add_chunk()
364  // This loop simply copies the values from the temp_coords to chunk_coords - kln 5/1/19
365  for (unsigned int j = 0; j < chunk_coords.size(); ++j) {
366  chunk_coords[j] = temp_coords[j];
367  }
368 
369  // FIXME Modify add_chunk so that it takes a vector<unsigned long long> or <unsined long>
370  // (depending on the machine/OS/compiler). Limiting the offset to 32-bits won't work
371  // for large files. jhrg 5/21/19
372  if (dc) dc->add_chunk("", size, addr, chunk_coords);
373  }
374 
375  break;
376  }
377 
378  case H5D_COMPACT: { /* Compact storage */
379  //else if (layout_type == 3) {
380  VERBOSE(cerr << "Storage: compact" << endl);
381  size_t comp_size = 0;
382  //if (H5Dget_dataset_compact_storage_info(dataset, &comp_size) < 0) {
383  // throw BESInternalError("Cannot obtain the compact storage info.", __FILE__, __LINE__);
384  //}
385  comp_size = H5Dget_storage_size(dataset);
386  if (comp_size < 0) {
387  throw BESInternalError("Cannot obtain the compact storage size.", __FILE__, __LINE__);
388  }
389  VERBOSE(cerr << " Size: " << comp_size << endl);
390 
391  break;
392  }
393 
394  default: {
395  ostringstream oss("Unsupported HDF5 dataset layout type: ", std::ios::ate);
396  oss << layout_type << ".";
397  BESInternalError(oss.str(), __FILE__, __LINE__);
398  }
399  } // end switch
400  }
401  catch (...) {
402  H5Dclose(dataset);
403  throw;
404  }
405 
406  H5Dclose(dataset);
407 }
408 
416 static void get_chunks_for_all_variables(hid_t file, D4Group *group)
417 {
418  // variables in the group
419  for (Constructor::Vars_iter v = group->var_begin(), ve = group->var_end(); v != ve; ++v) {
420  // if this variable has a 'fullnamepath' attribute, use that and not the
421  // FQN value.
422  D4Attributes *d4_attrs = (*v)->attributes();
423  if (!d4_attrs)
424  throw BESInternalError("Expected to find an attribute table for " + (*v)->name() + " but did not.", __FILE__, __LINE__);
425 
426  // Look for the full name path for this variable
427  // If one was not given via an attribute, use BaseType::FQN() which
428  // relies on the varaible's position in the DAP dataset hierarchy.
429  D4Attribute *attr = d4_attrs->get("fullnamepath");
430  string FQN;
431  // I believe the logic is more clear in this way:
432  // If fullnamepath exists and the H5Dopen2 fails to open, it should throw an error.
433  // If fullnamepath doesn't exist, we should ignore the error as the reason described below:
434  // (However, we should supress the HDF5 dataset open error message.) KY 2019-12-02
435  // It's not an error if a DAP variable in a DMR from the hdf5 handler
436  // doesn't exist in the file _if_ there's no 'fullnamepath' because
437  // that variable was synthesized (likely for CF compliance)
438  hid_t dataset = -1;
439  if(attr) {
440  if(attr->num_values() == 1)
441  FQN = attr->value(0);
442  else
443  FQN = (*v)->FQN();
444  BESDEBUG("dmrpp","Working on: " <<FQN<<endl);
445  dataset = H5Dopen2(file, FQN.c_str(), H5P_DEFAULT);
446  if(dataset <0)
447  throw BESInternalError("HDF5 dataset '" + FQN + "' cannot be opened.", __FILE__, __LINE__);
448 
449  }
450  else {
451  // The current design seems to still prefer to open the dataset when the fullnamepath doesn't exist
452  // So go ahead to open the dataset. Continue even if the dataset cannot be open. KY 2019-12-02
453  H5Eset_auto2(H5E_DEFAULT,NULL,NULL);
454  FQN = (*v)->FQN();
455  BESDEBUG("dmrpp","Working on: " <<FQN<<endl);
456  dataset = H5Dopen2(file, FQN.c_str(), H5P_DEFAULT);
457  if(dataset <0)
458  continue;
459  }
460 
461 
462 #if 0
463  if (attr && attr->num_values() == 1)
464  FQN = attr->value(0);
465  else
466  FQN = (*v)->FQN();
467 
468  VERBOSE(cerr << "Working on: " << FQN << endl);
469  hid_t dataset = H5Dopen2(file, FQN.c_str(), H5P_DEFAULT);
470  // It's not an error if a DAP variable in a DMR from the hdf5 handler
471  // doesn't exist in the file _if_ there's no 'fullnamepath' because
472  // that variable was synthesized (likely for CF compliance)
473  if (dataset < 0 && attr == 0) {
474  cerr<<"Unable to open dataset name "<<FQN <<endl;
475  continue;
476  }
477  else if (dataset < 0)
478  throw BESInternalError("HDF5 dataset '" + FQN + "' cannot be opened.", __FILE__, __LINE__);
479 #endif
480  get_variable_chunk_info(dataset, dynamic_cast<DmrppCommon*>(*v));
481  }
482 
483  // all groups in the group
484  D4Group::groupsIter g = group->grp_begin();
485  D4Group::groupsIter ge = group->grp_end();
486  while (g != ge)
487  get_chunks_for_all_variables(file, *g++);
488 }
489 
490 int main(int argc, char*argv[])
491 {
492  string h5_file_name = "";
493  string h5_dset_path = "";
494  string dmr_name = "";
495  string url_name = "";
496  int status=0;
497 
498  GetOpt getopt(argc, argv, "c:f:r:u:dhv");
499  int option_char;
500  while ((option_char = getopt()) != -1) {
501  switch (option_char) {
502  case 'v':
503  verbose = true; // verbose hdf5 errors
504  break;
505 
506  case 'd':
507  BESDebug::SetUp(string("cerr,").append(DEBUG_KEY));
508  break;
509 
510  case 'f':
511  h5_file_name = getopt.optarg;
512  break;
513  case 'r':
514  dmr_name = getopt.optarg;
515  break;
516  case 'u':
517  url_name = getopt.optarg;
518  break;
519  case 'c':
520  TheBESKeys::ConfigFile = getopt.optarg;
521  break;
522  case 'h':
523  cerr << "build_dmrpp [-v] -c <bes.conf> -f <data file> [-u <href url>] | build_dmrpp -f <data file> -r <dmr file> | build_dmrpp -h" << endl;
524  exit(1);
525  default:
526  break;
527  }
528  }
529 
530  if (h5_file_name.empty()) {
531  cerr << "HDF5 file name must be given (-f <input>)." << endl;
532  return 1;
533  }
534 
535  hid_t file = 0;
536  try {
537  // Turn off automatic hdf5 error printing.
538  // See: https://support.hdfgroup.org/HDF5/doc1.8/RM/RM_H5E.html#Error-SetAuto2
539  //if (!verbose) H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
540 
541  // For a given HDF5, get info for all the HDF5 datasets in a DMR or for a
542  // given HDF5 dataset
543  if (!dmr_name.empty()) {
544  // Get dmr:
545  unique_ptr<DMRpp> dmrpp(new DMRpp);
546  DmrppTypeFactory dtf;
547  dmrpp->set_factory(&dtf);
548 
549  ifstream in(dmr_name.c_str());
550  D4ParserSax2 parser;
551  parser.intern(in, dmrpp.get(), false);
552 
553  // Open the hdf5 file
554  file = H5Fopen(h5_file_name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
555  if (file < 0) {
556  cerr << "Error: HDF5 file '" + h5_file_name + "' cannot be opened." << endl;
557  return 1;
558  }
559 
560  // iterate over all the variables in the DMR
561  get_chunks_for_all_variables(file, dmrpp->root());
562 
563  XMLWriter writer;
564  dmrpp->print_dmrpp(writer, url_name);
565 
566  cout << writer.get_doc();
567  }
568  else {
569  bool found;
570  string bes_data_root;
571  try {
572  TheBESKeys::TheKeys()->get_value(ROOT_DIRECTORY, bes_data_root, found);
573  if (!found) {
574  cerr << "Error: Could not find the BES root directory key." << endl;
575  return 1;
576  }
577  }
578  catch (BESError &e) {
579  cerr << "BESError: " << e.get_message() << endl;
580  return 1;
581  }
582 
583  // Use the values from the bes.conf file... jhrg 5/21/18
585  if (!mds) {
586  cerr << "The Metadata Store (MDS) must be configured for this command to work." << endl;
587  return 1;
588  }
589 
590  // Use the full path to open the file, but use the 'name' (which is the
591  // path relative to the BES Data Root) with the MDS.
592  // Changed this to utilze assmeblePath() because simply concatenating the strings
593  // is fragile. - ndp 6/6/18
594  string h5_file_path = BESUtil::assemblePath(bes_data_root,h5_file_name);
595 
596  //bes::DmrppMetadataStore::MDSReadLock lock = mds->is_dmr_available(h5_file_name /*h5_file_path*/);
597  bes::DmrppMetadataStore::MDSReadLock lock = mds->is_dmr_available(h5_file_path, h5_file_name, "h5");
598  if (lock()) {
599  // parse the DMR into a DMRpp (that uses the DmrppTypes)
600  unique_ptr<DMRpp> dmrpp(dynamic_cast<DMRpp*>(mds->get_dmr_object(h5_file_name /*h5_file_path*/)));
601  if (!dmrpp.get()) {
602  cerr << "Expected a DMR++ object from the DmrppMetadataStore." << endl;
603  return 1;
604  }
605 
606  // Open the hdf5 file
607  file = H5Fopen(h5_file_path.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
608  if (file < 0) {
609  cerr << "Error: HDF5 file '" + h5_file_path + "' cannot be opened." << endl;
610  return 1;
611  }
612 
613  get_chunks_for_all_variables(file, dmrpp->root());
614 
615  dmrpp->set_href(url_name);
616 
617  mds->add_dmrpp_response(dmrpp.get(), h5_file_name /*h5_file_path*/);
618 
619  XMLWriter writer;
620  dmrpp->set_print_chunks(true);
621  dmrpp->print_dap4(writer);
622 
623  cout << writer.get_doc();
624  }
625  else {
626  cerr << "Error: Could not get a lock on the DMR for '" + h5_file_path + "'." << endl;
627  return 1;
628  }
629  }
630  }
631  catch (BESError &e) {
632  cerr << "BESError: " << e.get_message() << endl;
633  status = 1;
634  }
635  catch (std::exception &e) {
636  cerr << "std::exception: " << e.what() << endl;
637  status = 1;
638  }
639  catch (...) {
640  cerr << "Unknown error." << endl;
641  status = 1;
642  }
643 
644  H5Fclose(file);
645 
646  return status;
647 }
TheBESKeys::ConfigFile
static std::string ConfigFile
Definition: TheBESKeys.h:149
bes::GlobalMetadataStore::MDSReadLock
Unlock and close the MDS item when the ReadLock goes out of scope.
Definition: GlobalMetadataStore.h:193
dmrpp::DmrppTypeFactory
Definition: DmrppTypeFactory.h:39
BESNotFoundError
error thrown if the resource requested cannot be found
Definition: BESNotFoundError.h:40
BESError::get_message
virtual std::string get_message()
get the error message for this exception
Definition: BESError.h:99
dmrpp::DmrppCommon
Size and offset information of data included in DMR++ files.
Definition: DmrppCommon.h:62
dmrpp::DmrppCommon::add_chunk
virtual unsigned long add_chunk(const std::string &data_url, unsigned long long size, unsigned long long offset, std::string position_in_array="")
Add a new chunk as defined by an h4:byteStream element.
Definition: DmrppCommon.cc:153
BESUtil::assemblePath
static std::string assemblePath(const std::string &firstPart, const std::string &secondPart, bool leadingSlash=false, bool trailingSlash=false)
Assemble path fragments making sure that they are separated by a single '/' character.
Definition: BESUtil.cc:821
BESDebug::SetUp
static void SetUp(const std::string &values)
Sets up debugging for the bes.
Definition: BESDebug.cc:64
bes::DmrppMetadataStore::get_dmr_object
virtual libdap::DMR * get_dmr_object(const string &name)
Use the DMR response to build a DMR with Dmrpp Types.
Definition: DmrppMetadataStore.cc:242
libdap
Definition: BESDapFunctionResponseCache.h:35
TheBESKeys::TheKeys
static TheBESKeys * TheKeys()
Definition: TheBESKeys.cc:62
bes::DmrppMetadataStore::get_instance
static DmrppMetadataStore * get_instance()
Definition: DmrppMetadataStore.cc:137
dmrpp::DmrppCommon::set_deflate
void set_deflate(bool value)
Set the value of the deflate property.
Definition: DmrppCommon.h:112
dmrpp::DmrppCommon::set_shuffle
void set_shuffle(bool value)
Set the value of the shuffle property.
Definition: DmrppCommon.h:122
bes::DmrppMetadataStore
Store the DAP DMR++ metadata responses.
Definition: DmrppMetadataStore.h:83
BESInternalError
exception thrown if internal error encountered
Definition: BESInternalError.h:43
TheBESKeys::get_value
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: TheBESKeys.cc:272
dmrpp::DmrppCommon::set_chunk_dimension_sizes
void set_chunk_dimension_sizes(const std::vector< size_t > &chunk_dims)
Set the value of the chunk dimension sizes given a vector of HDF5 hsize_t.
Definition: DmrppCommon.h:155
dmrpp::DMRpp
Provide a way to print the DMR++ response.
Definition: DMRpp.h:42
BESError
Abstract exception class for the BES with basic string message.
Definition: BESError.h:58
bes::GlobalMetadataStore::is_dmr_available
virtual MDSReadLock is_dmr_available(const std::string &name)
Is the DMR response for.
Definition: GlobalMetadataStore.cc:771