Getting a detailed message from a H5::Exceptions


#1

I set out to do a simple task: Catch an H5::Exception and capture its error message in a string.

I already know what the error is (because I introduced it for testing): I’m accessing a group that does not exist.

I can see “Object not found” on the console. I would like to have the string “Object not found” in my code please. How do I do that?

I tried to call H5::Exception::getDetailMsg(), but that gives me a completely useless H5Gopen2 failed.

The method H5::Exception::getMinorString looked promising! Turns out, this method needs a minor number.

First question: Why is this a member function if it doesn’t reference anything in the Exception object? Why isn’t it just static? What is even the point of this function?

Second question: How do I get the minor error number? There are no member functions in the Exception class that give me this information. I find this bewildering, because apparently, this object was constructed during error handling, but did not bother to save the actual error state.

I then set out to find the minor error code in the C API, but I could not find a simple function that returns it. Why not?

Then I set out to “walk” the error stack to get my minor code from there. To my dismay, I find out the error stack does not survive stack unwinding. Presumably, some H5:: object 's destructor calls API functions that destroy the error stack.

To summarize:
getDetailMsg() is useless.
getMinorString() needs a minor code.
Getting the minor code is impossible unless
Therefor, getting a usable error message is impossible.

Has anybody of the authors of the C++ API actually ever tried to use the C++ API? The more I use it, the more I start to doubt that.

How are you supposed to do error handling in C++?


#2

So, I haven’t used the C++ API. I recall struggling with some similar issues with C API in this regard. I wanted to translate a few of the HDF5 errors to a Silo (my package) error. I wound up doing…

PRIVATE herr_t
silo_walk_cb(int n, H5E_error_t *err_desc, void *client_data)
{   
    int *silo_error_code_p = (int *) client_data;

     /* Note that error code can be overwritten by later strstr
       comparisons. Where both checksum and compression errors
       occur, we declare it a compression error. */
    if (strstr(err_desc->desc, "letcher32") != 0)
        *silo_error_code_p = E_CHECKSUM; 
    if (strstr(err_desc->desc, "zip") != 0)
        *silo_error_code_p = E_COMPRESSION;
    if (strstr(err_desc->desc, "Lindstrom-") != 0)
        *silo_error_code_p = E_COMPRESSION;

    return 0;
}

PRIVATE void
hdf5_to_silo_error(char const *vname, char const *fname)
{
    int silo_error_code = E_NOERROR;

    H5Ewalk(H5E_WALK_UPWARD, silo_walk_cb, &silo_error_code);

    if (silo_error_code == E_NOERROR)
        silo_error_code = E_CALLFAIL;

    db_perror((char*)vname, silo_error_code, (char*)fname);
}

I don’t honestly know if this might be any help but provided in case so.


#3

Thank you @miller86 , this is what I use in C++:

herr_t visitErrorStackLevel(unsigned n, const H5E_error2_t *err_desc, void *client_data)
{
  *reinterpret_cast<H5E_minor_t*>(client_data) = err_desc->min_num;
  return 0;
}

std::string getLastError()
{
  H5E_minor_t min_num = 0;
  H5::Exception::walkErrorStack(H5E_WALK_DOWNWARD, visitErrorStackLevel, &min_num);

  if (min_num != 0)
    return H5Eget_minor(min_num);
  else
    return "";
}

It works when called right after the failed H5:: API call. Unfortunately, it does not work when I catch the exceptions several call frames up from where it is thrown. As mentioned, my guess is that the objects destructors call API functions themselves which destroy the stack.


#4

Hi,

any interest in taking a look at H5CPP? This is a new approach to HDF5, and low latency high throughput persistence for modern C++ in general. The code base is a result of coordinated work between the HDFGroup and I. Most credit going to Gerd Heber and Elena Pourmal for their limitless patience, as well as the participants of our regular HDF5 C++ user group conference.

This header only library has a structured exception support. In addition to that comes with many advanced features including but not limited to MPI-IO, compiler assisted seamless persistence of C POD struct types, and of course support for major linear algebra libraries + std::vector.
Most importantly: all H5CPP resource handles are binary equivalent with HDF5 CAPI hid_t, there is only a compile time thin layer on top of it – the design allows seamless integration with existing CAPI code base. If you missing any feature, you can pass the handle ie: h5::ds_t to H5D_calls seamlessly.

Here you can view the ISC19 presentation slides.
best:
steven


#5

Hello @steven ,

I took a look at H5CPP and it looks like it is not a good fit for us. It introduces an additional dependency, and looking at the examples it seems that while it is very featureful, it’s rather complicated to use. For example, from your presentation it looks like the use of the h5cpp compiler is mandatory, is that correct?

BTW, are you aware that your library has the same name as another C++ hdf5 library?
https://ess-dmsc.github.io/h5cpp/index.html
I think having H5CPP (#include <h5cpp/*>), h5cpp (#include <h5cpp/*>) and HDF5 C++ API (#include <H5Cpp.h>) could be quite confusing.


#6

It is incorrect, there are no dependencies to H5CPP. Optionally you may use the h5cpp compiler which generates platform independent header files. Then you can include the generated header file along the standard H5CPP headers.
Similarly you may include 3th party linear algebra libraries, which are recognized and the necessary code will be generated. The project is under MIT license you may include it and or ship it with your commercial or scientific product as you see fit.

Yes there are other project under the same name, independently developed. This happened becuase of my library was factored out from a commercial library rooting back to 2012 ish. For now there is no reason to take action to remedy it. H5CPP is a descriptive unregistered name, the European gentlemen have the same right to use it as I do.

In fact we are aware of each other, and meet regularly in HDFGroup C++ meeting. You may consider their library as an alternative if you think it has features better fitting for your needs.
Addition to this, Marc Paterno from the Fermi group also actively develops CPP ntuples which I recommend, and if I recall right there is HighFive around and maintained.

Hope it helps.