summaryrefslogtreecommitdiffstats
path: root/doxygen/examples/DebuggingHDF5Applications.html
blob: c6aaf74f92abc1d3fa886ee55ba32e23dea3008a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
<html>
  <head>
    <title>Debugging HDF5 Applications</title>

    <h2>Introduction</h2>

    <p>The HDF5 library contains a number of debugging features to
      make programmers' lives easier including the ability to print
      detailed error messages, check invariant conditions, display
      timings and other statistics, and trace API function calls and
      return values.

    </p><dl>
      <dt><b>Error Messages</b>
      </dt><dd>Error messages are normally displayed automatically on the
	standard error stream and include a stack trace of the library
	including file names, line numbers, and function names. The
	application has complete control over how error messages are
	displayed and can disable the display on a permanent or
	temporary basis. Refer to the documentation for the H5E error
	handling package.

	<br><br>
      </dd><dt><b>Invariant Conditions</b>
      </dt><dd>Unless <code>NDEBUG</code> is defined during compiling, the
	library will include code to verify that invariant conditions
	have the expected values.  When a problem is detected the
	library will display the file and line number within the
	library and the invariant condition that failed.  A core dump
	may be generated for post mortem debugging. The code to
	perform these checks can be included on a per-package bases.

	<br><br>
      </dd><dt><b>Timings and Statistics</b>
      </dt><dd>The library can be configured to accumulate certain
	statistics about things like cache performance, datatype
	conversion, data space conversion, and data filters. The code
	is included on a per-package basis and enabled at runtime by
	an environment variable.

	<br><br>
      </dd><dt><b>API Tracing</b>
      </dt><dd>All API calls made by an application can be displayed and
	include formal argument names and actual values and the
	function return value. This code is also conditionally
	included at compile time and enabled at runtime.
    </dd></dl>

    <p>The statistics and tracing can be displayed on any output
      stream (including streams opened by the shell) with output from
      different packages even going to different streams.

    </p><h2>Error Messages</h2>

    <p>By default any API function that fails will print an error
      stack to the standard error stream.

    </p><p>
      </p><center>
	<table border="" align="center" width="100%">
	  <tbody><tr>
	    <td>
	      <p><code></code></p><pre><code>
HDF5-DIAG: Error detected in thread 0.  Back trace follows.
  #000: H5F.c line 1245 in H5Fopen(): unable to open file
    major(04): File interface
    minor(10): Unable to open file
  #001: H5F.c line 846 in H5F_open(): file does not exist
    major(04): File interface
    minor(10): Unable to open file
	      </code></pre>
	    </td>
	  </tr>
	</tbody></table>
      </center>

    <p>The error handling package (H5E) is described
      <a href="./group___h5_e.html">elsewhere</a>.

    </p><h2>Invariant Conditions</h2>

    <p>To include checks for invariant conditions the library should
      be configured with <code>--disable-production</code>, the
      default for versions before 1.2. The library designers have made
      every attempt to handle error conditions gracefully but an
      invariant condition assertion may fail in certain cases.  The
      output from a failure usually looks something like this:

    </p><p>
      </p><center>
	<table border="" align="center" width="100%">
	  <tbody><tr>
	    <td>
	      <p><code></code></p><pre><code>
Assertion failed: H5.c:123: i&lt;NELMTS(H5_debug_g)
IOT Trap, core dumped.
	      </code></pre>
	    </td>
	  </tr>
	</tbody></table>
      </center>

    <h2>Timings and Statistics</h2>

    <p>Code to accumulate statistics is included at compile time by
      using the <code>--enable-debug</code> configure switch. The
      switch can be followed by an equal sign and a comma-separated
      list of package names or else a default list is used.

    </p><p>
      </p><center>
        <table border="" align="center" width="80%">
          <tbody><tr>
            <th>Name</th>
	    <th>Default</th>
            <th>Description</th>
          </tr>
	  <tr>
	    <td align="center">a</td>
	    <td align="center">No</td>
	    <td>Attributes</td>
	  </tr>
	  <tr>
	    <td align="center">ac</td>
	    <td align="center">Yes</td>
	    <td>Meta data cache</td>
	  </tr>
	  <tr>
	    <td align="center">b</td>
	    <td align="center">Yes</td>
	    <td>B-Trees</td>
	  </tr>
	  <tr>
	    <td align="center">d</td>
	    <td align="center">Yes</td>
	    <td>Datasets</td>
	  </tr>
	  <tr>
	    <td align="center">e</td>
	    <td align="center">Yes</td>
	    <td>Error handling</td>
	  </tr>
	  <tr>
	    <td align="center">f</td>
	    <td align="center">Yes</td>
	    <td>Files</td>
	  </tr>
	  <tr>
	    <td align="center">g</td>
	    <td align="center">Yes</td>
	    <td>Groups</td>
	  </tr>
	  <tr>
	    <td align="center">hg</td>
	    <td align="center">Yes</td>
	    <td>Global heap</td>
	  </tr>
	  <tr>
	    <td align="center">hl</td>
	    <td align="center">No</td>
	    <td>Local heaps</td>
	  </tr>
	  <tr>
	    <td align="center">i</td>
	    <td align="center">Yes</td>
	    <td>Interface abstraction</td>
	  </tr>
	  <tr>
	    <td align="center">mf</td>
	    <td align="center">No</td>
	    <td>File memory management</td>
	  </tr>
	  <tr>
	    <td align="center">mm</td>
	    <td align="center">Yes</td>
	    <td>Library memory managment</td>
	  </tr>
	  <tr>
	    <td align="center">o</td>
	    <td align="center">No</td>
	    <td>Object headers and messages</td>
	  </tr>
	  <tr>
	    <td align="center">p</td>
	    <td align="center">Yes</td>
	    <td>Property lists</td>
	  </tr>
	  <tr>
	    <td align="center">s</td>
	    <td align="center">Yes</td>
	    <td>Data spaces</td>
	  </tr>
	  <tr>
	    <td align="center">t</td>
	    <td align="center">Yes</td>
	    <td>Datatypes</td>
	  </tr>
	  <tr>
	    <td align="center">v</td>
	    <td align="center">Yes</td>
	    <td>Vectors</td>
	  </tr>
	  <tr>
	    <td align="center">z</td>
	    <td align="center">Yes</td>
	    <td>Raw data filters</td>
	  </tr>
        </tbody></table>
      </center>

    <p>In addition to including the code at compile time the
      application must enable each package at runtime.  This is done
      by listing the package names in the <code>HDF5_DEBUG</code>
      environment variable. That variable may also contain file
      descriptor numbers (the default is `2') which control the output
      for all following packages up to the next file number.  The
      word <code>all</code> refers to all packages. Any word my be
      preceded by a minus sign to turn debugging off for the package.

    </p><p>
      </p><center>
	<table border="" align="center" width="100%">
	  <caption align="top"><b>Sample debug specifications</b></caption>
	  <tbody><tr valign="top">
	    <td><code>all</code></td>
	    <td>This causes debugging output from all packages to be
	      sent to the standard error stream.</td>
	  </tr>
	  <tr valign="top">
	    <td><code>all -t -s</code></td>
	    <td>Debugging output for all packages except datatypes
	      and data spaces will appear on the standard error
	      stream.</td>
	  </tr>
	  <tr valign="top">
	    <td><code>-all ac 255 t,s</code></td>
	    <td>This disables all debugging even if the default was to
	      debug something, then output from the meta data cache is
	      send to the standard error stream and output from data
	      types and spaces is sent to file descriptor 255 which
	      should be redirected by the shell.</td>
	  </tr>
	</tbody></table>
      </center>

    <p>The components of the <code>HDF5_DEBUG</code> value may be
      separated by any non-lowercase letter.

    </p><h2>API Tracing</h2>

    <p>The HDF5 library can trace API calls by printing the
      function name, the argument names and their values, and the
      return value. Some people like to see lots of output during
      program execution instead of using a good symbolic debugger, and
      this feature is intended for their consumption.  For example,
      the output from <code>h5ls foo</code> after turning on tracing,
      includes:

    </p><p>
      </p><center>
	<table border="" align="center" width="100%">
	  <tbody><tr>
	    <td>
	      <code><pre>
H5Tcopy(type=184549388) = 184549419 (type);
H5Tcopy(type=184549392) = 184549424 (type);
H5Tlock(type=184549424) = SUCCEED;
H5Tcopy(type=184549393) = 184549425 (type);
H5Tlock(type=184549425) = SUCCEED;
H5Fopen(filename="foo", flags=0, access=H5P_DEFAULT) = FAIL;
HDF5-DIAG: Error detected in thread 0.  Back trace follows.
  #000: H5F.c line 1245 in H5Fopen(): unable to open file
    major(04): File interface
    minor(10): Unable to open file
  #001: H5F.c line 846 in H5F_open(): file does not exist
    major(04): File interface
    minor(10): Unable to open file
	      </pre></code>
	    </td>
	  </tr>
	</tbody></table>
      </center>

    <p>The code that performs the tracing must be included in the
      library by specifying the <code>--enable-trace</code>
      configuration switch (the default for versions before 1.2). Then
      the word <code>trace</code> must appear in the value of the
      <code>HDF5_DEBUG</code> variable.  The output will appear on the
      last file descriptor before the word <code>trace</code> or two
      (standard error) by default.

    </p><p>
      </p><center>
	<table border="" align="center" width="100%">
	  <tbody><tr>
	    <td>To display the trace on the standard error stream:
	      <code><pre>$ env HDF5_DEBUG=trace a.out
	      </pre></code>
	    </td>
	  </tr>
	  <tr>
	    <td>To send the trace to a file:
	      <code><pre>$ env HDF5_DEBUG="55 trace" a.out 55&gt;trace-output
	      </pre></code>
	    </td>
	  </tr>
	</tbody></table>
      </center>

    <h3>Performance</h3>

    <p>If the library was not configured for tracing then there is no
      unnecessary overhead since all tracing code is excluded.
      However, if tracing is enabled but not used there is a small
      penalty. First, code size is larger because of extra
      statically-declared character strings used to store argument
      types and names and extra auto variable pointer in each
      function.  Also, execution is slower because each function sets
      and tests a local variable and each API function calls the
      <code>H5_trace()</code> function.

    </p><p>If tracing is enabled and turned on then the penalties from the
      previous paragraph apply plus the time required to format each
      line of tracing information.  There is also an extra call to
      H5_trace() for each API function to print the return value.

    </p><h3>Safety</h3>

    <p>The tracing mechanism is invoked for each API function before
      arguments are checked for validity.  If bad arguments are passed
      to an API function it could result in a segmentation fault.
      However, the tracing output is line-buffered so all previous
      output will appear.

    </p><h3>Completeness</h3>

    <p>There are two API functions that don't participate in
      tracing. They are <code>H5Eprint()</code> and
      <code>H5Eprint_cb()</code> because their participation would
      mess up output during automatic error reporting.

    </p><p>On the other hand, a number of API functions are called during
      library initialization and they print tracing information.

    </p><h3>Implementation</h3>

    <p>For those interested in the implementation here is a
      description.  Each API function should have a call to one of the
      <code>H5TRACE()</code> macros immediately after the
      <code>FUNC_ENTER()</code> macro.  The first argument is the
      return type encoded as a string.  The second argument is the
      types of all the function arguments encoded as a string.  The
      remaining arguments are the function arguments.  This macro was
      designed to be as terse and unobtrousive as possible.

    </p><p>In order to keep the <code>H5TRACE()</code> calls synchronized
      with the source code we've written a perl script which gets
      called automatically just before Makefile dependencies are
      calculated for the file.  However, this only works when one is
      using GNU make.  To reinstrument the tracing explicitly, invoke
      the <code>trace</code> program from the hdf5 bin directory with
      the names of the source files that need to be updated.  If any
      file needs to be modified then a backup is created by appending
      a tilde to the file name.

    </p><p>
      </p><center>
	<table border="" align="center" width="100%">
	  <caption align="top"><b>Explicit Instrumentation</b></caption>
	  <tbody><tr>
	    <td>
	      <code><pre>
$ ../bin/trace *.c
H5E.c: in function `H5Ewalk_cb':
H5E.c:336: warning: trace info was not inserted
	      </pre></code>
	    </td>
	  </tr>
	</tbody></table>
      </center>

    <p>Note: The warning message is the result of a comment of the
      form <code>/*NO TRACE*/</code> somewhere in the function
      body. Tracing information will not be updated or inserted if
      such a comment exists.

    </p><p>Error messages have the same format as a compiler so that they
      can be parsed from program development environments like
      Emacs. Any function which generates an error will not be
      modified.</p>

</body></html>