[svn-r467] Restructuring documentation.
177
doc/html/Attributes.html
Normal file
@ -0,0 +1,177 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Attributes</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Attributes</h1>
|
||||
|
||||
<h2>1. Introduction</h2>
|
||||
|
||||
<p>The appribute API (H5A) is primarily designed to easily allow small
|
||||
datasets to be attached to primary datasets as metadata information.
|
||||
Additional goals for the H5A interface include keeping storage
|
||||
requirement for each attribute to a minimum and easily sharing
|
||||
attributes among datasets.
|
||||
<p>Because attributes are intended to be small objects, large datasets
|
||||
intended as additional information for a primary dataset should be
|
||||
stored as supplemental datasets in a group with the primary dataset.
|
||||
Attributes can then be attached to the group containing everything to
|
||||
indicate a particular type of dataset with supplemental datasets is
|
||||
located in the group. How small is "small" is not defined by the
|
||||
library and is up to the user's interpretation.
|
||||
<p>Attributes are not seperate objects in the file, they are always
|
||||
contained in the object header of the object they are attached to. The
|
||||
I/O functions defined below are required to read or write attribute
|
||||
information, not the H5D I/O routines.
|
||||
|
||||
<h2>2. Creating, Opening, Closing and Deleting Attributes</h2>
|
||||
|
||||
<p>Attributes are created with the <code>H5Acreate()</code> function,
|
||||
and existing attributes can be accessed with either the
|
||||
<code>H5Aopen_name()</code> or <code>H5Aopen_idx()</code> functions. All
|
||||
three functions return an object ID which should be eventually released
|
||||
by calling <code>H5Aclose()</code>.
|
||||
|
||||
<dl>
|
||||
<dt><code>hid_t H5Acreate (hid_t <em>loc_id</em>, const char
|
||||
*<em>name</em>, hid_t <em>type_id</em>, hid_t <em>space_id</em>,
|
||||
hid_t <em>create_plist_id</em>)</code>
|
||||
<dd>This function creates an attribute which is attached to the object
|
||||
specified with <em>loc_id</em>. The name specified with <em>name</em>
|
||||
for each attribute for an object must be unique for that object. The <em>type_id</em>
|
||||
and <em>space_id</em> are created with the H5T and H5S interfaces
|
||||
respectively. Currently only simple dataspaces are allowed for attribute
|
||||
dataspaces. The <em>create_plist_id</em> property list is currently
|
||||
unused, but will be used int the future for optional properties of
|
||||
attributes. The attribute ID returned from this function must be released
|
||||
with H5Aclose or resource leaks will develop. Attempting to create an
|
||||
attribute with the same name as an already existing attribute will fail,
|
||||
leaving the pre-existing attribute in place.
|
||||
This function returns a attribute ID for success or negative for failure.
|
||||
|
||||
<br><br>
|
||||
<dt><code>hid_t H5Aopen_name (hid_t <em>loc_id</em>, const char
|
||||
*<em>name</em>)</code>
|
||||
<dd> This function opens an attribute which is attached to the object
|
||||
specified with <em>loc_id</em>. The name specified with <em>name</em>
|
||||
indicates the attribute to access. The attribute ID returned from this
|
||||
function must be released with H5Aclose or resource leaks will develop.
|
||||
This function returns a attribute ID for success or negative for failure.
|
||||
|
||||
<br><br>
|
||||
<dt><code>hid_t H5Aopen_idx (hid_t <em>loc_id</em>, unsigned
|
||||
<em>idx</em>)</code>
|
||||
<dd>This function opens an attribute which is attached to the object
|
||||
specified with <em>loc_id</em>. The attribute specified with <em>idx</em>
|
||||
indicates the <em>idx</em>th attribute to access, starting with '0'. The
|
||||
attribute ID returned from this function must be released with H5Aclose or
|
||||
resource leaks will develop.
|
||||
This function returns a attribute ID for success or negative for failure.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Aclose (hid_t <em>attr_id</em>)</code>
|
||||
<dd>This function releases an attribute from use. Further use of the
|
||||
attribute ID will result in undefined behavior.
|
||||
This function returns non-negative on success, negative on failure.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Adelete (hid_t <em>loc_id</em>,
|
||||
const char *<em>name</em>)</code>
|
||||
<dd>This function removes the named attribute from a dataset or group.
|
||||
This function should not be used when attribute IDs are open on <em>loc_id</em>
|
||||
as it may cause the internal indexes of the attributes to change and future
|
||||
writes to the open attributes to produce incorrect results.
|
||||
Returns non-negative on success, negative on failure.
|
||||
</dl>
|
||||
|
||||
<h2>3. Attribute I/O Functions</h2>
|
||||
|
||||
<p>Attributes may only be written as an entire object, no partial I/O
|
||||
is currently supported.
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Awrite (hid_t <em>attr_id</em>,
|
||||
hid_t <em>mem_type_id</em>, void *<em>buf</em>)</code>
|
||||
<dd>This function writes an attribute, specified with <em>attr_id</em>,
|
||||
with <em>mem_type_id</em> specifying the datatype in memory. The entire
|
||||
attribute is written from <em>buf</em> to the file.
|
||||
This function returns non-negative on success, negative on failure.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Aread (hid_t <em>attr_id</em>,
|
||||
hid_t <em>mem_type_id</em>, void *<em>buf</em>)</code>
|
||||
<dd>This function read an attribute, specified with <em>attr_id</em>, with
|
||||
<em>mem_type_id</em> specifying the datatype in memory. The entire
|
||||
attribute is read into <em>buf</em> from the file.
|
||||
This function returns non-negative on success, negative on failure.
|
||||
|
||||
</dl>
|
||||
|
||||
<h2>4. Attribute Inquiry Functions</h2>
|
||||
|
||||
<dl>
|
||||
<dt><code>int H5Aiterate (hid_t <em>loc_id</em>,
|
||||
unsigned *<em>attr_number</em>,
|
||||
H5A_operator <em>operator</em>,
|
||||
void *<em>operator_data</em>)</code>
|
||||
<dd> This function interates over the attributes of dataset or group
|
||||
specified with <em>loc_id</em>. For each attribute of the object, the
|
||||
<em>operator_data</em> and some additional information (specified below)
|
||||
are passed to the <em>operator</em> function. The iteration begins with
|
||||
the <em>*attr_number</em> object in the group and the next attribute to be
|
||||
processed by the operator is returned in <em>*attr_number</em>.
|
||||
<P>The iterator returns a negative value if something is wrong, the return
|
||||
value of the last operator if it was non-zero, or zero if all attributes
|
||||
were processed.
|
||||
<P>The prototype for H5A_operator_t is: <br>
|
||||
<code>typedef herr_t (*H5A_operator_t)(hid_t <em>loc_id</em>,
|
||||
const char *<em>attr_name</em>, void *<em>operator_data</em>);</code>
|
||||
<P>The operation receives the ID for the group or dataset being iterated over
|
||||
(<em>loc_id</em>), the name of the current attribute about the object (<em>attr_name</em>)
|
||||
and the pointer to the operator data passed in to H5Aiterate
|
||||
(<em>operator_data</em>). The return values from an operator are:
|
||||
<ul>
|
||||
<li>Zero causes the iterator to continue, returning zero when all
|
||||
attributes have been processed.
|
||||
<li>Positive causes the iterator to immediately return that positive
|
||||
value, indicating short-circuit success. The iterator can be
|
||||
restarted at the next attribute.
|
||||
<li>Negative causes the iterator to immediately return that value,
|
||||
indicating failure. The iterator can be restarted at the next
|
||||
attribute.
|
||||
</ul>
|
||||
<br><br>
|
||||
<dt><code>hid_t H5Aget_space (hid_t <em>attr_id</em>)</code>
|
||||
<dd>This function retrieves a copy of the dataspace for an attribute.
|
||||
The dataspace ID returned from this function must be released with H5Sclose
|
||||
or resource leaks will develop.
|
||||
This function returns a dataspace ID for success or negative for failure.
|
||||
<br><br>
|
||||
<dt><code>hid_t H5Aget_type (hid_t <em>attr_id</em>)</code>
|
||||
<dd>This function retrieves a copy of the datatype for an attribute.
|
||||
The datatype ID returned from this function must be released with H5Tclose
|
||||
or resource leaks will develop.
|
||||
This function returns a datatype ID for success or negative for failure.
|
||||
<br><br>
|
||||
<dt><code>size_t H5Aget_name (hid_t <em>attr_id</em>,
|
||||
char *<em>buf</em>, size_t <em>buf_size</em>)</code>
|
||||
<dd>This function retrieves the name of an attribute for an attribute ID.
|
||||
Up to <em>buf_size</em> characters are stored in <em>buf</em> followed by a
|
||||
'\0' string terminator. If the name of the attribute is longer than
|
||||
<em>buf_size</em>-1, the string terminator is stored in the last position
|
||||
of the buffer to properly terminate the string.
|
||||
This function returns the length of the attribute's name (which may be
|
||||
longer than <em>buf_size</em>) on success or negative for failure.
|
||||
<br><br>
|
||||
<dt><code>int H5Anum_attrs (hid_t <em>loc_id</em>)</code>
|
||||
<dd>This function returns the number of attributes attached to a dataset or
|
||||
group, <em>loc_id</em>.
|
||||
This function returns non-negative for success or negative for failure.
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:hdfhelp@ncsa.uiuc.edu">HDF Support</a></address>
|
||||
</body>
|
||||
</html>
|
111
doc/html/Big.html
Normal file
@ -0,0 +1,111 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Big Datasets on Small Machines</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Big Datasets on Small Machines</h1>
|
||||
|
||||
<h2>1. Introduction</h2>
|
||||
|
||||
<p>The HDF5 library is able to handle files larger than the
|
||||
maximum file size, and datasets larger than the maximum memory
|
||||
size. For instance, a machine where <code>sizeof(off_t)</code>
|
||||
and <code>sizeof(size_t)</code> are both four bytes can handle
|
||||
datasets and files as large as 18x10^18 bytes. However, most
|
||||
Unix systems limit the number of concurrently open files, so a
|
||||
practical file size limit is closer to 512GB or 1TB.
|
||||
|
||||
<p>Two "tricks" must be imployed on these small systems in order
|
||||
to store large datasets. The first trick circumvents the
|
||||
<code>off_t</code> file size limit and the second circumvents
|
||||
the <code>size_t</code> main memory limit.
|
||||
|
||||
<h2>2. File Size Limits</h2>
|
||||
|
||||
<p>Some 32-bit operating systems have special file systems that
|
||||
can support large (>2GB) files and HDF5 will detect these and
|
||||
use them automatically. If this is the case, the output from
|
||||
configure will show:
|
||||
|
||||
<p><code><pre>
|
||||
checking for lseek64... yes
|
||||
checking for fseek64... yes
|
||||
</pre></code>
|
||||
|
||||
<p>Otherwise one must use an HDF5 file family. Such a family is
|
||||
created by setting file family properties in a file access
|
||||
property list and then supplying a file name that includes a
|
||||
<code>printf</code>-style integer format. For instance:
|
||||
|
||||
<p><code><pre>
|
||||
hid_t plist, file;
|
||||
plist = H5Pcreate (H5P_FILE_ACCESS);
|
||||
H5Pset_family (plist, 1<<30, H5P_DEFAULT);
|
||||
file = H5Fcreate ("big%03d.h5", H5F_ACC_TRUNC, H5P_DEFAULT, plist);
|
||||
</code></pre>
|
||||
|
||||
<p>The second argument (<code>30</code>) to
|
||||
<code>H5Pset_family()</code> indicates that the family members
|
||||
are to be 2^30 bytes (1GB) each. In general, family members
|
||||
cannot be 2GB because writes to byte number 2,147,483,647 will
|
||||
fail, so the largest safe value for a family member is
|
||||
2,147,483,647. HDF5 will create family members on demand as the
|
||||
HDF5 address space increases, but since most Unix systems limit
|
||||
the number of concurrently open files the effective maximum size
|
||||
of the HDF5 address space will be limited.
|
||||
|
||||
<p>If the effective HDF5 address space is limited then one may be
|
||||
able to store datasets as external datasets each spanning
|
||||
multiple files of any length since HDF5 opens external dataset
|
||||
files one at a time. To arrange storage for a 5TB dataset one
|
||||
could say:
|
||||
|
||||
<p><code><pre>
|
||||
hid_t plist = H5Pcreate (H5P_DATASET_CREATE);
|
||||
for (i=0; i<5*1024; i++) {
|
||||
sprintf (name, "velocity-%04d.raw", i);
|
||||
H5Pset_external (plist, name, 0, (size_t)1<<30);
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h2>3. Dataset Size Limits</h2>
|
||||
|
||||
<p>The second limit which must be overcome is that of
|
||||
<code>sizeof(size_t)</code>. HDF5 defines a new data type
|
||||
called <code>hsize_t</code> which is used for sizes of datasets
|
||||
and is, by default, defined as <code>unsigned long long</code>.
|
||||
|
||||
<p>To create a dataset with 8*2^30 4-byte integers for a total of
|
||||
32GB one first creates the dataspace. We give two examples
|
||||
here: a 4-dimensional dataset whose dimension sizes are smaller
|
||||
than the maximum value of a <code>size_t</code>, and a
|
||||
1-dimensional dataset whose dimension size is too large to fit
|
||||
in a <code>size_t</code>.
|
||||
|
||||
<p><code><pre>
|
||||
hsize_t size1[4] = {8, 1024, 1024, 1024};
|
||||
hid_t space1 = H5Screate_simple (4, size1, size1);
|
||||
|
||||
hsize_t size2[1] = {8589934592LL};
|
||||
hid_t space2 = H5Screate_simple (1, size2, size2};
|
||||
</pre></code>
|
||||
|
||||
<p>However, the <code>LL</code> suffix is not portable, so it may
|
||||
be better to replace the number with
|
||||
<code>(hsize_t)8*1024*1024*1024</code>.
|
||||
|
||||
<p>For compilers that don't support <code>long long</code> large
|
||||
datasets will not be possible. The library performs too much
|
||||
arithmetic on <code>hsize_t</code> types to make the use of a
|
||||
struct feasible.
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Fri Apr 10 13:26:04 EDT 1998 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Wed May 13 12:36:47 EDT 1998
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
82
doc/html/Caching.html
Normal file
@ -0,0 +1,82 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Data Caching</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Meta Data Caching</h1>
|
||||
|
||||
<p>The HDF5 library caches two types of data: meta data and raw
|
||||
data. The meta data cache holds file objects like the file
|
||||
header, symbol table nodes, global heap collections, object
|
||||
headers and their messages, etc. in a partially decoded
|
||||
state. The cache has a fixed number of entries which is set with
|
||||
the file access property list (defaults to 10k) and each entry
|
||||
can hold a single meta data object. Collisions between objects
|
||||
are handled by preempting the older object in favor of the new
|
||||
one.
|
||||
|
||||
<h1>Raw Data Chunk Caching</h1>
|
||||
|
||||
<p>Raw data chunks are cached because I/O requests at the
|
||||
application level typically don't map well to chunks at the
|
||||
storage level. The chunk cache has a maximum size in bytes
|
||||
set with the file access property list (defaults to 1MB) and
|
||||
when the limit is reached chunks are preempted based on the
|
||||
following set of heuristics.
|
||||
|
||||
<ul>
|
||||
<li>Chunks which have not been accessed for a long time
|
||||
relative to other chunks are penalized.
|
||||
<li>Chunks which have been accessed frequently in the recent
|
||||
past are favored.
|
||||
<li>Chunks which are completely read and not written, completely
|
||||
written but not read, or completely read and completely
|
||||
written are penalized according to <em>w0</em>, an
|
||||
application-defined weight between 0 and 1 inclusive. A weight
|
||||
of zero does not penalize such chunks while a weight of 1
|
||||
penalizes those chunks more than all other chunks. The
|
||||
default is 0.75.
|
||||
<li>Chunks which are larger than the maximum cache size do not
|
||||
participate in the cache.
|
||||
</ul>
|
||||
|
||||
<p>One should choose large values for <em>w0</em> if I/O requests
|
||||
typically do not overlap but smaller values for <em>w0</em> if
|
||||
the requests do overlap. For instance, reading an entire 2d
|
||||
array by reading from non-overlapping "windows" in a row-major
|
||||
order would benefit from a high <em>w0</em> value while reading
|
||||
a diagonal accross the dataset where each request overlaps the
|
||||
previous request would benefit from a small <em>w0</em>.
|
||||
|
||||
<h1>The API</h1>
|
||||
|
||||
<p>The cache parameters for both caches are part of a file access
|
||||
property list and are set and queried with this pair of
|
||||
functions:
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Pset_cache(hid_t <em>plist</em>, unsigned int
|
||||
<em>mdc_nelmts</em>, size_t <em>rdcc_nbytes</em>, double
|
||||
<em>w0</em>)</code>
|
||||
<dt><code>herr_t H5Pget_cache(hid_t <em>plist</em>, unsigned int
|
||||
*<em>mdc_nelmts</em>, size_t *<em>rdcc_nbytes</em>, double
|
||||
<em>w0</em>)</code>
|
||||
<dd>Sets or queries the meta data cache and raw data chunk cache
|
||||
parameters. The <em>plist</em> is a file access property
|
||||
list. The number of elements (objects) in the meta data cache
|
||||
is <em>mdc_nelmts</em>. The total size of the raw data chunk
|
||||
cache and the preemption policy is <em>rdcc_nbytes</em> and
|
||||
<em>w0</em>. For <code>H5Pget_cache()</code> any (or all) of
|
||||
the pointer arguments may be null pointers.
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Tue May 26 15:20:14 EDT 1998 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Tue May 26 15:38:27 EDT 1998
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
300
doc/html/CodeReview.html
Normal file
@ -0,0 +1,300 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Code Review</title>
|
||||
</head>
|
||||
<body>
|
||||
<center><h1>Code Review 1</h1></center>
|
||||
|
||||
<h3>Some background...</h3>
|
||||
<p>This is one of the functions exported from the
|
||||
<code>H5B.c</code> file that implements a B-link-tree class
|
||||
without worrying about concurrency yet (thus the `Note:' in the
|
||||
function prologue). The <code>H5B.c</code> file provides the
|
||||
basic machinery for operating on generic B-trees, but it isn't
|
||||
much use by itself. Various subclasses of the B-tree (like
|
||||
symbol tables or indirect storage) provide their own interface
|
||||
and back end to this function. For instance,
|
||||
<code>H5G_stab_find()</code> takes a symbol table OID and a name
|
||||
and calls <code>H5B_find()</code> with an appropriate
|
||||
<code>udata</code> argument that eventually gets passed to the
|
||||
<code>H5G_stab_find()</code> function.
|
||||
|
||||
<p><code><pre>
|
||||
1 /*-------------------------------------------------------------------------
|
||||
2 * Function: H5B_find
|
||||
3 *
|
||||
4 * Purpose: Locate the specified information in a B-tree and return
|
||||
5 * that information by filling in fields of the caller-supplied
|
||||
6 * UDATA pointer depending on the type of leaf node
|
||||
7 * requested. The UDATA can point to additional data passed
|
||||
8 * to the key comparison function.
|
||||
9 *
|
||||
10 * Note: This function does not follow the left/right sibling
|
||||
11 * pointers since it assumes that all nodes can be reached
|
||||
12 * from the parent node.
|
||||
13 *
|
||||
14 * Return: Success: SUCCEED if found, values returned through the
|
||||
15 * UDATA argument.
|
||||
16 *
|
||||
17 * Failure: FAIL if not found, UDATA is undefined.
|
||||
18 *
|
||||
19 * Programmer: Robb Matzke
|
||||
20 * matzke@llnl.gov
|
||||
21 * Jun 23 1997
|
||||
22 *
|
||||
23 * Modifications:
|
||||
24 *
|
||||
25 *-------------------------------------------------------------------------
|
||||
26 */
|
||||
27 herr_t
|
||||
28 H5B_find (H5F_t *f, const H5B_class_t *type, const haddr_t *addr, void *udata)
|
||||
29 {
|
||||
30 H5B_t *bt=NULL;
|
||||
31 intn idx=-1, lt=0, rt, cmp=1;
|
||||
32 int ret_value = FAIL;
|
||||
</pre></code>
|
||||
|
||||
<p>All pointer arguments are initialized when defined. I don't
|
||||
worry much about non-pointers because it's usually obvious when
|
||||
the value isn't initialized.
|
||||
|
||||
<p><code><pre>
|
||||
33
|
||||
34 FUNC_ENTER (H5B_find, NULL, FAIL);
|
||||
35
|
||||
36 /*
|
||||
37 * Check arguments.
|
||||
38 */
|
||||
39 assert (f);
|
||||
40 assert (type);
|
||||
41 assert (type->decode);
|
||||
42 assert (type->cmp3);
|
||||
43 assert (type->found);
|
||||
44 assert (addr && H5F_addr_defined (addr));
|
||||
</pre></code>
|
||||
|
||||
<p>I use <code>assert</code> to check invariant conditions. At
|
||||
this level of the library, none of these assertions should fail
|
||||
unless something is majorly wrong. The arguments should have
|
||||
already been checked by higher layers. It also provides
|
||||
documentation about what arguments might be optional.
|
||||
|
||||
<p><code><pre>
|
||||
45
|
||||
46 /*
|
||||
47 * Perform a binary search to locate the child which contains
|
||||
48 * the thing for which we're searching.
|
||||
49 */
|
||||
50 if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type, udata))) {
|
||||
51 HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
|
||||
52 }
|
||||
</pre></code>
|
||||
|
||||
<p>You'll see this quite often in the low-level stuff and it's
|
||||
documented in the <code>H5AC.c</code> file. The
|
||||
<code>H5AC_protect</code> insures that the B-tree node (which
|
||||
inherits from the H5AC package) whose OID is <code>addr</code>
|
||||
is locked into memory for the duration of this function (see the
|
||||
<code>H5AC_unprotect</code> on line 90). Most likely, if this
|
||||
node has been accessed in the not-to-distant past, it will still
|
||||
be in memory and the <code>H5AC_protect</code> is almost a
|
||||
no-op. If cache debugging is compiled in, then the protect also
|
||||
prevents other parts of the library from accessing the node
|
||||
while this function is protecting it, so this function can allow
|
||||
the node to be in an inconsistent state while calling other
|
||||
parts of the library.
|
||||
|
||||
<p>The alternative is to call the slighlty cheaper
|
||||
<code>H5AC_find</code> and assume that the pointer it returns is
|
||||
valid only until some other library function is called, but
|
||||
since we're accessing the pointer throughout this function, I
|
||||
chose to use the simpler protect scheme. All protected objects
|
||||
<em>must be unprotected</em> before the file is closed, thus the
|
||||
use of <code>HGOTO_ERROR</code> instead of
|
||||
<code>HRETURN_ERROR</code>.
|
||||
|
||||
<p><code><pre>
|
||||
53 rt = bt->nchildren;
|
||||
54
|
||||
55 while (lt<rt && cmp) {
|
||||
56 idx = (lt + rt) / 2;
|
||||
57 if (H5B_decode_keys (f, bt, idx)<0) {
|
||||
58 HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
|
||||
59 }
|
||||
60
|
||||
61 /* compare */
|
||||
62 if ((cmp=(type->cmp3)(f, bt->key[idx].nkey, udata,
|
||||
63 bt->key[idx+1].nkey))<0) {
|
||||
64 rt = idx;
|
||||
65 } else {
|
||||
66 lt = idx+1;
|
||||
67 }
|
||||
68 }
|
||||
69 if (cmp) {
|
||||
70 HGOTO_ERROR (H5E_BTREE, H5E_NOTFOUND, FAIL);
|
||||
71 }
|
||||
</pre></code>
|
||||
|
||||
<p>Code is arranged in paragraphs with a comment starting each
|
||||
paragraph. The previous paragraph is a standard binary search
|
||||
algorithm. The <code>(type->cmp3)()</code> is an indirect
|
||||
function call into the subclass of the B-tree. All indirect
|
||||
function calls have the function part in parentheses to document
|
||||
that it's indirect (quite obvious here, but not so obvious when
|
||||
the function is a variable).
|
||||
|
||||
<p>It's also my standard practice to have side effects in
|
||||
conditional expressions because I can write code faster and it's
|
||||
more apparent to me what the condition is testing. But if I
|
||||
have an assignment in a conditional expr, then I use an extra
|
||||
set of parens even if they're not required (usually they are, as
|
||||
in this case) so it's clear that I meant <code>=</code> instead
|
||||
of <code>==</code>.
|
||||
|
||||
<p><code><pre>
|
||||
72
|
||||
73 /*
|
||||
74 * Follow the link to the subtree or to the data node.
|
||||
75 */
|
||||
76 assert (idx>=0 && idx<bt->nchildren);
|
||||
77 if (bt->level > 0) {
|
||||
78 if ((ret_value = H5B_find (f, type, bt->child+idx, udata))<0) {
|
||||
79 HGOTO_ERROR (H5E_BTREE, H5E_NOTFOUND, FAIL);
|
||||
80 }
|
||||
81 } else {
|
||||
82 ret_value = (type->found)(f, bt->child+idx, bt->key[idx].nkey,
|
||||
83 udata, bt->key[idx+1].nkey);
|
||||
84 if (ret_value<0) {
|
||||
85 HGOTO_ERROR (H5E_BTREE, H5E_NOTFOUND, FAIL);
|
||||
86 }
|
||||
87 }
|
||||
</pre></code>
|
||||
|
||||
<p>Here I broke the "side effect in conditional" rule, which I
|
||||
sometimes do if the expression is so long that the
|
||||
<code><0</code> gets lost at the end. Another thing to note is
|
||||
that success/failure is always determined by comparing with zero
|
||||
instead of <code>SUCCEED</code> or <code>FAIL</code>. I do this
|
||||
because occassionally one might want to return other meaningful
|
||||
values (always non-negative) or distinguish between various types of
|
||||
failure (always negative).
|
||||
|
||||
<p><code><pre>
|
||||
88
|
||||
89 done:
|
||||
90 if (bt && H5AC_unprotect (f, H5AC_BT, addr, bt)<0) {
|
||||
91 HRETURN_ERROR (H5E_BTREE, H5E_PROTECT, FAIL);
|
||||
92 }
|
||||
93 FUNC_LEAVE (ret_value);
|
||||
94 }
|
||||
</pre></code>
|
||||
|
||||
<p>For lack of a better way to handle errors during error cleanup,
|
||||
I just call the <code>HRETURN_ERROR</code> macro even though it
|
||||
will make the error stack not quite right. I also use short
|
||||
circuiting boolean operators instead of nested <code>if</code>
|
||||
statements since that's standard C practice.
|
||||
|
||||
<center><h1>Code Review 2</h1></center>
|
||||
|
||||
|
||||
<p>The following code is an API function from the H5F package...
|
||||
|
||||
<p><code><pre>
|
||||
1 /*--------------------------------------------------------------------------
|
||||
2 NAME
|
||||
3 H5Fflush
|
||||
4
|
||||
5 PURPOSE
|
||||
6 Flush all cached data to disk and optionally invalidates all cached
|
||||
7 data.
|
||||
8
|
||||
9 USAGE
|
||||
10 herr_t H5Fflush(fid, invalidate)
|
||||
11 hid_t fid; IN: File ID of file to close.
|
||||
12 hbool_t invalidate; IN: Invalidate all of the cache?
|
||||
13
|
||||
14 ERRORS
|
||||
15 ARGS BADTYPE Not a file atom.
|
||||
16 ATOM BADATOM Can't get file struct.
|
||||
17 CACHE CANTFLUSH Flush failed.
|
||||
18
|
||||
19 RETURNS
|
||||
20 SUCCEED/FAIL
|
||||
21
|
||||
22 DESCRIPTION
|
||||
23 This function flushes all cached data to disk and, if INVALIDATE
|
||||
24 is non-zero, removes cached objects from the cache so they must be
|
||||
25 re-read from the file on the next access to the object.
|
||||
26
|
||||
27 MODIFICATIONS:
|
||||
28 --------------------------------------------------------------------------*/
|
||||
</pre></code>
|
||||
|
||||
<p>An API prologue is used for each API function instead of my
|
||||
normal function prologue. I use the prologue from Code Review 1
|
||||
for non-API functions because it's more suited to C programmers,
|
||||
it requires less work to keep it synchronized with the code, and
|
||||
I have better editing tools for it.
|
||||
|
||||
<p><code><pre>
|
||||
29 herr_t
|
||||
30 H5Fflush (hid_t fid, hbool_t invalidate)
|
||||
31 {
|
||||
32 H5F_t *file = NULL;
|
||||
33
|
||||
34 FUNC_ENTER (H5Fflush, H5F_init_interface, FAIL);
|
||||
35 H5ECLEAR;
|
||||
</pre></code>
|
||||
|
||||
<p>API functions are never called internally, therefore I always
|
||||
clear the error stack before doing anything.
|
||||
|
||||
<p><code><pre>
|
||||
36
|
||||
37 /* check arguments */
|
||||
38 if (H5_FILE!=H5Aatom_group (fid)) {
|
||||
39 HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL); /*not a file atom*/
|
||||
40 }
|
||||
41 if (NULL==(file=H5Aatom_object (fid))) {
|
||||
42 HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL); /*can't get file struct*/
|
||||
43 }
|
||||
</pre></code>
|
||||
|
||||
<p>If something is wrong with the arguments then we raise an
|
||||
error. We never <code>assert</code> arguments at this level.
|
||||
We also convert atoms to pointers since atoms are really just a
|
||||
pointer-hiding mechanism. Functions that can be called
|
||||
internally always have pointer arguments instead of atoms
|
||||
because (1) then they don't have to always convert atoms to
|
||||
pointers, and (2) the various pointer data types provide more
|
||||
documentation and type checking than just an <code>hid_t</code>
|
||||
type.
|
||||
|
||||
<p><code><pre>
|
||||
44
|
||||
45 /* do work */
|
||||
46 if (H5F_flush (file, invalidate)<0) {
|
||||
47 HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL); /*flush failed*/
|
||||
48 }
|
||||
</pre></code>
|
||||
|
||||
<p>An internal version of the function does the real work. That
|
||||
internal version calls <code>assert</code> to check/document
|
||||
it's arguments and can be called from other library functions.
|
||||
|
||||
<p><code><pre>
|
||||
49
|
||||
50 FUNC_LEAVE (SUCCEED);
|
||||
51 }
|
||||
</pre></code>
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Sat Nov 8 17:09:33 EST 1997 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Mon Nov 10 15:33:33 EST 1997
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
300
doc/html/Coding.html
Normal file
@ -0,0 +1,300 @@
|
||||
<HTML>
|
||||
<HEAD><TITLE>
|
||||
HDF5 Naming Scheme
|
||||
</TITLE> </HEAD>
|
||||
|
||||
<BODY bgcolor="#ffffff">
|
||||
|
||||
|
||||
<H1>
|
||||
<FONT color="#c80028"
|
||||
<I> <B> <CENTER> HDF5 Naming Scheme for </CENTER> </B> </I> </H1>
|
||||
</FONT>
|
||||
<P>
|
||||
<UL>
|
||||
|
||||
<LI> <A HREF = "#01"><I> FILES </I> </A>
|
||||
<LI> <A HREF = "#02"><I> PACKAGES </I> </A>
|
||||
<LI> <A HREF = "#03"><I> PUBLIC vs PRIVATE </I> </A>
|
||||
<LI> <A HREF = "#04"><I> INTEGRAL TYPES </I> </A>
|
||||
<LI> <A HREF = "#05"><I> OTHER TYPES </I> </A>
|
||||
<LI> <A HREF = "#06"><I> GLOBAL VARIABLES </I> </A>
|
||||
<LI> <A HREF = "#07"><I> MACROS, PREPROCESSOR CONSTANTS, AND ENUM MEMEBERs </I> </A>
|
||||
|
||||
</UL>
|
||||
<P>
|
||||
<center>
|
||||
Authors: <A HREF = "mailto:koziol@ncsa.uiuc.edu">
|
||||
<I>Quincey Koziol</I> </A> and
|
||||
<A HREF = "mailto:matzke@llnl.gov">
|
||||
<I> Robb Matzke </I> </A>
|
||||
|
||||
</center>
|
||||
<UL>
|
||||
|
||||
<FONT color="#c80028"
|
||||
<LI> <A NAME="01"> <B> <I> FILES </I> </B> </A>
|
||||
</FONT>
|
||||
|
||||
<UL>
|
||||
|
||||
<LI> Source files are named according to the package they contain (see
|
||||
below). All files will begin with `H5' so we can stuff our
|
||||
object files into someone else's library and not worry about file
|
||||
name conflicts.
|
||||
<P>For Example:
|
||||
<i><b>
|
||||
<dd> H5.c -- "Generic" library functions
|
||||
<br>
|
||||
<dd> H5B.c -- B-link tree functions
|
||||
</i></b>
|
||||
<p>
|
||||
<LI> If a package is in more than one file, then another name is tacked
|
||||
on. It's all lower case with no underscores or hyphens.
|
||||
<P>For Example:
|
||||
<i><b>
|
||||
<dd> H5F.c -- the file for this package
|
||||
<br>
|
||||
<dd> H5Fstdio.c -- stdio functions (just an example)
|
||||
<br>
|
||||
<dd> H5Ffcntl.c -- fcntl functions (just an example)
|
||||
</i></b>
|
||||
<p>
|
||||
<LI> Each package file has a header file of API stuff (unless there is
|
||||
no API component to the package)
|
||||
<P>For Example:
|
||||
<i><b>
|
||||
<dd> H5F.h -- things an application would see. </i> </b>
|
||||
<P>
|
||||
and a header file of private stuff
|
||||
<i><b>
|
||||
<p>
|
||||
<dd> H5Fprivate.h -- things an application wouldn't see. The
|
||||
private header includes the public header.
|
||||
</i></b>
|
||||
<p>
|
||||
and a header for private prototypes
|
||||
<i><b>
|
||||
<p>
|
||||
<dd> H5Fproto.h -- prototypes for internal functions.
|
||||
</i></b>
|
||||
<P>
|
||||
By splitting the prototypes into separate include files we don't
|
||||
have to recompile everything when just one function prototype
|
||||
changes.
|
||||
|
||||
<LI> The main API header file is `hdf5.h' and it includes each of the
|
||||
public header files but none of the private header files. Or the
|
||||
application can include just the public header files it needs.
|
||||
|
||||
<LI> There is no main private or prototype header file because it
|
||||
prevents make from being efficient. Instead, each source file
|
||||
includes only the private header and prototype files it needs
|
||||
(first all the private headers, then all the private prototypes).
|
||||
|
||||
<LI> Header files should include everything they need and nothing more.
|
||||
|
||||
</UL>
|
||||
<P>
|
||||
|
||||
<FONT color="#c80028"
|
||||
<LI> <A NAME="02"> <B> <I> PACKAGES </I> </B> </A>
|
||||
</FONT>
|
||||
|
||||
<P>
|
||||
Names exported beyond function scope begin with `H5' followed by zero,
|
||||
one, or two upper-case letters that describe the class of object.
|
||||
This prefix is the package name. The implementation of packages
|
||||
doesn't necessarily have to map 1:1 to the source files.
|
||||
<P>
|
||||
<i><b>
|
||||
<dd> H5 -- library functions
|
||||
<br>
|
||||
<dd> H5A -- atoms
|
||||
<br>
|
||||
<dd> H5AC -- cache
|
||||
<br>
|
||||
<dd> H5B -- B-link trees
|
||||
<br>
|
||||
<dd> H5D -- datasets
|
||||
<br>
|
||||
<dd> H5E -- error handling
|
||||
<br>
|
||||
<dd> H5F -- files
|
||||
<br>
|
||||
<dd> H5G -- groups
|
||||
<br>
|
||||
<dd> H5M -- meta data
|
||||
<br>
|
||||
<dd> H5MM -- core memory management
|
||||
<br>
|
||||
<dd> H5MF -- file memory management
|
||||
<br>
|
||||
<dd> H5O -- object headers
|
||||
<br>
|
||||
<dd> H5P -- Property Lists
|
||||
<br>
|
||||
<dd> H5S -- dataspaces
|
||||
<br>
|
||||
<dd> H5R -- relationships
|
||||
<br>
|
||||
<dd> H5T -- datatype
|
||||
</i></b>
|
||||
<p>
|
||||
Each package implements a single main class of object (e.g., the H5B
|
||||
package implements B-link trees). The main data type of a package is
|
||||
the package name followed by `_t'.
|
||||
<p>
|
||||
<i><b>
|
||||
<dd> H5F_t -- HDF5 file type
|
||||
<br>
|
||||
<dd> H5B_t -- B-link tree data type
|
||||
</i></b>
|
||||
<p>
|
||||
|
||||
Not all packages implement a data type (H5, H5MF) and some
|
||||
packages provide access to a preexisting data type (H5MM, H5S).
|
||||
<p>
|
||||
|
||||
|
||||
<FONT color="#c80028"
|
||||
<LI> <A NAME="03"> <B> <I> PUBLIC vs PRIVATE </I> </B> </A>
|
||||
</FONT>
|
||||
<p>
|
||||
If the symbol is for internal use only, then the package name is
|
||||
followed by an underscore and the rest of the name. Otherwise, the
|
||||
symbol is part of the API and there is no underscore between the
|
||||
package name and the rest of the name.
|
||||
<p>
|
||||
<i><b>
|
||||
<dd> H5Fopen -- an API function.
|
||||
<br>
|
||||
<dd> H5B_find -- an internal function.
|
||||
</i></b>
|
||||
<p>
|
||||
For functions, this is important because the API functions never pass
|
||||
pointers around (they use atoms instead for hiding the implementation)
|
||||
and they perform stringent checks on their arguments. Internal
|
||||
unctions, on the other hand, check arguments with assert().
|
||||
<p>
|
||||
Data types like H5B_t carry no information about whether the type is
|
||||
public or private since it doesn't matter.
|
||||
|
||||
<p>
|
||||
|
||||
|
||||
<FONT color="#c80028"
|
||||
<LI> <A NAME="04"> <B> <I> INTEGRAL TYPES </I> </B> </A>
|
||||
</FONT>
|
||||
<p>
|
||||
Integral fixed-point type names are an optional `u' followed by `int'
|
||||
followed by the size in bits (8, 16,
|
||||
32, or 64). There is no trailing `_t' because these are common
|
||||
enough and follow their own naming convention.
|
||||
<p>
|
||||
<pre><H4>
|
||||
<dd> hbool_t -- boolean values (BTRUE, BFALSE, BFAIL)
|
||||
<br>
|
||||
<dd> int8 -- signed 8-bit integers
|
||||
<br>
|
||||
<dd> uint8 -- unsigned 8-bit integers
|
||||
<br>
|
||||
<dd> int16 -- signed 16-bit integers
|
||||
<br>
|
||||
<dd> uint16 -- unsigned 16-bit integers
|
||||
<br>
|
||||
<dd> int32 -- signed 32-bit integers
|
||||
<br>
|
||||
<dd> uint32 -- unsigned 32-bit integers
|
||||
<br>
|
||||
<dd> int64 -- signed 64-bit integers
|
||||
<br>
|
||||
<dd> uint64 -- unsigned 64-bit integers
|
||||
<br>
|
||||
<dd> intn -- "native" integers
|
||||
<br>
|
||||
<dd> uintn -- "native" unsigned integers
|
||||
|
||||
</pre></H4>
|
||||
<p>
|
||||
|
||||
<FONT color="#c80028"
|
||||
<LI> <A NAME="05"> <B> <I> OTHER TYPES </I> </B> </A>
|
||||
</FONT>
|
||||
|
||||
<p>
|
||||
|
||||
Other data types are always followed by `_t'.
|
||||
<p>
|
||||
<pre><H4>
|
||||
<dd> H5B_key_t-- additional data type used by H5B package.
|
||||
</pre></H4>
|
||||
<p>
|
||||
|
||||
However, if the name is so common that it's used almost everywhere,
|
||||
then we make an alias for it by removing the package name and leading
|
||||
underscore and replacing it with an `h' (the main datatype for a
|
||||
package already has a short enough name, so we don't have aliases for
|
||||
them).
|
||||
<P>
|
||||
<pre><H4>
|
||||
<dd> typedef H5E_err_t herr_t;
|
||||
</pre> </H4>
|
||||
<p>
|
||||
|
||||
<FONT color="#c80028"
|
||||
<LI> <A NAME="06"> <B> <I> GLOBAL VARIABLES </I> </B> </A>
|
||||
</FONT>
|
||||
<p>
|
||||
Global variables include the package name and end with `_g'.
|
||||
<p>
|
||||
<pre><H4>
|
||||
<dd> H5AC_methods_g -- global variable in the H5AC package.
|
||||
</pre> </H4>
|
||||
<p>
|
||||
|
||||
|
||||
<FONT color="#c80028"
|
||||
<LI> <A NAME="07">
|
||||
<I> <B>
|
||||
MACROS, PREPROCESSOR CONSTANTS, AND ENUM MEMBERS
|
||||
</I> </B> </A>
|
||||
</FONT>
|
||||
<p>
|
||||
Same rules as other symbols except the name is all upper case. There
|
||||
are a few exceptions: <br>
|
||||
<ul>
|
||||
<li> Constants and macros defined on a system that is deficient:
|
||||
<p><pre><H4>
|
||||
<dd> MIN(x,y), MAX(x,y) and their relatives
|
||||
</pre></H4>
|
||||
|
||||
<li> Platform constants :
|
||||
<P>
|
||||
No naming scheme; determined by OS and compiler.<br>
|
||||
These appear only in one header file anyway.
|
||||
<p>
|
||||
<li> Feature test constants (?)<br>
|
||||
Always start with `HDF5_HAVE_' like HDF5_HAVE_STDARG_H for a
|
||||
header file, or HDF5_HAVE_DEV_T for a data type, or
|
||||
HDF5_HAVE_DIV for a function.
|
||||
</UL>
|
||||
<p>
|
||||
|
||||
</UL>
|
||||
<p>
|
||||
<H6>
|
||||
<center>
|
||||
This file /hdf3/web/hdf/internal/HDF_standard/HDF5.coding_standard.html is
|
||||
maintained by Elena Pourmal <A HREF = "mailto:epourmal@ncsa.uiuc.edu">
|
||||
<I>epourmal@ncsa.uiuc.edu</I> </A>.
|
||||
</center>
|
||||
<p>
|
||||
<center>
|
||||
Last modified August 5, 1997
|
||||
</center>
|
||||
|
||||
</H6>
|
||||
</BODY>
|
||||
<HTML>
|
||||
|
409
doc/html/Compression.html
Normal file
@ -0,0 +1,409 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Compression</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Compression</h1>
|
||||
|
||||
<h2>1. Introduction</h2>
|
||||
|
||||
<p>HDF5 supports compression of raw data by compression methods
|
||||
built into the library or defined by an application. A
|
||||
compression method is associated with a dataset when the dataset
|
||||
is created and is applied independently to each storage chunk of
|
||||
the dataset.
|
||||
|
||||
The dataset must use the <code>H5D_CHUNKED</code> storage
|
||||
layout. The library doesn't support compression for contiguous
|
||||
datasets because of the difficulty of implementing random access
|
||||
for partial I/O, and compact dataset compression is not
|
||||
supported because it wouldn't produce significant results.
|
||||
|
||||
<h2>2. Supported Compression Methods</h2>
|
||||
|
||||
<p>The library identifies compression methods with small
|
||||
integers, with values less than 16 reserved for use by NCSA and
|
||||
values between 16 and 255 (inclusive) available for general
|
||||
use. This range may be extended in the future if it proves to
|
||||
be too small.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table align=center width="80%">
|
||||
<tr>
|
||||
<th width="30%">Method Name</th>
|
||||
<th width="70%">Description</th>
|
||||
</tr>
|
||||
|
||||
<tr valign=top>
|
||||
<td><code>H5Z_NONE</code></td>
|
||||
<td>The default is to not use compression. Specifying
|
||||
<code>H5Z_NONE</code> as the compression method results
|
||||
in better perfomance than writing a function that just
|
||||
copies data because the library's I/O pipeline
|
||||
recognizes this method and is able to short circuit
|
||||
parts of the pipeline.</td>
|
||||
</tr>
|
||||
|
||||
<tr valign=top>
|
||||
<td><code>H5Z_DEFLATE</code></td>
|
||||
<td>The <em>deflate</em> method is the algorithm used by
|
||||
the GNU <code>gzip</code>program. It's a combination of
|
||||
a Huffman encoding followed by a 1977 Lempel-Ziv (LZ77)
|
||||
dictionary encoding. The aggressiveness of the
|
||||
compression can be controlled by passing an integer value
|
||||
to the compressor with <code>H5Pset_deflate()</code>
|
||||
(see below). In order for this compression method to be
|
||||
used, the HDF5 library must be configured and compiled
|
||||
in the presence of the GNU zlib version 1.1.2 or
|
||||
later.</td>
|
||||
</tr>
|
||||
|
||||
<tr valign=top>
|
||||
<td><code>H5Z_RES_<em>N</em></code></td>
|
||||
<td>These compression methods (where <em>N</em> is in the
|
||||
range two through 15, inclusive) are reserved by NCSA
|
||||
for future use.</td>
|
||||
</tr>
|
||||
|
||||
<tr valign=top>
|
||||
<td>Values of <em>N</em> between 16 and 255, inclusive</td>
|
||||
<td>These values can be used to represent application-defined
|
||||
compression methods. We recommend that methods under
|
||||
testing should be in the high range and when a method is
|
||||
about to be published it should be given a number near
|
||||
the low end of the range (or even below 16). Publishing
|
||||
the compression method and its numeric ID will make a
|
||||
file sharable.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>Setting the compression for a dataset to a method which was
|
||||
not compiled into the library and/or not registered by the
|
||||
application is allowed, but writing to such a dataset will
|
||||
silently <em>not</em> compress the data. Reading a compressed
|
||||
dataset for a method which is not available will result in
|
||||
errors (specifically, <code>H5Dread()</code> will return a
|
||||
negative value). The errors will be displayed in the
|
||||
compression statistics if the library was compiled with
|
||||
debugging turned on for the "z" package. See the
|
||||
section on diagnostics below for more details.
|
||||
|
||||
<h2>3. Application-Defined Methods</h2>
|
||||
|
||||
<p>Compression methods 16 through 255 can be defined by an
|
||||
application. As mentioned above, methods that have not been
|
||||
released should use high numbers in that range while methods
|
||||
that have been published will be assigned an official number in
|
||||
the low region of the range (possibly less than 16). Users
|
||||
should be aware that using unpublished compression methods
|
||||
results in unsharable files.
|
||||
|
||||
<p>A compression method has two halves: one have handles
|
||||
compression and the other half handles uncompression. The
|
||||
halves are implemented as functions
|
||||
<code><em>method</em>_c</code> and
|
||||
<code><em>method</em>_u</code> respectively. One should not use
|
||||
the names <code>compress</code> or <code>uncompress</code> since
|
||||
they are likely to conflict with other compression libraries
|
||||
(like the GNU zlib).
|
||||
|
||||
<p>Both the <code><em>method</em>_c</code> and
|
||||
<code><em>method</em>_u</code> functions take the same arguments
|
||||
and return the same values. They are defined with the type:
|
||||
|
||||
<dl>
|
||||
<dt><code>typedef size_t (*H5Z_func_t)(unsigned int
|
||||
<em>flags</em>, size_t <em>cd_size</em>, const void
|
||||
*<em>client_data</em>, size_t <em>src_nbytes</em>, const
|
||||
void *<em>src</em>, size_t <em>dst_nbytes</em>, void
|
||||
*<em>dst</em>/*out*/)</code>
|
||||
<dd>The <em>flags</em> are an 8-bit vector which is stored in
|
||||
the file and which is defined when the compression method is
|
||||
defined. The <em>client_data</em> is a pointer to
|
||||
<em>cd_size</em> bytes of configuration data which is also
|
||||
stored in the file. The function compresses or uncompresses
|
||||
<em>src_nbytes</em> from the source buffer <em>src</em> into
|
||||
at most <em>dst_nbytes</em> of the result buffer <em>dst</em>.
|
||||
The function returns the number of bytes written to the result
|
||||
buffer or zero if an error occurs. But if a result buffer
|
||||
overrun occurs the function should return a value at least as
|
||||
large as <em>dst_size</em> (the uncompressor will see an
|
||||
overrun only for corrupt data).
|
||||
</dl>
|
||||
|
||||
<p>The application associates the pair of functions with a name
|
||||
and a method number by calling <code>H5Zregister()</code>. This
|
||||
function can also be used to remove a compression method from
|
||||
the library by supplying null pointers for the functions.
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Zregister (H5Z_method_t <em>method</em>,
|
||||
const char *<em>name</em>, H5Z_func_t <em>method_c</em>,
|
||||
H5Z_func_t <em>method_u</em>)</code>
|
||||
<dd>The pair of functions to be used for compression
|
||||
(<em>method_c</em>) and uncompression (<em>method_u</em>) are
|
||||
associated with a short <em>name</em> used for debugging and a
|
||||
<em>method</em> number in the range 16 through 255. This
|
||||
function can be called as often as desired for a particular
|
||||
compression method with each call replacing the information
|
||||
stored by the previous call. Sometimes it's convenient to
|
||||
supply only one half of the compression, for instance in an
|
||||
application that opens files for read-only. Compression
|
||||
statistics for the method are accumulated across calls to this
|
||||
function.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=bottom><h4>Example: Registering an
|
||||
Application-Defined Compression Method</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p>Here's a simple-minded "compression" method
|
||||
that just copies the input value to the output. It's
|
||||
similar to the <code>H5Z_NONE</code> method but
|
||||
slower. Compression and uncompression are performed
|
||||
by the same function.
|
||||
|
||||
<p><code><pre>
|
||||
size_t
|
||||
bogus (unsigned int flags,
|
||||
size_t cd_size, const void *client_data,
|
||||
size_t src_nbytes, const void *src,
|
||||
size_t dst_nbytes, void *dst/*out*/)
|
||||
{
|
||||
memcpy (dst, src, src_nbytes);
|
||||
return src_nbytes;
|
||||
}
|
||||
</pre></code>
|
||||
|
||||
<p>The function could be registered as method 250 as
|
||||
follows:
|
||||
|
||||
<p><code><pre>
|
||||
#define H5Z_BOGUS 250
|
||||
H5Zregister (H5Z_BOGUS, "bogus", bogus, bogus);
|
||||
</pre></code>
|
||||
|
||||
<p>The function can be unregistered by saying:
|
||||
|
||||
<p><code><pre>
|
||||
H5Zregister (H5Z_BUGUS, "bogus", NULL, NULL);
|
||||
</pre></code>
|
||||
|
||||
<p>Notice that we kept the name "bogus" even
|
||||
though we unregistered the functions that perform the
|
||||
compression and uncompression. This makes compression
|
||||
statistics more understandable when they're printed.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<h2>4. Enabling Compression for a Dataset</h2>
|
||||
|
||||
<p>If a dataset is to be compressed then the compression
|
||||
information must be specified when the dataset is created since
|
||||
once a dataset is created compression parameters cannot be
|
||||
adjusted. The compression is specified through the dataset
|
||||
creation property list (see <code>H5Pcreate()</code>).
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Pset_deflate (hid_t <em>plist</em>, int
|
||||
<em>level</em>)</code>
|
||||
<dd>The compression method for dataset creation property list
|
||||
<em>plist</em> is set to <code>H5Z_DEFLATE</code> and the
|
||||
aggression level is set to <em>level</em>. The <em>level</em>
|
||||
must be a value between one and nine, inclusive, where one
|
||||
indicates no (but fast) compression and nine is aggressive
|
||||
compression.
|
||||
|
||||
<br><br>
|
||||
<dt><code>int H5Pget_deflate (hid_t <em>plist</em>)</code>
|
||||
<dd>If dataset creation property list <em>plist</em> is set to
|
||||
use <code>H5Z_DEFLATE</code> compression then this function
|
||||
will return the aggression level, an integer between one and
|
||||
nine inclusive. If <em>plist</em> isn't a valid dataset
|
||||
creation property list or it isn't set to use the deflate
|
||||
method then a negative value is returned.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pset_compression (hid_t <em>plist</em>,
|
||||
H5Z_method_t <em>method</em>, unsigned int <em>flags</em>,
|
||||
size_t <em>cd_size</em>, const void *<em>client_data</em>)</code>
|
||||
<dd>This is a catch-all function for defining compresion methods
|
||||
and is intended to be called from a wrapper such as
|
||||
<code>H5Pset_deflate()</code>. The dataset creation property
|
||||
list <em>plist</em> is adjusted to use the specified
|
||||
compression method. The <em>flags</em> is an 8-bit vector
|
||||
which is stored in the file as part of the compression message
|
||||
and passed to the compress and uncompress functions. The
|
||||
<em>client_data</em> is a byte array of length
|
||||
<em>cd_size</em> which is copied to the file and passed to the
|
||||
compress and uncompress methods.
|
||||
|
||||
<br><br>
|
||||
<dt><code>H5Z_method_t H5Pget_compression (hid_t <em>plist</em>,
|
||||
unsigned int *<em>flags</em>, size_t *<em>cd_size</em>, void
|
||||
*<em>client_data</em>)</code>
|
||||
<dd>This is a catch-all function for querying the compression
|
||||
method associated with dataset creation property list
|
||||
<em>plist</em> and is intended to be called from a wrapper
|
||||
function such as <code>H5Pget_deflate()</code>. The
|
||||
compression method (or a negative value on error) is returned
|
||||
by value, and compression flags and client data is returned by
|
||||
argument. The application should allocate the
|
||||
<em>client_data</em> and pass its size as the
|
||||
<em>cd_size</em>. On return, <em>cd_size</em> will contain
|
||||
the actual size of the client data. If <em>client_data</em>
|
||||
is not large enough to hold the entire client data then
|
||||
<em>cd_size</em> bytes are copied into <em>client_data</em>
|
||||
and <em>cd_size</em> is set to the total size of the client
|
||||
data, a value larger than the original.
|
||||
</dl>
|
||||
|
||||
<p>It is possible to set the compression to a method which hasn't
|
||||
been defined with <code>H5Zregister()</code> and which isn't
|
||||
supported as a predefined method (for instance, setting the
|
||||
method to <code>H5Z_DEFLATE</code> when the GNU zlib isn't
|
||||
available). If that happens then data will be written to the
|
||||
file in its uncompressed form and the compression statistics
|
||||
will show failures for the compression.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=bottom><h4>Example: Statistics for an
|
||||
Unsupported Compression Method</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p>If an application attempts to use an unsupported
|
||||
method then the compression statistics will show large
|
||||
numbers of compression errors and no data
|
||||
uncompressed.
|
||||
|
||||
<p><code><pre>
|
||||
H5Z: compression statistics accumulated over life of library:
|
||||
Method Total Overrun Errors User System Elapsed Bandwidth
|
||||
------ ----- ------- ------ ---- ------ ------- ---------
|
||||
deflate-c 160000 0 160000 0.00 0.01 0.01 1.884e+07
|
||||
deflate-u 0 0 0 0.00 0.00 0.00 NaN
|
||||
</pre></code>
|
||||
|
||||
<p>This example is from a program that tried to use
|
||||
<code>H5Z_DEFLATE</code> on a system that didn't have
|
||||
the GNU zlib to write to a dataset and then read the
|
||||
result. The read and write both succeeded but the
|
||||
data was not compressed.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<h2>5. Compression Diagnostics</h2>
|
||||
|
||||
<p>If the library is compiled with debugging turned on for the H5Z
|
||||
layer (usually as a result of <code>configure --enable-debug=z</code>)
|
||||
then statistics about data compression are printed when the
|
||||
application exits normally or the library is closed. The
|
||||
statistics are written to the standard error stream and include
|
||||
two lines for each compression method that was used: the first
|
||||
line shows compression statistics while the second shows
|
||||
uncompression statistics. The following fields are displayed:
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table align=center width="80%">
|
||||
<tr>
|
||||
<th width="30%">Field Name</th>
|
||||
<th width="70%">Description</th>
|
||||
</tr>
|
||||
|
||||
<tr valign=top>
|
||||
<td>Method</td>
|
||||
<td>This is the name of the method as defined with
|
||||
<code>H5Zregister()</code> with the letters
|
||||
"-c" or "-u" appended to indicate
|
||||
compression or uncompression.</td>
|
||||
</tr>
|
||||
|
||||
<tr valign=top>
|
||||
<td>Total</td>
|
||||
<td>The total number of bytes compressed or decompressed
|
||||
including buffer overruns and errors. Bytes of
|
||||
non-compressed data are counted.</td>
|
||||
</tr>
|
||||
|
||||
<tr valign=top>
|
||||
<td>Overrun</td>
|
||||
<td>During compression, if the algorithm causes the result
|
||||
to be at least as large as the input then a buffer
|
||||
overrun error occurs. This field shows the total number
|
||||
of bytes from the Total column which can be attributed to
|
||||
overruns. Overruns for decompression can only happen if
|
||||
the data has been corrupted in some way and will result
|
||||
in failure of <code>H5Dread()</code>.</td>
|
||||
</tr>
|
||||
|
||||
<tr valign=top>
|
||||
<td>Errors</td>
|
||||
<td>If an error occurs during compression the data is
|
||||
stored in it's uncompressed form; and an error during
|
||||
uncompression causes <code>H5Dread()</code> to return
|
||||
failure. This field shows the number of bytes of the
|
||||
Total column which can be attributed to errors.</td>
|
||||
</tr>
|
||||
|
||||
<tr valign=top>
|
||||
<td>User, System, Elapsed</td>
|
||||
<td>These are the amount of user time, system time, and
|
||||
elapsed time in seconds spent by the library to perform
|
||||
compression. Elapsed time is sensitive to system
|
||||
load. These times may be zero on operating systems that
|
||||
don't support the required operations.</td>
|
||||
</tr>
|
||||
|
||||
<tr valign=top>
|
||||
<td>Bandwidth</td>
|
||||
<td>This is the compression bandwidth which is the total
|
||||
number of bytes divided by elapsed time. Since elapsed
|
||||
time is subject to system load the bandwidth numbers
|
||||
cannot always be trusted. Furthermore, the bandwidth
|
||||
includes overrun and error bytes which may significanly
|
||||
taint the value.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=bottom><h4>Example: Compression
|
||||
Statistics</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p><code><pre>
|
||||
H5Z: compression statistics accumulated over life of library:
|
||||
Method Total Overrun Errors User System Elapsed Bandwidth
|
||||
------ ----- ------- ------ ---- ------ ------- ---------
|
||||
deflate-c 160000 200 0 0.62 0.74 1.33 1.204e+05
|
||||
deflate-u 120000 0 0 0.11 0.00 0.12 9.885e+05
|
||||
</pre></code>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Fri Apr 17 13:39:35 EDT 1998 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Fri Apr 17 16:15:21 EDT 1998
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
839
doc/html/Datasets.html
Normal file
@ -0,0 +1,839 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>The Dataset Interface (H5D)</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>The Dataset Interface (H5D)</h1>
|
||||
|
||||
<h2>1. Introduction</h2>
|
||||
|
||||
<p>The purpose of the dataset interface is to provide a mechanism
|
||||
to describe properties of datasets and to transfer data between
|
||||
memory and disk. A dataset is composed of a collection of raw
|
||||
data points and four classes of meta data to describe the data
|
||||
points. The interface is hopefully designed in such a way as to
|
||||
allow new features to be added without disrupting current
|
||||
applications that use the dataset interface.
|
||||
|
||||
<p>The four classes of meta data are:
|
||||
|
||||
<dl>
|
||||
<dt>Constant Meta Data
|
||||
<dd>Meta data that is created when the dataset is created and
|
||||
exists unchanged for the life of the dataset. For instance,
|
||||
the data type of stored array elements is defined when the
|
||||
dataset is created and cannot be subsequently changed.
|
||||
|
||||
<dt>Persistent Meta Data
|
||||
<dd>Meta data that is an integral and permanent part of a
|
||||
dataset but can change over time. For instance, the size in
|
||||
any dimension can increase over time if such an increase is
|
||||
allowed when the dataset was created.
|
||||
|
||||
<dt>Memory Meta Data
|
||||
<dd>Meta data that exists to describe how raw data is organized
|
||||
in the application's memory space. For instance, the data
|
||||
type of elements in an application array might not be the same
|
||||
as the data type of those elements as stored in the HDF5 file.
|
||||
|
||||
<dt>Transport Meta Data
|
||||
<dd>Meta data that is used only during the transfer of raw data
|
||||
from one location to another. For instance, the number of
|
||||
processes participating in a collective I/O request or hints
|
||||
to the library to control caching of raw data.
|
||||
</dl>
|
||||
|
||||
<p>Each of these classes of meta data is handled differently by
|
||||
the library although the same API might be used to create them.
|
||||
For instance, the data type exists as constant meta data and as
|
||||
memory meta data; the same API (the <code>H5T</code> API) is
|
||||
used to manipulate both pieces of meta data but they're handled
|
||||
by the dataset API (the <code>H5D</code> API) in different
|
||||
manners.
|
||||
|
||||
|
||||
|
||||
<h2>2. Storage Layout Properties</h2>
|
||||
|
||||
<p>The dataset API partitions these terms on three orthogonal axes
|
||||
(layout, compression, and external storage) and uses a
|
||||
<em>dataset creation property list</em> to hold the various
|
||||
settings and pass them through the dataset interface. This is
|
||||
similar to the way HDF5 files are created with a file creation
|
||||
property list. A dataset creation property list is always
|
||||
derived from the default dataset creation property list (use
|
||||
<code>H5Pcreate()</code> to get a copy of the default property
|
||||
list) by modifying properties with various
|
||||
<code>H5Pset_<em>property</em>()</code> functions.
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Pset_layout (hid_t <em>plist_id</em>,
|
||||
H5D_layout_t <em>layout</em>)</code>
|
||||
<dd>The storage layout is a piece of constant meta data that
|
||||
describes what method the library uses to organize the raw
|
||||
data on disk. The default layout is contiguous storage.
|
||||
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><code>H5D_COMPACT</code>
|
||||
<dd>The raw data is presumably small and can be stored
|
||||
directly in the object header. Such data is
|
||||
non-extendible, non-compressible, non-sparse, and cannot
|
||||
be stored externally. Most of these restrictions are
|
||||
arbitrary but are enforced because of the small size of
|
||||
the raw data. Storing data in this format eliminates the
|
||||
disk seek/read request normally necessary to read raw
|
||||
data. <b>This layout is not implemented yet.</b>
|
||||
|
||||
<br><br>
|
||||
<dt><code>H5D_CONTIGUOUS</code>
|
||||
<dd>The raw data is large, non-extendible, non-compressible,
|
||||
non-sparse, and can be stored externally. This is the
|
||||
default value for the layout property. The term
|
||||
<em>large</em> means that it may not be possible to hold
|
||||
the entire dataset in memory. The non-compressibility is
|
||||
a side effect of the data being large, contiguous, and
|
||||
fixed-size at the physical level, which could cause
|
||||
partial I/O requests to be extremely expensive if
|
||||
compression were allowed.
|
||||
|
||||
<br><br>
|
||||
<dt><code>H5D_CHUNKED</code>
|
||||
<dd>The raw data is large and can be extended in any
|
||||
dimension at any time (provided the data space also allows
|
||||
the extension). It may be sparse at the chunk level (each
|
||||
chunk is non-sparse, but there might only be a few chunks)
|
||||
and each chunk can be compressed and/or stored externally.
|
||||
A dataset is partitioned into chunks so each chunk is the
|
||||
same logical size. The chunks are indexed by a B-tree and
|
||||
are allocated on demand (although it might be useful to be
|
||||
able to preallocate storage for parts of a chunked array
|
||||
to reduce contention for the B-tree in a parallel
|
||||
environment). The chunk size must be defined with
|
||||
<code>H5Pset_chunk()</code>.
|
||||
|
||||
<br><br>
|
||||
<dt><em>others...</em>
|
||||
<dd>Other layout types may be defined later without breaking
|
||||
existing code. However, to be able to correctly read or
|
||||
modify data stored with one of these new layouts, the
|
||||
application will need to be linked with a new version of
|
||||
the library. This happens automatically on systems with
|
||||
dynamic linking.
|
||||
</dl>
|
||||
</dl>
|
||||
|
||||
<p>Once the general layout is defined, the user can define
|
||||
properties of that layout. Currently, the only layout that has
|
||||
user-settable properties is the <code>H5D_CHUNKED</code> layout,
|
||||
which needs to know the dimensionality and chunk size.
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Pset_chunk (hid_t <em>plist_id</em>, int
|
||||
<em>ndims</em>, hsize_t <em>dim</em>[])</code>
|
||||
<dd>This function defines the logical size of a chunk for
|
||||
chunked layout. If the layout property is set to
|
||||
<code>H5D_CHUNKED</code> and the chunk size is set to
|
||||
<em>dim</em>. The number of elements in the <em>dim</em> array
|
||||
is the dimensionality, <em>ndims</em>. One need not call
|
||||
<code>H5Dset_layout()</code> when using this function since
|
||||
the chunked layout is implied.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=bottom><h4>Example: Chunked Storage</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p>This example shows how a two-dimensional dataset
|
||||
is partitioned into chunks. The library can manage file
|
||||
memory by moving the chunks around, and each chunk could be
|
||||
compressed. The chunks are allocated in the file on demand
|
||||
when data is written to the chunk.
|
||||
<center>
|
||||
<img alt="Chunked Storage" src="chunk1.gif">
|
||||
</center>
|
||||
|
||||
<p><code><pre>
|
||||
size_t hsize[2] = {1000, 1000};
|
||||
plist = H5Pcreate (H5P_DATASET_CREATE);
|
||||
H5Pset_chunk (plist, 2, size);
|
||||
</pre></code>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
|
||||
<p>Although it is most efficient if I/O requests are aligned on chunk
|
||||
boundaries, this is not a constraint. The application can perform I/O
|
||||
on any set of data points as long as the set can be described by the
|
||||
data space. The set on which I/O is performed is called the
|
||||
<em>selection</em>.
|
||||
|
||||
<h2>3. Compression Properties</h2>
|
||||
|
||||
<p>Some types of storage layout allow data compression which is
|
||||
defined by the functions described here. <b>Compression is not
|
||||
implemented yet.</b>
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Pset_compression (hid_t <em>plist_id</em>,
|
||||
H5Z_method_t <em>method</em>)</code>
|
||||
<dt><code>H5Z_method_t H5Pget_compression (hid_t
|
||||
<em>plist_id</em>)</code>
|
||||
<dd>These functions set and query the compression method that
|
||||
is used to compress the raw data of a dataset. The
|
||||
<em>plist_id</em> is a dataset creation property list. The
|
||||
possible values for the compression method are:
|
||||
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><code>H5Z_NONE</code>
|
||||
<dd>This is the default and specifies that no compression is
|
||||
to be performed.
|
||||
|
||||
<br><br>
|
||||
<dt><code>H5Z_DEFLATE</code>
|
||||
<dd>This specifies that a variation of the Lempel-Ziv 1977
|
||||
(LZ77) encoding is used, the same encoding used by the
|
||||
free GNU <code>gzip</code> program.
|
||||
</dl>
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pset_deflate (hid_t <em>plist_id</em>,
|
||||
int <em>level</em>)</code>
|
||||
<dt><code>int H5Pget_deflate (hid_t <em>plist_id</em>)</code>
|
||||
<dd>These functions set or query the deflate level of
|
||||
dataset creation property list <em>plist_id</em>. The
|
||||
<code>H5Pset_deflate()</code> sets the compression method to
|
||||
<code>H5Z_DEFLATE</code> and sets the compression level to
|
||||
some integer between one and nine (inclusive). One results in
|
||||
the fastest compression while nine results in the best
|
||||
compression ratio. The default value is six if
|
||||
<code>H5Pset_deflate()</code> isn't called. The
|
||||
<code>H5Pget_deflate()</code> returns the compression level
|
||||
for the deflate method, or negative if the method is not the
|
||||
deflate method.
|
||||
</dl>
|
||||
|
||||
<h2>4. External Storage Properties</h2>
|
||||
|
||||
<p>Some storage formats may allow storage of data across a set of
|
||||
non-HDF5 files. Currently, only the <code>H5D_CONTIGUOUS</code> storage
|
||||
format allows external storage. A set segments (offsets and sizes) in
|
||||
one or more files is defined as an external file list, or <em>EFL</em>,
|
||||
and the contiguous logical addresses of the data storage are mapped onto
|
||||
these segments.
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Pset_external (hid_t <em>plist</em>, const
|
||||
char *<em>name</em>, off_t <em>offset</em>, hsize_t
|
||||
<em>size</em>)</code>
|
||||
<dd>This function adds a new segment to the end of the external
|
||||
file list of the specified dataset creation property list. The
|
||||
segment begins a byte <em>offset</em> of file <em>name</em> and
|
||||
continues for <em>size</em> bytes. The space represented by this
|
||||
segment is adjacent to the space already represented by the external
|
||||
file list. The last segment in a file list may have the size
|
||||
<code>H5F_UNLIMITED</em>.
|
||||
|
||||
<br><br>
|
||||
<dt><code>int H5Pget_external_count (hid_t <em>plist</em>)</code>
|
||||
<dd>Calling this function returns the number of segments in an
|
||||
external file list. If the dataset creation property list has no
|
||||
external data then zero is returned.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pget_external (hid_t <em>plist</em>, int
|
||||
<em>idx</em>, size_t <em>name_size</em>, char *<em>name</em>, off_t
|
||||
*<em>offset</em>, hsize_t *<em>size</em>)</code>
|
||||
<dd>This is the counterpart for the <code>H5Pset_external()</code>
|
||||
function. Given a dataset creation property list and a zero-based
|
||||
index into that list, the file name, byte offset, and segment size are
|
||||
returned through non-null arguments. At most <em>name_size</em>
|
||||
characters are copied into the <em>name</em> argument which is not
|
||||
null terminated if the file name is longer than the supplied name
|
||||
buffer (this is similar to <code>strncpy()</code>).
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=bottom><h4>Example: Multiple Segments</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p>This example shows how a contiguous, one-dimensional dataset
|
||||
is partitioned into three parts and each of those parts is
|
||||
stored in a segment of an external file. The top rectangle
|
||||
represents the logical address space of the dataset
|
||||
while the bottom rectangle represents an external file.
|
||||
<center>
|
||||
<img alt="Multiple Segments" src="extern1.gif">
|
||||
</center>
|
||||
|
||||
<p><code><pre>
|
||||
plist = H5Pcreate (H5P_DATASET_CREATE);
|
||||
H5Pset_external (plist, "velocity.data", 3000, 1000);
|
||||
H5Pset_external (plist, "velocity.data", 0, 2500);
|
||||
H5Pset_external (plist, "velocity.data", 4500, 1500);
|
||||
</pre></code>
|
||||
|
||||
<p>One should note that the segments are defined in order of the
|
||||
logical addresses they represent, not their order within the
|
||||
external file. It would also have been possible to put the
|
||||
segments in separate files. Care should be taken when setting
|
||||
up segments in a single file since the library doesn't
|
||||
automatically check for segments that overlap.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=bottom><h4>Example: Multi-Dimensional</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p>This example shows how a contiguous, two-dimensional dataset
|
||||
is partitioned into three parts and each of those parts is
|
||||
stored in a separate external file. The top rectangle
|
||||
represents the logical address space of the dataset
|
||||
while the bottom rectangles represent external files.
|
||||
<center>
|
||||
<img alt="Multiple Dimensions" src="extern2.gif">
|
||||
</center>
|
||||
|
||||
<p><code><pre>
|
||||
plist = H5Pcreate (H5P_DATASET_CREATE);
|
||||
H5Pset_external (plist, "scan1.data", 0, 24);
|
||||
H5Pset_external (plist, "scan2.data", 0, 24);
|
||||
H5Pset_external (plist, "scan3.data", 0, 16);
|
||||
</pre></code>
|
||||
|
||||
<p>The library maps the multi-dimensional array onto a linear
|
||||
address space like normal, and then maps that address space
|
||||
into the segments defined in the external file list.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>The segments of an external file can exist beyond the end of the
|
||||
file. The library reads that part of a segment as zeros. When writing
|
||||
to a segment that exists beyond the end of a file, the file is
|
||||
automatically extended. Using this feature, one can create a segment
|
||||
(or set of segments) which is larger than the current size of the
|
||||
dataset, which allows to dataset to be extended at a future time
|
||||
(provided the data space also allows the extension).
|
||||
|
||||
<p>All referenced external data files must exist before performing raw
|
||||
data I/O on the dataset. This is normally not a problem since those
|
||||
files are being managed directly by the application, or indirectly
|
||||
through some other library.
|
||||
|
||||
|
||||
<h2>5. Data Type</h2>
|
||||
|
||||
<p>Raw data has a constant data type which describes the data type
|
||||
of the raw data stored in the file, and a memory data type that
|
||||
describes the data type stored in application memory. Both data
|
||||
types are manipulated with the <a
|
||||
href="Datatypes.html"><code>H5T</code></a> API.
|
||||
|
||||
<p>The constant file data type is associated with the dataset when
|
||||
the dataset is created in a manner described below. Once
|
||||
assigned, the constant datatype can never be changed.
|
||||
|
||||
<p>The memory data type is specified when data is transferred
|
||||
to/from application memory. In the name of data sharability,
|
||||
the memory data type must be specified, but can be the same
|
||||
type identifier as the constant data type.
|
||||
|
||||
<p>During dataset I/O operations, the library translates the raw
|
||||
data from the constant data type to the memory data type or vice
|
||||
versa. Structured data types include member offsets to allow
|
||||
reordering of struct members and/or selection of a subset of
|
||||
members and array data types include index permutation
|
||||
information to allow things like transpose operations (<b>the
|
||||
prototype does not support array reordering</b>) Permutations
|
||||
are relative to some extrinsic descritpion of the dataset.
|
||||
|
||||
|
||||
|
||||
<h2>6. Data Space</h2>
|
||||
|
||||
<p>The dataspace of a dataset defines the number of dimensions
|
||||
and the size of each dimension and is manipulated with the
|
||||
<code>H5S</code> API. The <em>simple</em> dataspace consists of
|
||||
maximum dimension sizes and actual dimension sizes, which are
|
||||
usually the same. However, maximum dimension sizes can be the
|
||||
constant <code>H5D_UNLIMITED</code> in which case the actual
|
||||
dimension size can be incremented with calls to
|
||||
<code>H5Dextend()</code>. The maximium dimension sizes are
|
||||
constant meta data while the actual dimension sizes are
|
||||
persistent meta data. Initial actual dimension sizes are
|
||||
supplied at the same time as the maximum dimension sizes when
|
||||
the dataset is created.
|
||||
|
||||
<p>The dataspace can also be used to define partial I/O
|
||||
operations. Since I/O operations have two end-points, the raw
|
||||
data transfer functions take two data space arguments: one which
|
||||
describes the application memory data space or subset thereof
|
||||
and another which describes the file data space or subset
|
||||
thereof.
|
||||
|
||||
|
||||
<h2>7. Setting Constant or Persistent Properties</h2>
|
||||
|
||||
<p>Each dataset has a set of constant and persistent properties
|
||||
which describe the layout method, pre-compression
|
||||
transformation, compression method, data type, external storage,
|
||||
and data space. The constant properties are set as described
|
||||
above in a dataset creation property list whose identifier is
|
||||
passed to <code>H5Dcreate()</code>.
|
||||
|
||||
<dl>
|
||||
<dt><code>hid_t H5Dcreate (hid_t <em>file_id</em>, const char
|
||||
*<em>name</em>, hid_t <em>type_id</em>, hid_t
|
||||
<em>space_id</em>, hid_t <em>create_plist_id</em>)</code>
|
||||
<dd>A dataset is created by calling <code>H5Dcreate</code> with
|
||||
a file identifier, a dataset name, a data type, a data space,
|
||||
and constant properties. The data type and data space are the
|
||||
type and space of the dataset as it will exist in the file,
|
||||
which may be different than in application memory. The
|
||||
<em>create_plist_id</em> is a <code>H5P_DATASET_CREATE</code>
|
||||
property list created with <code>H5Pcreate()</code> and
|
||||
initialized with the various functions described above.
|
||||
<code>H5Dcreate()</code> returns a dataset handle for success
|
||||
or negative for failure. The handle should eventually be
|
||||
closed by calling <code>H5Dclose()</code> to release resources
|
||||
it uses.
|
||||
|
||||
<br><br>
|
||||
<dt><code>hid_t H5Dopen (hid_t <em>file_id</em>, const char
|
||||
*<em>name</em>)</code>
|
||||
<dd>An existing dataset can be opened for access by calling this
|
||||
function. A dataset handle is returned for success or a
|
||||
negative value is returned for failure. The handle should
|
||||
eventually be closed by calling <code>H5Dclose()</code> to
|
||||
release resources it uses.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Dclose (hid_t <em>dataset_id</em>)</code>
|
||||
<dd>This function closes a dataset handle and releases all
|
||||
resources it might have been using. The handle should not be
|
||||
used in subsequent calls to the library.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Dextend (hid_t <em>dataset_id</em>,
|
||||
hsize_t <em>dim</em>[])</code>
|
||||
<dd>This function extends a dataset by increasing the size in
|
||||
one or more dimensions. Not all datasets can be extended.
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
<h2>8. Querying Constant or Persistent Properties</h2>
|
||||
|
||||
<p>Constant or persistent properties can be queried with a set of
|
||||
three functions. Each function returns an identifier for a copy
|
||||
of the requested properties. The identifier can be passed to
|
||||
various functions which modify the underlying object to derive a
|
||||
new object; the original dataset is completely unchanged. The
|
||||
return values from these functions should be properly destroyed
|
||||
when no longer needed.
|
||||
|
||||
<dl>
|
||||
<dt><code>hid_t H5Dget_type (hid_t <em>dataset_id</em>)</code>
|
||||
<dd>Returns an identifier for a copy of the dataset permanent
|
||||
data type or negative for failure.
|
||||
|
||||
<dt><code>hid_t H5Dget_space (hid_t <em>dataset_id</em>)</code>
|
||||
<dd>Returns an identifier for a copy of the dataset permanent
|
||||
data space, which also contains information about the current
|
||||
size of the dataset if the data set is extendable with
|
||||
<code>H5Dextend()</code>.
|
||||
|
||||
<dt><code>hid_t H5Dget_create_plist (hid_t
|
||||
<em>dataset_id</em>)</code>
|
||||
<dd>Returns an identifier for a copy of the dataset creation
|
||||
property list. The new property list is created by examining
|
||||
various permanent properties of the dataset. This is mostly a
|
||||
catch-all for everything but type and space.
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
<h2>9. Setting Memory and Transfer Properties</h2>
|
||||
|
||||
<p>A dataset also has memory properties which describe memory
|
||||
within the application, and transfer properties that control
|
||||
various aspects of the I/O operations. The memory can have a
|
||||
data type different than the permanent file data type (different
|
||||
number types, different struct member offsets, different array
|
||||
element orderings) and can also be a different size (memory is a
|
||||
subset of the permanent dataset elements, or vice versa). The
|
||||
transfer properties might provide caching hints or collective
|
||||
I/O information. Therefore, each I/O operation must specify
|
||||
memory and transfer properties.
|
||||
|
||||
<p>The memory properties are specified with <em>type_id</em> and
|
||||
<em>space_id</em> arguments while the transfer properties are
|
||||
specified with the <em>transfer_id</em> property list for the
|
||||
<code>H5Dread()</code> and <code>H5Dwrite()</code> functions
|
||||
(these functions are described below).
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Pset_buffer (hid_t <em>xfer_plist</em>,
|
||||
size_t <em>max_buf_size</em>, void *<em>tconv_buf</em>, void
|
||||
*<em>bkg_buf</em>)</code>
|
||||
<dt><code>size_t H5Pget_buffer (hid_t <em>xfer_plist</em>, void
|
||||
**<em>tconv_buf</em>, void **<em>bkg_buf</em>)</code>
|
||||
<dd>Sets or retrieves the maximum size in bytes of the temporary
|
||||
buffer used for data type conversion in the I/O pipeline. An
|
||||
application-defined buffer can also be supplied as the
|
||||
<em>tconv_buf</em> argument, otherwise a buffer will be
|
||||
allocated and freed on demand by the library. A second
|
||||
temporary buffer <em>bkg_buf</em> can also be supplied and
|
||||
should be the same size as the <em>tconv_buf</em>. The
|
||||
default values are 1MB for the maximum buffer size, and null
|
||||
pointers for each buffer indicating that they should be
|
||||
allocated on demand and freed when no longer needed. The
|
||||
<code>H5Pget_buffer()</code> function returns the maximum
|
||||
buffer size or zero on error.
|
||||
</dl>
|
||||
|
||||
<p>If the maximum size of the temporary I/O pipeline buffers is
|
||||
too small to hold the entire I/O request, then the I/O request
|
||||
will be fragmented and the transfer operation will be strip
|
||||
mined. However, certain restrictions apply to the strip
|
||||
mining. For instance, when performing I/O on a hyperslab of a
|
||||
simple data space the strip mining is in terms of the slowest
|
||||
varying dimension. So if a 100x200x300 hyperslab is requested,
|
||||
the temporary buffer must be large enough to hold a 1x200x300
|
||||
sub-hyperslab.
|
||||
|
||||
<p>To prevent strip mining from happening, the application should
|
||||
use <code>H5Pset_buffer()</code> to set the size of the
|
||||
temporary buffer so it's large enough to hold the entire
|
||||
request.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=bottom><h4>Example</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p>This example shows how to define a function that sets
|
||||
a dataset transfer property list so that strip mining
|
||||
does not occur. It takes an (optional) dataset transfer
|
||||
property list, a dataset, a data space that describes
|
||||
what data points are being transfered, and a data type
|
||||
for the data points in memory. It returns a (new)
|
||||
dataset transfer property list with the temporary
|
||||
buffer size set to an appropriate value. The return
|
||||
value should be passed as the fifth argument to
|
||||
<code>H5Dread()</code> or <code>H5Dwrite()</code>.
|
||||
<p><code><pre>
|
||||
1 hid_t
|
||||
2 disable_strip_mining (hid_t xfer_plist, hid_t dataset,
|
||||
3 hid_t space, hid_t mem_type)
|
||||
4 {
|
||||
5 hid_t file_type; /* File data type */
|
||||
6 size_t type_size; /* Sizeof larger type */
|
||||
7 size_t size; /* Temp buffer size */
|
||||
8 hid_t xfer_plist; /* Return value */
|
||||
9
|
||||
10 file_type = H5Dget_type (dataset);
|
||||
11 type_size = MAX(H5Tget_size(file_type), H5Tget_size(mem_type));
|
||||
12 H5Tclose (file_type);
|
||||
13 size = H5Sget_npoints(space) * type_size;
|
||||
14 if (xfer_plist<0) xfer_plist = H5Pcreate (H5P_DATASET_XFER);
|
||||
15 H5Pset_buffer(xfer_plist, size, NULL, NULL);
|
||||
16 return xfer_plist;
|
||||
17 }
|
||||
</pre></code>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
|
||||
|
||||
<h2>10. Querying Memory or Transfer Properties</h2>
|
||||
|
||||
<p>Unlike constant and persistent properties, a dataset cannot be
|
||||
queried for it's memory or transfer properties. Memory
|
||||
properties cannot be queried because the application already
|
||||
stores those properties separate from the buffer that holds the
|
||||
raw data, and the buffer may hold multiple segments from various
|
||||
datasets and thus have more than one set of memory properties.
|
||||
The transfer properties cannot be queried from the dataset
|
||||
because they're associated with the transfer itself and not with
|
||||
the dataset (but one can call
|
||||
<code>H5Pget_<em>property</em>()</code> to query transfer
|
||||
properties from a tempalate).
|
||||
|
||||
|
||||
<h2>11. Raw Data I/O</h2>
|
||||
|
||||
<p>All raw data I/O is accomplished through these functions which
|
||||
take a dataset handle, a memory data type, a memory data space,
|
||||
a file data space, transfer properties, and an application
|
||||
memory buffer. They translate data between the memory data type
|
||||
and space and the file data type and space. The data spaces can
|
||||
be used to describe partial I/O operations.
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Dread (hid_t <em>dataset_id</em>, hid_t
|
||||
<em>mem_type_id</em>, hid_t <em>mem_space_id</em>, hid_t
|
||||
<em>file_space_id</em>, hid_t <em>xfer_plist_id</em>,
|
||||
void *<em>buf</em>/*out*/)</code>
|
||||
<dd>Reads raw data from the specified dataset into <em>buf</em>
|
||||
converting from file data type and space to memory data type
|
||||
and space.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Dwrite (hid_t <em>dataset_id</em>, hid_t
|
||||
<em>mem_type_id</em>, hid_t <em>mem_space_id</em>, hid_t
|
||||
<em>file_space_id</em>, hid_t <em>xfer_plist_id</em>,
|
||||
const void *<em>buf</em>)</code>
|
||||
<dd>Writes raw data from an application buffer <em>buf</em> to
|
||||
the specified dataset converting from memory data type and
|
||||
space to file data type and space.
|
||||
</dl>
|
||||
|
||||
|
||||
<p>In the name of sharability, the memory datatype must be
|
||||
supplied. However, it can be the same identifier as was used to
|
||||
create the dataset or as was returned by
|
||||
<code>H5Dget_type()</code>; the library will not implicitly
|
||||
derive memory data types from constant data types.
|
||||
|
||||
<p>For complete reads of the dataset one may supply
|
||||
<code>H5S_ALL</code> as the argument for the file data space.
|
||||
If <code>H5S_ALL</code> is also supplied as the memory data
|
||||
space then no data space conversion is performed. This is a
|
||||
somewhat dangerous situation since the file data space might be
|
||||
different than what the application expects.
|
||||
|
||||
|
||||
|
||||
<h2>12. Examples</h2>
|
||||
|
||||
<p>The examples in this section illustrate some common dataset
|
||||
practices.
|
||||
|
||||
|
||||
<p>This example shows how to create a dataset which is stored in
|
||||
memory as a two-dimensional array of native <code>double</code>
|
||||
values but is stored in the file in Cray <code>float</code>
|
||||
format using LZ77 compression. The dataset is written to the
|
||||
HDF5 file and then read back as a two-dimensional array of
|
||||
<code>float</code> values.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=bottom><h4>Example 1</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p><code><pre>
|
||||
1 hid_t file, data_space, dataset, properties;
|
||||
2 double dd[500][600];
|
||||
3 float ff[500][600];
|
||||
4 hsize_t dims[2], chunk_size[2];
|
||||
5
|
||||
6 /* Describe the size of the array */
|
||||
7 dims[0] = 500;
|
||||
8 dims[1] = 600;
|
||||
9 data_space = H5Screate_simple (2, dims);
|
||||
10
|
||||
11
|
||||
12 /*
|
||||
13 * Create a new file using with read/write access,
|
||||
14 * default file creation properties, and default file
|
||||
15 * access properties.
|
||||
16 */
|
||||
17 file = H5Fcreate ("test.h5", H5F_ACC_RDWR, H5P_DEFAULT,
|
||||
18 H5P_DEFAULT);
|
||||
19
|
||||
20 /*
|
||||
21 * Set the dataset creation plist to specify that
|
||||
22 * the raw data is to be partitioned into 100x100 element
|
||||
23 * chunks and that each chunk is to be compressed with
|
||||
24 * LZ77.
|
||||
25 */
|
||||
26 chunk_size[0] = chunk_size[1] = 100;
|
||||
27 properties = H5Pcreate (H5P_DATASET_CREATE);
|
||||
28 H5Pset_chunk (properties, 2, chunk_size);
|
||||
29 H5Pset_compression (properties, H5D_COMPRESS_LZ77);
|
||||
30
|
||||
31 /*
|
||||
32 * Create a new dataset within the file. The data type
|
||||
33 * and data space describe the data on disk, which may
|
||||
34 * be different than the format used in the application's
|
||||
35 * memory.
|
||||
36 */
|
||||
37 dataset = H5Dcreate (file, "dataset", H5T_CRAY_FLOAT,
|
||||
38 data_space, properties);
|
||||
39
|
||||
40 /*
|
||||
41 * Write the array to the file. The data type and data
|
||||
42 * space describe the format of the data in the `dd'
|
||||
43 * buffer. The raw data is translated to the format
|
||||
44 * required on disk defined above. We use default raw
|
||||
45 * data transfer properties.
|
||||
46 */
|
||||
47 H5Dwrite (dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL,
|
||||
48 H5P_DEFAULT, dd);
|
||||
49
|
||||
50 /*
|
||||
51 * Read the array as floats. This is similar to writing
|
||||
52 * data except the data flows in the opposite direction.
|
||||
53 */
|
||||
54 H5Dread (dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL,
|
||||
55 H5P_DEFAULT, ff);
|
||||
56
|
||||
64 H5Dclose (dataset);
|
||||
65 H5Sclose (data_space);
|
||||
66 H5Pclose (properties);
|
||||
67 H5Fclose (file);
|
||||
</pre></code>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>This example uses the file created in Example 1 and reads a
|
||||
hyperslab of the 500x600 file dataset. The hyperslab size is
|
||||
100x200 and it is located beginning at element
|
||||
<200,200>. We read the hyperslab into an 200x400 array in
|
||||
memory beginning at element <0,0> in memory. Visually,
|
||||
the transfer looks something like this:
|
||||
|
||||
<center>
|
||||
<img alt="Raw Data Transfer" src="dataset_p1.gif">
|
||||
</center>
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=bottom><h4>Example 2</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p><code><pre>
|
||||
1 hid_t file, mem_space, file_space, dataset;
|
||||
2 double dd[200][400];
|
||||
3 hssize_t offset[2];
|
||||
4 hsize size[2];
|
||||
5
|
||||
6 /*
|
||||
7 * Open an existing file and its dataset.
|
||||
8 */
|
||||
9 file = H5Fopen ("test.h5", H5F_ACC_RDONLY, H5P_DEFAULT);
|
||||
10 dataset = H5Dopen (file, "dataset");
|
||||
11
|
||||
12 /*
|
||||
13 * Describe the file data space.
|
||||
14 */
|
||||
15 offset[0] = 200; /*offset of hyperslab in file*/
|
||||
16 offset[1] = 200;
|
||||
17 size[0] = 100; /*size of hyperslab*/
|
||||
18 size[1] = 200;
|
||||
19 file_space = H5Dget_space (dataset);
|
||||
20 H5Sset_hyperslab (file_space, 2, offset, size);
|
||||
21
|
||||
22 /*
|
||||
23 * Describe the memory data space.
|
||||
24 */
|
||||
25 size[0] = 200; /*size of memory array*/
|
||||
26 size[1] = 400;
|
||||
27 mem_space = H5Screate_simple (2, size);
|
||||
28
|
||||
29 offset[0] = 0; /*offset of hyperslab in memory*/
|
||||
30 offset[1] = 0;
|
||||
31 size[0] = 100; /*size of hyperslab*/
|
||||
32 size[1] = 200;
|
||||
33 H5Sset_hyperslab (mem_space, 2, offset, size);
|
||||
34
|
||||
35 /*
|
||||
36 * Read the dataset.
|
||||
37 */
|
||||
38 H5Dread (dataset, H5T_NATIVE_DOUBLE, mem_space,
|
||||
39 file_space, H5P_DEFAULT, dd);
|
||||
40
|
||||
41 /*
|
||||
42 * Close/release resources.
|
||||
43 */
|
||||
44 H5Dclose (dataset);
|
||||
45 H5Sclose (mem_space);
|
||||
46 H5Sclose (file_space);
|
||||
47 H5Fclose (file);
|
||||
</pre></code>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>If the file contains a compound data structure one of whose
|
||||
members is a floating point value (call it "delta") but the
|
||||
application is interested in reading an array of floating point
|
||||
values which are just the "delta" values, then the application
|
||||
should cast the floating point array as a struct with a single
|
||||
"delta" member.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=bottom><h4>Example 3</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p><code><pre>
|
||||
1 hid_t file, dataset, type;
|
||||
2 double delta[200];
|
||||
3
|
||||
4 /*
|
||||
5 * Open an existing file and its dataset.
|
||||
6 */
|
||||
7 file = H5Fopen ("test.h5", H5F_ACC_RDONLY, H5P_DEFAULT);
|
||||
8 dataset = H5Dopen (file, "dataset");
|
||||
9
|
||||
10 /*
|
||||
11 * Describe the memory data type, a struct with a single
|
||||
12 * "delta" member.
|
||||
13 */
|
||||
14 type = H5Tcreate (H5T_COMPOUND, sizeof(double));
|
||||
15 H5Tinsert (type, "delta", 0, H5T_NATIVE_DOUBLE);
|
||||
16
|
||||
17 /*
|
||||
18 * Read the dataset.
|
||||
19 */
|
||||
20 H5Dread (dataset, type, H5S_ALL, H5S_ALL,
|
||||
21 H5P_DEFAULT, dd);
|
||||
22
|
||||
23 /*
|
||||
24 * Close/release resources.
|
||||
25 */
|
||||
26 H5Dclose (dataset);
|
||||
27 H5Tclose (type);
|
||||
28 H5Fclose (file);
|
||||
</pre></code>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Tue Dec 2 09:17:09 EST 1997 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Wed May 13 18:57:47 EDT 1998
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
568
doc/html/Dataspaces.html
Normal file
@ -0,0 +1,568 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
||||
<TITLE>The Data Space Interface (H5S)</TITLE>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
|
||||
<H1>
|
||||
The Dataspace Interface (H5S)</H1>
|
||||
|
||||
<H2>
|
||||
1. Introduction</H2>
|
||||
The dataspace interface (H5S) provides a mechanism to describe the positions
|
||||
of the elements of a dataset and is designed in such a way as to allow
|
||||
new features to be easily added without disrupting applications that use
|
||||
the dataspace interface. A dataset (defined with the dataset interface) is
|
||||
composed of a collection of raw data points of homogeneous type, defined in the
|
||||
datatype (H5T) interface, organized according to the dataspace with this
|
||||
interface.
|
||||
|
||||
<P>A dataspace describes the locations that dataset elements are located at.
|
||||
A dataspace is either a regular N-dimensional array of data points,
|
||||
called a <I>simple</I> dataspace, or a more general collection of data
|
||||
points organized in another manner, called a <I>complex</I> dataspace.
|
||||
A <I>scalar</I> dataspace is a special case of the <I>simple</I> data
|
||||
space and is defined to be a 0-dimensional single data point in size. Currently
|
||||
only <I>scalar</I> and <I>simple</I> dataspaces are supported with this version
|
||||
of the H5S interface.
|
||||
<I>Complex</I> dataspaces will be defined and implemented in a future
|
||||
version. <I>Complex</I> dataspaces are intended to be used for such structures
|
||||
which are awkward to express in <I>simple</I> dataspaces, such as irregularly
|
||||
gridded data or adaptive mesh refinement data. This interface provides
|
||||
functions to set and query properties of a dataspace.
|
||||
|
||||
<P>Operations on a dataspace include defining or extending the extent of
|
||||
the dataspace, selecting portions of the dataspace for I/O and storing the
|
||||
dataspaces in the file. The extent of a dataspace is the range of coordinates
|
||||
over which dataset elements are defined and stored. Dataspace selections are
|
||||
subsets of the extent (up to the entire extent) which are selected for some
|
||||
operation.
|
||||
|
||||
<P>For example, a 2-dimensional dataspace with an extent of 10 by 10 may have
|
||||
the following very simple selection:
|
||||
<br><br><center>
|
||||
<table border cellpadding=4>
|
||||
<tr align=center>
|
||||
<th > </th> <th >0</th> <th >1</th> <th >2</th> <th >3</th> <th >4</th> <th >5</th> <th >6</th> <th >7</th> <th >8</th> <th >9</th>
|
||||
<tr align=center>
|
||||
<th>0</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>1</th>
|
||||
<td>-</td><td>X</td><td>X</td><td>X</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>2</th>
|
||||
<td>-</td><td>X</td><td>X</td><td>X</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>3</th>
|
||||
<td>-</td><td>X</td><td>X</td><td>X</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>4</th>
|
||||
<td>-</td><td>X</td><td>X</td><td>X</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>5</th>
|
||||
<td>-</td><td>X</td><td>X</td><td>X</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>6</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>7</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>8</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>9</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
</table>
|
||||
<br><strong>Example 1: Contiguous rectangular selection</strong>
|
||||
</center>
|
||||
|
||||
|
||||
<br>Or, a more complex selection may be defined:
|
||||
<br><br><center>
|
||||
<table border cellpadding=4>
|
||||
<tr align=center>
|
||||
<th > </th> <th >0</th> <th >1</th> <th >2</th> <th >3</th> <th >4</th> <th >5</th> <th >6</th> <th >7</th> <th >8</th> <th >9</th>
|
||||
<tr align=center>
|
||||
<th>0</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>1</th>
|
||||
<td>-</td><td>X</td><td>X</td><td>X</td><td>-</td><td>-</td><td>X</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>2</th>
|
||||
<td>-</td><td>X</td><td>-</td><td>X</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>3</th>
|
||||
<td>-</td><td>X</td><td>-</td><td>X</td><td>-</td><td>-</td><td>X</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>4</th>
|
||||
<td>-</td><td>X</td><td>-</td><td>X</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>5</th>
|
||||
<td>-</td><td>X</td><td>X</td><td>X</td><td>-</td><td>-</td><td>X</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>6</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>7</th>
|
||||
<td>-</td><td>-</td><td>X</td><td>X</td><td>X</td><td>X</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>8</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>9</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
</table>
|
||||
<br><strong>Example 2: Non-contiguous selection</strong>
|
||||
</center>
|
||||
|
||||
<P>Selections within dataspaces have an offset within the extent which is used
|
||||
to locate the selection within the extent of the dataspace. Selection offsets
|
||||
default to 0 in each dimension, but may be changed to move the selection within
|
||||
a dataspace. In example 2 above, if the offset was changed to 1,1, the selection
|
||||
would look like this:
|
||||
<br><br><center>
|
||||
<table border cellpadding=4>
|
||||
<tr align=center>
|
||||
<th > </th> <th >0</th> <th >1</th> <th >2</th> <th >3</th> <th >4</th> <th >5</th> <th >6</th> <th >7</th> <th >8</th> <th >9</th>
|
||||
<tr align=center>
|
||||
<th>0</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>1</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>2</th>
|
||||
<td>-</td><td>-</td><td>X</td><td>X</td><td>X</td><td>-</td><td>-</td><td>X</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>3</th>
|
||||
<td>-</td><td>-</td><td>X</td><td>-</td><td>X</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>4</th>
|
||||
<td>-</td><td>-</td><td>X</td><td>-</td><td>X</td><td>-</td><td>-</td><td>X</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>5</th>
|
||||
<td>-</td><td>-</td><td>X</td><td>-</td><td>X</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>6</th>
|
||||
<td>-</td><td>-</td><td>X</td><td>X</td><td>X</td><td>-</td><td>-</td><td>X</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>7</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>8</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>X</td><td>X</td><td>X</td><td>X</td><td>-</td><td>-</td><td>-</td>
|
||||
<tr align=center>
|
||||
<th>9</th>
|
||||
<td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td>
|
||||
</table>
|
||||
<br><strong>Example 3: Non-contiguous selection with 1,1 offset</strong>
|
||||
</center>
|
||||
|
||||
<P>Selections also have an linearization ordering of the points selected
|
||||
(defaulting to "C" order, ie. last dimension changing fastest). The
|
||||
linearization order may be specified for each point or it may be chosen by
|
||||
the axis of the dataspace. For example, with the default "C" ordering,
|
||||
example 1's selected points are iterated through in this order: (1,1), (2,1),
|
||||
(3,1), (1,2), (2,2), etc. With "FORTRAN" ordering, example 1's selected points
|
||||
would be iterated through in this order: (1,1), (1,2), (1,3), (1,4), (1,5),
|
||||
(2,1), (2,2), etc.
|
||||
|
||||
<P>A dataspace may be stored in the file as a permanent object, to allow many
|
||||
datasets to use a commonly defined dataspace. Dataspaces with extendable
|
||||
extents (ie. unlimited dimensions) are not able to be stored as permanent
|
||||
dataspaces.
|
||||
|
||||
<P>Dataspaces may be created using an existing permanent dataspace as a
|
||||
container to locate the new dataspace within. These dataspaces are complete
|
||||
dataspaces and may be used to define datasets. A dataspaces with a "parent"
|
||||
can be queried to determine the parent dataspace and the location within the
|
||||
parent. These dataspaces must currently be the same number of dimensions as
|
||||
the parent dataspace.
|
||||
|
||||
<H2> 2. General Dataspace Operations</H2>
|
||||
The functions defined in this section operate on dataspaces as a whole.
|
||||
New dataspaces can be created from scratch or copied from existing data
|
||||
spaces. When a dataspace is no longer needed its resources should be released
|
||||
by calling <TT>H5Sclose()</TT>.
|
||||
<DL>
|
||||
|
||||
<DT>
|
||||
<TT>hid_t H5Screate(H5S_class_t <I>type</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function creates a new dataspace of a particular <I>type</I>. The
|
||||
types currently supported are H5S_SCALAR, H5S_SIMPLE, or H5S_NONE, although
|
||||
others are planned to be added later. The H5S_NONE dataspace can only hold a
|
||||
selection, not an extent.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>hid_t H5Sopen(hid_t <I>location</I>, const char *<I>name</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function opens a permanent dataspace for use in an application.
|
||||
The <I>location</I> argument is a file or group ID and <I>name</I> is
|
||||
an absolute or relative path to the permanent dataspace. The dataspace ID which
|
||||
is returned is a handle to a permanent dataspace which can't be modified.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>hid_t H5Scopy (hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function creates a new dataspace which is an exact copy of the
|
||||
dataspace <I>space</I>.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>hid_t H5Ssubspace (hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function uses the currently defined selection and offset in <I>space</I>
|
||||
to create a dataspace which is located within <I>space</I>. The <I>space</I>
|
||||
dataspace must be a sharable dataspace located in the file, not a dataspace for
|
||||
a dataset. The relationship of the new dataspace within the existing dataspace
|
||||
is preserved when the new dataspace is used to create datasets. Currently,
|
||||
only subspaces which are equivalent to simple dataspaces (ie. rectangular
|
||||
contiguous areas) are allowed. A subspace is not "simplified" or reduced in
|
||||
the number of dimensions used if the selection is "flat" in one dimension, they
|
||||
always have the same number of dimensions as their parent dataspace.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Scommit (hid_t <I>location</I>, const char *<I>name</I>, hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
The dataspaces specified with <I>space</I> is stored in the file specified
|
||||
by <I>location</I>. <I>Location</I> may be either a file or group handle
|
||||
and <I>name</I> is an absolute or relative path to the location to store the
|
||||
dataspace. After this call, the dataspace is permanent and can't be modified.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Sclose (hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
Releases resources associated with a dataspace. Subsequent use of the
|
||||
dataspace identifier after this call is undefined.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>H5S_class_t H5Sget_class (hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
Query a dataspace to determine the current class of a dataspace. The value
|
||||
which is returned is one of: H5S_SCALAR, H5S_SIMPLE, or H5S_NONE on success or
|
||||
FAIL on failure.
|
||||
</DD>
|
||||
</DL>
|
||||
|
||||
|
||||
<H2> 3. Dataspace Extent Operations</H2>
|
||||
These functions operate on the extent portion of a dataspace.
|
||||
|
||||
<DL>
|
||||
<DT>
|
||||
<TT>herr_t H5Sset_extent_simple (hid_t <I>space</I>, int <I>rank</I>, const hsize_t
|
||||
*<I>current_size</I>, const hsize_t *<I>maximum_size</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
Sets or resets the size of an existing dataspace, where <I>rank</I> is
|
||||
the dimensionality, or number of dimensions, of the dataspace.
|
||||
<I>current_size</I> is an array of size <I>rank</I> which contains the new size
|
||||
of each dimension in the dataspace. <I>maximum_size</I> is an array of size
|
||||
<I>rank</I> which contains the maximum size of each dimension in the dataspace.
|
||||
Any previous extent is removed from the dataspace, the dataspace type is set to
|
||||
H5S_SIMPLE and the extent is set as specified.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Sset_extent_none (hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
Removes the extent from a dataspace and sets the type to H5S_NONE.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Sextent_copy (hid_t <I>dest_space</I>,
|
||||
hid_t <I>source_space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
Copies the extent from <I>source_space</I> to <I>dest_space</I>, which may
|
||||
change the type of the dataspace. Returns non-negative on success, negative on
|
||||
failure.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>hsize_t H5Sextent_npoints (hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function determines the number of elements in a dataspace. For example, a
|
||||
simple 3-dimensional dataspace with dimensions 2, 3 and 4 would have 24
|
||||
elements.
|
||||
Returns the number of elements in the dataspace, negative on failure.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>int H5Sextent_ndims (hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function determines the dimensionality (or rank) of a dataspace.
|
||||
Returns the number of dimensions in the dataspace, negative on failure.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Sextent_dims (hid_t <I>space</I>, hsize_t *<I>dims</I>,
|
||||
hsize_t *<I>max</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
The function retrieves the size of the extent of the dataspace <I>space</I> by
|
||||
placing the size of each dimension in the array <I>dims</I>. Also retrieves
|
||||
the size of the maximum extent of the dataspace, placing the results in
|
||||
<I>max</I>.
|
||||
Returns non-negative on success, negative on failure.
|
||||
</DD>
|
||||
|
||||
</DL>
|
||||
|
||||
<H2> 4. Dataspace Selection Operations</H2>
|
||||
Selections are maintained separately from extents in dataspaces and operations
|
||||
on the selection of a dataspace do not affect the extent of the dataspace.
|
||||
Selections are independent of extent type and the boundaries of selections are
|
||||
reconciled with the extent at the time of the data transfer. Selection offsets
|
||||
apply a selection to a location within an extent, allowing the same selection
|
||||
to be moved within the extent without requiring a new selection to be specified.
|
||||
Offsets default to 0 when the dataspace is created. Offsets are applied when
|
||||
an I/O transfer is performed (and checked during calls to H5Sselect_valid).
|
||||
Selections have an iteration order for the points selected, which can be any
|
||||
permutation of the dimensions involved (defaulting to 'C' array order) or a
|
||||
specific order for the selected points, for selections composed of single array
|
||||
elements with H5Sselect_elements. Selections can also be copied or combined
|
||||
together in various ways with H5Sselect_op. Further methods of selecting
|
||||
portions of a dataspace may be added in the future.
|
||||
|
||||
<DL>
|
||||
<DT>
|
||||
<TT>herr_t H5Sselect_hyperslab (hid_t <I>space</I>, h5s_selopt_t <I>op</I>,
|
||||
const hssize_t * <I>start</I>, const hsize_t * <I>stride</I>,
|
||||
const hsize_t * <I>count</I>, const hsize_t * <I>block</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function selects a hyperslab region to add to the current selected region
|
||||
for the <I>space</I> dataspace. The <I>start</I>, <I>stride</I>, <I>count</I>
|
||||
and <I>block</I> arrays must be the same size as the rank of the dataspace.
|
||||
The selection operator <I>op</I> determines how the new selection is to be
|
||||
combined with the already existing selection for the dataspace. Currently,
|
||||
only the H5S_SELECT_SET operator is supported, which replaces the existing
|
||||
selection with the parameters from this call. Overlapping blocks are not
|
||||
supported with the H5S_SELECT_SET operator.
|
||||
<P>The <I>start</I> array determines the starting coordinates of the hyperslab
|
||||
to select. The <I>stride</I> array chooses array locations from the dataspace
|
||||
with each value in the <I>stride</I> array determining how many elements to move
|
||||
in each dimension. Setting a value in the <I>stride</I> array to 1 moves to
|
||||
each element in that dimension of the dataspace, setting a value of 2 in a
|
||||
location in the <I>stride</I> array moves to every other element in that
|
||||
dimension of the dataspace. In other words, the <I>stride</I> determines the
|
||||
number of elements to move from the <I>start</I> location in each dimension.
|
||||
Stride values of 0 are not allowed. If the <I>stride</I> parameter is <TT>NULL</TT>,
|
||||
a contiguous hyperslab is selected (as if each value in the <I>stride</I> array
|
||||
was set to all 1's). The <I>count</I> array determines how many blocks to
|
||||
select from the dataspace, in each dimension. The <I>block</I> array determines
|
||||
the size of the element block selected from the dataspace. If the <I>block</I>
|
||||
parameter is set to <TT>NULL</TT>, the block size defaults to a single element
|
||||
in each dimension (as if the <I>block</I> array was set to all 1's).
|
||||
<P>For example, in a 2-dimensional dataspace, setting <I>start</I> to [1,1],
|
||||
<I>stride</I> to [4,4], <I>count</I> to [3,7] and <I>block</I> to [2,2] selects
|
||||
21 2x2 blocks of array elements starting with location (1,1) and selecting
|
||||
blocks at locations (1,1), (5,1), (9,1), (1,5), (5,5), etc.
|
||||
<P>Regions selected with this function call default to 'C' order iteration when
|
||||
I/O is performed.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Sselect_elements (hid_t <I>space</I>, h5s_selopt_t <I>op</I>,
|
||||
const size_t <I>num_elements</I>, const hssize_t *<I>coord</I>[])</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function selects array elements to be included in the selection for the
|
||||
<I>space</I> dataspace. The number of elements selected must be set with the
|
||||
<I>num_elements</I>. The <I>coord</I> array is a two-dimensional array of size
|
||||
<dataspace rank> by <<I>num_elements</I>> in size (ie. a list of
|
||||
coordinates in the array). The order of the element coordinates in the
|
||||
<I>coord</I> array also specifies the order that the array elements are
|
||||
iterated through when I/O is performed. Duplicate coordinate locations are not
|
||||
checked for.
|
||||
|
||||
<P>The selection operator <I>op</I> determines how the new selection is to be
|
||||
combined with the already existing selection for the dataspace. Currently,
|
||||
only the H5S_SELECT_SET operator is supported, which replaces the existing
|
||||
selection with the parameters from this call. When operators other than
|
||||
H5S_SELECT_SET are used to combine a new selection with an existing selection,
|
||||
the selection ordering is reset to 'C' array ordering.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Sselect_all (hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function selects the special H5S_SELECT_ALL region for the <I>space</I>
|
||||
dataspace. H5S_SELECT_ALL selects the entire dataspace for any dataspace is is
|
||||
applied to.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Sselect_none (hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function resets the selection region for the <I>space</I>
|
||||
dataspace not to include any elements.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Sselect_op (hid_t <I>space1</I>, h5s_selopt_t <I>op</I>,
|
||||
hid_t <I>space2</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
Uses <I>space2</I> to perform an operation on <I>space1</I>. The valid
|
||||
operations for <I>op</I> are:
|
||||
<DL>
|
||||
<DT>H5S_SELECT_COPY
|
||||
<DD>Copies the selection from <I>space2</I> into <I>space1</I>, removing any
|
||||
previously defined selection for <I>space1</I>. The selection order
|
||||
and offset are also copied to <I>space1</I>
|
||||
<DT>H5S_SELECT_UNION
|
||||
<DD>Performs a set union of the selection of the dataspace <I>space2</I>
|
||||
with the selection from the dataspace <I>space1</I>, with the result
|
||||
being stored in <I>space1</I>. The selection order for <I>space1</I> is
|
||||
reset to 'C' order.
|
||||
<DT>H5S_SELECT_INTERSECT
|
||||
<DD>Performs an set intersection of the selection from <I>space2</I> with
|
||||
<I>space1</I>, with the result being stored in <I>space1</I>. The
|
||||
selection order for <I>space1</I> is reset to 'C' order.
|
||||
<DT>H5S_SELECT_DIFFERENCE
|
||||
<DD>Performs a set difference of the selection from <I>space2</I> with
|
||||
<I>space1</I>, with the result being stored in <I>space1</I>. The
|
||||
selection order for <I>space1</I> is reset to 'C' order.
|
||||
</DL>
|
||||
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Sselect_order (hid_t <I>space</I>,
|
||||
hsize_t <I>perm_vector</I>[])</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function selects the order to iterate through the dimensions of a dataspace
|
||||
when performing I/O on a selection. If a specific order has already been
|
||||
selected for the selection with H5Sselect_elements, this function will remove
|
||||
it and use a dimension oriented ordering on the selected elements. The elements
|
||||
of the <I>perm_vector</I> array must be unique and between 0 and the rank of the
|
||||
dataspace, minus 1. The order of the elements in <I>perm_vector</I> specify
|
||||
the order to iterate through the selection for each dimension of the dataspace.
|
||||
To iterate through a 3-dimensional dataspace selection in 'C' order, specify
|
||||
the elements of the <I>perm_vector</I> as [0, 1, 2], for FORTRAN order they
|
||||
would be [2, 1, 0]. Other orderings, such as [1, 2, 0] are also possible, but
|
||||
may execute slower.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>hbool_t H5Sselect_valid (hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function verifies that the selection for a dataspace is within the extent
|
||||
of the dataspace, if the currently set offset for the dataspace is used.
|
||||
Returns TRUE if the selection is contained within the extent, FALSE if it
|
||||
is not contained within the extent and FAIL on error conditions (such as if
|
||||
the selection or extent is not defined).
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>hsize_t H5Sselect_npoints (hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function determines the number of elements in the current selection
|
||||
of a dataspace.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Soffset_simple (hid_t <I>space</I>, const hssize_t *
|
||||
<I>offset</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
Sets the offset of a simple dataspace <I>space</I>. The <I>offset</I> array
|
||||
must be the same number of elements as the number of dimensions for the
|
||||
dataspace. If the <I>offset</I> array is set to <TT>NULL</TT>, the offset
|
||||
for the dataspace is reset to 0.
|
||||
</DD>
|
||||
|
||||
</DL>
|
||||
|
||||
<H2> 5. Misc. Dataspace Operations</H2>
|
||||
|
||||
<DL>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Slock (hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
Locks the dataspace so that it cannot be modified or closed. When the library
|
||||
exits, the dataspace will be unlocked and closed.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>hid_t H5Screate_simple(int <I>rank</I>, const hsize_t *<I>current_size</I>,
|
||||
const hsize_t *<I>maximum_size</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function is a "convenience" wrapper to create a simple dataspace
|
||||
and set it's extent in one call. It is equivalent to calling H5Screate
|
||||
and H5Sset_extent_simple() in two steps.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>int H5Sis_subspace(hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function returns positive if <I>space</I> is located within another
|
||||
dataspace, zero if it is not, and negative on a failure.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>char *H5Ssubspace_name(hid_t <I>space</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
This function returns the name of the named dataspace that <I>space</I>
|
||||
is located within. If <I>space</I> is not located within another dataspace,
|
||||
or an error occurs, NULL is returned. The application is responsible for
|
||||
freeing the string returned.
|
||||
</DD>
|
||||
|
||||
<DT>
|
||||
<TT>herr_t H5Ssubspace_location(hid_t <I>space</I>, hsize_t *<I>loc</I>)</TT></DT>
|
||||
|
||||
<DD>
|
||||
If <I>space</I> is located within another dataspace, this function puts
|
||||
the location of the origin of <I>space</I> in the <I>loc</I> array. The <I>loc</I>
|
||||
array must be at least as large as the number of dimensions of <I>space</I>.
|
||||
If <I>space</I> is not located within another dataspace
|
||||
or an error occurs, a negative value is returned, otherwise a non-negative value
|
||||
is returned.
|
||||
</DD>
|
||||
|
||||
</DL>
|
||||
|
||||
<HR>
|
||||
<ADDRESS>
|
||||
<A HREF="mailto:matzke@llnl.gov">Robb Matzke</A></ADDRESS>
|
||||
|
||||
<ADDRESS>
|
||||
<A HREF="mailto:koziol@ncsa.uiuc.edu">Quincey Koziol</A></ADDRESS>
|
||||
|
||||
<BR><!-- Created: Thu Dec 4 14:57:32 EST 1997 --><!-- hhmts start -->Last
|
||||
modified: Thu May 28 15:12:04 EST 1998 <!-- hhmts end -->
|
||||
</BODY>
|
||||
</HTML>
|
1370
doc/html/Datatypes.html
Normal file
281
doc/html/Errors.html
Normal file
@ -0,0 +1,281 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>The Error Handling Interface (H5E)</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>The Error Handling Interface (H5E)</h1>
|
||||
|
||||
<h2>1. Introduction</h2>
|
||||
|
||||
<p>When an error occurs deep within the HDF5 library a record is
|
||||
pushed onto an error stack and that function returns a failure
|
||||
indication. Its caller detects the failure, pushes another
|
||||
record onto the stack, and returns a failure indication. This
|
||||
continues until the application-called API function returns a
|
||||
failure indication (a negative integer or null pointer). The
|
||||
next API function which is called (with a few exceptions) resets
|
||||
the stack.
|
||||
|
||||
<p>In normal circumstances, an error causes the stack to be
|
||||
printed on the standard error stream. The first item, number
|
||||
"#000" is produced by the API function itself and is usually
|
||||
sufficient to indicate to the application programmer what went
|
||||
wrong.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=top><h4>Example: An Error Message</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p>If an application calls <code>H5Tclose</code> on a
|
||||
predefined data type then the following message is
|
||||
printed on the standard error stream. This is a
|
||||
simple error that has only one component, the API
|
||||
function; other errors may have many components.
|
||||
|
||||
<p><code><pre>
|
||||
HDF5-DIAG: Error detected in thread 0. Back trace follows.
|
||||
#000: H5T.c line 462 in H5Tclose(): predefined data type
|
||||
major(01): Function argument
|
||||
minor(05): Bad value
|
||||
</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>The error stack can also be printed and manipulated by these
|
||||
functions, but if an application wishes make explicit calls to
|
||||
<code>H5Eprint()</code> then the automatic printing should be
|
||||
turned off to prevent error messages from being displayed twice
|
||||
(see <code>H5Eset_auto()</code> below).
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Eprint (FILE *<em>stream</em>)</code>
|
||||
<dd>The error stack is printed on the specified stream. Even if
|
||||
the error stack is empty a one-line message will be printed:
|
||||
<code>HDF5-DIAG: Error detected in thread 0.</code>
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Eclear (void)</code>
|
||||
<dd>The error stack can be explicitly cleared by calling this
|
||||
function. The stack is also cleared whenever an API function
|
||||
is called, with certain exceptions (for instance,
|
||||
<code>H5Eprint()</code>).
|
||||
</dl>
|
||||
|
||||
<p>Sometimes an application will call a function for the sake of
|
||||
its return value, fully expecting the function to fail. Under
|
||||
these conditions, it would be misleading if an error message
|
||||
were automatically printed. Automatic printing of messages is
|
||||
controlled by the <code>H5Eset_auto()</code> function:
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Eset_auto (herr_t(*<em>func</em>)(void*),
|
||||
void *<em>client_data</em>)</code>
|
||||
<dd>If <em>func</em> is not a null pointer, then the function to
|
||||
which it points will be called automatically when an API
|
||||
function is about to return an indication of failure. The
|
||||
function is called with a single argument, the
|
||||
<em>client_data</em> pointer. When the library is first
|
||||
initialized the auto printing function is set to
|
||||
<code>H5Eprint()</code> (cast appropriately) and
|
||||
<em>client_data</em> is the standard error stream pointer,
|
||||
<code>stderr</code>.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Eget_auto (herr_t(**<em>func</em>)(void*),
|
||||
void **<em>client_data</em>)</code>
|
||||
<dd>This function returns the current automatic error traversal
|
||||
settings through the <em>func</em> and <em>client_data</em>
|
||||
arguments. Either (or both) arguments may be null pointers in
|
||||
which case the corresponding information is not returned.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=top><h4>Example: Error Control</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p>An application can temporarily turn off error
|
||||
messages while "probing" a function.
|
||||
|
||||
<p><code><pre>
|
||||
/* Save old error handler */
|
||||
herr_t (*old_func)(void*);
|
||||
void *old_client_data;
|
||||
H5Eget_auto(&old_func, &old_client_data);
|
||||
|
||||
/* Turn off error handling */
|
||||
H5Eset_auto(NULL, NULL);
|
||||
|
||||
/* Probe. Likely to fail, but that's okay */
|
||||
status = H5Fopen (......);
|
||||
|
||||
/* Restore previous error handler */
|
||||
H5Eset_auto(old_func, old_client_data);
|
||||
</code></pre>
|
||||
|
||||
<p>Or automatic printing can be disabled altogether and
|
||||
error messages can be explicitly printed.
|
||||
|
||||
<p><code><pre>
|
||||
/* Turn off error handling permanently */
|
||||
H5Eset_auto (NULL, NULL);
|
||||
|
||||
/* If failure, print error message */
|
||||
if (H5Fopen (....)<0) {
|
||||
H5Eprint (stderr);
|
||||
exit (1);
|
||||
}
|
||||
</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>The application is allowed to define an automatic error
|
||||
traversal function other than the default
|
||||
<code>H5Eprint()</code>. For instance, one could define a
|
||||
function that prints a simple, one-line error message to the
|
||||
standard error stream and then exits.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=top><h4>Example: Simple Messages</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p>The application defines a function to print a simple
|
||||
error message to the standard error stream.
|
||||
|
||||
<p><code><pre>
|
||||
herr_t
|
||||
my_hdf5_error_handler (void *unused)
|
||||
{
|
||||
fprintf (stderr, "An HDF5 error was detected. Bye.\n");
|
||||
exit (1);
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<p>The function is installed as the error handler by
|
||||
saying
|
||||
|
||||
<p><code><pre>
|
||||
H5Eset_auto (my_hdf5_error_handler, NULL);
|
||||
</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>The <code>H5Eprint()</code> function is actually just a wrapper
|
||||
around the more complex <code>H5Ewalk()</code> function which
|
||||
traverses an error stack and calls a user-defined function for
|
||||
each member of the stack.
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Ewalk (H5E_direction_t <em>direction</em>,
|
||||
H5E_walk_t <em>func</em>, void *<em>client_data</em>)</code>
|
||||
<dd>The error stack is traversed and <em>func</em> is called for
|
||||
each member of the stack. Its arguments are an integer
|
||||
sequence number beginning at zero (regardless of
|
||||
<em>direction</em>), a pointer to an error description record,
|
||||
and the <em>client_data</em> pointer. If <em>direction</em>
|
||||
is <code>H5E_WALK_UPWARD</em> then traversal begins at the
|
||||
inner-most function that detected the error and concludes with
|
||||
the API function. The opposite order is
|
||||
<code>H5E_WALK_DOWNWARD</code>.
|
||||
|
||||
<br><br>
|
||||
<dt><code>typedef herr_t (*H5E_walk_t)(int <em>n</em>,
|
||||
H5E_error_t *<em>eptr</em>, void
|
||||
*<em>client_data</em>)</code>
|
||||
<dd>An error stack traversal callback function takes three
|
||||
arguments: <em>n</em> is a sequence number beginning at zero
|
||||
for each traversal, <em>eptr</em> is a pointer to an error
|
||||
stack member, and <em>client_data</em> is the same pointer
|
||||
passed to <code>H5Ewalk()</code>.
|
||||
|
||||
<br><br>
|
||||
<dt><pre><code>typedef struct {
|
||||
H5E_major_t <em>maj_num</em>;
|
||||
H5E_minor_t <em>min_num</em>;
|
||||
const char *<em>func_name</em>;
|
||||
const char *<em>file_name</em>;
|
||||
unsigned <em>line</em>;
|
||||
const char *<em>desc</em>;
|
||||
} H5E_error_t;</code></pre>
|
||||
<dd>The <em>maj_num</em> and <em>min_num</em> are major
|
||||
and minor error numbers, <em>func_name</em> is the name of
|
||||
the function where the error was detected,
|
||||
<em>file_name</em> and <em>line</em> locate the error
|
||||
within the HDF5 library source code, and <em>desc</em>
|
||||
points to a description of the error.
|
||||
|
||||
<br><br>
|
||||
<dt><code>const char *H5Eget_major (H5E_major_t <em>num</em>)</code>
|
||||
<dt><code>const char *H5Eget_minor (H5E_minor_t <em>num</em>)</code>
|
||||
<dd>These functions take a major or minor error number and
|
||||
return a constant string which describes the error. If
|
||||
<em>num</em> is out of range than a string like "Invalid major
|
||||
error number" is returned.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=top><h4>Example: H5Ewalk_cb</h4></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<p>This is the implementation of the default error stack
|
||||
traversal callback.
|
||||
|
||||
<p><code><pre>
|
||||
herr_t
|
||||
H5Ewalk_cb(int n, H5E_error_t *err_desc, void *client_data)
|
||||
{
|
||||
FILE *stream = (FILE *)client_data;
|
||||
const char *maj_str = NULL;
|
||||
const char *min_str = NULL;
|
||||
const int indent = 2;
|
||||
|
||||
/* Check arguments */
|
||||
assert (err_desc);
|
||||
if (!client_data) client_data = stderr;
|
||||
|
||||
/* Get descriptions for the major and minor error numbers */
|
||||
maj_str = H5Eget_major (err_desc->maj_num);
|
||||
min_str = H5Eget_minor (err_desc->min_num);
|
||||
|
||||
/* Print error message */
|
||||
fprintf (stream, "%*s#%03d: %s line %u in %s(): %s\n",
|
||||
indent, "", n, err_desc->file_name, err_desc->line,
|
||||
err_desc->func_name, err_desc->desc);
|
||||
fprintf (stream, "%*smajor(%02d): %s\n",
|
||||
indent*2, "", err_desc->maj_num, maj_str);
|
||||
fprintf (stream, "%*sminor(%02d): %s\n",
|
||||
indent*2, "", err_desc->min_num, min_str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:hdf5dev@ncsa.uiuc.edu">Robb Matzke</a></address>
|
||||
<!-- Created: Fri Feb 27 23:42:52 EST 1998 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Wed Mar 4 10:06:17 EST 1998
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
278
doc/html/ExternalFiles.html
Normal file
@ -0,0 +1,278 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>External Files in HDF5</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<center><h1>External Files in HDF5</h1></center>
|
||||
|
||||
<h3>Overview of Layers</h3>
|
||||
|
||||
<p>This table shows some of the layers of HDF5. Each layer calls
|
||||
functions at the same or lower layers and never functions at
|
||||
higher layers. An object identifier (OID) takes various forms
|
||||
at the various layers: at layer 0 an OID is an absolute physical
|
||||
file address; at layers 1 and 2 it's an absolute virtual file
|
||||
address. At layers 3 through 6 it's a relative address, and at
|
||||
layers 7 and above it's an object handle.
|
||||
|
||||
<p><center>
|
||||
<table border cellpadding=4 width="60%">
|
||||
<tr align=center>
|
||||
<td>Layer-7</td>
|
||||
<td>Groups</td>
|
||||
<td>Datasets</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>Layer-6</td>
|
||||
<td>Indirect Storage</td>
|
||||
<td>Symbol Tables</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>Layer-5</td>
|
||||
<td>B-trees</td>
|
||||
<td>Object Hdrs</td>
|
||||
<td>Heaps</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>Layer-4</td>
|
||||
<td>Caching</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>Layer-3</td>
|
||||
<td>H5F chunk I/O</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>Layer-2</td>
|
||||
<td>H5F low</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>Layer-1</td>
|
||||
<td>File Family</td>
|
||||
<td>Split Meta/Raw</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>Layer-0</td>
|
||||
<td>Section-2 I/O</td>
|
||||
<td>Standard I/O</td>
|
||||
<td>Malloc/Free</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<h3>Single Address Space</h3>
|
||||
|
||||
<p>The simplest form of hdf5 file is a single file containing only
|
||||
hdf5 data. The file begins with the boot block, which is
|
||||
followed until the end of the file by hdf5 data. The next most
|
||||
complicated file allows non-hdf5 data (user defined data or
|
||||
internal wrappers) to appear before the boot block and after the
|
||||
end of the hdf5 data. The hdf5 data is treated as a single
|
||||
linear address space in both cases.
|
||||
|
||||
<p>The next level of complexity comes when non-hdf5 data is
|
||||
interspersed with the hdf5 data. We handle that by including
|
||||
the non-hdf5 interspersed data in the hdf5 address space and
|
||||
simply not referencing it (eventually we might add those
|
||||
addresses to a "do-not-disturb" list using the same mechanism as
|
||||
the hdf5 free list, but it's not absolutely necessary). This is
|
||||
implemented except for the "do-not-disturb" list.
|
||||
|
||||
<p>The most complicated single address space hdf5 file is when we
|
||||
allow the address space to be split among multiple physical
|
||||
files. For instance, a >2GB file can be split into smaller
|
||||
chunks and transfered to a 32 bit machine, then accessed as a
|
||||
single logical hdf5 file. The library already supports >32 bit
|
||||
addresses, so at layer 1 we split a 64-bit address into a 32-bit
|
||||
file number and a 32-bit offset (the 64 and 32 are
|
||||
arbitrary). The rest of the library still operates with a linear
|
||||
address space.
|
||||
|
||||
<p>Another variation might be a family of two files where all the
|
||||
meta data is stored in one file and all the raw data is stored
|
||||
in another file to allow the HDF5 wrapper to be easily replaced
|
||||
with some other wrapper.
|
||||
|
||||
<p>The <code>H5Fcreate</code> and <code>H5Fopen</code> functions
|
||||
would need to be modified to pass file-type info down to layer 2
|
||||
so the correct drivers can be called and parameters passed to
|
||||
the drivers to initialize them.
|
||||
|
||||
<h4>Implementation</h4>
|
||||
|
||||
<p>I've implemented fixed-size family members. The entire hdf5
|
||||
file is partitioned into members where each member is the same
|
||||
size. The family scheme is used if one passes a name to
|
||||
<code>H5F_open</code> (which is called by <code>H5Fopen()</code>
|
||||
and <code>H5Fcreate</code>) that contains a
|
||||
<code>printf(3c)</code>-style integer format specifier.
|
||||
Currently, the default low-level file driver is used for all
|
||||
family members (H5F_LOW_DFLT, usually set to be Section 2 I/O or
|
||||
Section 3 stdio), but we'll probably eventually want to pass
|
||||
that as a parameter of the file access template, which hasn't
|
||||
been implemented yet. When creating a family, a default family
|
||||
member size is used (defined at the top H5Ffamily.c, currently
|
||||
64MB) but that also should be settable in the file access
|
||||
template. When opening an existing family, the size of the first
|
||||
member is used to determine the member size (flushing/closing a
|
||||
family ensures that the first member is the correct size) but
|
||||
the other family members don't have to be that large (the local
|
||||
address space, however, is logically the same size for all
|
||||
members).
|
||||
|
||||
<p>I haven't implemented a split meta/raw family yet but am rather
|
||||
curious to see how it would perform. I was planning to use the
|
||||
`.h5' extension for the meta data file and `.raw' for the raw
|
||||
data file. The high-order bit in the address would determine
|
||||
whether the address refers to meta data or raw data. If the user
|
||||
passes a name that ends with `.raw' to <code>H5F_open</code>
|
||||
then we'll chose the split family and use the default low level
|
||||
driver for each of the two family members. Eventually we'll
|
||||
want to pass these kinds of things through the file access
|
||||
template instead of relying on naming convention.
|
||||
|
||||
<h3>External Raw Data</h3>
|
||||
|
||||
<p>We also need the ability to point to raw data that isn't in the
|
||||
HDF5 linear address space. For instance, a dataset might be
|
||||
striped across several raw data files.
|
||||
|
||||
<p>Fortunately, the only two packages that need to be aware of
|
||||
this are the packages for reading/writing contiguous raw data
|
||||
and discontiguous raw data. Since contiguous raw data is a
|
||||
special case, I'll discuss how to implement external raw data in
|
||||
the discontiguous case.
|
||||
|
||||
<p>Discontiguous data is stored as a B-tree whose keys are the
|
||||
chunk indices and whose leaf nodes point to the raw data by
|
||||
storing a file address. So what we need is some way to name the
|
||||
external files, and a way to efficiently store the external file
|
||||
name for each chunk.
|
||||
|
||||
<p>I propose adding to the object header an <em>External File
|
||||
List</em> message that is a 1-origin array of file names.
|
||||
Then, in the B-tree, each key has an index into the External
|
||||
File List (or zero for the HDF5 file) for the file where the
|
||||
chunk can be found. The external file index is only used at
|
||||
the leaf nodes to get to the raw data (the entire B-tree is in
|
||||
the HDF5 file) but because of the way keys are copied among
|
||||
the B-tree nodes, it's much easier to store the index with
|
||||
every key.
|
||||
|
||||
<h3>Multiple HDF5 Files</h3>
|
||||
|
||||
<p>One might also want to combine two or more HDF5 files in a
|
||||
manner similar to mounting file systems in Unix. That is, the
|
||||
group structure and meta data from one file appear as though
|
||||
they exist in the first file. One opens File-A, and then
|
||||
<em>mounts</em> File-B at some point in File-A, the <em>mount
|
||||
point</em>, so that traversing into the mount point actually
|
||||
causes one to enter the root object of File-B. File-A and
|
||||
File-B are each complete HDF5 files and can be accessed
|
||||
individually without mounting them.
|
||||
|
||||
<p>We need a couple additional pieces of machinery to make this
|
||||
work. First, an haddr_t type (a file address) doesn't contain
|
||||
any info about which HDF5 file's address space the address
|
||||
belongs to. But since haddr_t is an opaque type except at
|
||||
layers 2 and below, it should be quite easy to add a pointer to
|
||||
the HDF5 file. This would also remove the H5F_t argument from
|
||||
most of the low-level functions since it would be part of the
|
||||
OID.
|
||||
|
||||
<p>The other thing we need is a table of mount points and some
|
||||
functions that understand them. We would add the following
|
||||
table to each H5F_t struct:
|
||||
|
||||
<p><code><pre>
|
||||
struct H5F_mount_t {
|
||||
H5F_t *parent; /* Parent HDF5 file if any */
|
||||
struct {
|
||||
H5F_t *f; /* File which is mounted */
|
||||
haddr_t where; /* Address of mount point */
|
||||
} *mount; /* Array sorted by mount point */
|
||||
intn nmounts; /* Number of mounted files */
|
||||
intn alloc; /* Size of mount table */
|
||||
}
|
||||
</pre></code>
|
||||
|
||||
<p>The <code>H5Fmount</code> function takes the ID of an open
|
||||
file, the name of a to-be-mounted file, the name of the mount
|
||||
point, and a file access template (like <code>H5Fopen</code>).
|
||||
It opens the new file and adds a record to the parent's mount
|
||||
table. The <code>H5Funmount</code> function takes the parent
|
||||
file ID and the name of the mount point and closes the file
|
||||
that's mounted at that point. The <code>H5Fclose</code>
|
||||
function closes/unmounts files recursively.
|
||||
|
||||
<p>The <code>H5G_iname</code> function which translates a name to
|
||||
a file address (<code>haddr_t</code>) looks at the mount table
|
||||
at each step in the translation and switches files where
|
||||
appropriate. All name-to-address translations occur through
|
||||
this function.
|
||||
|
||||
<h3>How Long?</h3>
|
||||
|
||||
<p>I'm expecting to be able to implement the two new flavors of
|
||||
single linear address space in about two days. It took two hours
|
||||
to implement the malloc/free file driver at level zero and I
|
||||
don't expect this to be much more work.
|
||||
|
||||
<p>I'm expecting three days to implement the external raw data for
|
||||
discontiguous arrays. Adding the file index to the B-tree is
|
||||
quite trivial; adding the external file list message shouldn't
|
||||
be too hard since the object header message class from wich this
|
||||
message derives is fully implemented; and changing
|
||||
<code>H5F_istore_read</code> should be trivial. Most of the
|
||||
time will be spent designing a way to cache Unix file
|
||||
descriptors efficiently since the total number open files
|
||||
allowed per process could be much smaller than the total number
|
||||
of HDF5 files and external raw data files.
|
||||
|
||||
<p>I'm expecting four days to implement being able to mount one
|
||||
HDF5 file on another. I was originally planning a lot more, but
|
||||
making <code>haddr_t</code> opaque turned out to be much easier
|
||||
than I planned (I did it last Fri). Most of the work will
|
||||
probably be removing the redundant H5F_t arguments for lots of
|
||||
functions.
|
||||
|
||||
<h3>Conclusion</h3>
|
||||
|
||||
<p>The external raw data could be implemented as a single linear
|
||||
address space, but doing so would require one to allocate large
|
||||
enough file addresses throughout the file (>32bits) before the
|
||||
file was created. It would make mixing an HDF5 file family with
|
||||
external raw data, or external HDF5 wrapper around an HDF4 file
|
||||
a more difficult process. So I consider the implementation of
|
||||
external raw data files as a single HDF5 linear address space a
|
||||
kludge.
|
||||
|
||||
<p>The ability to mount one HDF5 file on another might not be a
|
||||
very important feature especially since each HDF5 file must be a
|
||||
complete file by itself. It's not possible to stripe an array
|
||||
over multiple HDF5 files because the B-tree wouldn't be complete
|
||||
in any one file, so the only choice is to stripe the array
|
||||
across multiple raw data files and store the B-tree in the HDF5
|
||||
file. On the other hand, it might be useful if one file
|
||||
contains some public data which can be mounted by other files
|
||||
(e.g., a mesh topology shared among collaborators and mounted by
|
||||
files that contain other fields defined on the mesh). Of course
|
||||
the applications can open the two files separately, but it might
|
||||
be more portable if we support it in the library.
|
||||
|
||||
<p>So we're looking at about two weeks to implement all three
|
||||
versions. I didn't get a chance to do any of them in AIO
|
||||
although we had long-term plans for the first two with a
|
||||
possibility of the third. They'll be much easier to implement in
|
||||
HDF5 than AIO since I've been keeping these in mind from the
|
||||
start.
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Sat Nov 8 18:08:52 EST 1997 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Wed Nov 12 15:01:14 EST 1997
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
529
doc/html/Files.html
Normal file
@ -0,0 +1,529 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>HDF5 Files</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Files</h1>
|
||||
|
||||
<h2>1. Introduction</h2>
|
||||
|
||||
<p>HDF5 files are composed of a "boot block" describing information
|
||||
required to portably access files on multiple platforms, followed
|
||||
by information about the groups in a file and the datasets in the
|
||||
file. The boot block contains information about the size of offsets
|
||||
and lengths of objects, the number of entries in symbol tables
|
||||
(used to store groups) and additional version information for the
|
||||
file.
|
||||
|
||||
<h2>2. File access modes</h2>
|
||||
|
||||
<p>The HDF5 library assumes that all files are implicitly opened for read
|
||||
access at all times. Passing the <code>H5F_ACC_RDWR</code>
|
||||
parameter to <code>H5Fopen()</code> allows write access to a
|
||||
file also. <code>H5Fcreate()</code> assumes write access as
|
||||
well as read access, passing <code>H5F_ACC_TRUNC</code> forces
|
||||
the truncation of an existing file, otherwise H5Fcreate will
|
||||
fail to overwrite an existing file.
|
||||
|
||||
<h2>3. Creating, Opening, and Closing Files</h2>
|
||||
|
||||
<p>Files are created with the <code>H5Fcreate()</code> function,
|
||||
and existing files can be accessed with <code>H5Fopen()</code>. Both
|
||||
functions return an object ID which should be eventually released by
|
||||
calling <code>H5Fclose()</code>.
|
||||
|
||||
<dl>
|
||||
<dt><code>hid_t H5Fcreate (const char *<em>name</em>, uintn
|
||||
<em>flags</em>, hid_t <em>create_properties</em>, hid_t
|
||||
<em>access_properties</em>)</code>
|
||||
<dd>This function creates a new file with the specified name in
|
||||
the current directory. The file is opened with read and write
|
||||
permission, and if the <code>H5F_ACC_TRUNC</code> flag is set,
|
||||
any current file is truncated when the new file is created.
|
||||
If a file of the same name exists and the
|
||||
<code>H5F_ACC_TRUNC</code> flag is not set (or the
|
||||
<code>H5F_ACC_EXCL</code> bit is set), this function will
|
||||
fail. Passing <code>H5P_DEFAULT</code> for the creation
|
||||
and/or access property lists uses the library's default
|
||||
values for those properties. Creating and changing the
|
||||
values of a property list is documented further below. The
|
||||
return value is an ID for the open file and it should be
|
||||
closed by calling <code>H5Fclose()</code> when it's no longer
|
||||
needed. A negative value is returned for failure.
|
||||
|
||||
<br><br>
|
||||
<dt><code>hid_t H5Fopen (const char *<em>name</em>, uintn
|
||||
<em>flags</em>, hid_t <em>access_properties</em>)</code>
|
||||
<dd>This function opens an existing file with read permission
|
||||
and write permission if the <code>H5F_ACC_RDWR</code> flag is
|
||||
set. The <em>access_properties</em> is a file access property
|
||||
list ID or <code>H5P_DEFAULT</code> for the default I/O access
|
||||
parameters. Creating and changing the parameters for access
|
||||
templates is documented further below. Files which are opened
|
||||
more than once return a unique identifier for each
|
||||
<code>H5Fopen()</code> call and can be accessed through all
|
||||
file IDs. The return value is an ID for the open file and it
|
||||
should be closed by calling <code>H5Fclose()</code> when it's
|
||||
no longer needed. A negative value is returned for failure.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Fclose (hid_t <em>file_id</em>)</code>
|
||||
<dd>This function releases resources used by a file which was
|
||||
opened by <code>H5Fcreate()</code> or <code>H5Fopen()</code>. After
|
||||
closing a file the <em>file_id</em> should not be used again. This
|
||||
function returns zero for success or a negative value for failure.
|
||||
</dl>
|
||||
|
||||
<h2>4. File Property Lists</h2>
|
||||
|
||||
<p>Additional parameters to <code>H5Fcreate()</code> or
|
||||
<code>H5Fopen()</code> are passed through property list
|
||||
objects, which are created with the <code>H5Pcreate()</code>
|
||||
function. These objects allow many parameters of a file's
|
||||
creation or access to be changed from the default values.
|
||||
Property lists are used as a portable and extensible method of
|
||||
modifying multiple parameter values with simple API functions.
|
||||
There are two kinds of file-related property lists,
|
||||
namely file creation properties and file access properties.
|
||||
|
||||
<h3>4.1. File Creation Properties</h3>
|
||||
|
||||
<P>File creation property lists apply to <code>H5Fcreate()</code> only
|
||||
and are used to control the file meta-data which is maintained
|
||||
in the boot block of the file. The parameters which can be
|
||||
modified are:
|
||||
|
||||
<dl>
|
||||
<dt>User-Block Size <dd>The "user-block" is a fixed length block of
|
||||
data located at the beginning of the file which is ignored by the
|
||||
HDF5 library and may be used to store any data information found
|
||||
to be useful to applications. This value may be set to any power
|
||||
of two equal to 512 or greater (i.e. 512, 1024, 2048, etc). This
|
||||
parameter is set and queried with the
|
||||
<code>H5Pset_userblock()</code> and
|
||||
<code>H5Pget_userblock()</code> calls.
|
||||
|
||||
<br><br>
|
||||
<dt>Offset and Length Sizes
|
||||
<dd>The number of bytes used to store the offset and length of
|
||||
objects in the HDF5 file can be controlled with this
|
||||
parameter. Values of 2, 4 and 8 bytes are currently
|
||||
supported to allow 16-bit, 32-bit and 64-bit files to
|
||||
be addressed. These parameters are set and queried
|
||||
with the <code>H5Pset_sizes()</code> and
|
||||
<code>H5Pget_sizes()</code> calls.
|
||||
|
||||
<br><br>
|
||||
<dt>Symbol Table Parameters
|
||||
<dd>The size of symbol table B-trees can be controlled by setting
|
||||
the 1/2 rank and 1/2 node size parameters of the B-tree. These
|
||||
parameters are set and queried with the
|
||||
<code>H5Pset_sym_k()</code> and <code>H5Pget_sym_k()</code> calls.
|
||||
|
||||
<br><br>
|
||||
<dt>Indexed Storage Parameters
|
||||
<dd>The size of indexed storage B-trees can be controlled by
|
||||
setting the 1/2 rank and 1/2 node size parameters of the B-tree.
|
||||
These parameters are set and queried with the
|
||||
<code>H5Pset_istore_k()</code> and <code>H5Pget_istore_k()</code>
|
||||
calls.
|
||||
</dl>
|
||||
|
||||
<h3>4.2. File Access Property Lists</h3>
|
||||
|
||||
<p>File access property lists apply to <code>H5Fcreate()</code> or
|
||||
<code>H5Fopen()</code> and are used to control different methods of
|
||||
performing I/O on files.
|
||||
|
||||
<dl>
|
||||
<dt>Unbuffered I/O
|
||||
<dd>Local permanent files can be accessed with the functions described
|
||||
in Section 2 of the Posix manual, namely <code>open()</code>,
|
||||
<code>lseek()</code>, <code>read()</code>, <code>write()</code>, and
|
||||
<code>close()</code>. The <code>lseek64()</code> function is used
|
||||
on operating systems that support it. This driver is enabled and
|
||||
configured with <code>H5Pset_sec2()</code>, and queried with
|
||||
<code>H5Pget_sec2()</code>.
|
||||
|
||||
<br><br>
|
||||
<dt>Buffered I/O
|
||||
<dd>Local permanent files can be accessed with the functions declared
|
||||
in the <code>stdio.h</code> header file, namely
|
||||
<code>fopen()</code>, <code>fseek()</code>, <code>fread()</code>,
|
||||
<code>fwrite()</code>, and <code>fclose()</code>. The
|
||||
<code>fseek64()</code> function is used on operating systems that
|
||||
support it. This driver is enabled and configured with
|
||||
<code>H5Pset_stdio()</code>, and queried with
|
||||
<code>H5Pget_stdio()</code>.
|
||||
|
||||
<br><br>
|
||||
<dt>Memory I/O
|
||||
<dd>Local temporary files can be created and accessed directly from
|
||||
memory without ever creating permanent storage. The library uses
|
||||
<code>malloc()</code> and <code>free()</code> to create storage
|
||||
space for the file. The total size of the file must be small enough
|
||||
to fit in virtual memory. The name supplied to
|
||||
<code>H5Fcreate()</code> is irrelevant, and <code>H5Fopen()</code>
|
||||
will always fail.
|
||||
|
||||
<br><br>
|
||||
<dt>Parallel Files using MPI I/O
|
||||
<dd>This driver allows parallel access to a file through the MPI I/O
|
||||
library. The parameters which can be modified are the MPI
|
||||
communicator, the info object, and the access mode.
|
||||
The communicator and info object are saved and then
|
||||
passed to <code>MPI_File_open()</code> during file creation or open.
|
||||
The access_mode controls the kind of parallel access the application
|
||||
intends. (Note that it is likely that the next API revision will
|
||||
remove the access_mode parameter and have access control specified
|
||||
via the raw data transfer property list of <code>H5Dread()</code>
|
||||
and <code>H5Dwrite()</code>.) These parameters are set and queried
|
||||
with the <code>H5Pset_mpi()</code> and <code>H5Pget_mpi()</code>
|
||||
calls.
|
||||
|
||||
<br><br>
|
||||
<dt>Data Alignment
|
||||
<dd>Sometimes file access is faster if certain things are
|
||||
aligned on file blocks. This can be controlled by setting
|
||||
alignment properties of a file access property list with the
|
||||
<code>H5Pset_alignment()</code> function. Any allocation
|
||||
request at least as large as some threshold will be aligned on
|
||||
an address which is a multiple of some number.
|
||||
</dl> </ul>
|
||||
|
||||
<h2>5. Examples of using file templates</h2>
|
||||
|
||||
<h3>5.1. Example of using file creation templates</h3>
|
||||
|
||||
<p>This following example shows how to create a file with 64-bit object
|
||||
offsets and lengths:<br>
|
||||
<pre>
|
||||
hid_t create_template;
|
||||
hid_t file_id;
|
||||
|
||||
create_template = H5Pcreate(H5P_FILE_CREATE);
|
||||
H5Pset_sizes(create_template, 8, 8);
|
||||
|
||||
file_id = H5Fcreate("test.h5", H5F_ACC_TRUNC,
|
||||
create_template, H5P_DEFAULT);
|
||||
.
|
||||
.
|
||||
.
|
||||
H5Fclose(file_id);
|
||||
</pre>
|
||||
|
||||
<h3>5.2. Example of using file creation templates</h3>
|
||||
|
||||
<p>This following example shows how to open an existing file for
|
||||
independent datasets access by MPI parallel I/O:<br>
|
||||
<pre>
|
||||
hid_t access_template;
|
||||
hid_t file_id;
|
||||
|
||||
access_template = H5Pcreate(H5P_FILE_ACCESS);
|
||||
H5Pset_mpi(access_template, MPI_COMM_WORLD, MPI_INFO_NULL);
|
||||
|
||||
/* H5Fopen must be called collectively */
|
||||
file_id = H5Fopen("test.h5", H5F_ACC_RDWR, access_template);
|
||||
.
|
||||
.
|
||||
.
|
||||
/* H5Fclose must be called collectively */
|
||||
H5Fclose(file_id);
|
||||
</pre>
|
||||
|
||||
|
||||
<h2>6. Low-level File Drivers</h2>
|
||||
|
||||
<p>HDF5 is able to access its address space through various types of
|
||||
low-level <em>file drivers</em>. For instance, an address space might
|
||||
correspond to a single file on a Unix file system, multiple files on a
|
||||
Unix file system, multiple files on a parallel file system, or a block
|
||||
of memory within the application. Generally, an HDF5 address space is
|
||||
referred to as an "HDF5 file" regardless of how the space is organized
|
||||
at the storage level.
|
||||
|
||||
<h3>6.1 Unbuffered Permanent Files</h3>
|
||||
|
||||
<p>The <em>sec2</em> driver uses functions from section 2 of the
|
||||
Posix manual to access files stored on a local file system. These are
|
||||
the <code>open()</code>, <code>close()</code>, <code>read()</code>,
|
||||
<code>write()</code>, and <code>lseek()</code> functions. If the
|
||||
operating system supports <code>lseek64()</code> then it is used instead
|
||||
of <code>lseek()</code>. The library buffers meta data regardless of
|
||||
the low-level driver, but using this driver prevents data from being
|
||||
buffered again by the lowest layers of the HDF5 library.
|
||||
|
||||
<dl>
|
||||
<dt><code>H5F_driver_t H5Pget_driver (hid_t
|
||||
<em>access_properties</em>)</code>
|
||||
<dd>This function returns the constant <code>H5F_LOW_SEC2</code> if the
|
||||
<em>sec2</em> driver is defined as the low-level driver for the
|
||||
specified access property list.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pset_sec2 (hid_t <em>access_properties</em>)</code>
|
||||
<dd>The file access properties are set to use the <em>sec2</em>
|
||||
driver. Any previously defined driver properties are erased from the
|
||||
property list. Additional parameters may be added to this function in
|
||||
the future.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pget_sec2 (hid_t <em>access_properties</em>)</code>
|
||||
<dd>If the file access property list is set to the <em>sec2</em> driver
|
||||
then this function returns zero; otherwise it returns a negative
|
||||
value. In the future, additional arguments may be added to this
|
||||
function to match those added to <code>H5Pset_sec2()</code>.
|
||||
</dl>
|
||||
|
||||
<h3>6.2 Buffered Permanent Files</h3>
|
||||
|
||||
<p>The <em>stdio</em> driver uses the functions declared in the
|
||||
<code>stdio.h</code> header file to access permanent files in a local
|
||||
file system. These are the <code>fopen()</code>, <code>fclose()</code>,
|
||||
<code>fread()</code>, <code>fwrite()</code>, and <code>fseek()</code>
|
||||
functions. If the operating system supports <code>fseek64()</code> then
|
||||
it is used instead of <code>fseek()</code>. Use of this driver
|
||||
introduces an additional layer of buffering beneath the HDF5 library.
|
||||
|
||||
<dl>
|
||||
<dt><code>H5F_driver_t H5Pget_driver(hid_t
|
||||
<em>access_properties</em>)</code>
|
||||
<dd>This function returns the constant <code>H5F_LOW_STDIO</code> if the
|
||||
<em>stdio</em> driver is defined as the low-level driver for the
|
||||
specified access property list.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pset_stdio (hid_t <em>access_properties</em>)</code>
|
||||
<dd>The file access properties are set to use the <em>stdio</em>
|
||||
driver. Any previously defined driver properties are erased from the
|
||||
property list. Additional parameters may be added to this function in
|
||||
the future.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pget_stdio (hid_t <em>access_properties</em>)</code>
|
||||
<dd>If the file access property list is set to the <em>stdio</em> driver
|
||||
then this function returns zero; otherwise it returns a negative
|
||||
value. In the future, additional arguments may be added to this
|
||||
function to match those added to <code>H5Pset_stdio()</code>.
|
||||
</dl>
|
||||
|
||||
<h3>6.3 Buffered Temporary Files</h3>
|
||||
|
||||
<p>The <em>core</em> driver uses <code>malloc()</code> and
|
||||
<code>free()</code> to allocated space for a file in the heap. Reading
|
||||
and writing to a file of this type results in mem-to-mem copies instead
|
||||
of disk I/O and as a result is somewhat faster. However, the total file
|
||||
size must not exceed the amount of available virtual memory, and only
|
||||
one HDF5 file handle can access the file (because the name of such a
|
||||
file is insignificant and <code>H5Fopen()</code> always fails).
|
||||
|
||||
<dl>
|
||||
<dt><code>H5F_driver_t H5Pget_driver (hid_t
|
||||
<em>access_properties</em>)</code>
|
||||
<dd>This function returns the constant <code>H5F_LOW_CORE</code> if the
|
||||
<em>core</em> driver is defined as the low-level driver for the
|
||||
specified access property list.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pset_core (hid_t <em>access_properties</em>, size_t
|
||||
<em>block_size</em>)</code>
|
||||
<dd>The file access properties are set to use the <em>core</em>
|
||||
driver and any previously defined driver properties are erased from
|
||||
the property list. Memory for the file will always be allocated in
|
||||
units of the specified <em>block_size</em>. Additional parameters may
|
||||
be added to this function in the future.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pget_core (hid_t <em>access_properties</em>, size_t
|
||||
*<em>block_size</em>)</code>
|
||||
<dd>If the file access property list is set to the <em>core</em> driver
|
||||
then this function returns zero and <em>block_size</em> is set to the
|
||||
block size used for the file; otherwise it returns a negative
|
||||
value. In the future, additional arguments may be added to this
|
||||
function to match those added to <code>H5Pset_core()</code>.
|
||||
</dl>
|
||||
|
||||
<h3>6.4 Parallel Files</h3>
|
||||
|
||||
<p>This driver uses MPI I/O to provide parallel access to a file.
|
||||
|
||||
<dl>
|
||||
<dt><code>H5F_driver_t H5Pget_driver (hid_t
|
||||
<em>access_properties</em>)</code>
|
||||
<dd>This function returns the constant <code>H5F_LOW_MPI</code> if the
|
||||
<em>mpi</em> driver is defined as the low-level driver for the
|
||||
specified access property list.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pset_mpi (hid_t <em>access_properties</em>, MPI_Comm
|
||||
<em>comm</em>, MPI_info <em>info</em>)</code>
|
||||
<dd>The file access properties are set to use the <em>mpi</em>
|
||||
driver and any previously defined driver properties are erased from
|
||||
the property list. Additional parameters may be added to this
|
||||
function in the future.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pget_mpi (hid_t <em>access_properties</em>, MPI_Comm
|
||||
*<em>comm</em>, MPI_info *<em>info</em>)</code>
|
||||
<dd>If the file access property list is set to the <em>mpi</em> driver
|
||||
then this function returns zero and <em>comm</em>, and <em>info</em>
|
||||
are set to the values stored in the property
|
||||
list; otherwise the function returns a negative value. In the future,
|
||||
additional arguments may be added to this function to match those
|
||||
added to <code>H5Pset_mpi()</code>.
|
||||
</dl>
|
||||
|
||||
<h3>6.4 File Families</h3>
|
||||
|
||||
<p>A single HDF5 address space may be split into multiple files which,
|
||||
together, form a file family. Each member of the family must be the
|
||||
same logical size although the size and disk storage reported by
|
||||
<code>ls</code>(1) may be substantially smaller. The name passed to
|
||||
<code>H5Fcreate()</code> or <code>H5Fopen()</code> should include a
|
||||
<code>printf(3c)</code> style integer format specifier which will be
|
||||
replaced with the family member number (the first family member is
|
||||
zero).
|
||||
|
||||
<p>Any HDF5 file can be split into a family of files by running
|
||||
the file through <code>split</code>(1) and numbering the output
|
||||
files. However, because HDF5 is lazy about extending the size
|
||||
of family members, a valid file cannot generally be created by
|
||||
concatenation of the family members. Additionally,
|
||||
<code>split</code> and <code>cat</code> don't attempt to
|
||||
generate files with holes. The <code>h5repart</code> program
|
||||
can be used to repartition an HDF5 file or family into another
|
||||
file or family and preserves holes in the files.
|
||||
|
||||
<dl>
|
||||
<dt><code>h5repart</code> [<code>-v</code>] [<code>-b</code>
|
||||
<em>block_size</em>[<em>suffix</em>]] [<code>-m</code>
|
||||
<em>member_size</em>[<em>suffix</em>]] <em>source
|
||||
destination</em>
|
||||
<dd>This program repartitions an HDF5 file by copying the source
|
||||
file or family to the destination file or family preserving
|
||||
holes in the underlying Unix files. Families are used for the
|
||||
source and/or destination if the name includes a
|
||||
<code>printf</code>-style integer format such as "%d". The
|
||||
<code>-v</code> switch prints input and output file names on
|
||||
the standard error stream for progress monitoring,
|
||||
<code>-b</code> sets the I/O block size (the default is 1kB),
|
||||
and <code>-m</code> sets the output member size if the
|
||||
destination is a family name (the default is 1GB). The block
|
||||
and member sizes may be suffixed with the letters
|
||||
<code>g</code>, <code>m</code>, or <code>k</code> for GB, MB,
|
||||
or kB respectively.
|
||||
|
||||
<br><br>
|
||||
<dt><code>H5F_driver_t H5Pget_driver (hid_t
|
||||
<em>access_properties</em>)</code>
|
||||
<dd>This function returns the constant <code>H5F_LOW_FAMILY</code> if
|
||||
the <em>family</em> driver is defined as the low-level driver for the
|
||||
specified access property list.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pset_family (hid_t <em>access_properties</em>,
|
||||
hsize_t <em>memb_size</em>, hid_t <em>member_properties</em>)</code>
|
||||
<dd>The file access properties are set to use the <em>family</em>
|
||||
driver and any previously defined driver properties are erased
|
||||
from the property list. Each member of the file family will
|
||||
use <em>member_properties</em> as its file access property
|
||||
list. The <em>memb_size</em> argument gives the logical size
|
||||
in bytes of each family member but the actual size could be
|
||||
smaller depending on whether the file contains holes. The
|
||||
member size is only used when creating a new file or
|
||||
truncating an existing file; otherwise the member size comes
|
||||
from the size of the first member of the family being
|
||||
opened. Note: if the size of the <code>off_t</code> type is
|
||||
four bytes then the maximum family member size is usually
|
||||
2^31-1 because the byte at offset 2,147,483,647 is generally
|
||||
inaccessable. Additional parameters may be added to this
|
||||
function in the future.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pget_family (hid_t <em>access_properties</em>,
|
||||
hsize_t *<em>memb_size</em>, hid_t
|
||||
*<em>member_properties</em>)</code>
|
||||
<dd>If the file access property list is set to the <em>family</em>
|
||||
driver then this function returns zero; otherwise the function
|
||||
returns a negative value. On successful return,
|
||||
<em>access_properties</em> will point to a copy of the member
|
||||
access property list which should be closed by calling
|
||||
<code>H5Pclose()</em> when the application is finished with
|
||||
it. If <em>memb_size</em> is non-null then it will contain
|
||||
the logical size in bytes of each family member. In the
|
||||
future, additional arguments may be added to this function to
|
||||
match those added to <code>H5Pset_family()</code>.
|
||||
</dl>
|
||||
|
||||
<h3>6.5 Split Meta/Raw Files</h3>
|
||||
|
||||
<p>On occasion, it might be useful to separate meta data from raw
|
||||
data. The <em>split</em> driver does this by creating two files: one for
|
||||
meta data and another for raw data. The application provides a base
|
||||
file name to <code>H5Fcreate()</code> or <code>H5Fopen()</code> and this
|
||||
driver appends a file extension which defaults to ".meta" for the meta
|
||||
data file and ".raw" for the raw data file. Each file can have its own
|
||||
file access property list which allows, for instance, a split file with
|
||||
meta data stored with the <em>core</em> driver and raw data stored with
|
||||
the <em>sec2</em> driver.
|
||||
|
||||
<dl>
|
||||
<dt><code>H5F_driver_t H5Pget_driver (hid_t
|
||||
<em>access_properties</em>)</code>
|
||||
<dd>This function returns the constant <code>H5F_LOW_SPLIT</code> if
|
||||
the <em>split</em> driver is defined as the low-level driver for the
|
||||
specified access property list.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pset_split (hid_t <em>access_properties</em>,
|
||||
const char *<em>meta_extension</em>, hid_t
|
||||
<em>meta_properties</em>, const char *<em>raw_extension</em>, hid_t
|
||||
<em>raw_properties</em>)</code>
|
||||
<dd>The file access properties are set to use the <em>split</em>
|
||||
driver and any previously defined driver properties are erased from
|
||||
the property list. The meta file will have a name which is formed by
|
||||
adding <em>meta_extension</em> (or ".meta") to the end of the base
|
||||
name and will be accessed according to the
|
||||
<em>meta_properties</em>. The raw file will have a name which is
|
||||
formed by appending <em>raw_extension</em> (or ".raw") to the base
|
||||
name and will be accessed according to the <em>raw_properties</em>.
|
||||
Additional parameters may be added to this function in the future.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pget_split (hid_t <em>access_properties</em>,
|
||||
size_t <em>meta_ext_size</em>, const char *<em>meta_extension</em>,
|
||||
hid_t <em>meta_properties</em>, size_t <em>raw_ext_size</em>, const
|
||||
char *<em>raw_extension</em>, hid_t *<em>raw_properties</em>)</code>
|
||||
<dd>If the file access property list is set to the <em>split</em>
|
||||
driver then this function returns zero; otherwise the function
|
||||
returns a negative value. On successful return,
|
||||
<em>meta_properties</em> and <em>raw_properties</em> will
|
||||
point to copies of the meta and raw access property lists
|
||||
which should be closed by calling <code>H5Pclose()</em> when
|
||||
the application is finished with them, but if the meta and/or
|
||||
raw file has no property list then a negative value is
|
||||
returned for that property list handle. Also, if
|
||||
<em>meta_extension</em> and/or <em>raw_extension</em> are
|
||||
non-null pointers, at most <em>meta_ext_size</em> or
|
||||
<em>raw_ext_size</em> characters of the meta or raw file name
|
||||
extension will be copied to the specified buffer. If the
|
||||
actual name is longer than what was requested then the result
|
||||
will not be null terminated (similar to
|
||||
<code>strncpy()</code>). In the future, additional arguments
|
||||
may be added to this function to match those added to
|
||||
<code>H5Pset_split()</code>.
|
||||
</dl>
|
||||
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:koziol@ncsa.uiuc.edu">Quincey Koziol</a></address>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Tue Jan 27 09:11:27 EST 1998 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Tue Jun 9 15:03:44 EDT 1998
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
288
doc/html/Groups.html
Normal file
@ -0,0 +1,288 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Groups</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Groups</h1>
|
||||
|
||||
<h2>1. Introduction</h2>
|
||||
|
||||
<p>An object in HDF5 consists of an object header at a fixed file
|
||||
address that contains messages describing various properties of
|
||||
the object such as its storage location, layout, compression,
|
||||
etc. and some of these messages point to other data such as the
|
||||
raw data of a dataset. The address of the object header is also
|
||||
known as an <em>OID</em> and HDF5 has facilities for translating
|
||||
names to OIDs.
|
||||
|
||||
<p>Every HDF5 object has at least one name and a set of names can
|
||||
be stored together in a group. Each group implements a name
|
||||
space where the names are any length and unique with respect to
|
||||
other names in the group.
|
||||
|
||||
<p>Since a group is a type of HDF5 object it has an object header
|
||||
and a name which exists as a member of some other group. In this
|
||||
way, groups can be linked together to form a directed graph.
|
||||
One particular group is called the <em>Root Group</em> and is
|
||||
the group to which the HDF5 file boot block points. Its name is
|
||||
"/" by convention. The <em>full name</em> of an object is
|
||||
created by joining component names with slashes much like Unix.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<img alt="Group Graph Example" src="group_p1.gif">
|
||||
</center>
|
||||
|
||||
<p>However, unlike Unix which arranges directories hierarchically,
|
||||
HDF5 arranges groups in a directed graph. Therefore, there is
|
||||
no ".." entry in a group since a group can have more than one
|
||||
parent. There is no "." entry either but the library understands
|
||||
it internally.
|
||||
|
||||
<h2>2. Names</h2>
|
||||
|
||||
<p>HDF5 places few restrictions on names: component names may be
|
||||
any length except zero and may contain any character except
|
||||
slash ("/") and the null terminator. A full name may be
|
||||
composed of any number of component names separated by slashes,
|
||||
with any of the component names being the special name ".". A
|
||||
name which begins with a slash is an <em>absolute</em> name
|
||||
which is looked up beginning at the root group of the file while
|
||||
all other <em>relative</em> names are looked up beginning at the
|
||||
current working group (described below) or a specified group.
|
||||
Multiple consecutive slashes in a full name are treated as
|
||||
single slashes and trailing slashes are not significant. A
|
||||
special case is the name "/" (or equivalent) which refers to the
|
||||
root group.
|
||||
|
||||
<p>Functions which operate on names generally take a location
|
||||
identifier which is either a file ID or a group ID and perform
|
||||
the lookup with respect to that location. Some possibilities
|
||||
are:
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border cellpadding=4>
|
||||
<tr>
|
||||
<th>Location Type</th>
|
||||
<th>Object Name</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>File ID</td>
|
||||
<td><code>/foo/bar</code></td>
|
||||
<td>The object <code>bar</code> in group <code>foo</code>
|
||||
in the root group of the specified file.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Group ID</td>
|
||||
<td><code>/foo/bar</code></td>
|
||||
<td>The object <code>bar</code> in group <code>foo</code>
|
||||
in the root group of the file containing the specified
|
||||
group. In other words, the group ID's only purpose is
|
||||
to supply a file.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>File ID</td>
|
||||
<td><code>/</code></td>
|
||||
<td>The root group of the specified file.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Group ID</td>
|
||||
<td><code>/</code></td>
|
||||
<td>The root group of the file containing the specified
|
||||
group.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>File ID</td>
|
||||
<td><code>foo/bar</code></td>
|
||||
<td>The object <code>bar</code> in group <code>foo</code>
|
||||
in the current working group of the specified file. The
|
||||
initial current working group is the root group of the
|
||||
file as described below.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Group ID</td>
|
||||
<td><code>foo/bar</code></td>
|
||||
<td>The object <code>bar</code> in group <code>foo</code>
|
||||
in the specified group.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>File ID</td>
|
||||
<td><code>.</code></td>
|
||||
<td>The current working group of the specified file.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Group ID</td>
|
||||
<td><code>.</code></td>
|
||||
<td>The specified group.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Other ID</td>
|
||||
<td><code>.</code></td>
|
||||
<td>The specified object.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</center>
|
||||
|
||||
|
||||
<h2>3. Creating, Opening, and Closing Groups</h2>
|
||||
|
||||
<p>Groups are created with the <code>H5Gcreate()</code> function,
|
||||
and existing groups can be access with
|
||||
<code>H5Gopen()</code>. Both functions return an object ID which
|
||||
should be eventually released by calling
|
||||
<code>H5Gclose()</code>.
|
||||
|
||||
<dl>
|
||||
<dt><code>hid_t H5Gcreate (hid_t <em>location_id</em>, const char
|
||||
*<em>name</em>, size_t <em>size_hint</em>)</code>
|
||||
<dd>This function creates a new group with the specified
|
||||
name at the specified location which is either a file ID or a
|
||||
group ID. The name must not already be taken by some other
|
||||
object and all parent groups must already exist. The
|
||||
<em>size_hint</em> is a hint for the number of bytes to
|
||||
reserve to store the names which will be eventually added to
|
||||
the new group. Passing a value of zero for <em>size_hint</em>
|
||||
is usually adequate since the library is able to dynamically
|
||||
resize the name heap, but a correct hint may result in better
|
||||
performance. The return value is a handle for the open group
|
||||
and it should be closed by calling <code>H5Gclose()</code>
|
||||
when it's no longer needed. A negative value is returned for
|
||||
failure.
|
||||
|
||||
<br><br>
|
||||
<dt><code>hid_t H5Gopen (hid_t <em>location_id</em>, const char
|
||||
*<em>name</em>)</code>
|
||||
<dd>This function opens an existing group with the specified
|
||||
name at the specified location which is either a file ID or a
|
||||
group ID and returns an object ID. The object ID should be
|
||||
released by calling <code>H5Gclose()</code> when it is no
|
||||
longer needed. A negative value is returned for failure.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Gclose (hid_t <em>group_id</em>)</code>
|
||||
<dd>This function releases resources used by an group which was
|
||||
opened by <code>H5Gcreate()</code> or
|
||||
<code>H5Gopen()</code>. After closing a group the
|
||||
<em>group_id</em> should not be used again. This function
|
||||
returns zero for success or a negative value for failure.
|
||||
</dl>
|
||||
|
||||
<h2>4. Current Working Group</h2>
|
||||
|
||||
<p>Each file handle (<code>hid_t <em>file_id</em></code>) has a
|
||||
current working group, initially the root group of the file.
|
||||
Names which do not begin with a slash are relative to the
|
||||
specified group or to the current working group as described
|
||||
above. For instance, the name "/Foo/Bar/Baz" is resolved by
|
||||
first looking up "Foo" in the root group. But the name
|
||||
"Foo/Bar/Baz" is resolved by first looking up "Foo" in the
|
||||
current working group.
|
||||
|
||||
<dl>
|
||||
<dt><code>herr_t H5Gset (hid_t <em>location_id</em>, const char
|
||||
*<em>name</em>)</code>
|
||||
<dd>The group with the specified name is made the current
|
||||
working group for the file which contains it. The
|
||||
<em>location_id</em> can be a file handle or a group handle
|
||||
and the name is resolved as described above. Each file handle
|
||||
has it's own current working group and if the
|
||||
<em>location_id</em> is a group handle then the file handle is
|
||||
derived from the group handle. This function returns zero for
|
||||
success or negative for failure.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Gpush (hid_t <em>location_id</em>, const char
|
||||
*<em>name</em>)</code>
|
||||
<dd>Each file handle has a stack of groups and the top group on
|
||||
that stack is the current working group. The stack initially
|
||||
contains only the root group. This function pushes a new
|
||||
group onto the stack and returns zero for success or negative
|
||||
for failure.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Gpop (hid_t <em>location_id</em>)</code>
|
||||
<dd>This function pops one group off the group stack for the
|
||||
specified file (if the <em>location_id</em> is a group then
|
||||
the file is derived from that group), changing the current
|
||||
working group to the new top-of-stack group. The function
|
||||
returns zero for success or negative for failure (failure
|
||||
includes attempting to pop from an empty stack). If the last
|
||||
item is popped from the stack then the current working group
|
||||
is set to the root group.
|
||||
</dl>
|
||||
|
||||
<h2>5. Objects with Multiple Names</h2>
|
||||
|
||||
<p>An object (including a group) can have more than one
|
||||
name. Creating the object gives it the first name, and then
|
||||
functions described here can be used to give it additional
|
||||
names. The association between a name and the object is called
|
||||
a <em>link</em> and HDF5 supports two types of links: a <em>hard
|
||||
link</em> is a direct association between the name and the
|
||||
object where both exist in a single HDF5 address space, and a
|
||||
<em>soft link</em> is an indirect association.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<img alt="Hard Link Example" src="group_p2.gif">
|
||||
</center>
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<img alt="Soft Link Example" src="group_p3.gif">
|
||||
</center>
|
||||
|
||||
<dl>
|
||||
<dt>Object Creation</dt>
|
||||
<dd>The creation of an object creates a hard link which is
|
||||
indistinguishable from other hard links that might be added
|
||||
later.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Glink (hid_t <em>file_id</em>, H5G_link_t
|
||||
<em>link_type</em>, const char *<em>current_name</em>,
|
||||
const char *<em>new_name</em>)</code>
|
||||
<dd>Creates a new name for an object that has some current name
|
||||
(possibly one of many names it currently has). If the
|
||||
<em>link_type</em> is <code>H5G_LINK_HARD</code> then a new
|
||||
hard link is created. Otherwise if <em>link_type</em> is
|
||||
<code>H5T_LINK_SOFT</code> a soft link is created which is an
|
||||
alias for the <em>current_name</em>. When creating a soft
|
||||
link the object need not exist. This function returns zero
|
||||
for success or negative for failure. <b>This function is not
|
||||
part of the prototype API.</b>
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Gunlink (hid_t <em>file_id</em>, const char
|
||||
*<em>name</em>)</code>
|
||||
<dd>This function removes an association between a name and an
|
||||
object. Object headers keep track of how many hard links refer
|
||||
to the object and when the hard link count reaches zero the
|
||||
object can be removed from the file (but objects which are
|
||||
open are not removed until all handles to the object are
|
||||
closed). <b>This function is not part of the prototype
|
||||
API.</b>
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Tue Jan 27 09:11:27 EST 1998 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Tue Mar 24 15:52:14 EST 1998
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
4611
doc/html/H5.api.html
Normal file
849
doc/html/H5.api_map.html
Normal file
@ -0,0 +1,849 @@
|
||||
<html><head><title>
|
||||
HDF5 Legacy API Equivalence
|
||||
</title></head><body>
|
||||
|
||||
<center>
|
||||
<h1>HDF5: API Mapping to legacy APIs</h1>
|
||||
</center>
|
||||
|
||||
<table border=1 cellpadding=2 cellspacing=0>
|
||||
<tr>
|
||||
<th>Functionality</th>
|
||||
<th>netCDF</th>
|
||||
<th>SD</th>
|
||||
<th>AIO</th>
|
||||
<th>HDF5</th>
|
||||
<th>Comments</th>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Open existing file for read/write</td>
|
||||
<td>ncopen</td>
|
||||
<td>SDstart</td>
|
||||
<td>AIO_open</td>
|
||||
<td>H5Fopen</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Creates new file for read/write.</td>
|
||||
<td>nccreate</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>H5Fcreate</td>
|
||||
<td>SD API handles this with SDopen</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Close file</td>
|
||||
<td>ncclose</td>
|
||||
<td>SDend</td>
|
||||
<td>AIO_close</td>
|
||||
<td>H5Fclose</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Redefine parameters</td>
|
||||
<td>ncredef</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Unneccessary under SD & HDF5 data-models</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>End "define" mode</td>
|
||||
<td>ncendef</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Unneccessary under SD & HDF5 data-models</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Query the number of datasets, dimensions and attributes in a file</td>
|
||||
<td>ncinquire</td>
|
||||
<td>SDfileinfo</td>
|
||||
<td><hr></td>
|
||||
<td>H5Dget_info<br>H5Rget_num_relations<br>H5Gget_num_contents</td>
|
||||
<td>HDF5 interface is more granular and flexible</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Update a writeable file with current changes</td>
|
||||
<td>ncsync</td>
|
||||
<td><hr></td>
|
||||
<td>AIO_flush</td>
|
||||
<td>H5Mflush</td>
|
||||
<td>HDF5 interface is more flexible because it can be applied to parts of the
|
||||
file hierarchy instead of the whole file at once. The SD interface does not
|
||||
have this feature, although most of the lower HDF library supports it.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Close file access without applying recent changes</td>
|
||||
<td>ncabort</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>How useful is this feature?</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Create new dimension</td>
|
||||
<td>ncdimdef</td>
|
||||
<td>SDsetdimname</td>
|
||||
<td><hr></td>
|
||||
<td>H5Mcreate</td>
|
||||
<td>SD interface actually creates dimensions with datasets, this just allows
|
||||
naming them</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get ID of existing dimension</td>
|
||||
<td>ncdimid</td>
|
||||
<td>SDgetdimid</td>
|
||||
<td><hr></td>
|
||||
<td>H5Maccess</td>
|
||||
<td>SD interface looks up dimensions by index and the netCDF interface uses
|
||||
names, but they are close enough. The HDF5 interface does not current allow
|
||||
access to particular dimensions, only the dataspace as a whole.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get size & name of dimension</td>
|
||||
<td>ncdiminq</td>
|
||||
<td>SDdiminfo</td>
|
||||
<td><hr></td>
|
||||
<td>H5Mget_name<br>H5Sget_lrank</td>
|
||||
<td>Only a rough match</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Rename dimension</td>
|
||||
<td>ncdimrename</td>
|
||||
<td>SDsetdimname</td>
|
||||
<td><hr></td>
|
||||
<td>H5Mset_name</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Create a new dataset</td>
|
||||
<td>ncvardef</td>
|
||||
<td>SDcreate</td>
|
||||
<td>AIO_mkarray</td>
|
||||
<td>H5Mcreate</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Attach to an existing dataset</td>
|
||||
<td>ncvarid</td>
|
||||
<td>SDselect</td>
|
||||
<td>AIO_arr_load</td>
|
||||
<td>H5Maccess</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get basic information about a dataset</td>
|
||||
<td>ncvarinq</td>
|
||||
<td>SDgetinfo</td>
|
||||
<td>AIO_arr_get_btype<br>AIO_arr_get_nelmts<br>AIO_arr_get_nbdims<br>AIO_arr_get_bdims<br>AIO_arr_get_slab</td>
|
||||
<td>H5Dget_info</td>
|
||||
<td>All interfaces have different levels of information that they return, some
|
||||
use of auxilliary functions is required to get equivalent amount of information</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Write a single value to a dataset</td>
|
||||
<td>ncvarput1</td>
|
||||
<td>SDwritedata</td>
|
||||
<td>AIO_write</td>
|
||||
<td>H5Dwrite</td>
|
||||
<td>What is this useful for?</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Read a single value from a dataset</td>
|
||||
<td>ncvarget1</td>
|
||||
<td>SDreaddata</td>
|
||||
<td>AIO_read</td>
|
||||
<td>H5Dread</td>
|
||||
<td>What is this useful for?</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Write a solid hyperslab of data (i.e. subset) to a dataset</td>
|
||||
<td>ncvarput</td>
|
||||
<td>SDwritedata</td>
|
||||
<td>AIO_write</td>
|
||||
<td>H5Dwrite</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Read a solid hyperslab of data (i.e. subset) from a dataset</td>
|
||||
<td>ncvarget</td>
|
||||
<td>SDreaddata</td>
|
||||
<td>AIO_read</td>
|
||||
<td>H5Dread</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Write a general hyperslab of data (i.e. possibly subsampled) to a dataset</td>
|
||||
<td>ncvarputg</td>
|
||||
<td>SDwritedata</td>
|
||||
<td>AIO_write</td>
|
||||
<td>H5Dwrite</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Read a general hyperslab of data (i.e. possibly subsampled) from a dataset</td>
|
||||
<td>ncvargetg</td>
|
||||
<td>SDreaddata</td>
|
||||
<td>AIO_read</td>
|
||||
<td>H5Dread</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Rename a dataset variable</td>
|
||||
<td>ncvarrename</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>H5Mset_name</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Add an attribute to a dataset</td>
|
||||
<td>ncattput</td>
|
||||
<td>SDsetattr</td>
|
||||
<td><hr></td>
|
||||
<td>H5Rattach_oid</td>
|
||||
<td>HDF5 requires creating a seperate object to attach to a dataset, but it also
|
||||
allows objects to be attributes of any other object, even nested.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get attribute information</td>
|
||||
<td>ncattinq</td>
|
||||
<td>SDattrinfo</td>
|
||||
<td><hr></td>
|
||||
<td>H5Dget_info</td>
|
||||
<td>HDF5 has no specific function for attributes, they are treated as all other
|
||||
objects in the file.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Retrieve attribute for a dataset</td>
|
||||
<td>ncattget</td>
|
||||
<td>SDreadattr</td>
|
||||
<td><hr></td>
|
||||
<td>H5Dread</td>
|
||||
<td>HDF5 uses general dataset I/O for attributes.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Copy attribute from one dataset to another</td>
|
||||
<td>ncattcopy</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>What is this used for?</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get name of attribute</td>
|
||||
<td>ncattname</td>
|
||||
<td>SDattrinfo</td>
|
||||
<td><hr></td>
|
||||
<td>H5Mget_name</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Rename attribute</td>
|
||||
<td>ncattrename</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>H5Mset_name</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Delete attribute</td>
|
||||
<td>ncattdel</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>H5Mdelete</td>
|
||||
<td>This can be faked in current HDF interface with lower-level calls</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Compute # of bytes to store a number-type</td>
|
||||
<td>nctypelen</td>
|
||||
<td>DFKNTsize</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Hmm, the HDF5 Datatype interface needs this functionality.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Indicate that fill-values are to be written to dataset</td>
|
||||
<td>ncsetfill</td>
|
||||
<td>SDsetfillmode</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>HDF5 Datatype interface should work on this functionality</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get information about "record" variables (Those datasets which share the
|
||||
same unlimited dimension</td>
|
||||
<td>ncrecinq</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>This should probably be wrapped in a higher layer interface, if it's
|
||||
needed for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get a record from each dataset sharing the unlimited dimension</td>
|
||||
<td>ncrecget</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>This is somewhat equivalent to reading a vdata with non-interlaced
|
||||
fields, only in a dataset oriented way. This should also be wrapped in a
|
||||
higher layer interface if it's necessary for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Put a record from each dataset sharing the unlimited dimension</td>
|
||||
<td>ncrecput</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>This is somewhat equivalent to writing a vdata with non-interlaced
|
||||
fields, only in a dataset oriented way. This should also be wrapped in a
|
||||
higher layer interface if it's necessary for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Map a dataset's name to an index to reference it with</td>
|
||||
<td><hr></td>
|
||||
<td>SDnametoindex</td>
|
||||
<td><hr></td>
|
||||
<td>H5Mfind_name</td>
|
||||
<td>Equivalent functionality except HDF5 call returns an OID instead of an
|
||||
index.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get the valid range of values for data in a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDgetrange</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Easily implemented with attributes at a higher level for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Release access to a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDendaccess</td>
|
||||
<td>AIO_arr_destroy</td>
|
||||
<td>H5Mrelease</td>
|
||||
<td>Odd that the netCDF API doesn't have this...</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Set the valid range of data in a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetrange</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Easily implemented with attributes at a higher level for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Set the label, units, format, etc. of the data values in a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetdatastrs</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Easily implemented with attributes at a higher level for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get the label, units, format, etc. of the data values in a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDgetdatastrs</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Easily implemented with attributes at a higher level for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Set the label, units, format, etc. of the dimensions in a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetdimstrs</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Easily implemented with attributes at a higher level for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get the label, units, format, etc. of the dimensions in a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDgetdimstrs</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Easily implemented with attributes at a higher level for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Set the scale of the dimensions in a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetdimscale</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Easily implemented with attributes at a higher level for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get the scale of the dimensions in a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDgetdimscale</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Easily implemented with attributes at a higher level for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Set the calibration parameters of the data values in a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetcal</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Easily implemented with attributes at a higher level for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get the calibration parameters of the data values in a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDgetcal</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Easily implemented with attributes at a higher level for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Set the fill value for the data values in a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetfillvalue</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>HDF5 needs something like this, I'm not certain where to put it.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get the fill value for the data values in a dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDgetfillvalue</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>HDF5 needs something like this, I'm not certain where to put it.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Move/Set the dataset to be in an 'external' file</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetexternalfile</td>
|
||||
<td><hr></td>
|
||||
<td>H5Dset_storage</td>
|
||||
<td>HDF5 has simple functions for this, but needs an API for setting up the
|
||||
storage flow.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Move/Set the dataset to be stored using only certain bits from the dataset</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetnbitdataset</td>
|
||||
<td><hr></td>
|
||||
<td>H5Dset_storage</td>
|
||||
<td>HDF5 has simple functions for this, but needs an API for setting up the
|
||||
storage flow.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Move/Set the dataset to be stored in compressed form</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetcompress</td>
|
||||
<td><hr></td>
|
||||
<td>H5Dset_storage</td>
|
||||
<td>HDF5 has simple functions for this, but needs an API for setting up the
|
||||
storage flow.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Search for an dataset attribute with particular name</td>
|
||||
<td><hr></td>
|
||||
<td>SDfindattr</td>
|
||||
<td><hr></td>
|
||||
<td>H5Mfind_name<br>H5Mwild_search</td>
|
||||
<td>HDF5 can handle wildcard searchs for this feature.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Map a run-time dataset handle to a persistant disk reference</td>
|
||||
<td><hr></td>
|
||||
<td>SDidtoref</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>I'm not certain this is needed for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Map a persistant disk reference for a dataset to an index in a group</td>
|
||||
<td><hr></td>
|
||||
<td>SDreftoindex</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>I'm not certain this is needed for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Determine if a dataset is a 'record' variable (i.e. it has an unlimited dimension)</td>
|
||||
<td><hr></td>
|
||||
<td>SDisrecord</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Easily implemented by querying the dimensionality at a higher level for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Determine if a dataset is a 'coordinate' variable (i.e. it is used as a dimension)</td>
|
||||
<td><hr></td>
|
||||
<td>SDiscoord</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>I'm not certain this is needed for HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Set the access type (i.e. parallel or serial) for dataset I/O</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetaccesstype</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>HDF5 has functions for reading the information about this, but needs a better
|
||||
API for setting up the storage flow.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Set the size of blocks used to store a dataset with unlimited dimensions</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetblocksize</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>HDF5 has functions for reading the information about this, but needs a better
|
||||
API for setting up the storage flow.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Sets backward compatibility of dimensions created.</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetdimval_comp</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Unneccessary in HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Checks backward compatibility of dimensions created.</td>
|
||||
<td><hr></td>
|
||||
<td>SDisdimval_comp</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>Unneccessary in HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Move/Set the dataset to be stored in chunked form</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetchunk</td>
|
||||
<td><hr></td>
|
||||
<td>H5Dset_storage</td>
|
||||
<td>HDF5 has simple functions for this, but needs an API for setting up the
|
||||
storage flow.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get the chunking information for a dataset stored in chunked form</td>
|
||||
<td><hr></td>
|
||||
<td>SDgetchunkinfo</td>
|
||||
<td><hr></td>
|
||||
<td>H5Dstorage_detail</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Read/Write chunks of a dataset using a chunk index</td>
|
||||
<td><hr></td>
|
||||
<td>SDreadchunk<br>SDwritechunk</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>I'm not certain that HDF5 needs something like this.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Tune chunk caching parameters for chunked datasets</td>
|
||||
<td><hr></td>
|
||||
<td>SDsetchunkcache</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>HDF5 needs something like this.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Change some default behavior of the library</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_defaults</td>
|
||||
<td><hr></td>
|
||||
<td>Something like this would be useful in HDF5, to tune I/O pipelines, etc.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Flush and close all open files</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_exit</td>
|
||||
<td><hr></td>
|
||||
<td>Something like this might be useful in HDF5, although it could be
|
||||
encapsulated with a higher-level function.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Target an architecture for data-type storage</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_target</td>
|
||||
<td><hr></td>
|
||||
<td>There are some rough parallels with using the data-type in HDF5 to create
|
||||
data-type objects which can be used to write out future datasets.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Map a filename to a file ID</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_filename</td>
|
||||
<td>H5Mget_name</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get the active directory (where new datasets are created)</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_getcwd</td>
|
||||
<td><hr></td>
|
||||
<td>HDF5 allows multiple directories (groups) to be attached to, any of which
|
||||
can have new datasets created within it.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Change active directory</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_chdir</td>
|
||||
<td><hr></td>
|
||||
<td>Since HDF5 has a slightly different access method for directories (groups),
|
||||
this functionality can be wrapped around calls to H5Gget_oid_by_name.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Create directory</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_mkdir</td>
|
||||
<td>H5Mcreate</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Return detailed information about an object</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_stat</td>
|
||||
<td>H5Dget_info<br>H5Dstorage_detail</td>
|
||||
<td>Perhaps more information should be provided through another function in
|
||||
HDF5?</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get "flag" information</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_getflags</td>
|
||||
<td><hr></td>
|
||||
<td>Not required in HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Set "flag" information</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_setflags</td>
|
||||
<td><hr></td>
|
||||
<td>Not required in HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get detailed information about all objects in a directory</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_ls</td>
|
||||
<td>H5Gget_content_info_mult<br>H5Dget_info<br>H5Dstorage_detail</td>
|
||||
<td>Only roughly equivalent functionality in HDF5, perhaps more should be
|
||||
added?</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Get base type of object</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_BASIC</td>
|
||||
<td>H5Gget_content_info</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Set base type of dataset</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_arr_set_btype</td>
|
||||
<td>H5Mcreate(DATATYPE)</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Set dimensionality of dataset</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_arr_set_bdims</td>
|
||||
<td>H5Mcreate(DATASPACE)</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Set slab of dataset to write</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_arr_set_slab</td>
|
||||
<td><hr></td>
|
||||
<td>This is similar to the process of creating a dataspace for use when
|
||||
performing I/O on an HDF5 dataset</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Describe chunking of dataset to write</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_arr_set_chunk</td>
|
||||
<td>H5Dset_storage</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Describe array index permutation of dataset to write</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_arr_set_perm</td>
|
||||
<td>H5Dset_storage</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Create a new dataset with dataspace and datatype information from an
|
||||
existing dataset.</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_arr_copy</td>
|
||||
<td><hr></td>
|
||||
<td>This can be mimicked in HDF5 by attaching to the datatype and dataspace of
|
||||
an existing dataset and using the IDs to create new datasets.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Create a new directory to group objects within</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_mkgroup</td>
|
||||
<td>H5Mcreate(GROUP)</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Read name of objects in directory</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_read_group</td>
|
||||
<td>H5Gget_content_info_mult</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Add objects to directory</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_write_group</td>
|
||||
<td>H5Ginsert_item_mult</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Combine an architecture and numeric type to derive the format's datatype</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_COMBINE</td>
|
||||
<td><hr></td>
|
||||
<td>This is a nice feature to add to HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Derive an architecture from the format's datatype</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_ARCH</td>
|
||||
<td><hr></td>
|
||||
<td>This is a nice feature to add to HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Derive a numeric type from the format's datatype</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_PNT</td>
|
||||
<td><hr></td>
|
||||
<td>This is a nice feature to add to HDF5.</td>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>Register error handling function for library to call when errors occur</td>
|
||||
<td><hr></td>
|
||||
<td><hr></td>
|
||||
<td>AIO_error_handler</td>
|
||||
<td><hr></td>
|
||||
<td>This should be added to HDF5.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
3183
doc/html/H5.format.html
Normal file
997
doc/html/H5.intro.html
Normal file
@ -0,0 +1,997 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
|
||||
<META NAME="Generator" CONTENT="Microsoft Word 97">
|
||||
<TITLE>H5introH</TITLE>
|
||||
<META NAME="Template" CONTENT="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
||||
</HEAD>
|
||||
<BODY LINK="#0000ff" VLINK="#800080">
|
||||
|
||||
<B><FONT FACE="Times" SIZE=6><P ALIGN="CENTER">Introduction to HDF5 1.0 Alpha1.0</P>
|
||||
</B></FONT><FONT FACE="Times"><P>This is a brief introduction to the HDF5 data model and programming model. It is not a full user's guide, but should provide enough information for you to understand how HDF5 is meant to work. Knowledge of the current version of HDF should make it easier to follow the text, but it is not required. For further information on the topics covered here, see the HDF5 documentation at </FONT><A HREF="http://hdf.ncsa.uiuc.edu/nra/BigHDF/"><FONT FACE="Times">http://hdf.ncsa.uiuc.edu/nra/BigHDF/</FONT></A><FONT FACE="Times">. </P>
|
||||
</FONT><H2>What is the HDF5 prototype?</H2>
|
||||
<FONT FACE="Times"><P>HDF5 is a new, experimental version of HDF that is designed to address some of the limitations of the current version of HDF (HDF4.1) and to address current and anticipated requirements of modern systems and applications. </P>
|
||||
<P>This HDF5 prototype is not complete, but it should be sufficient show the basic features of HDF5. We urge you to look at it and give us feedback on what you like or don't like about it, and what features you would like to see added to it.</P>
|
||||
<B><P>Why HDF5?</B> The development of HDF5 is motivated by a number of limitations in the current HDF format, as well as limitations in the library. Some of these limitations are:</P>
|
||||
|
||||
<UL>
|
||||
</FONT><LI>A single file cannot store more than 20,000 complex objects, and a single file cannot be larger than 2 gigabytes </LI>
|
||||
<LI>The data models are less consistent than they should be, there are more object types than necessary, and datatypes are too restricted. </LI>
|
||||
<LI>The library source is old and overly complex, does not support parallel I/O effectively, and is difficult to use in threaded applications.</LI></UL>
|
||||
|
||||
<FONT FACE="Times"><P>When complete HDF5 will include the following improvements.</P>
|
||||
|
||||
<UL>
|
||||
</FONT><LI>A new file format designed to address some of the deficiencies of HDF4.1, particularly the need to store larger files and more objects per file. </LI>
|
||||
<LI>A simpler, more comprehensive data model that includes only two basic structures: a multidimensional array of record structures, and a grouping structure. </LI>
|
||||
<LI>A simpler, better-engineered library and API, with improved support for parallel i/o, threads, and other requirements imposed by modern systems and applications.</LI></UL>
|
||||
|
||||
<H2>Limitations of the current prototype</H2>
|
||||
<FONT FACE="Times"><P>The prototype release includes most of the <I>basic</I> functionality that is planned for the HDF5 library. However, the library does not implement all of the features detailed in the format and API specifications. Here is a listing of some of the limitations of the current release: </P>
|
||||
|
||||
<UL>
|
||||
</FONT><LI>Attributes for data objects are not supported </LI>
|
||||
<LI>Data compression is not supported </LI>
|
||||
<LI>External storage of objects are not supported </LI>
|
||||
<LI>Some functions for manipulating datasets, dataspaces, and groups have not been implemented </LI>
|
||||
<FONT FACE="Times"><LI>Some number types, including user-defined number types are not supported. Also number type conversion is limited.</LI></UL>
|
||||
|
||||
<P>See the API Specification at </FONT><A HREF="http://hdf.ncsa.uiuc.edu/nra/BigHDF/"><FONT FACE="Times">http://hdf.ncsa.uiuc.edu/nra/BigHDF/</FONT></A><FONT FACE="Times"> for a complete listing of all routines that have been implemented.</P>
|
||||
</FONT><H2>HDF5 file organization and data model.</H2>
|
||||
<FONT FACE="Times"><P>HDF5 files are organized in a hierarchical structure, with two primary structures: "groups" and "datasets."</P>
|
||||
|
||||
<UL>
|
||||
</FONT><I><LI>HDF5 group: </I>a grouping structure containing instances of zero or more groups or datasets, together with supporting metadata </LI>
|
||||
<I><LI>HD5F dataset:</I> a multidimensional array of data elements, together with supporting metadata. </LI></UL>
|
||||
|
||||
<FONT FACE="Times"><P>Working with groups and group members is similar in many ways to working with directories and files in UNIX. As with UNIX directories and files, objects in an HDF5 file are often described by giving their full path names. "/" signifies the root group. "/foo" signifies a member of the root group called "foo." "/foo/zoo" signifies a member of the group "foo," which in turn is a member of the root group.</P>
|
||||
<P>Any HDF5 group or dataset may have an associated <I>attribute list.</I> An HDF5 <I>attribute</I> is a user-defined HDF5 structure that provides extra information about an HDF5 object. Attributes are described in more detail below. <I>(Note: attributes are not supported in the current prototype.)</P>
|
||||
</I></FONT><H3>HDF5 Groups</H3>
|
||||
<FONT FACE="Times"><P>An<I> HDF5 group</I> is a structure containing zero or more HDF5 objects. A group has two parts:</P>
|
||||
|
||||
<UL>
|
||||
</FONT><LI>A <I>group header</I>, which contains a group name and a list of group attributes. (Attributes are not yet implemented.) </LI>
|
||||
<LI>A group symbol table, which is a list of the HDF5 objects that belong to the group.</LI></UL>
|
||||
|
||||
<P> </P>
|
||||
<H3>HDF5 Datasets</H3>
|
||||
<FONT FACE="Times"><P>A dataset is stored in a file in two parts: a header and a data array. </P>
|
||||
<P>The header contains information that is needed to interpret the array portion of the dataset, as well as metadata, or pointers to metadata, that describes or annotates the dataset. Header information includes the name of the object, its dimensionality, its number-type, information about how the data itself is stored on disk, and other information used by the library to speed up access to the dataset or maintain the file's integrity.</P>
|
||||
<P>There are four essential classes of information in any header: <I>name</I>, <I>datatype</I>, <I>dataspace</I>, and <I>storage layout</I>:</P>
|
||||
<B><P>Name</B><I>.</I> A dataset <I>name</I> is a sequence of alphanumeric ASCII characters.</P>
|
||||
<B><DFN><P>Datatype</DFN><I>.</B></I> HDF5 allows one to define many different kinds of <B>datatypes</B>. There are two basic categories of data types: "atomic" types and "compound" types. Atomic types are those that are not decomposed at the data type interface level, such as integers and floats. Compound types are made up of atomic types. </P>
|
||||
<I><P>Atomic datatypes</I> include integers and floating-point numbers. Each atomic type belongs to a particular class and has several properties: size, order, precision, and offset. In this introduction, we consider only a few of these properties.</P>
|
||||
<P>Atomic datatypes include integer, float, date and time, string, bit field, and opaque. <I>(Note: Only integer and float classes are available in the current implementation.)</P>
|
||||
</I><P>Properties of integer types include size, order (endian-ness), and signed-ness (signed/unsigned).</P>
|
||||
<P>Properties of float types include the size and location of the exponent and mantissa, and the location of the sign bit.</P>
|
||||
<P>The datatypes that are supported in the current implementation are: </P>
|
||||
|
||||
<UL>
|
||||
</FONT><LI>Integer datatypes: 8-bit, 16-bit, 32-bit, and 64-bit integers in both little and big-endian format. </LI>
|
||||
<LI>Floating-point numbers: IEEE 32-bit and 64-bit floating-point numbers in both little and big-endian format.</LI></UL>
|
||||
|
||||
<FONT FACE="Times"><P>A <I>compound datatype</I> is one in which a collection of simple datatypes are represented as a single unit, similar to a "struct" in C. The parts of a compound datatype are called <I>members.</I> The members of a compound datatype may be of any datatype, including another compound datatype. It is possible to read members from a compound type without reading the whole type.</P>
|
||||
<B><DFN><P>Dataspace.</B> </DFN>A dataset <I>dataspace </I>describes the dimensionality of the dataset. The dimensions of a dataset can be fixed (unchanging), or they may be <I>unlimited</I>, which means that they are extendible (i.e. they can grow larger). </P>
|
||||
<P>Properties of a dataspace consist of the <I>rank </I>(number of dimensions) of the data array, and the <I>actual sizes of the dimensions</I> of the array, and the <I>maximum sizes of the dimensions </I>of the array. For a fixed-dimension dataset, the actual size is the same as the maximum size of a dimension. When a dimension is unlimited, the maximum size is set to the value </FONT><FONT FACE="Courier">H5S_UNLIMITED</FONT><FONT FACE="Times">. (An example below shows how to create extendible datasets.)</P>
|
||||
<P>A dataspace can also describe portions of a dataset, making it possible to do partial I/O (hyperslab) operations.</P>
|
||||
<P>Since I/O operations have two end-points, the raw data transfer functions require two dataspace arguments: one describes the application memory dataspace or subset thereof, and the other describes the file dataspace or subset thereof.</P>
|
||||
<B><P>Storage layout.</B> The HDF5 format makes it possible to store data in a variety of ways. The default storage layout format is <I>contiguous</I>, meaning that data is stored in the same linear way that it is organized in memory. Two other storage layout formats are currently defined for HDF5: <I>compact, </I>and<I> chunked. </I>In the future, other storage layouts may be added.<I> </P>
|
||||
<P>Compact</I> storage is used when the amount of data is small and can be stored directly in the object header. <I>(Note: Compact storage is not supported in this prototype.)</I> </P>
|
||||
<I><P>Chunked</I> storage involves dividing the dataset into equal-sized "chunks" that are stored separately. Chunking has three important benefits. </P>
|
||||
<OL>
|
||||
|
||||
<LI>It makes it possible to achieve good performance when accessing subsets of the datasets, even when the subset to be chosen is orthogonal to the normal storage order of the dataset. </LI>
|
||||
<LI>It makes it possible to compress large datasets and still achieve good performance when accessing subsets of the dataset. </LI>
|
||||
<LI>It makes it possible efficiently to extend the dimensions of a dataset in any direction.</LI></OL>
|
||||
|
||||
</FONT><H3>HDF5 attribute lists</H3>
|
||||
<FONT FACE="Times"><P>An <I>attribute list</I> for an dataset or group is a listing of objects in the HDF file that are used as attributes, or metadata for the object. The attribute list is composed of two lists of objects, the first being simple attributes about the object, and the second being pointers to attribute objects. <I>(Note: Attributes are not supported in this prototype.)</P>
|
||||
</I><P> </P>
|
||||
</FONT><H2>The HDF5 Applications Programming Interface (API)</H2>
|
||||
<FONT FACE="Times"><P>The current HDF5 API is implemented only in C. The API provides routines for creating HDF5 files, creating and writing groups, datasets, and their attributes to HDF5 files, and reading groups, datasets and their attributes from HDF5 files.</P>
|
||||
</FONT><H3>Naming conventions</H3>
|
||||
<FONT FACE="Times"><P>All C routines on the HDF 5 library begin with a prefix of the form "H5*", where "*" is a single letter indicating the object on which the operation is to be performed:</P>
|
||||
|
||||
<UL>
|
||||
</FONT><B><LI>H5F</B>: <B>F</B>ile-level access routines. <BR>
|
||||
Example: <FONT FACE="Courier">H5Fopen</FONT>, which opens an HDF5 file. </LI>
|
||||
<B><LI>H5G</B>: <B>G</B>roup functions, for creating and operating on physical groups of objects. <BR>
|
||||
Example: <FONT FACE="Courier">H5Gset,</FONT>which sets the working group to the specified group. </LI>
|
||||
<B><LI>H5T: </B>Data<B>T</B>ype functions, for creating and operating on simple and compound datatypes to be used as the elements in data arrays.<B><BR>
|
||||
</B>Example: <FONT FACE="Courier">H5Tcopy,</FONT>which creates a copy of an existing data type. </LI>
|
||||
<B><LI>H5S: </B>DataS<B>P</B>ace functions, which create and manipulate the dataspace in which the elements of a data array are stored.<BR>
|
||||
Example: <FONT FACE="Courier">H5Sget_ndims</FONT>, which retrieves the number of dimensions of a data array. </LI>
|
||||
<B><LI>H5D: D</B>ataset functions, which manipulate the data within datasets and determine how the data is to be stored in the file. <BR>
|
||||
Example: H5D<FONT FACE="Courier">read</FONT>, which reads all or part of a dataset into a buffer in memory. </LI>
|
||||
<B><LI>H5P</B>: <B>T</B>emplate functions, for manipulating object templates. <BR>
|
||||
Example: <FONT FACE="Courier">H5Pset_chunk</FONT>, which sets the number of dimensions and the size of a chunk.</LI></UL>
|
||||
|
||||
<H3>Include files </H3>
|
||||
<FONT FACE="Times"><P>There are a number definitions and declarations that should be included with any HDF5 program. These definitions and declarations are contained in several "include" files. The main include file is <I>hdf5.h</I>. This file includes all of the other files that your program is likely to need. <I>Be sure to include hdf5.h in any program that accesses HDF5.</P>
|
||||
</I></FONT><H3>Predefined simple numeric scalar datatypes</H3>
|
||||
<FONT FACE="Times"><P>The HDF5 prototype currently supports simple signed and unsigned 8-bit, 16-bit, 32-bit , and 64-bit integers, and floating point numbers. The naming scheme for type definitions uses the following conventions:</P>
|
||||
|
||||
<UL>
|
||||
</FONT><LI>"int" stands for "integer" </LI>
|
||||
<LI>the prefix "u" stands for "unsigned" </LI>
|
||||
<LI>the integer suffix indicates the number of bits in the number</LI></UL>
|
||||
|
||||
<FONT FACE="Times"><P>For example, "uint16" indicates an unsigned 16-bit integer. Datatypes that are supported in this prototype are:</P>
|
||||
</FONT><PRE> char
|
||||
int8
|
||||
uint8
|
||||
int16
|
||||
uint16
|
||||
int32
|
||||
uint32
|
||||
int64
|
||||
uint64
|
||||
float32
|
||||
float64</PRE>
|
||||
<FONT FACE="Times"><P>These datatypes are defined in the file H5public.h together with keywords used to refer to them. H5public.h is included by the file hdf5.h described earlier. These datatypes should be used whenever you declare a variable to be used with an HDF5 routine. For instance, a 32-bit floating point variable should always be declared using a declaration such as</P>
|
||||
</FONT><CODE><PRE>float32 x;</PRE>
|
||||
</CODE><H3>Programming models</H3>
|
||||
<FONT FACE="Times"><P>In this section we describe how to program some basic operations on files, including how to</P>
|
||||
|
||||
<UL>
|
||||
</FONT><LI>create a file </LI>
|
||||
<LI>create and initialize a dataset </LI>
|
||||
<LI>discard objects when they are no longer needed </LI>
|
||||
<LI>write a dataset to a new file </LI>
|
||||
<LI>obtain information about a dataset </LI>
|
||||
<LI>read a portion of a dataset </LI>
|
||||
<LI>create and write compound datatypes </LI>
|
||||
<LI>create and write extendible datasets </LI>
|
||||
<LI>create and populate groups </LI></UL>
|
||||
|
||||
<H4>How to create an HDF5 file</H4>
|
||||
<FONT FACE="Times"><P>This programming model shows how to create a file and also how to close the file.</P>
|
||||
<OL>
|
||||
|
||||
<LI>Create the file using </FONT><FONT FACE="Courier">H5Fcreate.</FONT><FONT FACE="Times"> Obtain a file ID (e.g. </FONT><FONT FACE="Courier">file_id</FONT><FONT FACE="Times">).</LI>
|
||||
<LI>Close the file with </FONT><FONT FACE="Courier">H5Fclose(file_id)</FONT><FONT FACE="Times">.</LI>
|
||||
<P>The following code fragment implements the specified model. If there is a possibility that the file already exists, the user must add the flag </FONT><FONT FACE="Courier">H5F_ACC_TRUNC </FONT><FONT FACE="Times">to the access mode to overwrite the previous file's information. </P>
|
||||
</FONT><CODE><PRE>hid_t file; /* handle */
|
||||
/*
|
||||
* Create a new file using H5F_ACC_TRUNC access,
|
||||
* default file creation properties, and default file
|
||||
* access properties.
|
||||
* Then close the file.
|
||||
*/
|
||||
file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
|
||||
status = H5Fclose(file); </PRE>
|
||||
</CODE><H4>How to create and initialize the essential components of a dataset for writing to a file.</H4>
|
||||
<FONT FACE="Times"><P>Recall that datatypes and dimensionality (dataspace) are independent objects, which are created separately from any dataset that they might be attached to. Because of this the creation of a dataset requires, at a minimum, separate definitions of datatype, dimensionality, and dataset. Hence, to create a dataset the following steps need to be taken:</P>
|
||||
<LI VALUE=1>Create and initialize a dataspace for the dataset to be written.</LI>
|
||||
<LI>Define the datatype for the dataset to be written. </LI>
|
||||
<LI>Create and initialize the dataset itself.</LI></OL>
|
||||
|
||||
</FONT><FONT FACE="Courier New"><P> </P>
|
||||
</FONT><FONT FACE="Times"><P>The following code illustrates the creation of these three components of a dataset object.</P>
|
||||
</FONT><CODE><PRE>hid_t dataset, datatype, dataspace; /* declare handles */
|
||||
|
||||
/*
|
||||
* 1. Create dataspace: Describe the size of the array and
|
||||
* create the data space for fixed size dataset.
|
||||
*/
|
||||
dimsf[0] = NX;
|
||||
dimsf[1] = NY;
|
||||
dataspace = H5Screate_simple(RANK, dimsf, NULL);
|
||||
/*
|
||||
/*
|
||||
* 2. Define datatype for the data in the file.
|
||||
* We will store little endian INT32 numbers.
|
||||
*/
|
||||
datatype = H5Tcopy(H5T_NATIVE_INT32);
|
||||
status = H5Tset_order(datatype, H5T_ORDER_LE);
|
||||
/*
|
||||
* 3. Create a new dataset within the file using defined
|
||||
* dataspace and datatype and default dataset creation
|
||||
* properties.
|
||||
* NOTE: H5T_NATIVE_INT32 can be used as datatype if conversion
|
||||
* to little endian is not needed.
|
||||
*/
|
||||
dataset = H5Dcreate(file, DATASETNAME, datatype, dataspace, H5P_DEFAULT);</PRE><DIR>
|
||||
<DIR>
|
||||
|
||||
</CODE><H4>How to discard objects when they are no longer needed</H4></DIR>
|
||||
</DIR>
|
||||
|
||||
<FONT FACE="Times"><P>The type, dataspace and dataset objects should be released once they are no longer needed by a program. Since each is an independent object, the must be released ("closed") separately. The following lines of code close the type, dataspace, datasets, and file that were created in the preceding section.</P>
|
||||
</FONT><CODE><P>H5Tclose(datatype);</P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>H5Sclose(dataspace);</P><DIR>
|
||||
<DIR>
|
||||
|
||||
</CODE><H4>How to write a dataset to a new file</H4></DIR>
|
||||
</DIR>
|
||||
|
||||
<FONT FACE="Times"><P>Having defined the datatype, dataset, and dataspace parameters, you write out the data with a call to </FONT><FONT FACE="Courier">H5Dwrite.</P>
|
||||
</FONT><CODE><PRE>/*
|
||||
* Write the data to the dataset using default transfer
|
||||
* properties.
|
||||
*/
|
||||
status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
|
||||
H5P_DEFAULT, data);</PRE>
|
||||
</CODE><FONT FACE="Times"><P>The third and fourth parameters of </FONT><FONT FACE="Courier">H5Dwrite</FONT><FONT FACE="Times"> in the example describe the dataspaces in memory and in the file, respectively. They are set to the value </FONT><FONT FACE="Courier">H5S_ALL</FONT><FONT FACE="Times"> to indicate that an entire dataset is to be written. In a later section we look at how we would access a portion of a dataset.</P>
|
||||
</FONT><P><A HREF="#CreateExample"><FONT FACE="Times">Example 1</FONT></A><FONT FACE="Times"> contains a program that creates a file and a dataset, and writes the dataset to the file. </P>
|
||||
<P>Reading is analogous to writing. If, in the previous example, we wish to read an entire dataset, we would use the same basic calls with the same parameters. Of course, the routine </FONT><FONT FACE="Courier">H5Dread</FONT><FONT FACE="Times"> would replace </FONT><FONT FACE="Courier">H5Dwrite.</FONT><FONT FACE="Times"> </P><DIR>
|
||||
<DIR>
|
||||
|
||||
</FONT><H4>Getting information about a dataset</H4></DIR>
|
||||
</DIR>
|
||||
|
||||
<FONT FACE="Times"><P>Although reading is analogous to writing, it is often necessary to query a file to obtain information about a dataset. For instance, we often need to know about the datatype associated with a dataset, as well dataspace information (e.g. rank and dimensions). There are several "get" routines for obtaining this information The following code segment illustrates how we would get this kind of information: </P>
|
||||
</FONT><CODE><PRE>/*
|
||||
* Get datatype and dataspace handles and then query
|
||||
* dataset class, order, size, rank and dimensions.
|
||||
*/
|
||||
|
||||
datatype = H5Dget_type(dataset); /* datatype handle */
|
||||
class = H5Tget_class(datatype);
|
||||
if (class == H5T_INTEGER) printf("Data set has INTEGER type \n");
|
||||
order = H5Tget_order(datatype);
|
||||
if (order == H5T_ORDER_LE) printf("Little endian order \n");
|
||||
|
||||
size = H5Tget_size(datatype);
|
||||
printf(" Data size is %d \n", size);
|
||||
|
||||
dataspace = H5Dget_space(dataset); /* dataspace handle */
|
||||
rank = H5Sget_ndims(dataspace);
|
||||
status_n = H5Sget_dims(dataspace, dims_out, NULL);
|
||||
printf("rank %d, dimensions %d x %d \n", rank, dims_out[0], dims_out[1]);</PRE>
|
||||
</CODE><FONT FACE="Times"><P> </P><DIR>
|
||||
<DIR>
|
||||
|
||||
</FONT><H4>Reading a portion of a dataset: defining dataspaces</H4></DIR>
|
||||
</DIR>
|
||||
|
||||
<FONT FACE="Times"><P>In the previous discussion, we describe how to access an entire dataset with one write (or read) operation. To read or write a <I>portion</I> of a dataset, we need to provide more contextual information.</P>
|
||||
<P>Consider the following example. Suppose there is 500x600 dataset in a file, and we wish to read from the dataset a 100x200 hyperslab located beginning at element <200,200>. In addition, suppose we wish to read the hyperslab into an 200x400 array in memory beginning at element <0,0> in memory. Visually, the transfer looks something like this: </P>
|
||||
</FONT><FONT FACE="Times" SIZE=6><P> <IMG SRC="dataset_p1.gif" WIDTH=521 HEIGHT=420></P>
|
||||
</FONT><FONT FACE="Times"><P>As the example illustrates, whenever we read part of a dataset from a file we must provide two dataspaces: the dataspace of the object in the file as well as the dataspace of the object in memory into which we read. There are dataspace routines (</FONT><FONT FACE="Courier">H5S...</FONT><FONT FACE="Times">) for doing this. </P>
|
||||
<P>For example, suppose we want to read a 3x4 hyperslab from a dataset in a file beginning at the element <1,2> in the dataset. In order to do this, we must create a dataspace that describes the overall rank and dimensions of the dataset in the file, as well as the position and size of the hyperslab that we are extracting from that dataset. The following code illustrates how this would be done. </P>
|
||||
</FONT><CODE><PRE>/*
|
||||
* Get overall rank and dimensions of dataspace.
|
||||
*/
|
||||
dataspace = H5Dget_space(dataset); /* get dataspace handle */
|
||||
rank = H5Sget_ndims(dataspace);
|
||||
status_n = H5Sget_dims(dataspace, dims_out, NULL);
|
||||
|
||||
/*
|
||||
* Define hyperslab in the dataset.
|
||||
*/
|
||||
offset[0] = 1;
|
||||
offset[1] = 2;
|
||||
count[0] = 3;
|
||||
count[1] = 4;
|
||||
status = H5Sset_hyperslab(dataspace, offset, count, NULL);</PRE>
|
||||
</CODE><FONT FACE="Times"><P>This describes the dataspace from which we wish to read. We need to define the dataspace in memory analogously. Suppose, for instance, that we have in memory a 3 dimensional 7x7x3 array into which we wish to read the 3x4 hyperslab described above beginning at the element <3,0,0>. Since the in-memory dataspace has three dimensions, we have to describe the hyperslab as an array with three dimensions, with the last dimension being 1: <3,4,1>.</P>
|
||||
<P>Notice that now we must describe two things: the dimensions of the in-memory array, and the size and position of the hyperslab that we wish to read in. The following code illustrates how this would be done. </P>
|
||||
</FONT><CODE><PRE>/*
|
||||
* Define the memory dataspace.
|
||||
*/
|
||||
dimsm[0] = 7;
|
||||
dimsm[1] = 7;
|
||||
dimsm[2] = 3;
|
||||
memspace = H5Screate_simple(RANK_OUT,dimsm,NULL);
|
||||
|
||||
/*
|
||||
* Define memory hyperslab.
|
||||
*/
|
||||
offset_out[0] = 3;
|
||||
offset_out[1] = 0;
|
||||
offset_out[2] = 0;
|
||||
count_out[0] = 3;
|
||||
count_out[1] = 4;
|
||||
count_out[2] = 1;
|
||||
status = H5Sset_hyperslab(memspace, offset_out, count_out, NULL);
|
||||
|
||||
/*</PRE>
|
||||
</CODE><P><A HREF="#ReadExample"><FONT FACE="Times">Example 2</FONT></A><FONT FACE="Times"> contains a complete program that performs these operations.</P>
|
||||
</FONT><H4>Creating compound datatypes</H4>
|
||||
<P>Properties of compound datatypes.</B>A compound datatype is similar to a struct in C or a common block in Fortran. It is a collection of one or more atomic types or small arrays of such types. To create and use of a compound datatype requires you need to refer to various <I>properties</I> of the data compound datatype:</P>
|
||||
|
||||
<UL>
|
||||
<LI>It is of class <I>compound.</I> </LI>
|
||||
<LI>It has a fixed total <I>size</I>, in bytes. </LI>
|
||||
<LI>It consists of zero or more <I>members</I> (defined in any order) with unique names and which occupy non-overlapping regions within the datum. </LI>
|
||||
<LI>Each member has its own <I>datatype</I>. </LI>
|
||||
<LI>Each member is referenced by an <I>index number</I> between zero and N-1, where N is the number of members in the compound datatype. </LI>
|
||||
<LI>Each member has a <I>name</I> which is unique among its siblings in a compound data type. </LI>
|
||||
<LI>Each member has a fixed <I>byte offset</I>, which is the first byte (smallest byte address) of that member in a compound datatype. </LI>
|
||||
<LI>Each member can be a small array of up to four dimensions.</LI></UL>
|
||||
|
||||
<FONT FACE="Times"><P>Properties of members of a compound data type are defined when the member is added to the compound type and cannot be subsequently modified.</P>
|
||||
<B><P>Defining compound datatypes.</P> </B>
|
||||
<P>Compound datatypes must be built out of other datatypes. First, one creates an empty compound data type and specifies its total size. Then members are added to the compound data type in any order.</P>
|
||||
<I><P>Member names. </I>Each member must have a descriptive name, which is the key used to uniquely identify the member within the compound data type. A member name in an HDF5 data type does not necessarily have to be the same as the name of the corresponding member in the C struct in memory, although this is often the case. Nor does one need to define all members of the C struct in the HDF5 compound data type (or vice versa). </P>
|
||||
<I><P>Offsets. </I>Usually a C struct will be defined to hold a data point in memory, and the offsets of the members in memory will be the offsets of the struct members from the beginning of an instance of the struct. The library defines two macros to compute the offset of a member within a struct (The only difference between the two is that one uses </FONT><CODE>s.m</CODE><FONT FACE="Times"> as the struct member while the other uses </FONT><CODE>p->m</CODE><FONT FACE="Times" SIZE=2>)</FONT><FONT FACE="Times">: </P>
|
||||
</FONT><CODE><P>HOFFSET(s,m)<FONT SIZE=5>. </FONT></CODE><FONT FACE="Times">This macro computes the offset of member </FONT><FONT FACE="Courier"><EM>m</EM> </FONT><FONT FACE="Times">within a struct variable <EM>s</EM>. </P>
|
||||
</FONT><CODE><P>HPOFFSET(p,m)<FONT SIZE=5>. </FONT></CODE><FONT FACE="Times">This macro computes the offset of member </FONT><FONT FACE="Courier"><EM>m</FONT></EM><FONT FACE="Times"> from a pointer to a struct </FONT><FONT FACE="Courier"><EM>p</FONT></EM><FONT FACE="Times">. </P>
|
||||
<P>Here is an example in which a compound data type is created to describe complex numbers whose type is defined by the </FONT><CODE>complex_t</CODE><FONT FACE="Times" SIZE=2> </FONT><FONT FACE="Times">struct. </P>
|
||||
</FONT><CODE><PRE>typedef struct {
|
||||
double re; /*real part */
|
||||
double im; /*imaginary part */
|
||||
} complex_t;
|
||||
|
||||
complex_t tmp; /*used only to compute offsets */
|
||||
hid_t complex_id = H5Tcreate (H5T_COMPOUND, sizeof tmp);
|
||||
H5Tinsert (complex_id, "real", HOFFSET(tmp,re),
|
||||
H5T_NATIVE_DOUBLE);
|
||||
H5Tinsert (complex_id, "imaginary", HOFFSET(tmp,im),
|
||||
H5T_NATIVE_DOUBLE);</PRE>
|
||||
</CODE>
|
||||
<P> <A HREF="#CompoundExample"><FONT FACE="Times">Example 3</A> shows how to create a compound data type,
|
||||
write an array that has the compound data type to the file, and read back subsets of the members.</P>
|
||||
<P> </P>
|
||||
</FONT><H4>Creating and writing extendible datasets</H4>
|
||||
<P>An <I>extendible</I> dataset is one whose dimensions can grow. In HDF5, it is possible to define a dataset to have certain initial dimensions, then later to increase the size of any of the initial dimensions. </P>
|
||||
<P>For example, you can create and store the following 3x3 HDF5 dataset:</P>
|
||||
<CODE><PRE><P>1 1 1 </P>
|
||||
<P>1 1 1 </P>
|
||||
<P>1 1 1 </P>
|
||||
</PRE>
|
||||
</CODE>
|
||||
<FONT FACE="Times"><P>then later to extend this into a 10x3 dataset by adding 7 rows, such as this:</P>
|
||||
</FONT><CODE><PRE><P>1 1 1 </P>
|
||||
<P>1 1 1 </P>
|
||||
<P>1 1 1 </P>
|
||||
<P>2 2 2</P>
|
||||
<P>2 2 2</P>
|
||||
<P>2 2 2</P>
|
||||
<P>2 2 2</P>
|
||||
<P>2 2 2</P>
|
||||
<P>2 2 2</P>
|
||||
<P>2 2 2</P>
|
||||
</PRE>
|
||||
</CODE>
|
||||
</FONT><FONT FACE="Times"><P>then further extend it to a 10x5 dataset by adding two columns, such as this:</P>
|
||||
</FONT><CODE><PRE><P>1 1 1 3 3 </P>
|
||||
<P>1 1 1 3 3 </P>
|
||||
<P>1 1 1 3 3 </P>
|
||||
<P>2 2 2 3 3</P>
|
||||
<P>2 2 2 3 3</P>
|
||||
<P>2 2 2 3 3</P>
|
||||
<P>2 2 2 3 3</P>
|
||||
<P>2 2 2 3 3</P>
|
||||
<P>2 2 2 3 3</P>
|
||||
<P>2 2 2 3 3</P>
|
||||
</PRE>
|
||||
</CODE>
|
||||
</FONT><FONT FACE="Times"><P>The current version of HDF 5 requires you to use <I>chunking</I> in order to define extendible datasets. Chunking makes it possible to extend datasets efficiently, without having to reorganize storage excessively. </P>
|
||||
<P>Three operations are required in order to write an extendible dataset:</P>
|
||||
<OL>
|
||||
|
||||
<LI>Declare the dataspace of the dataset to have <I>unlimited dimensions</I> for all dimensions that might eventually be extended.</LI>
|
||||
<LI>When creating the dataset, set the storage layout for the dataset to <I>chunked</I>.</LI>
|
||||
<LI>Extend the size of the dataset.</LI></OL>
|
||||
|
||||
<P>For example, suppose we wish to create a dataset similar to the one shown above. We want to start with a 3x3 dataset, then later extend it in both directions. </P>
|
||||
<B><P>Declaring unlimited dimensions. </B>We could declare the dataspace to have unlimited dimensions with the following code, which uses the predefined constant H5S_UNLIMITED to specify unlimited dimensions.</P>
|
||||
</FONT><CODE><PRE><P>hsize_t dims[2] = { 3, 3}; /* dataset dimensions at the creation time */ </P>
|
||||
<P>hsize_t maxdims[2] = {H5S_UNLIMITED, H5S_UNLIMITED};
|
||||
</P>
|
||||
<P>/*</P>
|
||||
<P>* 1. Create the data space with unlimited dimensions. </P>
|
||||
<P>*/</P>
|
||||
<P>dataspace = H5Screate_simple(RANK, dims, maxdims); </P>
|
||||
</PRE>
|
||||
</CODE>
|
||||
<B><P>Enabling chunking. </B>We can then modify the dataset storage layout properties to
|
||||
enable chunking. We do this using the routine H5Pset_chunk:
|
||||
<CODE><PRE><P>hid_t cparms; </P>
|
||||
<P>hsize_t chunk_dims[2] ={2, 5};</P>
|
||||
<P>/* </P>
|
||||
<P>* 2. Modify dataset creation properties to enable chunking.</P>
|
||||
<P>*/</P>
|
||||
<P>cparms = H5Pcreate (H5P_DATASET_CREATE);</P>
|
||||
<P>status = H5Pset_chunk( cparms, RANK, chunk_dims);</CODE></PRE></P>
|
||||
<B>Extending dataset size. </B>Finally, when we want to extend the size of the dataset,
|
||||
we invoke H5Dextend to extend the size of the dataset. In the following example, we extend the dataset along the first dimension, by seven rows, so that the new dimensions are <10,3>.:
|
||||
<CODE><PRE><P>/*</P>
|
||||
<P>* Extend the dataset. Dataset becomes 10 x 3.</P>
|
||||
<P>*/</P>
|
||||
<P>dims[0] = dims[0] + 7;</P>
|
||||
<P>size[0] = dims[0]; </P>
|
||||
<P>size[1] = dims[1]; </P>
|
||||
<P>status = H5Dextend (dataset, size);</P>
|
||||
<P> </P>
|
||||
</CODE></PRE>
|
||||
<A HREF="#ExtendibleExample"><FONT FACE="Times">Example 4</A> shows how to create a 3x3 extendible dataset, to extend the dataset to 10x3, then to extend it again to 10x5.</P>
|
||||
</FONT><H3>Working with groups in a file</H3>
|
||||
<P>Groups provide a mechanism for organizing datasets in an HDF5 file extendable meaningful ways. The H5G API contains routines for working with groups. </P>
|
||||
<B>To create a group</B>, use H5Gcreate>. For example, the following code creates two groups that are members of the root group. They are called "/IntData" and "/FloatData." The return value ("dir") is the group ID.
|
||||
<CODE><PRE>/*<BR>
|
||||
* Create two groups in a file.
|
||||
*/
|
||||
dir = H5Gcreate(file, "/IntData", 0);
|
||||
status = H5Gclose(dir);
|
||||
dir = H5Gcreate(file,"/FloatData", 0);
|
||||
status = H5Gclose(dir);</CODE></PRE></P>
|
||||
</FONT><PRE>The third parameter in <CODE>H5Gcreate</CODE> optionally specifies how much file space to reserve to store the names that will appear in this group. If a non-positive value is supplied then a default size is chosen.
|
||||
<CODE>H5Gclose</CODE> closes the group and releases the group ID.<P>
|
||||
<B><P>Creating an object in a particular group. </B>Except for single-object HDF5 files, every object in an HDF5 file must belong to a group, and hence has a path name. Hence, we put an object in a particular group by giving its path name when we create it. For example, the following code creates a dataset "IntArray" in the group "/IntData":</P>
|
||||
</FONT><CODE><PRE>/*
|
||||
* Create dataset in the /IntData group by specifying full path.
|
||||
*/
|
||||
dims[0] = 2;
|
||||
dims[1] = 3;
|
||||
dataspace = H5Screate_simple(2, dims, NULL);
|
||||
dataset = H5Dcreate(file, "/IntData/IntArray", H5T_NATIVE_INT, dataspace, H5P_DEFAULT); </PRE>
|
||||
</CODE><B><P>Changing the current group. </B>The HDF5 Group API supports the idea of a "current," group. This is analogous to the "current working directory" idea in UNIX. You can set the current group in HDF5 with the routine H5Gset. The following code shows how to set a current group, then create a certain dataset ("FloatData") in that group. </P>
|
||||
</FONT><CODE><PRE>/*
|
||||
* Set current group to /FloatData.
|
||||
*/
|
||||
status = H5Gset (file, "/FloatData");
|
||||
|
||||
/*
|
||||
* Create two datasets
|
||||
*/
|
||||
|
||||
dims[0] = 5;
|
||||
dims[1] = 10;
|
||||
dataspace = H5Screate_simple(2, dims, NULL);
|
||||
dataset = H5Dcreate(file, "FloatArray", H5T_NATIVE_FLOAT, dataspace, H5P_DEFAULT); </PRE>
|
||||
</CODE>
|
||||
<A HREF="#GroupExample"><FONT FACE="Times">Example 5</A> shows how to create an HDF5 file with two group, and to place some datasets within those groups.</P>
|
||||
</FONT><H3>Example code</H3>
|
||||
<H4><A NAME="CreateExample">Example 1: How to create a homogeneous multi-dimensional dataset</A> and write it to a file.</H4>
|
||||
<P>This example creates a 2-dimensional HDF 5 dataset of little endian 32-bit integers.</P>
|
||||
<CODE><PRE><P><A NAME="CheckAndReadExample">/* </P>
|
||||
<P>* This example writes data to HDF5 file.</P>
|
||||
<P>* Data conversion is performed during write operation. </P>
|
||||
<P>*/</P>
|
||||
<P>#include "hdf5.h"</P>
|
||||
<P>#define FILE "SDS.h5"</P>
|
||||
<P>#define DATASETNAME "IntArray" </P>
|
||||
<P>#define NX 5 /* dataset dimensions */</P>
|
||||
<P>#define NY 6</P>
|
||||
<P>#define RANK 2</P>
|
||||
<P>main ()</P>
|
||||
<P>{</P>
|
||||
<P>hid_t file, dataset; /* file and dataset handles */</P>
|
||||
<P>hid_t datatype, dataspace; /* handles */</P>
|
||||
<P>hsize_t dimsf[2]; /* dataset dimensions */</P>
|
||||
<P>herr_t status; </P>
|
||||
<P>int32 data[NX][NY]; /* data to write */</P>
|
||||
<P>int i, j;</P>
|
||||
<P>/* </P>
|
||||
<P>* Data and output buffer initialization. </P>
|
||||
<P>*/</P>
|
||||
<P>for (j = 0; j < NX; j++) {</P>
|
||||
<P>for (i = 0; i < NY; i++)</P>
|
||||
<P>data[j][i] = i + j;</P>
|
||||
<P>} </P>
|
||||
<P>/* 0 1 2 3 4 5 </P>
|
||||
<P>1 2 3 4 5 6</P>
|
||||
<P>2 3 4 5 6 7</P>
|
||||
<P>3 4 5 6 7 8</P>
|
||||
<P>4 5 6 7 8 9 */</P>
|
||||
<P>/*</P>
|
||||
<P>* Create a new file using H5F_ACC_TRUNC access,</P>
|
||||
<P>* default file creation properties, and default file</P>
|
||||
<P>* access properties.</P>
|
||||
<P>*/</P>
|
||||
<P>file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);</P>
|
||||
<P>/*</P>
|
||||
<P>* Describe the size of the array and create the data space for fixed</P>
|
||||
<P>* size dataset. </P>
|
||||
<P>*/</P>
|
||||
<P>dimsf[0] = NX;</P>
|
||||
<P>dimsf[1] = NY;</P>
|
||||
<P>dataspace = H5Screate_simple(RANK, dimsf, NULL); </P>
|
||||
<P>/* </P>
|
||||
<P>* Define datatype for the data in the file.</P>
|
||||
<P>* We will store little endian INT32 numbers.</P>
|
||||
<P>*/</P>
|
||||
<P>datatype = H5Tcopy(H5T_NATIVE_INT32);</P>
|
||||
<P>status = H5Tset_order(datatype, H5T_ORDER_LE);</P>
|
||||
<P>/*</P>
|
||||
<P>* Create a new dataset within the file using defined dataspace and</P>
|
||||
<P>* datatype and default dataset creation properties.</P>
|
||||
<P>*/</P>
|
||||
<P>dataset = H5Dcreate(file, DATASETNAME, datatype, dataspace,</P>
|
||||
<P>H5P_DEFAULT);</P>
|
||||
<P>/*</P>
|
||||
<P>* Write the data to the dataset using default transfer properties.</P>
|
||||
<P>*/</P>
|
||||
<P>status = H5Dwrite(dataset, H5T_NATIVE_INT32, H5S_ALL, H5S_ALL,</P>
|
||||
<P>H5P_DEFAULT, data);</P>
|
||||
<P>/*</P>
|
||||
<P>* Close/release resources.</P>
|
||||
<P>*/</P>
|
||||
<P>H5Sclose(dataspace);</P>
|
||||
<P>H5Tclose(datatype);</P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>H5Fclose(file);</P>
|
||||
<P>} </P>
|
||||
<P> </P>
|
||||
</CODE></PRE>
|
||||
<H4><A NAME="ReadExample"> Example 2. How to read a hyperslab from file into memory.</A></H4>
|
||||
<P>This example reads a hyperslab from a 2-d HDF5 dataset into a 3-d dataset in memory.</P>
|
||||
<CODE><PRE><P>/* </P>
|
||||
<P>* This example reads hyperslab from the SDS.h5 file </P>
|
||||
<P>* created by h5_write.c program into two-dimensional</P>
|
||||
<P>* plane of the tree-dimensional array. </P>
|
||||
<P>* Information about dataset in the SDS.h5 file is obtained. </P>
|
||||
<P>*/</P>
|
||||
<P>#include "hdf5.h"</P>
|
||||
<P>#define FILE "SDS.h5"</P>
|
||||
<P>#define DATASETNAME "IntArray" </P>
|
||||
<P>#define NX_SUB 3 /* hyperslab dimensions */ </P>
|
||||
<P>#define NY_SUB 4 </P>
|
||||
<P>#define NX 7 /* output buffer dimensions */ </P>
|
||||
<P>#define NY 7 </P>
|
||||
<P>#define NZ 3 </P>
|
||||
<P>#define RANK 2</P>
|
||||
<P>#define RANK_OUT 3</P>
|
||||
<P>main ()</P>
|
||||
<P>{</P>
|
||||
<P>hid_t file, dataset; /* handles */</P>
|
||||
<P>hid_t datatype, dataspace; </P>
|
||||
<P>hid_t memspace; </P>
|
||||
<P>H5T_class_t class; /* data type class */</P>
|
||||
<P>H5T_order_t order; /* data order */</P>
|
||||
<P>size_t size; /* size of the data element</P>
|
||||
<P>stored in file */ </P>
|
||||
<P>hsize_t dimsm[3]; /* memory space dimensions */</P>
|
||||
<P>hsize_t dims_out[2]; /* dataset dimensions */ </P>
|
||||
<P>herr_t status; </P>
|
||||
<P>int data_out[NX][NY][NZ ]; /* output buffer */</P>
|
||||
<P>hsize_t count[2]; /* size of the hyperslab in the file */</P>
|
||||
<P>hssize_t offset[2]; /* hyperslab offset in the file */</P>
|
||||
<P>hsize_t count_out[3]; /* size of the hyperslab in memory */</P>
|
||||
<P>hssize_t offset_out[3]; /* hyperslab offset in memory */</P>
|
||||
<P>int i, j, k, status_n, rank;</P>
|
||||
<P>for (j = 0; j < NX; j++) {</P>
|
||||
<P>for (i = 0; i < NY; i++) {</P>
|
||||
<P>for (k = 0; k < NZ ; k++)</P>
|
||||
<P>data_out[j][i][k] = 0;</P>
|
||||
<P>}</P>
|
||||
<P>} </P>
|
||||
<P>/*</P>
|
||||
<P>* Open the file and the dataset.</P>
|
||||
<P>*/</P>
|
||||
<P>file = H5Fopen(FILE, H5F_ACC_RDONLY, H5P_DEFAULT);</P>
|
||||
<P>dataset = H5Dopen(file, DATASETNAME);</P>
|
||||
<P>/*</P>
|
||||
<P>* Get datatype and dataspace handles and then query</P>
|
||||
<P>* dataset class, order, size, rank and dimensions.</P>
|
||||
<P>*/</P>
|
||||
<P>datatype = H5Dget_type(dataset); /* datatype handle */ </P>
|
||||
<P>class = H5Tget_class(datatype);</P>
|
||||
<P>if (class == H5T_INTEGER) printf("Data set has INTEGER type \n");</P>
|
||||
<P>order = H5Tget_order(datatype);</P>
|
||||
<P>if (order == H5T_ORDER_LE) printf("Little endian order \n");</P>
|
||||
<P>size = H5Tget_size(datatype);</P>
|
||||
<P>printf(" Data size is %d \n", size);</P>
|
||||
<P>dataspace = H5Dget_space(dataset); /* dataspace handle */</P>
|
||||
<P>rank = H5Sget_ndims(dataspace);</P>
|
||||
<P>status_n = H5Sget_dims(dataspace, dims_out, NULL);</P>
|
||||
<P>printf("rank %d, dimensions %d x %d \n", rank, dims_out[0], dims_out[1]);</P>
|
||||
<P>/* </P>
|
||||
<P>* Define hyperslab in the dataset. </P>
|
||||
<P>*/</P>
|
||||
<P>offset[0] = 1;</P>
|
||||
<P>offset[1] = 2;</P>
|
||||
<P>count[0] = NX_SUB;</P>
|
||||
<P>count[1] = NY_SUB;</P>
|
||||
<P>status = H5Sset_hyperslab(dataspace, offset, count, NULL);</P>
|
||||
<P>/*</P>
|
||||
<P>* Define the memory dataspace.</P>
|
||||
<P>*/</P>
|
||||
<P>dimsm[0] = NX;</P>
|
||||
<P>dimsm[1] = NY;</P>
|
||||
<P>dimsm[2] = NZ ;</P>
|
||||
<P>memspace = H5Screate_simple(RANK_OUT,dimsm,NULL); </P>
|
||||
<P>/* </P>
|
||||
<P>* Define memory hyperslab. </P>
|
||||
<P>*/</P>
|
||||
<P>offset_out[0] = 3;</P>
|
||||
<P>offset_out[1] = 0;</P>
|
||||
<P>offset_out[2] = 0;</P>
|
||||
<P>count_out[0] = NX_SUB;</P>
|
||||
<P>count_out[1] = NY_SUB;</P>
|
||||
<P>count_out[2] = 1;</P>
|
||||
<P>status = H5Sset_hyperslab(memspace, offset_out, count_out, NULL);</P>
|
||||
<P>/*</P>
|
||||
<P>* Read data from hyperslab in the file into the hyperslab in </P>
|
||||
<P>* memory and display.</P>
|
||||
<P>*/</P>
|
||||
<P>status = H5Dread(dataset, H5T_NATIVE_INT, memspace, dataspace,</P>
|
||||
<P>H5P_DEFAULT, data_out);</P>
|
||||
<P>for (j = 0; j < NX; j++) {</P>
|
||||
<P>for (i = 0; i < NY; i++) printf("%d ", data_out[j][i][0]);</P>
|
||||
<P>printf("\n");</P>
|
||||
<P>}</P>
|
||||
<P>/* 0 0 0 0 0 0 0</P>
|
||||
<P>0 0 0 0 0 0 0</P>
|
||||
<P>0 0 0 0 0 0 0</P>
|
||||
<P>3 4 5 6 0 0 0 </P>
|
||||
<P>4 5 6 7 0 0 0</P>
|
||||
<P>5 6 7 8 0 0 0</P>
|
||||
<P>0 0 0 0 0 0 0 */</P>
|
||||
<P>/*</P>
|
||||
<P>* Close/release resources.</P>
|
||||
<P>*/</P>
|
||||
<P>H5Tclose(datatype);</P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>H5Sclose(dataspace);</P>
|
||||
<P>H5Sclose(memspace);</P>
|
||||
<P>H5Fclose(file);</P>
|
||||
<P>} </P>
|
||||
</CODE></PRE>
|
||||
<P> </P>
|
||||
<H4><A NAME="CompoundExample">Example 3. Working with compound datatypes.</A></H4>
|
||||
<P>This example shows how to create a compound data type, write an array which has the compound data type to the file, and read back subsets of fields.</P>
|
||||
<CODE><PRE><P>/*</P>
|
||||
<P>* This example shows how to create a compound data type,</P>
|
||||
<P>* write an array which has the compound data type to the file,</P>
|
||||
<P>* and read back fields' subsets.</P>
|
||||
<P>*/</P>
|
||||
<P>#include "hdf5.h"</P>
|
||||
<P>#define FILE "SDScompound.h5"</P>
|
||||
<P>#define DATASETNAME "ArrayOfStructures"</P>
|
||||
<P>#define LENGTH 10</P>
|
||||
<P>#define RANK 1</P>
|
||||
<P>main()</P>
|
||||
<P>{</P>
|
||||
<P>/* First structure and dataset*/</P>
|
||||
<P>typedef struct s1_t {</P>
|
||||
<P>int a;</P>
|
||||
<P>float b;</P>
|
||||
<P>double c; </P>
|
||||
<P>} s1_t;</P>
|
||||
<P>s1_t s1[LENGTH];</P>
|
||||
<P>hid_t s1_tid; /* File datatype handle */</P>
|
||||
<P>/* Second structure (subset of s1_t) and dataset*/</P>
|
||||
<P>typedef struct s2_t {</P>
|
||||
<P>double c;</P>
|
||||
<P>int a;</P>
|
||||
<P>} s2_t;</P>
|
||||
<P>s2_t s2[LENGTH];</P>
|
||||
<P>hid_t s2_tid; /* Memory datatype handle */</P>
|
||||
<P>/* Third "structure" ( will be used to read float field of s1) */</P>
|
||||
<P>hid_t s3_tid; /* Memory datatype handle */</P>
|
||||
<P>float s3[LENGTH];</P>
|
||||
<P>int i;</P>
|
||||
<P>hid_t file, datatype, dataset, space; /* Handles */</P>
|
||||
<P>herr_t status;</P>
|
||||
<P>hsize_t dim[] = {LENGTH}; /* Dataspace dimensions */</P>
|
||||
<P>H5T_class_t class;</P>
|
||||
<P>size_t size;</P>
|
||||
<P>/*</P>
|
||||
<P>* Initialize the data</P>
|
||||
<P>*/</P>
|
||||
<P>for (i = 0; i< LENGTH; i++) {</P>
|
||||
<P>s1[i].a = i;</P>
|
||||
<P>s1[i].b = i*i;</P>
|
||||
<P>s1[i].c = 1./(i+1);</P>
|
||||
<P>}</P>
|
||||
<P>/*</P>
|
||||
<P>* Create the data space.</P>
|
||||
<P>*/</P>
|
||||
<P>space = H5Screate_simple(RANK, dim, NULL);</P>
|
||||
<P>/*</P>
|
||||
<P>* Create the file.</P>
|
||||
<P>*/</P>
|
||||
<P>file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);</P>
|
||||
<P>/*</P>
|
||||
<P>* Create the memory data type. </P>
|
||||
<P>*/</P>
|
||||
<P>s1_tid = H5Tcreate (H5T_COMPOUND, sizeof(s1_t));</P>
|
||||
<P>status = H5Tinsert(s1_tid, "a_name", HPOFFSET(s1, a), H5T_NATIVE_INT);</P>
|
||||
<P>status = H5Tinsert(s1_tid, "c_name", HPOFFSET(s1, c), H5T_NATIVE_DOUBLE);</P>
|
||||
<P>status = H5Tinsert(s1_tid, "b_name", HPOFFSET(s1, b), H5T_NATIVE_FLOAT);</P>
|
||||
<P>/* </P>
|
||||
<P>* Create the dataset.</P>
|
||||
<P>*/</P>
|
||||
<P>dataset = H5Dcreate(file, DATASETNAME, s1_tid, space, H5P_DEFAULT);</P>
|
||||
<P>/*</P>
|
||||
<P>* Write data to the dataset; </P>
|
||||
<P>*/</P>
|
||||
<P>status = H5Dwrite(dataset, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, s1);</P>
|
||||
<P>/*</P>
|
||||
<P>* Release resources</P>
|
||||
<P>*/</P>
|
||||
<P>H5Tclose(s1_tid);</P>
|
||||
<P>H5Sclose(space);</P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>H5Fclose(file);</P>
|
||||
<P>/*</P>
|
||||
<P>* Open the file and the dataset.</P>
|
||||
<P>*/</P>
|
||||
<P>file = H5Fopen(FILE, H5F_ACC_RDONLY, H5P_DEFAULT);</P>
|
||||
<P>dataset = H5Dopen(file, DATASETNAME);</P>
|
||||
<P>/* </P>
|
||||
<P>* Create a data type for s2</P>
|
||||
<P>*/</P>
|
||||
<P>s2_tid = H5Tcreate(H5T_COMPOUND, sizeof(s2_t));</P>
|
||||
<P>status = H5Tinsert(s2_tid, "c_name", HPOFFSET(s2, c), H5T_NATIVE_DOUBLE);</P>
|
||||
<P>status = H5Tinsert(s2_tid, "a_name", HPOFFSET(s2, a), H5T_NATIVE_INT);</P>
|
||||
<P>/*</P>
|
||||
<P>* Read two fields c and a from s1 dataset. Fields in the file</P>
|
||||
<P>* are found by their names "c_name" and "a_name".</P>
|
||||
<P>*/</P>
|
||||
<P>status = H5Dread(dataset, s2_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, s2);</P>
|
||||
<P>/*</P>
|
||||
<P>* Display the fields</P>
|
||||
<P>*/</P>
|
||||
<P>printf("\n");</P>
|
||||
<P>printf("Field c : \n");</P>
|
||||
<P>for( i = 0; i < LENGTH; i++) printf("%.4f ", s2[i].c);</P>
|
||||
<P>printf("\n");</P>
|
||||
<P>printf("\n");</P>
|
||||
<P>printf("Field a : \n");</P>
|
||||
<P>for( i = 0; i < LENGTH; i++) printf("%d ", s2[i].a);</P>
|
||||
<P>printf("\n");</P>
|
||||
<P>/* </P>
|
||||
<P>* Create a data type for s3.</P>
|
||||
<P>*/</P>
|
||||
<P>s3_tid = H5Tcreate(H5T_COMPOUND, sizeof(float));</P>
|
||||
<P>status = H5Tinsert(s3_tid, "b_name", 0, H5T_NATIVE_FLOAT);</P>
|
||||
<P>/*</P>
|
||||
<P>* Read field b from s1 dataset. Field in the file is found by its name.</P>
|
||||
<P>*/</P>
|
||||
<P>status = H5Dread(dataset, s3_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, s3);</P>
|
||||
<P>/*</P>
|
||||
<P>* Display the field</P>
|
||||
<P>*/</P>
|
||||
<P>printf("\n");</P>
|
||||
<P>printf("Field b : \n");</P>
|
||||
<P>for( i = 0; i < LENGTH; i++) printf("%.4f ", s3[i]);</P>
|
||||
<P>printf("\n");</P>
|
||||
<P>/*</P>
|
||||
<P>* Release resources</P>
|
||||
<P>*/</P>
|
||||
<P>H5Tclose(s2_tid);</P>
|
||||
<P>H5Tclose(s3_tid);</P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>H5Sclose(space);</P>
|
||||
<P>H5Fclose(file);</P>
|
||||
<P>}</P>
|
||||
</CODE></PRE>
|
||||
<P> </P>
|
||||
<H4><A NAME="ExtendibleExample">Example 4. Creating and writing an extendible dataset.</A></H4>
|
||||
<P>This example shows how to create a 3x3 extendible dataset, to extend the dataset to 10x3, then to extend it again to 10x5.</P>
|
||||
<CODE><PRE><P>/* </P>
|
||||
<P>* This example shows how to work with extendible dataset.</P>
|
||||
<P>* In the current version of the library dataset MUST be</P>
|
||||
<P>* chunked.</P>
|
||||
<P>* </P>
|
||||
<P>*/</P>
|
||||
<P>#include "hdf5.h"</P>
|
||||
<P>#define FILE "SDSextendible.h5"</P>
|
||||
<P>#define DATASETNAME "ExtendibleArray" </P>
|
||||
<P>#define RANK 2</P>
|
||||
<P>#define NX 10</P>
|
||||
<P>#define NY 5 </P>
|
||||
<P>main ()</P>
|
||||
<P>{</P>
|
||||
<P>hid_t file; /* handles */</P>
|
||||
<P>hid_t datatype, dataspace, dataset; </P>
|
||||
<P>hid_t filespace; </P>
|
||||
<P>hid_t cparms; </P>
|
||||
<P>hsize_t dims[2] = { 3, 3}; /* dataset dimensions</P>
|
||||
<P>at the creation time */ </P>
|
||||
<P>hsize_t dims1[2] = { 3, 3}; /* data1 dimensions */ </P>
|
||||
<P>hsize_t dims2[2] = { 7, 1}; /* data2 dimensions */ </P>
|
||||
<P>hsize_t dims3[2] = { 2, 2}; /* data3 dimensions */ </P>
|
||||
<P>hsize_t maxdims[2] = {H5S_UNLIMITED, H5S_UNLIMITED};</P>
|
||||
<P>hsize_t chunk_dims[2] ={2, 5};</P>
|
||||
<P>hsize_t size[2];</P>
|
||||
<P>hssize_t offset[2];</P>
|
||||
<P>herr_t status; </P>
|
||||
<P>int data1[3][3] = { 1, 1, 1, /* data to write */</P>
|
||||
<P>1, 1, 1,</P>
|
||||
<P>1, 1, 1 }; </P>
|
||||
<P>int data2[7] = { 2, 2, 2, 2, 2, 2, 2};</P>
|
||||
<P>int data3[2][2] = { 3, 3,</P>
|
||||
<P>3, 3};</P>
|
||||
<P>/*</P>
|
||||
<P>* Create the data space with unlimited dimensions. </P>
|
||||
<P>*/</P>
|
||||
<P>dataspace = H5Screate_simple(RANK, dims, maxdims); </P>
|
||||
<P>/*</P>
|
||||
<P>* Create a new file. If file exists its contents will be overwritten.</P>
|
||||
<P>*/</P>
|
||||
<P>file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);</P>
|
||||
<P>/* </P>
|
||||
<P>* Modify dataset creation properties, i.e. enable chunking.</P>
|
||||
<P>*/</P>
|
||||
<P>cparms = H5Pcreate (H5P_DATASET_CREATE);</P>
|
||||
<P>status = H5Pset_chunk( cparms, RANK, chunk_dims);</P>
|
||||
<P>/*</P>
|
||||
<P>* Create a new dataset within the file using cparms</P>
|
||||
<P>* creation properties.</P>
|
||||
<P>*/</P>
|
||||
<P>dataset = H5Dcreate(file, DATASETNAME, H5T_NATIVE_INT, dataspace,</P>
|
||||
<P>cparms);</P>
|
||||
<P>/*</P>
|
||||
<P>* Extend the dataset. This call assures that dataset is at least 3 x 3.</P>
|
||||
<P>*/</P>
|
||||
<P>size[0] = 3; </P>
|
||||
<P>size[1] = 3; </P>
|
||||
<P>status = H5Dextend (dataset, size);</P>
|
||||
<P>/*</P>
|
||||
<P>* Select a hyperslab.</P>
|
||||
<P>*/</P>
|
||||
<P>filespace = H5Dget_space (dataset);</P>
|
||||
<P>offset[0] = 0;</P>
|
||||
<P>offset[1] = 0;</P>
|
||||
<P>status = H5Sset_hyperslab(filespace, offset, dims1, NULL); </P>
|
||||
<P>/*</P>
|
||||
<P>* Write the data to the hyperslab.</P>
|
||||
<P>*/</P>
|
||||
<P>status = H5Dwrite(dataset, H5T_NATIVE_INT, dataspace, filespace,</P>
|
||||
<P>H5P_DEFAULT, data1);</P>
|
||||
<P>/*</P>
|
||||
<P>* Extend the dataset. Dataset becomes 10 x 3.</P>
|
||||
<P>*/</P>
|
||||
<P>dims[0] = dims1[0] + dims2[0];</P>
|
||||
<P>size[0] = dims[0]; </P>
|
||||
<P>size[1] = dims[1]; </P>
|
||||
<P>status = H5Dextend (dataset, size);</P>
|
||||
<P>/*</P>
|
||||
<P>* Select a hyperslab.</P>
|
||||
<P>*/</P>
|
||||
<P>filespace = H5Dget_space (dataset);</P>
|
||||
<P>offset[0] = 3;</P>
|
||||
<P>offset[1] = 0;</P>
|
||||
<P>status = H5Sset_hyperslab(filespace, offset, dims2, NULL); </P>
|
||||
<P>/*</P>
|
||||
<P>* Define memory space</P>
|
||||
<P>*/</P>
|
||||
<P>dataspace = H5Screate_simple(RANK, dims2, NULL); </P>
|
||||
<P>/*</P>
|
||||
<P>* Write the data to the hyperslab.</P>
|
||||
<P>*/</P>
|
||||
<P>status = H5Dwrite(dataset, H5T_NATIVE_INT, dataspace, filespace,</P>
|
||||
<P>H5P_DEFAULT, data2);</P>
|
||||
<P>/*</P>
|
||||
<P>* Extend the dataset. Dataset becomes 10 x 5.</P>
|
||||
<P>*/</P>
|
||||
<P>dims[1] = dims1[1] + dims3[1];</P>
|
||||
<P>size[0] = dims[0]; </P>
|
||||
<P>size[1] = dims[1]; </P>
|
||||
<P>status = H5Dextend (dataset, size);</P>
|
||||
<P>/*</P>
|
||||
<P>* Select a hyperslab</P>
|
||||
<P>*/</P>
|
||||
<P>filespace = H5Dget_space (dataset);</P>
|
||||
<P>offset[0] = 0;</P>
|
||||
<P>offset[1] = 3;</P>
|
||||
<P>status = H5Sset_hyperslab(filespace, offset, dims3, NULL); </P>
|
||||
<P>/*</P>
|
||||
<P>* Define memory space.</P>
|
||||
<P>*/</P>
|
||||
<P>dataspace = H5Screate_simple(RANK, dims3, NULL); </P>
|
||||
<P>/*</P>
|
||||
<P>* Write the data to the hyperslab.</P>
|
||||
<P>*/</P>
|
||||
<P>status = H5Dwrite(dataset, H5T_NATIVE_INT, dataspace, filespace,</P>
|
||||
<P>H5P_DEFAULT, data3);</P>
|
||||
<P>/*</P>
|
||||
<P>* Resulting dataset</P>
|
||||
<P>* </P>
|
||||
<P>3 3 3 2 2</P>
|
||||
<P>3 3 3 2 2</P>
|
||||
<P>3 3 3 0 0</P>
|
||||
<P>2 0 0 0 0</P>
|
||||
<P>2 0 0 0 0</P>
|
||||
<P>2 0 0 0 0</P>
|
||||
<P>2 0 0 0 0</P>
|
||||
<P>2 0 0 0 0</P>
|
||||
<P>2 0 0 0 0</P>
|
||||
<P>2 0 0 0 0</P>
|
||||
<P>*/ </P>
|
||||
<P>/*</P>
|
||||
<P>* Close/release resources.</P>
|
||||
<P>*/</P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>H5Sclose(dataspace);</P>
|
||||
<P>H5Sclose(filespace);</P>
|
||||
<P>H5Fclose(file);</P>
|
||||
<P>} </P>
|
||||
</CODE></PRE>
|
||||
<P> </P>
|
||||
<H4><A NAME="GroupExample">Example 5. Creating groups.</A></H4>
|
||||
<P>This example shows how to create an HDF5 file with two groups, and to place some datasets within those groups.</P>
|
||||
<CODE><PRE><P>/*</P>
|
||||
<P>* This example shows how to create groups within the file and </P>
|
||||
<P>* datasets within the file and groups.</P>
|
||||
<P>*/ </P>
|
||||
<P> </P>
|
||||
<P>#include "hdf5.h"</P>
|
||||
<P> </P>
|
||||
<P>#define FILE "DIR.h5"</P>
|
||||
<P>#define RANK 2</P>
|
||||
<P>main()</P>
|
||||
<P>{</P>
|
||||
<P>hid_t file, dir;</P>
|
||||
<P>hid_t dataset, dataspace;</P>
|
||||
<P>herr_t status;</P>
|
||||
<P>hsize_t dims[2];</P>
|
||||
<P>hsize_t size[1];</P>
|
||||
<P>/*</P>
|
||||
<P>* Create a file.</P>
|
||||
<P>*/</P>
|
||||
<P>file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);</P>
|
||||
<P>/*</P>
|
||||
<P>* Create two groups in a file.</P>
|
||||
<P>*/</P>
|
||||
<P>dir = H5Gcreate(file, "/IntData", 0);</P>
|
||||
<P>status = H5Gclose(dir);</P>
|
||||
<P>dir = H5Gcreate(file,"/FloatData", 0);</P>
|
||||
<P>status = H5Gclose(dir);</P>
|
||||
<P>/* </P>
|
||||
<P>* Create dataspace for the character string</P>
|
||||
<P>*/</P>
|
||||
<P>size[0] = 80;</P>
|
||||
<P>dataspace = H5Screate_simple(1, size, NULL);</P>
|
||||
<P>/*</P>
|
||||
<P>* Create dataset "String" in the root group. </P>
|
||||
<P>*/</P>
|
||||
<P>dataset = H5Dcreate(file, "String", H5T_NATIVE_CHAR, dataspace, H5P_DEFAULT);</P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>/*</P>
|
||||
<P>* Create dataset "String" in the /IntData group. </P>
|
||||
<P>*/</P>
|
||||
<P>dataset = H5Dcreate(file, "/IntData/String", H5T_NATIVE_CHAR, dataspace,</P>
|
||||
<P>H5P_DEFAULT);</P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>/*</P>
|
||||
<P>* Create dataset "String" in the /FloatData group. </P>
|
||||
<P>*/</P>
|
||||
<P>dataset = H5Dcreate(file, "/FloatData/String", H5T_NATIVE_CHAR, dataspace,</P>
|
||||
<P>H5P_DEFAULT);</P>
|
||||
<P>H5Sclose(dataspace);</P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>/*</P>
|
||||
<P>* Create IntArray dataset in the /IntData group by specifying full path.</P>
|
||||
<P>*/</P>
|
||||
<P>dims[0] = 2;</P>
|
||||
<P>dims[1] = 3;</P>
|
||||
<P>dataspace = H5Screate_simple(RANK, dims, NULL);</P>
|
||||
<P>dataset = H5Dcreate(file, "/IntData/IntArray", H5T_NATIVE_INT, dataspace,</P>
|
||||
<P>H5P_DEFAULT); </P>
|
||||
<P>H5Sclose(dataspace);</P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>/*</P>
|
||||
<P>* Set current group to /IntData and attach to the dataset String.</P>
|
||||
<P>*/</P>
|
||||
<P>status = H5Gset (file, "/IntData");</P>
|
||||
<P>dataset = H5Dopen(file, "String");</P>
|
||||
<P>if (dataset > 0) printf("String dataset in /IntData group is found\n"); </P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>/*</P>
|
||||
<P>* Set current group to /FloatData.</P>
|
||||
<P>*/</P>
|
||||
<P>status = H5Gset (file, "/FloatData");</P>
|
||||
<P>/* </P>
|
||||
<P>* Create two datasets FlatArray and DoubleArray.</P>
|
||||
<P>*/</P>
|
||||
<P>dims[0] = 5;</P>
|
||||
<P>dims[1] = 10;</P>
|
||||
<P>dataspace = H5Screate_simple(RANK, dims, NULL);</P>
|
||||
<P>dataset = H5Dcreate(file, "FloatArray", H5T_NATIVE_FLOAT, dataspace, H5P_DEFAULT); </P>
|
||||
<P>H5Sclose(dataspace);</P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>dims[0] = 4;</P>
|
||||
<P>dims[1] = 6;</P>
|
||||
<P>dataspace = H5Screate_simple(RANK, dims, NULL);</P>
|
||||
<P>dataset = H5Dcreate(file, "DoubleArray", H5T_NATIVE_DOUBLE, dataspace,</P>
|
||||
<P>H5P_DEFAULT); </P>
|
||||
<P>H5Sclose(dataspace);</P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>/* </P>
|
||||
<P>* Attach to /FloatData/String dataset.</P>
|
||||
<P>*/</P>
|
||||
<P>dataset = H5Dopen(file, "/FloatData/String");</P>
|
||||
<P>if (dataset > 0) printf("/FloatData/String dataset is found\n"); </P>
|
||||
<P>H5Dclose(dataset);</P>
|
||||
<P>H5Fclose(file);</P>
|
||||
<P>}</P></CODE></PRE></BODY>
|
||||
|
||||
</HTML>
|
123
doc/html/H5.sample_code.html
Normal file
@ -0,0 +1,123 @@
|
||||
<html><head><title>
|
||||
HDF5 Draft API Example Code
|
||||
</title></head><body>
|
||||
|
||||
<center>
|
||||
<h1>HDF5: API Example Code</h1>
|
||||
</center>
|
||||
|
||||
<P>Example programs/sections of code below:
|
||||
<dl COMPACT>
|
||||
<dt><a href="#Example1">#1</a>
|
||||
<dd>A simple example showing how to create a file.
|
||||
<dt><a href="#Example2">#2</a>
|
||||
<dd>A example showing how to create a homogenous multi-dimensional dataset.
|
||||
<dt><a href="#Example3">#3</a>
|
||||
<dd>A example showing how to read a generic dataset.
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example1">Simple Example showing how to create a file.</a></h2>
|
||||
|
||||
<P>Notes:<br>
|
||||
This example creates a new HDF5 file and allows write access.
|
||||
If the file exists already, the H5F_ACC_TRUNC flag would also be necessary to
|
||||
overwrite the previous file's information.
|
||||
|
||||
<P>Code:
|
||||
|
||||
<code> <pre>
|
||||
hid_t file_id;
|
||||
|
||||
file_id=<A HREF="H5.apiv2.html#File-Create">H5Fcreate</a>("example1.h5",H5F_ACC_EXCL,H5P_DEFAULT_TEMPLATE,H5P_DEFAULT_TEMPLATE);
|
||||
|
||||
<A HREF="H5.apiv2.html#File-Close">H5Fclose</a>(file_id);
|
||||
|
||||
</pre> </code>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example2">Example showing how create a homogenous multi-dimensional dataset.</a></h2>
|
||||
|
||||
<P>Notes:<br>
|
||||
This example creates a 4-dimensional dataset of 32-bit floating-point
|
||||
numbers, corresponding to the current Scientific Dataset functionality.
|
||||
|
||||
<P>Code:
|
||||
|
||||
<code> <pre>
|
||||
1 hid_t file_id; /* new file's ID */
|
||||
2 hid_t dim_id; /* new dimensionality's ID */
|
||||
3 int rank=4; /* the number of dimensions */
|
||||
4 hsize_t dims[4]={6,5,4,3}; /* the size of each dimension */
|
||||
5 hid_t dataset_id; /* new dataset's ID */
|
||||
6 float buf[6][5][4][3]; /* storage for the dataset's data */
|
||||
7 herr_t status; /* function return status */
|
||||
8
|
||||
9 file_id = H5Fcreate ("example3.h5", H5F_ACC_TRUNC, H5P_DEFAULT,
|
||||
10 H5P_DEFAULT);
|
||||
11 assert (file_id >= 0);
|
||||
12
|
||||
13 /* Create & initialize a dimensionality object */
|
||||
14 dim_id = H5Screate_simple (rank, dims);
|
||||
15 assert (dim_id >= 0);
|
||||
16
|
||||
17 /* Create & initialize the dataset object */
|
||||
18 dataset_id = H5Dcreate (file_id, "Simple Object", H5T_NATIVE_FLOAT,
|
||||
19 dim_id, H5P_DEFAULT);
|
||||
20 assert (dataset_id >= 0);
|
||||
21
|
||||
22 <initialize data array>
|
||||
23
|
||||
24 /* Write the entire dataset out */
|
||||
25 status = H5Dwrite (dataset_id, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL,
|
||||
26 H5P_DEFAULT, buf);
|
||||
27 assert (status >= 0);
|
||||
28
|
||||
29 /* Release the IDs we've created */
|
||||
30 H5Sclose (dim_id);
|
||||
31 H5Dclose (dataset_id);
|
||||
32 H5Fclose (file_id);
|
||||
</pre> </code>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example3">Example showing how read a generic dataset.</a></h2>
|
||||
|
||||
<P>Notes:<br>
|
||||
This example shows how to get the information for and display a generic
|
||||
dataset.
|
||||
|
||||
<P>Code:
|
||||
|
||||
<code> <pre>
|
||||
1 hid_t file_id; /* file's ID */
|
||||
2 hid_t dataset_id; /* dataset's ID in memory */
|
||||
3 hid_t space_id; /* dataspace's ID in memory */
|
||||
4 uintn nelems; /* number of elements in array */
|
||||
5 double *buf; /* pointer to the dataset's data */
|
||||
6 herr_t status; /* function return value */
|
||||
7
|
||||
8 file_id = H5Fopen ("example6.h5", H5F_ACC_RDONLY, H5P_DEFAULT);
|
||||
9 assert (file_id >= 0);
|
||||
10
|
||||
11 /* Attach to a datatype object */
|
||||
12 dataset_id = H5Dopen (file_id, "dataset1");
|
||||
13 assert (dataset_id >= 0);
|
||||
14
|
||||
15 /* Get the OID for the dataspace */
|
||||
16 space_id = H5Dget_space (dataset_id);
|
||||
17 assert (space_id >= 0);
|
||||
18
|
||||
19 /* Allocate space for the data */
|
||||
20 nelems = H5Sget_npoints (space_id);
|
||||
21 buf = malloc (nelems * sizeof(double));
|
||||
22
|
||||
23 /* Read in the dataset */
|
||||
24 status = H5Dread (dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL,, H5S_ALL,
|
||||
25 H5P_DEFAULT, buf);
|
||||
26 assert (status >= 0);
|
||||
27
|
||||
28 /* Release the IDs we've accessed */
|
||||
29 H5Sclose (space_id);
|
||||
30 H5Dclose (dataset_id);
|
||||
31 H5Fclose (file_id);
|
||||
</pre> </code>
|
71
doc/html/H5.user.html
Normal file
@ -0,0 +1,71 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
HDF5 Uer's Guide
|
||||
</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<center><h1>A User Guide for HDF5</h1></center>
|
||||
|
||||
<p>The following documents form a loosely organized user's guide
|
||||
to the HDF5 library.
|
||||
|
||||
<ul>
|
||||
<li><a href="Files.html">HDF5 Files</a> -
|
||||
A guide to the H5F interface.
|
||||
<li><a href="Datasets.html">Datasets</a> -
|
||||
A guide to the H5D interface.
|
||||
<li><a href="Datatypes.html">Data types</a> -
|
||||
A guide to the H5T interface.
|
||||
<li><a href="Dataspaces.html">Data spaces</a> -
|
||||
A guide to the H5S interface.
|
||||
<li><a href="Groups.html">Groups</a> -
|
||||
A guide to the H5G interface.
|
||||
<li><a href="Attributes.html">Attributes</a> -
|
||||
A guide to the H5A interface.
|
||||
<li><a href="Properties.html">Property lists</a> -
|
||||
A guide to the H5P interface.
|
||||
<li><a href="Errors.html">Error handling</a> -
|
||||
A guide to the H5E interface.
|
||||
<li><a href="Caching.html">Caching</a> -
|
||||
A guide for meta and raw data caching.
|
||||
</ul>
|
||||
|
||||
<p>The following documents form a loosely organized developer's guide to
|
||||
aspects of the HDF5 library. (Some of the following documents
|
||||
may be rather out of date as they were working papers for design
|
||||
goals.)
|
||||
|
||||
<ul>
|
||||
<li><a href="Version.html">Version Numbers</a> -
|
||||
A description of HDF5 version numbers.
|
||||
<li><a href="IOPipe.html">I/O Pipeline</a> -
|
||||
A description of the raw data I/O pipeline.
|
||||
<li><a href="Compression.html">Compression</a> -
|
||||
A guide to the use of compression for datasets.
|
||||
<li><a href="ExternalFiles.html">Working with external files</a> -
|
||||
A guide to the use of multiple files with HDF5.
|
||||
<li><a href="Big.html">Large Datasets</a> -
|
||||
A guide to accessing large datasets on small computers.
|
||||
<li><a href="MemoryManagement.html">Memory management</a> -
|
||||
A white paper about memory management issues in HDF5.
|
||||
<li><a href="Coding.html">Coding style</a> -
|
||||
A white paper about coding style in the HDF5 library code.
|
||||
<li><a href="compat.html">HDF4/HDF5 compatibility</a> -
|
||||
A white paper about compatibility issues between HDF4 and HDF5.
|
||||
<li><a href="study.html">Chunking performance study</a> -
|
||||
A white paper describing the HDF5 chunking performance.
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:koziol@ncsa.uiuc.edu">Quincey Koziol</a></address>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- hhmts start -->
|
||||
Last modified: Tue May 26 15:39:47 EDT 1998
|
||||
<!-- hhmts end -->
|
||||
|
||||
</body>
|
||||
</html>
|
114
doc/html/IOPipe.html
Normal file
@ -0,0 +1,114 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>The Raw Data I/O Pipeline</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>The Raw Data I/O Pipeline</h1>
|
||||
|
||||
<p>The HDF5 raw data pipeline is a complicated beast that handles
|
||||
all aspects of raw data storage and transfer of that data
|
||||
between the file and the application. Data can be stored
|
||||
contiguously (internal or external), in variable size external
|
||||
segments, or regularly chunked; it can be sparse, extendible,
|
||||
and/or compressible. Data transfers must be able to convert from
|
||||
one data space to another, convert from one number type to
|
||||
another, and perform partial I/O operations. Furthermore,
|
||||
applications will expect their common usage of the pipeline to
|
||||
perform well.
|
||||
|
||||
<p>To accomplish these goals, the pipeline has been designed in a
|
||||
modular way so no single subroutine is overly complicated and so
|
||||
functionality can be inserted easily at the appropriate
|
||||
locations in the pipeline. A general pipeline was developed and
|
||||
then certain paths through the pipeline were optimized for
|
||||
performance.
|
||||
|
||||
<p>We describe only the file-to-memory side of the pipeline since
|
||||
the memory-to-file side is a mirror image. We also assume that a
|
||||
proper hyperslab of a simple data space is being read from the
|
||||
file into a proper hyperslab of a simple data space in memory,
|
||||
and that the data type is a compound type which may require
|
||||
various number conversions on its members.
|
||||
|
||||
<img alt="Figure 1" src="pipe1.gif">
|
||||
|
||||
<p>The diagrams should be read from the top down. The Line A
|
||||
in the figure above shows that <code>H5Dread()</code> copies
|
||||
data from a hyperslab of a file dataset to a hyperslab of an
|
||||
application buffer by calling <code>H5D_read()</code>. And
|
||||
<code>H5D_read()</code> calls, in a loop,
|
||||
<code>H5S_simp_fgath()</code>, <code>H5T_conv_struct()</code>,
|
||||
and <code>H5S_simp_mscat()</code>. A temporary buffer, TCONV, is
|
||||
loaded with data points from the file, then data type conversion
|
||||
is performed on the temporary buffer, and finally data points
|
||||
are scattered out to application memory. Thus, data type
|
||||
conversion is an in-place operation and data space conversion
|
||||
consists of two steps. An additional temporary buffer, BKG, is
|
||||
large enough to hold <em>N</em> instances of the destination
|
||||
data type where <em>N</em> is the same number of data points
|
||||
that can be held by the TCONV buffer (which is large enough to
|
||||
hold either source or destination data points).
|
||||
|
||||
<p>The application sets an upper limit for the size of the TCONV
|
||||
buffer and optionally supplies a buffer. If no buffer is
|
||||
supplied then one will be created by calling
|
||||
<code>malloc()</code> when the pipeline is executed (when
|
||||
necessary) and freed when the pipeline exits. The size of the
|
||||
BKG buffer depends on the size of the TCONV buffer and if the
|
||||
application supplies a BKG buffer it should be at least as large
|
||||
as the TCONV buffer. The default size for these buffers is one
|
||||
megabyte but the buffer might not be used to full capacity if
|
||||
the buffer size is not an integer multiple of the source or
|
||||
destination data point size (whichever is larger, but only
|
||||
destination for the BKG buffer).
|
||||
|
||||
|
||||
|
||||
<p>Occassionally the destination data points will be partially
|
||||
initialized and the <code>H5Dread()</code> operation should not
|
||||
clobber those values. For instance, the destination type might
|
||||
be a struct with members <code>a</code> and <code>b</code> where
|
||||
<code>a</code> is already initialized and we're reading
|
||||
<code>b</code> from the file. An extra line, G, is added to the
|
||||
pipeline to provide the type conversion functions with the
|
||||
existing data.
|
||||
|
||||
<img alt="Figure 2" src="pipe2.gif">
|
||||
|
||||
<p>It will most likely be quite common that no data type
|
||||
conversion is necessary. In such cases a temporary buffer for
|
||||
data type conversion is not needed and data space conversion
|
||||
can happen in a single step. In fact, when the source and
|
||||
destination data are both contiguous (they aren't in the
|
||||
picture) the loop degenerates to a single iteration.
|
||||
|
||||
|
||||
<img alt="Figure 3" src="pipe3.gif">
|
||||
|
||||
<p>So far we've looked only at internal contiguous storage, but by
|
||||
replacing Line B in Figures 1 and 2 and Line A in Figure 3 with
|
||||
Figure 4 the pipeline is able to handle regularly chunked
|
||||
objects. Line B of Figure 4 is executed once for each chunk
|
||||
which contains data to be read and the chunk address is found by
|
||||
looking at a multi-dimensional key in a chunk B-tree which has
|
||||
one entry per chunk.
|
||||
|
||||
<img alt="Figure 4" src="pipe4.gif">
|
||||
|
||||
<p>If a single chunk is requested and the destination buffer is
|
||||
the same size/shape as the chunk, then the CHUNK buffer is
|
||||
bypassed and the destination buffer is used instead as shown in
|
||||
Figure 5.
|
||||
|
||||
<img alt="Figure 5" src="pipe5.gif">
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Tue Mar 17 11:13:35 EST 1998 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Wed Mar 18 10:38:30 EST 1998
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
510
doc/html/MemoryManagement.html
Normal file
@ -0,0 +1,510 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Memory Management in HDF5</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Memory Management in HDF5</h1>
|
||||
|
||||
<!-- ---------------------------------------------------------------- -->
|
||||
<h2>Is a Memory Manager Necessary?</h2>
|
||||
|
||||
<p>Some form of memory management may be necessary in HDF5 when
|
||||
the various deletion operators are implemented so that the
|
||||
file memory is not permanently orphaned. However, since an
|
||||
HDF5 file was designed with persistent data in mind, the
|
||||
importance of a memory manager is questionable.
|
||||
|
||||
<p>On the other hand, when certain meta data containers (file glue)
|
||||
grow, they may need to be relocated in order to keep the
|
||||
container contiguous.
|
||||
|
||||
<blockquote>
|
||||
<b>Example:</b> An object header consists of up to two
|
||||
chunks of contiguous memory. The first chunk is a fixed
|
||||
size at a fixed location when the header link count is
|
||||
greater than one. Thus, inserting additional items into an
|
||||
object header may require the second chunk to expand. When
|
||||
this occurs, the second chunk may need to move to another
|
||||
location in the file, freeing the file memory which that
|
||||
chunk originally occupied.
|
||||
</blockquote>
|
||||
|
||||
<p>The relocation of meta data containers could potentially
|
||||
orphan a significant amount of file memory if the application
|
||||
has made poor estimates for preallocation sizes.
|
||||
|
||||
<!-- ---------------------------------------------------------------- -->
|
||||
<h2>Levels of Memory Management</h2>
|
||||
|
||||
<p>Memory management by the library can be independent of memory
|
||||
management support by the file format. The file format can
|
||||
support no memory management, some memory management, or full
|
||||
memory management. Similarly with the library.
|
||||
|
||||
<h3>Support in the Library</h3>
|
||||
|
||||
<dl>
|
||||
<dt><b>No Support: I</b>
|
||||
<dd>When memory is deallocated it simply becomes unreferenced
|
||||
(orphaned) in the file. Memory allocation requests are
|
||||
satisfied by extending the file.
|
||||
|
||||
<dd>A separate off-line utility can be used to detect the
|
||||
unreferenced bytes of a file and "bubble" them up to the end
|
||||
of the file and then truncate the file.
|
||||
|
||||
<dt><b>Some Support: II</b>
|
||||
<dd>The library could support partial memory management all
|
||||
the time, or full memory management some of the time.
|
||||
Orphaning free blocks instead of adding them to a free list
|
||||
should not affect the file integrity, nor should fulfilling
|
||||
new requests by extending the file instead of using the free
|
||||
list.
|
||||
|
||||
<dt><b>Full Support: III</b>
|
||||
<dd>The library supports space-efficient memory management by
|
||||
always fulfilling allocation requests from the free list when
|
||||
possible, and by coalescing adjacent free blocks into a
|
||||
single larger free block.
|
||||
</dl>
|
||||
|
||||
<h3>Support in the File Format</h3>
|
||||
|
||||
<dl>
|
||||
<dt><b>No Support: A</b>
|
||||
<dd>The file format does not support memory management; any
|
||||
unreferenced block in the file is assumed to be free. If
|
||||
the library supports full memory management then it will
|
||||
have to traverse the entire file to determine which blocks
|
||||
are unreferenced.
|
||||
|
||||
<dt><b>Some Support: B</b>
|
||||
<dd>Assuming that unreferenced blocks are free can be
|
||||
dangerous in a situation where the file is not consistent.
|
||||
For instance, if a directory tree becomes detached from the
|
||||
main directory hierarchy, then the detached directory and
|
||||
everything that is referenced only through the detached
|
||||
directory become unreferenced. File repair utilities will
|
||||
be unable to determine which unreferenced blocks need to be
|
||||
linked back into the file hierarchy.
|
||||
|
||||
<dd>Therefore, it might be useful to keep an unsorted,
|
||||
doubly-linked list of free blocks in the file. The library
|
||||
can add and remove blocks from the list in constant time,
|
||||
and can generate its own internal free-block data structure
|
||||
in time proportional to the number of free blocks instead of
|
||||
the size of the file. Additionally, a library can use a
|
||||
subset of the free blocks, an alternative which is not
|
||||
feasible if the file format doesn't support any form of
|
||||
memory management.
|
||||
|
||||
<dt><b>Full Support: C</b>
|
||||
<dd>The file format can mirror library data structures for
|
||||
space-efficient memory management. The free blocks are
|
||||
linked in unsorted, doubly-linked lists with one list per
|
||||
free block size. The heads of the lists are pointed to by a
|
||||
B-tree whose nodes are sorted by free block size. At the
|
||||
same time, all free blocks are the leaf nodes of another
|
||||
B-tree sorted by starting and ending address. When the
|
||||
trees are used in combination we can deallocate and allocate
|
||||
memory in O(log <em>N</em>) time where <em>N</em> is the
|
||||
number of free blocks.
|
||||
</dl>
|
||||
|
||||
<h3>Combinations of Library and File Format Support</h3>
|
||||
|
||||
<p>We now evaluate each combination of library support with file
|
||||
support:
|
||||
|
||||
<dl>
|
||||
<dt><b>I-A</b>
|
||||
<dd>If neither the library nor the file support memory
|
||||
management, then each allocation request will come from the
|
||||
end of the file and each deallocation request is a no-op
|
||||
that simply leaves the free block unreferenced.
|
||||
|
||||
<ul>
|
||||
<li>Advantages
|
||||
<ul>
|
||||
<li>No file overhead for allocation or deallocation.
|
||||
<li>No library overhead for allocation or
|
||||
deallocation.
|
||||
<li>No file traversal required at time of open.
|
||||
<li>No data needs to be written back to the file when
|
||||
it's closed.
|
||||
<li>Trivial to implement (already implemented).
|
||||
</ul>
|
||||
|
||||
<li>Disadvantages
|
||||
<ul>
|
||||
<li>Inefficient use of file space.
|
||||
<li>A file repair utility must reclaim lost file space.
|
||||
<li>Difficulties for file repair utilities. (Is an
|
||||
unreferenced block a free block or orphaned data?)
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<dt><b>II-A</b>
|
||||
<dd>In order for the library to support memory management, it
|
||||
will be required to build the internal free block
|
||||
representation by traversing the entire file looking for
|
||||
unreferenced blocks.
|
||||
|
||||
<ul>
|
||||
<li>Advantages
|
||||
<ul>
|
||||
<li>No file overhead for allocation or deallocation.
|
||||
<li>Variable amount of library overhead for allocation
|
||||
and deallocation depending on how much work the
|
||||
library wants to do.
|
||||
<li>No data needs to be written back to the file when
|
||||
it's closed.
|
||||
<li>Might use file space efficiently.
|
||||
</ul>
|
||||
<li>Disadvantages
|
||||
<ul>
|
||||
<li>Might use file space inefficiently.
|
||||
<li>File traversal required at time of open.
|
||||
<li>A file repair utility must reclaim lost file space.
|
||||
<li>Difficulties for file repair utilities.
|
||||
<li>Sharing of the free list between processes falls
|
||||
outside the HDF5 file format documentation.
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<dt><b>III-A</b>
|
||||
<dd>In order for the library to support full memory
|
||||
management, it will be required to build the internal free
|
||||
block representation by traversing the entire file looking
|
||||
for unreferenced blocks.
|
||||
|
||||
<ul>
|
||||
<li>Advantages
|
||||
<ul>
|
||||
<li>No file overhead for allocation or deallocation.
|
||||
<li>Efficient use of file space.
|
||||
<li>No data needs to be written back to the file when
|
||||
it's closed.
|
||||
</ul>
|
||||
<li>Disadvantages
|
||||
<ul>
|
||||
<li>Moderate amount of library overhead for allocation
|
||||
and deallocation.
|
||||
<li>File traversal required at time of open.
|
||||
<li>A file repair utility must reclaim lost file space.
|
||||
<li>Difficulties for file repair utilities.
|
||||
<li>Sharing of the free list between processes falls
|
||||
outside the HDF5 file format documentation.
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<dt><b>I-B</b>
|
||||
<dd>If the library doesn't support memory management but the
|
||||
file format supports some level of management, then a file
|
||||
repair utility will have to be run occasionally to reclaim
|
||||
unreferenced blocks.
|
||||
|
||||
<ul>
|
||||
<li>Advantages
|
||||
<ul>
|
||||
<li>No file overhead for allocation or deallocation.
|
||||
<li>No library overhead for allocation or
|
||||
deallocation.
|
||||
<li>No file traversal required at time of open.
|
||||
<li>No data needs to be written back to the file when
|
||||
it's closed.
|
||||
</ul>
|
||||
<li>Disadvantages
|
||||
<ul>
|
||||
<li>A file repair utility must reclaim lost file space.
|
||||
<li>Difficulties for file repair utilities.
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<dt><b>II-B</b>
|
||||
<dd>Both the library and the file format support some level
|
||||
of memory management.
|
||||
|
||||
<ul>
|
||||
<li>Advantages
|
||||
<ul>
|
||||
<li>Constant file overhead per allocation or
|
||||
deallocation.
|
||||
<li>Variable library overhead per allocation or
|
||||
deallocation depending on how much work the library
|
||||
wants to do.
|
||||
<li>Traversal at file open time is on the order of the
|
||||
free list size instead of the file size.
|
||||
<li>The library has the option of reading only part of
|
||||
the free list.
|
||||
<li>No data needs to be written at file close time if
|
||||
it has been amortized into the cost of allocation
|
||||
and deallocation.
|
||||
<li>File repair utilties don't have to be run to
|
||||
reclaim memory.
|
||||
<li>File repair utilities can detect whether an
|
||||
unreferenced block is a free block or orphaned data.
|
||||
<li>Sharing of the free list between processes might
|
||||
be easier.
|
||||
<li>Possible efficient use of file space.
|
||||
</ul>
|
||||
<li>Disadvantages
|
||||
<ul>
|
||||
<li>Possible inefficient use of file space.
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<dt><b>III-B</b>
|
||||
<dd>The library provides space-efficient memory management but
|
||||
the file format only supports an unsorted list of free
|
||||
blocks.
|
||||
|
||||
<ul>
|
||||
<li>Advantages
|
||||
<ul>
|
||||
<li>Constant time file overhead per allocation or
|
||||
deallocation.
|
||||
<li>No data needs to be written at file close time if
|
||||
it has been amortized into the cost of allocation
|
||||
and deallocation.
|
||||
<li>File repair utilities don't have to be run to
|
||||
reclaim memory.
|
||||
<li>File repair utilities can detect whether an
|
||||
unreferenced block is a free block or orphaned data.
|
||||
<li>Sharing of the free list between processes might
|
||||
be easier.
|
||||
<li>Efficient use of file space.
|
||||
</ul>
|
||||
<li>Disadvantages
|
||||
<ul>
|
||||
<li>O(log <em>N</em>) library overhead per allocation or
|
||||
deallocation where <em>N</em> is the total number of
|
||||
free blocks.
|
||||
<li>O(<em>N</em>) time to open a file since the entire
|
||||
free list must be read to construct the in-core
|
||||
trees used by the library.
|
||||
<li>Library is more complicated.
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<dt><b>I-C</b>
|
||||
<dd>This has the same advantages and disadvantages as I-C with
|
||||
the added disadvantage that the file format is much more
|
||||
complicated.
|
||||
|
||||
<dt><b>II-C</b>
|
||||
<dd>If the library only provides partial memory management but
|
||||
the file requires full memory management, then this method
|
||||
degenerates to the same as II-A with the added disadvantage
|
||||
that the file format is much more complicated.
|
||||
|
||||
<dt><b>III-C</b>
|
||||
<dd>The library and file format both provide complete data
|
||||
structures for space-efficient memory management.
|
||||
|
||||
<ul>
|
||||
<li>Advantages
|
||||
<ul>
|
||||
<li>Files can be opened in constant time since the
|
||||
free list is read on demand and amortised into the
|
||||
allocation and deallocation requests.
|
||||
<li>No data needs to be written back to the file when
|
||||
it's closed.
|
||||
<li>File repair utilities don't have to be run to
|
||||
reclaim memory.
|
||||
<li>File repair utilities can detect whether an
|
||||
unreferenced block is a free block or orphaned data.
|
||||
<li>Sharing the free list between processes is easy.
|
||||
<li>Efficient use of file space.
|
||||
</ul>
|
||||
<li>Disadvantages
|
||||
<ul>
|
||||
<li>O(log <em>N</em>) file allocation and deallocation
|
||||
cost where <em>N</em> is the total number of free
|
||||
blocks.
|
||||
<li>O(log <em>N</em>) library allocation and
|
||||
deallocation cost.
|
||||
<li>Much more complicated file format.
|
||||
<li>More complicated library.
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
</dl>
|
||||
|
||||
<!-- ---------------------------------------------------------------- -->
|
||||
<h2>The Algorithm for II-B</h2>
|
||||
|
||||
<p>The file contains an unsorted, doubly-linked list of free
|
||||
blocks. The address of the head of the list appears in the
|
||||
boot block. Each free block contains the following fields:
|
||||
|
||||
<center>
|
||||
<table border cellpadding=4 width="60%">
|
||||
<tr align=center>
|
||||
<th width="25%">byte</th>
|
||||
<th width="25%">byte</th>
|
||||
<th width="25%">byte</th>
|
||||
<th width="25%">byte</th>
|
||||
|
||||
<tr align=center>
|
||||
<th colspan=4>Free Block Signature</th>
|
||||
|
||||
<tr align=center>
|
||||
<th colspan=4>Total Free Block Size</th>
|
||||
|
||||
<tr align=center>
|
||||
<th colspan=4>Address of Left Sibling</th>
|
||||
|
||||
<tr align=center>
|
||||
<th colspan=4>Address of Right Sibling</th>
|
||||
|
||||
<tr align=center>
|
||||
<th colspan=4><br><br>Remainder of Free Block<br><br><br></th>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>The library reads as much of the free list as convenient when
|
||||
convenient and pushes those entries onto stacks. This can
|
||||
occur when a file is opened or any time during the life of the
|
||||
file. There is one stack for each free block size and the
|
||||
stacks are sorted by size in a balanced tree in memory.
|
||||
|
||||
<p>Deallocation involves finding the correct stack or creating
|
||||
a new one (an O(log <em>K</em>) operation where <em>K</em> is
|
||||
the number of stacks), pushing the free block info onto the
|
||||
stack (a constant-time operation), and inserting the free
|
||||
block into the file free block list (a constant-time operation
|
||||
which doesn't necessarily involve any I/O since the free blocks
|
||||
can be cached like other objects). No attempt is made to
|
||||
coalesce adjacent free blocks into larger blocks.
|
||||
|
||||
<p>Allocation involves finding the correct stack (an O(log
|
||||
<em>K</em>) operation), removing the top item from the stack
|
||||
(a constant-time operation), and removing the block from the
|
||||
file free block list (a constant-time operation). If there is
|
||||
no free block of the requested size or larger, then the file
|
||||
is extended.
|
||||
|
||||
<p>To provide sharability of the free list between processes,
|
||||
the last step of an allocation will check for the free block
|
||||
signature and if it doesn't find one will repeat the process.
|
||||
Alternatively, a process can temporarily remove free blocks
|
||||
from the file and hold them in it's own private pool.
|
||||
|
||||
<p>To summarize...
|
||||
<dl>
|
||||
<dt>File opening
|
||||
<dd>O(<em>N</em>) amortized over the time the file is open,
|
||||
where <em>N</em> is the number of free blocks. The library
|
||||
can still function without reading any of the file free
|
||||
block list.
|
||||
|
||||
<dt>Deallocation
|
||||
<dd>O(log <em>K</em>) where <em>K</em> is the number of unique
|
||||
sizes of free blocks. File access is constant.
|
||||
|
||||
<dt>Allocation
|
||||
<dd>O(log <em>K</em>). File access is constant.
|
||||
|
||||
<dt>File closing
|
||||
<dd>O(1) even if the library temporarily removes free
|
||||
blocks from the file to hold them in a private pool since
|
||||
the pool can still be a linked list on disk.
|
||||
</dl>
|
||||
|
||||
<!-- ---------------------------------------------------------------- -->
|
||||
<h2>The Algorithm for III-C</h2>
|
||||
|
||||
<p>The HDF5 file format supports a general B-tree mechanism
|
||||
for storing data with keys. If we use a B-tree to represent
|
||||
all parts of the file that are free and the B-tree is indexed
|
||||
so that a free file chunk can be found if we know the starting
|
||||
or ending address, then we can efficiently determine whether a
|
||||
free chunk begins or ends at the specified address. Call this
|
||||
the <em>Address B-Tree</em>.
|
||||
|
||||
<p>If a second B-tree points to a set of stacks where the
|
||||
members of a particular stack are all free chunks of the same
|
||||
size, and the tree is indexed by chunk size, then we can
|
||||
efficiently find the best-fit chunk size for a memory request.
|
||||
Call this the <em>Size B-Tree</em>.
|
||||
|
||||
<p>All free blocks of a particular size can be linked together
|
||||
with an unsorted, doubly-linked, circular list and the left
|
||||
and right sibling addresses can be stored within the free
|
||||
chunk, allowing us to remove or insert items from the list in
|
||||
constant time.
|
||||
|
||||
<p>Deallocation of a block fo file memory consists of:
|
||||
|
||||
<ol type="I">
|
||||
<li>Add the new free block whose address is <em>ADDR</em> to the
|
||||
address B-tree.
|
||||
|
||||
<ol type="A">
|
||||
<li>If the address B-tree contains an entry for a free
|
||||
block that ends at <em>ADDR</em>-1 then remove that
|
||||
block from the B-tree and from the linked list (if the
|
||||
block was the first on the list then the size B-tree
|
||||
must be updated). Adjust the size and address of the
|
||||
block being freed to include the block just removed from
|
||||
the free list. The time required to search for and
|
||||
possibly remove the left block is O(log <em>N</em>)
|
||||
where <em>N</em> is the number of free blocks.
|
||||
|
||||
<li>If the address B-tree contains an entry for the free
|
||||
block that begins at <em>ADDR</em>+<em>LENGTH</em> then
|
||||
remove that block from the B-tree and from the linked
|
||||
list (if the block was the first on the list then the
|
||||
size B-tree must be updated). Adjust the size of the
|
||||
block being freed to include the block just removed from
|
||||
the free list. The time required to search for and
|
||||
possibly remove the right block is O(log <em>N</em>).
|
||||
|
||||
<li>Add the new (adjusted) block to the address B-tree.
|
||||
The time for this operation is O(log <em>N</em>).
|
||||
</ol>
|
||||
|
||||
<li>Add the new block to the size B-tree and linked list.
|
||||
|
||||
<ol type="A">
|
||||
<li>If the size B-tree has an entry for this particular
|
||||
size, then add the chunk to the tail of the list. This
|
||||
is an O(log <em>K</em>) operation where <em>K</em> is
|
||||
the number of unique free block sizes.
|
||||
|
||||
<li>Otherwise make a new entry in the B-tree for chunks of
|
||||
this size. This is also O(log <em>K</em>).
|
||||
</ol>
|
||||
</ol>
|
||||
|
||||
<p>Allocation is similar to deallocation.
|
||||
|
||||
<p>To summarize...
|
||||
|
||||
<dl>
|
||||
<dt>File opening
|
||||
<dd>O(1)
|
||||
|
||||
<dt>Deallocation
|
||||
<dd>O(log <em>N</em>) where <em>N</em> is the total number of
|
||||
free blocks. File access time is O(log <em>N</em>).
|
||||
|
||||
<dt>Allocation
|
||||
<dd>O(log <em>N</em>). File access time is O(log <em>N</em>).
|
||||
|
||||
<dt>File closing
|
||||
<dd>O(1).
|
||||
</dl>
|
||||
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Thu Jul 24 15:16:40 PDT 1997 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Thu Jul 31 14:41:01 EST
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
60
doc/html/ObjectHeader.txt
Normal file
@ -0,0 +1,60 @@
|
||||
OBJECT HEADERS
|
||||
--------------
|
||||
|
||||
haddr_t
|
||||
H5O_new (hdf5_file_t *f, intn nrefs, size_t size_hint)
|
||||
|
||||
Creates a new empty object header and returns its address.
|
||||
The SIZE_HINT is the initial size of the data portion of the
|
||||
object header and NREFS is the number of symbol table entries
|
||||
that reference this object header (normally one).
|
||||
|
||||
If SIZE_HINT is too small, then at least some default amount
|
||||
of space is allocated for the object header.
|
||||
|
||||
intn /*num remaining links */
|
||||
H5O_link (hdf5_file_t *f, /*file containing header */
|
||||
haddr_t addr, /*header file address */
|
||||
intn adjust) /*link adjustment amount */
|
||||
|
||||
|
||||
size_t
|
||||
H5O_sizeof (hdf5_file_t *f, /*file containing header */
|
||||
haddr_t addr, /*header file address */
|
||||
H5O_class_t *type, /*message type or H5O_ANY */
|
||||
intn sequence) /*sequence number, usually zero */
|
||||
|
||||
Returns the size of a particular instance of a message in an
|
||||
object header. When an object header has more than one
|
||||
instance of a particular message type, then SEQUENCE indicates
|
||||
which instance to return.
|
||||
|
||||
void *
|
||||
H5O_read (hdf5_file_t *f, /*file containing header */
|
||||
haddr_t addr, /*header file address */
|
||||
H5G_entry_t *ent, /*optional symbol table entry */
|
||||
H5O_class_t *type, /*message type or H5O_ANY */
|
||||
intn sequence, /*sequence number, usually zero */
|
||||
size_t size, /*size of output message */
|
||||
void *mesg) /*output buffer */
|
||||
|
||||
Reads a message from the object header into memory.
|
||||
|
||||
const void *
|
||||
H5O_peek (hdf5_file_t *f, /*file containing header */
|
||||
haddr_t addr, /*header file address */
|
||||
H5G_entry_t *ent, /*optional symbol table entry */
|
||||
H5O_class_t *type, /*type of message or H5O_ANY */
|
||||
intn sequence) /*sequence number, usually zero */
|
||||
|
||||
haddr_t /*new heap address */
|
||||
H5O_modify (hdf5_file_t *f, /*file containing header */
|
||||
haddr_t addr, /*header file address */
|
||||
H5G_entry_t *ent, /*optional symbol table entry */
|
||||
hbool_t *ent_modified, /*entry modification flag */
|
||||
H5O_class_t *type, /*message type */
|
||||
intn overwrite, /*sequence number or -1 */
|
||||
void *mesg) /*the message */
|
||||
|
||||
|
||||
|
81
doc/html/Properties.html
Normal file
@ -0,0 +1,81 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Property List Interface (H5P)</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Property List Interface (H5P)</h1>
|
||||
|
||||
<h2>1. Introduction</h2>
|
||||
|
||||
<p>The property list (a.k.a., template) interface provides a
|
||||
mechanism for default named arguments for a C function
|
||||
interface. A property list is a collection of name/value pairs
|
||||
which can be passed to various other HDF5 functions to control
|
||||
features that are typically unimportant or whose default values
|
||||
are usually used.
|
||||
|
||||
<p>For instance, file creation needs to know various things such
|
||||
as the size of the user-block at the beginning of the file, or
|
||||
the size of various file data structures. Wrapping this
|
||||
information in a property list simplifies the API by reducing
|
||||
the number of arguments to <code>H5Fcreate()</code>.
|
||||
|
||||
<h2>2. General Property List Operations</h2>
|
||||
|
||||
<p>Property lists follow the same create/open/close paradigm as
|
||||
the rest of the library.
|
||||
|
||||
<dl>
|
||||
<dt><code>hid_t H5Pcreate (H5P_class_t <em>class</em>)</code>
|
||||
<dd>A new property list can be created as an instance of some
|
||||
property list class. The new property list is initialized
|
||||
with default values for the specified class. The classes are:
|
||||
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><code>H5P_FILE_CREATE</code>
|
||||
<dd>Properties for file creation. See <a href="Files.html">H5F</a>
|
||||
for details about the file creation properties.
|
||||
<dt><code>H5P_FILE_ACCESS</code>
|
||||
<dd>Properties for file access. See <a href="Files.html">H5F</a>
|
||||
for details about the file creation properties.
|
||||
<dt><code>H5P_DATASET_CREATE</code>
|
||||
<dd>Properties for dataset creation. See
|
||||
<a href="Datasets.html">H5D</a> for details about dataset
|
||||
creation properties.
|
||||
<dt><code>H5P_DATASET_XFER</code>
|
||||
<dd>Properties for raw data transfer. See
|
||||
<a href="Datasets.html">H5D</a> for details about raw data
|
||||
transfer properties.
|
||||
</dl>
|
||||
|
||||
<br><br>
|
||||
<dt><code>hid_t H5Pcopy (hid_t <em>plist</em>)</code>
|
||||
<dd>A property list can be copied to create a new property
|
||||
list. The new property list has the same properties and values
|
||||
as the original property list.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5Pclose (hid_t <em>plist</em>)</code>
|
||||
<dd>All property lists should be closed when the application is
|
||||
finished accessing them. This frees resources used by the
|
||||
property list.
|
||||
|
||||
<br><br>
|
||||
<dt><code>H5P_class_t H5Pget_class (hid_t <em>plist</em>)</code>
|
||||
<dd>The class of which the property list is a member can be
|
||||
obtained by calling this function. The property list classes
|
||||
are defined above for <code>H5Pcreate()</code>.
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<address><a href="mailto:koziol@ncsa.uiuc.edu">Quincey Koziol</a></address>
|
||||
<!-- Created: Tue Feb 10 17:06:58 PST 1998 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Tue Feb 10 17:26:41 PST 1998
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
139
doc/html/Version.html
Normal file
@ -0,0 +1,139 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Version Numbers</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Version Numbers</h1>
|
||||
|
||||
<h2>1. Introduction</h2>
|
||||
|
||||
<p>The HDF5 version number is a set of three integer values and
|
||||
one lower-case letter written as, for example,
|
||||
<code>hdf5-1.2.0a</code>.
|
||||
|
||||
<p>The <code>5</code> is part of the library name and will only
|
||||
change if the entire file format and library are redesigned
|
||||
similar in scope to the changes between HDF4 and HDF5.
|
||||
|
||||
<p>The <code>1</code> is the <em>major version number</em> and
|
||||
changes when there is an extensive change to the file format or
|
||||
library. Such a change will likely require files to be
|
||||
translated and applications to be modified. This number is not
|
||||
expected to change frequently.
|
||||
|
||||
<p>The <code>2</code> is the <em>minor version number</em> and is
|
||||
incremented by each public release that presents new features.
|
||||
Even numbers are reserved for stable public versions of the
|
||||
library while odd numbers are reserved for developement
|
||||
versions. See the diagram below for examples.
|
||||
|
||||
<p>The <code>0</code> is the <em>release number</em>. For public
|
||||
versions of the library, the release number is incremented each
|
||||
time a bug(s) is fixed and the fix is made available to the
|
||||
public. For development versions, the release number is
|
||||
incremented automatically each time a CVS commit occurs anywhere
|
||||
in the source tree.
|
||||
|
||||
<p>The <code>a</code> is the <em>patch level</em> and is used only
|
||||
for public versions. It's incremented only for very minor
|
||||
changes that don't affect the usability of the library. For
|
||||
instance, fixing spelling errors, changing warning messages, or
|
||||
updating documentation.
|
||||
|
||||
<h2>2. Abbreviated Versions</h2>
|
||||
|
||||
<p>It's often convenient to drop the patch level and release
|
||||
number when referring to a version of the library, like saying
|
||||
version 1.2 of HDF5. The release number and patch level can be
|
||||
any value in this case.
|
||||
|
||||
<h2>3. Special Versions</h2>
|
||||
|
||||
<p>Version 1.0.0 was released for alpha testing the first week of
|
||||
March, 1998. The developement version number was incremented to
|
||||
1.0.1 and remained constant until the the last week of April,
|
||||
when the release number started to increase and development
|
||||
versions were made available to people outside the core HDF5
|
||||
development team.
|
||||
|
||||
<p>Version 1.1.0 will be the first official beta release but the
|
||||
1.1 branch will also serve as a development branch since we're
|
||||
not concerned about providing bug fixes separate from normal
|
||||
development for the beta version.
|
||||
|
||||
<p>Version 1.2 will be the first official HDF5 version. The
|
||||
version tree will fork at this point with public bug fixes
|
||||
provided on the 1.2 branch and development will continue on the
|
||||
1.3 branch.
|
||||
|
||||
<h2>4. Public versus Development</h2>
|
||||
|
||||
<p>The motivation for separate public and development versions is
|
||||
that the public version will receive only bug fixes while the
|
||||
development version will receive new features.
|
||||
|
||||
<p>Eventually, the development version will near completion and a
|
||||
new development branch will fork while the original one enters a
|
||||
feature freeze state. When the original development branch is
|
||||
ready for release the minor version number will be incremented
|
||||
to an even value.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<img alt="Version Example" src="version.gif">
|
||||
<br><b>Fig 1: Version Example</b>
|
||||
</center>
|
||||
|
||||
<h2>5. Version Support from the Library</h2>
|
||||
|
||||
<p>The library provides a set of macros and functions to query and
|
||||
check version numbers.
|
||||
|
||||
<dl>
|
||||
<dt><code>H5_VERS_MAJOR</code>
|
||||
<dt><code>H5_VERS_MINOR</code>
|
||||
<dt><code>H5_VERS_RELEASE</code>
|
||||
<dt><code>H5_VERS_PATCH</code>
|
||||
<dd>These preprocessor constants are defined in the public
|
||||
include file and determine the version of the include files.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5version (unsigned *<em>majnum</em>, unsigned
|
||||
*<em>minnum</em>, unsigned *<em>relnum</em>, unsigned
|
||||
*<em>patnum</em>)</code>
|
||||
<dd>This function returns through its arguments the version
|
||||
numbers for the library to which the application is linked.
|
||||
|
||||
<br><br>
|
||||
<dt><code>void H5check(void)</code>
|
||||
<dd>This is a macro that verifies that the version number of the
|
||||
HDF5 include file used to compile the application matches the
|
||||
version number of the library to which the application is
|
||||
linked. This check occurs automatically when the first HDF5
|
||||
file is created or opened and is important because a mismatch
|
||||
between the include files and the library is likely to result
|
||||
in corrupted data and/or segmentation faults. If a mismatch
|
||||
is detected the library issues an error message on the
|
||||
standard error stream and aborts with a core dump.
|
||||
|
||||
<br><br>
|
||||
<dt><code>herr_t H5vers_check (unsigned <em>majnum</em>,
|
||||
unsigned <em>minnum</em>, unsigned <em>relnum</em>, unsigned
|
||||
<em>patnum</em>)</code>
|
||||
<dd>This function is called by the <code>H5check()</code> macro
|
||||
with the include file version constants. The function
|
||||
compares its arguments to the result returned by
|
||||
<code>H5version()</code> and if a mismatch is detected prints
|
||||
an error message on the standard error stream and aborts.
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Wed Apr 22 11:24:40 EDT 1998 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Wed Apr 22 12:19:53 EDT 1998
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
BIN
doc/html/chunk1.gif
Normal file
After ![]() (image error) Size: 5.0 KiB |
52
doc/html/chunk1.obj
Normal file
@ -0,0 +1,52 @@
|
||||
%TGIF 3.0-p5
|
||||
state(0,33,100,0,0,0,16,1,9,1,1,0,0,3,0,1,1,'Courier',0,17,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1088,1408,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
box('black',64,64,384,384,5,2,1,29,0,0,0,0,0,'2',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
128,64,128,384],0,2,1,30,0,4,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
192,64,192,384],0,2,1,31,0,4,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
256,64,256,384],0,2,1,32,0,4,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
320,64,320,384],0,2,1,33,0,4,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
64,128,384,128],0,2,1,34,0,4,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
64,192,384,192],0,2,1,35,0,4,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
64,256,384,256],0,2,1,36,0,4,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
64,320,384,320],0,2,1,37,0,4,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
box('black',128,448,192,512,5,2,1,56,0,0,0,0,0,'2',[
|
||||
]).
|
||||
text('black',448,208,'Courier',0,17,2,1,0,1,84,28,61,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Entire array",
|
||||
"5000 x 5000"]).
|
||||
text('black',256,464,'Courier',0,17,2,1,0,1,84,28,63,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Single Chunk",
|
||||
"1000 x 1000"]).
|
||||
box('black',48,48,512,528,0,1,1,71,0,0,0,0,0,'1',[
|
||||
]).
|
271
doc/html/compat.html
Normal file
@ -0,0 +1,271 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Backward/Forward Compatability</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Backward/Forward Compatability</h1>
|
||||
|
||||
<p>The HDF5 development must proceed in such a manner as to
|
||||
satisfy the following conditions:
|
||||
|
||||
<ol type=A>
|
||||
<li>HDF5 applications can produce data that HDF5
|
||||
applications can read and write and HDF4 applications can produce
|
||||
data that HDF4 applications can read and write. The situation
|
||||
that demands this condition is obvious.</li>
|
||||
|
||||
<li>HDF5 applications are able to produce data that HDF4 applications
|
||||
can read and HDF4 applications can subsequently modify the
|
||||
file subject to certain constraints depending on the
|
||||
implementation. This condition is for the temporary
|
||||
situation where a consumer has neither been relinked with a new
|
||||
HDF4 API built on top of the HDF5 API nor recompiled with the
|
||||
HDF5 API.</li>
|
||||
|
||||
<li>HDF5 applications can read existing HDF4 files and subsequently
|
||||
modify the file subject to certain constraints depending on
|
||||
the implementation. This is condition is for the temporary
|
||||
situation in which the producer has neither been relinked with a
|
||||
new HDF4 API built on top of the HDF5 API nor recompiled with
|
||||
the HDF5 API, or the permanent situation of HDF5 consumers
|
||||
reading archived HDF4 files.</li>
|
||||
</ul>
|
||||
|
||||
<p>There's at least one invarient: new object features introduced
|
||||
in the HDF5 file format (like 2-d arrays of structs) might be
|
||||
impossible to "translate" to a format that an old HDF4
|
||||
application can understand either because the HDF4 file format
|
||||
or the HDF4 API has no mechanism to describe the object.
|
||||
|
||||
<p>What follows is one possible implementation based on how
|
||||
Condition B was solved in the AIO/PDB world. It also attempts
|
||||
to satisfy these goals:
|
||||
|
||||
<ol type=1>
|
||||
<li>The main HDF5 library contains as little extra baggage as
|
||||
possible by either relying on external programs to take care
|
||||
of compatability issues or by incorporating the logic of such
|
||||
programs as optional modules in the HDF5 library. Conditions B
|
||||
and C are separate programs/modules.</li>
|
||||
|
||||
<li>No extra baggage not only means the library proper is small,
|
||||
but also means it can be implemented (rather than migrated
|
||||
from HDF4 source) from the ground up with minimal regard for
|
||||
HDF4 thus keeping the logic straight forward.</li>
|
||||
|
||||
<li>Compatability issues are handled behind the scenes when
|
||||
necessary (and possible) but can be carried out explicitly
|
||||
during things like data migration.</li>
|
||||
</ol>
|
||||
|
||||
<hr>
|
||||
<h2>Wrappers</h2>
|
||||
|
||||
<p>The proposed implementation uses <i>wrappers</i> to handle
|
||||
compatability issues. A Format-X file is <i>wrapped</i> in a
|
||||
Format-Y file by creating a Format-Y skeleton that replicates
|
||||
the Format-X meta data. The Format-Y skeleton points to the raw
|
||||
data stored in Format-X without moving the raw data. The
|
||||
restriction is that raw data storage methods in Format-Y is a
|
||||
superset of raw data storage methods in Format-X (otherwise the
|
||||
raw data must be copied to Format-Y). We're assuming that meta
|
||||
data is small wrt the entire file.
|
||||
|
||||
<p>The wrapper can be a separate file that has pointers into the
|
||||
first file or it can be contained within the first file. If
|
||||
contained in a single file, the file can appear as a Format-Y
|
||||
file or simultaneously a Format-Y and Format-X file.
|
||||
|
||||
<p>The Format-X meta-data can be thought of as the original
|
||||
wrapper around raw data and Format-Y is a second wrapper around
|
||||
the same data. The wrappers are independend of one another;
|
||||
modifying the meta-data in one wrapper causes the other to
|
||||
become out of date. Modification of raw data doesn't invalidate
|
||||
either view as long as the meta data that describes its storage
|
||||
isn't modifed. For instance, an array element can change values
|
||||
if storage is already allocated for the element, but if storage
|
||||
isn't allocated then the meta data describing the storage must
|
||||
change, invalidating all wrappers but one.
|
||||
|
||||
<p>It's perfectly legal to modify the meta data of one wrapper
|
||||
without modifying the meta data in the other wrapper(s). The
|
||||
illegal part is accessing the raw data through a wrapper which
|
||||
is out of date.
|
||||
|
||||
<p>If raw data is wrapped by more than one internal wrapper
|
||||
(<i>internal</i> means that the wrapper is in the same file as
|
||||
the raw data) then access to that file must assume that
|
||||
unreferenced parts of that file contain meta data for another
|
||||
wrapper and cannot be reclaimed as free memory.
|
||||
|
||||
<hr>
|
||||
<h2>Implementation of Condition B</h2>
|
||||
|
||||
<p>Since this is a temporary situation which can't be
|
||||
automatically detected by the HDF5 library, we must rely
|
||||
on the application to notify the HDF5 library whether or not it
|
||||
must satisfy Condition B. (Even if we don't rely on the
|
||||
application, at some point someone is going to remove the
|
||||
Condition B constraint from the library.) So the module that
|
||||
handles Condition B is conditionally compiled and then enabled
|
||||
on a per-file basis.
|
||||
|
||||
<p>If the application desires to produce an HDF4 file (determined
|
||||
by arguments to <code>H5Fopen</code>), and the Condition B
|
||||
module is compiled into the library, then <code>H5Fclose</code>
|
||||
calls the module to traverse the HDF5 wrapper and generate an
|
||||
additional internal or external HDF4 wrapper (wrapper specifics
|
||||
are described below). If Condition B is implemented as a module
|
||||
then it can benefit from the metadata already cached by the main
|
||||
library.
|
||||
|
||||
<p>An internal HDF4 wrapper would be used if the HDF5 file is
|
||||
writable and the user doesn't mind that the HDF5 file is
|
||||
modified. An external wrapper would be used if the file isn't
|
||||
writable or if the user wants the data file to be primarily HDF5
|
||||
but a few applications need an HDF4 view of the data.
|
||||
|
||||
<p>Modifying through the HDF5 library an HDF5 file that has
|
||||
internal HDF4 wrapper should invalidate the HDF4 wrapper (and
|
||||
optionally regenerate it when <code>H5Fclose</code> is
|
||||
called). The HDF5 library must understand how wrappers work, but
|
||||
not necessarily anything about the HDF4 file format.
|
||||
|
||||
<p>Modifying through the HDF5 library an HDF5 file that has an
|
||||
external HDF4 wrapper will cause the HDF4 wrapper to become out
|
||||
of date (but possibly regenerated during <code>H5Fclose</code>).
|
||||
<b>Note: Perhaps the next release of the HDF4 library should
|
||||
insure that the HDF4 wrapper file has a more recent modification
|
||||
time than the raw data file (the HDF5 file) to which it
|
||||
points(?)</b>
|
||||
|
||||
<p>Modifying through the HDF4 library an HDF5 file that has an
|
||||
internal or external HDF4 wrapper will cause the HDF5 wrapper to
|
||||
become out of date. However, there is now way for the old HDF4
|
||||
library to notify the HDF5 wrapper that it's out of date.
|
||||
Therefore the HDF5 library must be able to detect when the HDF5
|
||||
wrapper is out of date and be able to fix it. If the HDF4
|
||||
wrapper is complete then the easy way is to ignore the original
|
||||
HDF5 wrapper and generate a new one from the HDF4 wrapper. The
|
||||
other approach is to compare the HDF4 and HDF5 wrappers and
|
||||
assume that if they differ HDF4 is the right one, if HDF4 omits
|
||||
data then it was because HDF4 is a partial wrapper (rather than
|
||||
assume HDF4 deleted the data), and if HDF4 has new data then
|
||||
copy the new meta data to the HDF5 wrapper. On the other hand,
|
||||
perhaps we don't need to allow these situations (modifying an
|
||||
HDF5 file with the old HDF4 library and then accessing it with
|
||||
the HDF5 library is either disallowed or causes HDF5 objects
|
||||
that can't be described by HDF4 to be lost).
|
||||
|
||||
<p>To convert an HDF5 file to an HDF4 file on demand, one simply
|
||||
opens the file with the HDF4 flag and closes it. This is also
|
||||
how AIO implemented backward compatability with PDB in its file
|
||||
format.
|
||||
|
||||
<hr>
|
||||
<h2>Implementation of Condition C</h2>
|
||||
|
||||
<p>This condition must be satisfied for all time because there
|
||||
will always be archived HDF4 files. If a pure HDF4 file (that
|
||||
is, one without HDF5 meta data) is opened with an HDF5 library,
|
||||
the <code>H5Fopen</code> builds an internal or external HDF5
|
||||
wrapper and then accesses the raw data through that wrapper. If
|
||||
the HDF5 library modifies the file then the HDF4 wrapper becomes
|
||||
out of date. However, since the HDF5 library hasn't been
|
||||
released, we can at least implement it to disable and/or reclaim
|
||||
the HDF4 wrapper.
|
||||
|
||||
<p>If an external and temporary HDF5 wrapper is desired, the
|
||||
wrapper is created through the cache like all other HDF5 files.
|
||||
The data appears on disk only if a particular cached datum is
|
||||
preempted. Instead of calling <code>H5Fclose</code> on the HDF5
|
||||
wrapper file we call <code>H5Fabort</code> which immediately
|
||||
releases all file resources without updating the file, and then
|
||||
we unlink the file from Unix.
|
||||
|
||||
<hr>
|
||||
<h2>What do wrappers look like?</h2>
|
||||
|
||||
<p>External wrappers are quite obvious: they contain only things
|
||||
from the format specs for the wrapper and nothing from the
|
||||
format specs of the format which they wrap.
|
||||
|
||||
<p>An internal HDF4 wrapper is added to an HDF5 file in such a way
|
||||
that the file appears to be both an HDF4 file and an HDF5
|
||||
file. HDF4 requires an HDF4 file header at file offset zero. If
|
||||
a user block is present then we just move the user block down a
|
||||
bit (and truncate it) and insert the minimum HDF4 signature.
|
||||
The HDF4 <code>dd</code> list and any other data it needs are
|
||||
appended to the end of the file and the HDF5 signature uses the
|
||||
logical file length field to determine the beginning of the
|
||||
trailing part of the wrapper.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border width="60%">
|
||||
<tr>
|
||||
<td>HDF4 minimal file header. Its main job is to point to
|
||||
the <code>dd</code> list at the end of the file.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>User-defined block which is truncated by the size of the
|
||||
HDF4 file header so that the HDF5 boot block file address
|
||||
doesn't change.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>The HDF5 boot block and data, unmodified by adding the
|
||||
HDF4 wrapper.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>The main part of the HDF4 wrapper. The <code>dd</code>
|
||||
list will have entries for all parts of the file so
|
||||
hdpack(?) doesn't (re)move anything.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>When such a file is opened by the HDF5 library for
|
||||
modification it shifts the user block back down to address zero
|
||||
and fills with zeros, then truncates the file at the end of the
|
||||
HDF5 data or adds the trailing HDF4 wrapper to the free
|
||||
list. This prevents HDF4 applications from reading the file with
|
||||
an out of date wrapper.
|
||||
|
||||
<p>If there is no user block then we have a problem. The HDF5
|
||||
boot block must be moved to make room for the HDF4 file header.
|
||||
But moving just the boot block causes problems because all file
|
||||
addresses stored in the file are relative to the boot block
|
||||
address. The only option is to shift the entire file contents
|
||||
by 512 bytes to open up a user block (too bad we don't have
|
||||
hooks into the Unix i-node stuff so we could shift the entire
|
||||
file contents by the size of a file system page without ever
|
||||
performing I/O on the file :-)
|
||||
|
||||
<p>Is it possible to place an HDF5 wrapper in an HDF4 file? I
|
||||
don't know enough about the HDF4 format, but I would suspect it
|
||||
might be possible to open a hole at file address 512 (and
|
||||
possibly before) by moving some things to the end of the file
|
||||
to make room for the HDF5 signature. The remainder of the HDF5
|
||||
wrapper goes at the end of the file and entries are added to the
|
||||
HDF4 <code>dd</code> list to mark the location(s) of the HDF5
|
||||
wrapper.
|
||||
|
||||
<hr>
|
||||
<h2>Other Thoughts</h2>
|
||||
|
||||
<p>Conversion programs that copy an entire HDF4 file to a separate,
|
||||
self-contained HDF5 file and vice versa might be useful.
|
||||
|
||||
|
||||
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Fri Oct 3 11:52:31 EST 1997 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Wed Oct 8 12:34:42 EST 1997
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
BIN
doc/html/dataset_p1.gif
Normal file
After ![]() (image error) Size: 3.3 KiB |
32
doc/html/dataset_p1.obj
Normal file
@ -0,0 +1,32 @@
|
||||
%TGIF 3.0-p5
|
||||
state(0,33,100,0,0,0,16,1,9,1,1,0,0,1,0,1,1,'Helvetica',0,24,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1088,1408,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
box('black',128,240,288,432,4,1,1,26,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',400,272,464,400,4,1,1,27,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',192,304,224,368,6,1,1,28,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',400,272,432,336,6,1,1,29,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
224,304,400,272],1,1,1,32,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
224,368,400,336],1,1,1,33,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
text('black',208,208,'Helvetica',0,20,1,1,0,1,77,17,40,0,14,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"File Dataset"]).
|
||||
text('black',432,208,'Helvetica',0,20,1,1,0,1,106,17,42,0,14,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Memory Dataset"]).
|
||||
text('black',320,144,'Helvetica',0,24,1,1,0,1,206,29,68,0,24,5,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Raw Data Transfer"]).
|
||||
box('black',96,128,512,464,0,1,1,70,0,0,0,0,0,'1',[
|
||||
]).
|
BIN
doc/html/extern1.gif
Normal file
After ![]() (image error) Size: 1.9 KiB |
40
doc/html/extern1.obj
Normal file
@ -0,0 +1,40 @@
|
||||
%TGIF 3.0-p5
|
||||
state(0,33,100,0,0,0,16,1,9,1,1,0,0,1,0,1,0,'Courier',0,17,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1088,1408,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
box('black',128,96,192,128,4,1,1,49,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',192,96,352,128,12,1,1,50,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',352,96,416,128,18,1,1,51,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',64,176,224,208,12,1,1,53,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',256,176,320,208,4,1,1,54,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',352,176,448,208,18,1,1,55,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',224,176,256,208,0,1,1,56,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',320,176,352,208,0,1,1,57,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',448,176,512,208,0,1,1,58,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
176,128,272,176],1,1,1,59,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
240,128,208,176],1,1,1,60,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
384,128,384,176],1,1,1,61,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
box('black',48,80,528,224,0,1,1,64,0,0,0,0,0,'1',[
|
||||
]).
|
BIN
doc/html/extern2.gif
Normal file
After ![]() (image error) Size: 4.0 KiB |
108
doc/html/extern2.obj
Normal file
@ -0,0 +1,108 @@
|
||||
%TGIF 3.0-p5
|
||||
state(0,33,100,0,0,0,16,1,9,1,1,1,1,0,0,1,1,'Courier',0,17,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1088,1408,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
box('black',48,48,464,432,0,1,1,144,0,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',80,240,'Courier',0,17,1,0,0,1,70,14,146,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"scan1.data"]).
|
||||
text('black',80,304,'Courier',0,17,1,0,0,1,70,14,148,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"scan2.data"]).
|
||||
text('black',80,368,'Courier',0,17,1,0,0,1,70,14,150,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"scan3.data"]).
|
||||
polygon('black',7,[
|
||||
64,64,64,128,192,128,192,96,320,96,320,64,64,64],20,1,1,0,181,0,0,0,0,0,'1',
|
||||
"00",[
|
||||
]).
|
||||
polygon('black',7,[
|
||||
64,128,64,160,320,160,320,96,192,96,192,128,64,128],4,1,1,0,182,0,0,0,0,0,'1',
|
||||
"00",[
|
||||
]).
|
||||
box('black',64,160,320,192,26,1,1,183,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
80,80,304,80],1,1,1,184,0,26,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
80,112,176,112],1,1,1,185,0,26,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
208,112,304,112],1,1,1,186,0,26,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
80,144,304,144],1,1,1,187,0,26,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
80,176,304,176],1,1,1,188,0,26,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
box('black',64,256,448,288,20,1,1,203,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',64,320,448,352,4,1,1,216,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',64,384,320,416,26,1,1,225,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
80,272,304,272],1,1,1,226,0,26,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
336,272,432,272],1,1,1,227,0,26,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
80,336,176,336],1,1,1,228,0,26,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
208,336,432,336],1,1,1,229,0,26,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
80,400,304,400],1,1,1,230,0,26,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
192,96,64,96],0,1,1,232,0,26,5,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
192,128,320,128],0,1,1,233,0,26,5,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
256,64,256,192],0,1,1,234,0,26,5,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
192,64,192,192],0,1,1,235,0,26,5,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
128,64,128,192],0,1,1,236,0,26,5,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
320,160,64,160],0,2,1,238,0,26,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',4,[
|
||||
320,96,192,96,192,128,64,128],0,2,1,240,0,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',6,[
|
||||
336,64,384,64,384,128,384,128,384,192,336,192],3,1,1,241,1,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"78",[
|
||||
]).
|
||||
text('black',429,124,'Courier',0,17,2,1,0,1,28,49,250,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,1,0,[
|
||||
429,124,405,124,454,152,0,1000,-1000,0,-15,2,404,123,455,153],[
|
||||
"2-d",
|
||||
"Dataset"]).
|
BIN
doc/html/group_p1.gif
Normal file
After ![]() (image error) Size: 3.6 KiB |
85
doc/html/group_p1.obj
Normal file
@ -0,0 +1,85 @@
|
||||
%TGIF 3.0-p5
|
||||
state(0,33,100,0,0,0,8,1,9,1,1,0,2,1,0,1,1,'Times-Roman',0,24,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1088,1408,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
text('black',80,168,'Courier',0,17,1,0,0,1,7,14,30,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',80,184,'Courier',0,17,1,0,0,1,7,14,34,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',80,200,'Courier',0,17,1,0,0,1,7,14,36,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',80,216,'Courier',0,17,1,0,0,1,21,14,38,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Foo"]).
|
||||
text('black',80,232,'Courier',0,17,1,0,0,1,7,14,43,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',80,248,'Courier',0,17,1,0,0,1,7,14,47,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
rcbox('black',64,152,128,280,0,1,1,0,16,49,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',208,152,'Courier',0,17,1,0,0,1,7,14,52,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',80,152,'Courier',0,17,1,0,0,1,7,14,56,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',208,168,'Courier',0,17,1,0,0,1,7,14,58,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',208,184,'Courier',0,17,1,0,0,1,21,14,60,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Bar"]).
|
||||
text('black',208,200,'Courier',0,17,1,0,0,1,7,14,62,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',208,216,'Courier',0,17,1,0,0,1,7,14,64,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',208,232,'Courier',0,17,1,0,0,1,7,14,68,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',208,248,'Courier',0,17,1,0,0,1,7,14,72,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
rcbox('black',192,152,256,280,0,1,1,0,16,74,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',336,152,'Courier',0,17,1,0,0,1,7,14,75,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',336,168,'Courier',0,17,1,0,0,1,7,14,77,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',336,184,'Courier',0,17,1,0,0,1,7,14,81,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',336,200,'Courier',0,17,1,0,0,1,7,14,88,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',336,216,'Courier',0,17,1,0,0,1,7,14,92,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',336,232,'Courier',0,17,1,0,0,1,7,14,94,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',336,248,'Courier',0,17,1,0,0,1,21,14,96,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Baz"]).
|
||||
rcbox('black',320,152,384,280,0,1,1,0,16,98,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',224,360,'NewCenturySchlbk-Roman',0,17,2,1,0,1,42,30,99,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Object",
|
||||
"Header"]).
|
||||
rcbox('black',192,344,256,408,0,1,1,0,16,101,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',4,[
|
||||
112,224,136,216,152,184,192,168],1,1,1,102,2,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"",[
|
||||
]).
|
||||
poly('black',4,[
|
||||
232,192,272,184,288,168,320,160],1,1,1,107,2,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"",[
|
||||
]).
|
||||
poly('black',4,[
|
||||
368,256,416,272,392,336,256,352],1,1,1,110,2,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"",[
|
||||
]).
|
||||
text('black',96,128,'Times-Roman',0,17,1,1,0,1,40,15,120,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Group 1"]).
|
||||
text('black',224,128,'Times-Roman',0,17,1,1,0,1,40,15,126,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Group 2"]).
|
||||
text('black',352,128,'Times-Roman',0,17,1,1,0,1,40,15,130,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Group 3"]).
|
||||
text('black',224,320,'Times-Roman',0,17,1,1,0,1,64,15,134,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Some Object"]).
|
||||
text('black',224,80,'Times-Roman',0,24,1,1,0,1,258,28,138,0,22,6,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"The name \"/Foo/Bar/Baz\""]).
|
||||
box('black',40,64,448,432,0,1,1,140,0,0,0,0,0,'1',[
|
||||
]).
|
BIN
doc/html/group_p2.gif
Normal file
After ![]() (image error) Size: 3.4 KiB |
57
doc/html/group_p2.obj
Normal file
@ -0,0 +1,57 @@
|
||||
%TGIF 3.0-p5
|
||||
state(0,33,100,0,0,0,8,1,9,1,1,0,2,1,0,1,0,'Courier',0,17,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1088,1408,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
text('black',144,128,'Courier',0,17,1,0,0,1,7,14,26,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',144,144,'Courier',0,17,1,0,0,1,7,14,30,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',144,160,'Courier',0,17,1,0,0,1,21,14,34,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Foo"]).
|
||||
text('black',144,176,'Courier',0,17,1,0,0,1,7,14,36,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',144,192,'Courier',0,17,1,0,0,1,7,14,38,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
rcbox('black',128,128,192,256,0,1,1,0,16,40,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',144,320,'Courier',0,17,1,0,0,1,7,14,43,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',144,336,'Courier',0,17,1,0,0,1,7,14,45,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',144,352,'Courier',0,17,1,0,0,1,21,14,47,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Bar"]).
|
||||
text('black',144,368,'Courier',0,17,1,0,0,1,7,14,49,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',144,384,'Courier',0,17,1,0,0,1,7,14,51,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
rcbox('black',128,320,192,448,0,1,1,0,16,53,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',160,96,'NewCenturySchlbk-Roman',0,17,1,1,0,1,46,15,64,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Group 1"]).
|
||||
text('black',160,288,'NewCenturySchlbk-Roman',0,17,1,1,0,1,46,15,68,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Group 2"]).
|
||||
text('black',352,224,'NewCenturySchlbk-Roman',0,17,2,1,0,1,35,30,70,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Some",
|
||||
"Object"]).
|
||||
rcbox('black',320,256,384,384,0,1,1,0,16,72,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',4,[
|
||||
176,168,224,192,264,240,320,264],1,1,1,73,2,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"",[
|
||||
]).
|
||||
poly('black',4,[
|
||||
176,360,232,344,272,288,320,272],1,1,1,74,2,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"",[
|
||||
]).
|
||||
text('black',264,40,'Helvetica',0,24,1,1,0,1,206,29,93,0,24,5,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Hard Link Example"]).
|
||||
box('black',88,24,424,496,0,1,1,95,0,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',240,192,'Courier',0,17,1,0,0,1,63,14,129,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"hard link"]).
|
||||
text('black',248,336,'Courier',0,17,1,0,0,1,63,14,131,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"hard link"]).
|
BIN
doc/html/group_p3.gif
Normal file
After ![]() (image error) Size: 3.3 KiB |
59
doc/html/group_p3.obj
Normal file
@ -0,0 +1,59 @@
|
||||
%TGIF 3.0-p5
|
||||
state(0,33,100,0,0,0,8,1,9,1,1,0,2,1,0,1,0,'Courier',0,17,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1088,1408,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
text('black',144,128,'Courier',0,17,1,0,0,1,7,14,26,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',144,144,'Courier',0,17,1,0,0,1,7,14,30,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',144,160,'Courier',0,17,1,0,0,1,21,14,34,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Foo"]).
|
||||
text('black',144,176,'Courier',0,17,1,0,0,1,7,14,36,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',144,192,'Courier',0,17,1,0,0,1,7,14,38,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
rcbox('black',128,128,192,256,0,1,1,0,16,40,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',144,320,'Courier',0,17,1,0,0,1,7,14,43,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',144,336,'Courier',0,17,1,0,0,1,7,14,45,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',144,352,'Courier',0,17,1,0,0,1,21,14,47,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Bar"]).
|
||||
text('black',144,368,'Courier',0,17,1,0,0,1,7,14,49,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
text('black',144,384,'Courier',0,17,1,0,0,1,7,14,51,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"."]).
|
||||
rcbox('black',128,320,192,448,0,1,1,0,16,53,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',160,96,'NewCenturySchlbk-Roman',0,17,1,1,0,1,46,15,64,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Group 1"]).
|
||||
text('black',160,288,'NewCenturySchlbk-Roman',0,17,1,1,0,1,46,15,68,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Group 2"]).
|
||||
text('black',352,96,'NewCenturySchlbk-Roman',0,17,2,1,0,1,35,30,70,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Some",
|
||||
"Object"]).
|
||||
rcbox('black',320,128,384,256,0,1,1,0,16,72,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',264,40,'Helvetica',0,24,1,1,0,1,197,29,93,0,24,5,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Soft Link Example"]).
|
||||
box('black',88,24,424,496,0,1,1,95,0,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',320,352,'Courier',0,17,1,0,0,1,35,14,105,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"\"Foo\""]).
|
||||
poly('black',4,[
|
||||
176,168,232,160,264,144,320,136],1,1,1,111,2,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
176,360,312,360],1,1,1,116,2,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"",[
|
||||
]).
|
||||
text('black',240,160,'Courier',0,17,1,0,0,1,63,14,119,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"hard link"]).
|
||||
text('black',216,368,'Courier',0,17,1,0,0,1,63,14,121,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"soft link"]).
|
347
doc/html/h5s.examples
Normal file
@ -0,0 +1,347 @@
|
||||
Example 1: Create a simple fixed size 3-D dataspace in memory and on disk and
|
||||
copy the entire dataset to disk.
|
||||
|
||||
{
|
||||
hid_t file; /* File ID */
|
||||
hid_t dataset; /* Dataset ID */
|
||||
hid_t mem_space, file_space; /* Dataspaces for memory and the file */
|
||||
uint8 *buf; /* Buffer for data */
|
||||
hsize_t curr_dims[3]={3,4,5}; /* Dimensions of the dataset */
|
||||
|
||||
/* Create file */
|
||||
file = H5Fcreate("example1.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
|
||||
|
||||
/* Create dataspace for dataset in the file */
|
||||
/* Selection for dataspace defaults to entire space */
|
||||
file_space=H5Screate(H5S_SIMPLE);
|
||||
|
||||
/* Set the extent & type of the dataset's dataspace */
|
||||
H5Sset_extent_simple(file_space,3,curr_dims,curr_dims);
|
||||
|
||||
/* Create the dataspace for the dataset in memory */
|
||||
/* Selection for dataspace defaults to entire space */
|
||||
mem_space=H5Screate(H5S_SIMPLE);
|
||||
|
||||
/* Set the extent & type of the memory dataspace */
|
||||
H5Sset_extent_simple(mem_space,3,curr_dims,curr_dims);
|
||||
|
||||
/* Create the dataset on disk */
|
||||
dataset=H5Dcreate(file,"Dataset",H5T_NATIVE_UINT8,file_space,H5P_DEFAULT);
|
||||
|
||||
/* Write the dataset to the file */
|
||||
H5Dwrite(dataset,H5T_NATIVE_UINT8,mem_space,file_space,H5P_DEFAULT,buf);
|
||||
|
||||
/* Close dataspaces */
|
||||
H5Sclose(mem_space);
|
||||
H5Sclose(file_space);
|
||||
|
||||
/* Close dataset & file */
|
||||
H5Dclose(dataset);
|
||||
H5Fclose(file);
|
||||
}
|
||||
|
||||
|
||||
Example 2: Create a simple fixed size 3-D dataspace in memory and on disk and
|
||||
copy a hyperslab to disk. The hyperslab blocks are packed and
|
||||
contiguous in memory, but are scattered when written to the dataset
|
||||
on disk.
|
||||
|
||||
{
|
||||
hid_t file; /* File ID */
|
||||
hid_t dataset; /* Dataset ID */
|
||||
hid_t mem_space, file_space; /* Dataspaces for memory and the file */
|
||||
uint8 *buf; /* Buffer for data */
|
||||
hssize_t start[3]={3,4,5}; /* Start of hyperslab */
|
||||
hsize_t stride[3]={1,2,2}; /* Stride for hyperslab */
|
||||
hsize_t count[3]={3,3,3}; /* Hyperslab block count in each dimension */
|
||||
hsize_t block[3]={2,2,2}; /* Hyperslab block size in each dimension */
|
||||
hsize_t curr_dims[3]={13,14,15}; /* Dimensions of the dataset */
|
||||
|
||||
/* Create file */
|
||||
file = H5Fcreate("example2.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
|
||||
|
||||
/* Create dataspace for dataset in the file */
|
||||
/* Selection for dataspace defaults to entire space */
|
||||
file_space=H5Screate(H5S_SIMPLE);
|
||||
|
||||
/* Set the extent & type of the dataset's dataspace */
|
||||
H5Sset_extent_simple(file_space,3,curr_dims,curr_dims);
|
||||
|
||||
/* Set the hyperslab selection for a file dataspace */
|
||||
H5Sselect_hyperslab(file_space,H5S_SELECT_SET,start,stride,count,block);
|
||||
|
||||
/* Create the dataspace for the dataset in memory */
|
||||
/* Selection for dataspace defaults to entire space */
|
||||
mem_space=H5Screate(H5S_SIMPLE);
|
||||
|
||||
/* Set the extent & type of the memory dataspace */
|
||||
/* Compute the memory dimensions based on the hyperslab blocks to write */
|
||||
for(i=0; i<3; i++)
|
||||
curr_dims[i]=count[i]*block[i];
|
||||
H5Sset_extent_simple(mem_space,3,curr_dims,curr_dims);
|
||||
|
||||
/* Create the dataset on disk */
|
||||
dataset=H5Dcreate(file,"Dataset",H5T_NATIVE_UINT8,file_space,H5P_DEFAULT);
|
||||
|
||||
/* Write the hyperslab to the file */
|
||||
H5Dwrite(dataset,H5T_NATIVE_UINT8,mem_space,file_space,H5P_DEFAULT,buf);
|
||||
|
||||
/* Close dataspaces */
|
||||
H5Sclose(mem_space);
|
||||
H5Sclose(file_space);
|
||||
|
||||
/* Close dataset & file */
|
||||
H5Dclose(dataset);
|
||||
H5Fclose(file);
|
||||
}
|
||||
|
||||
|
||||
Example 3: Create a simple fixed size 3-D dataspace in memory and on disk and
|
||||
copy a specific selection of points (with a particular order) to
|
||||
disk. The memory and file dataspaces are different sizes, but the number
|
||||
of points selected are the same.
|
||||
|
||||
{
|
||||
hid_t file; /* File ID */
|
||||
hid_t dataset; /* Dataset ID */
|
||||
hid_t mem_space, file_space; /* Dataspaces for memory and the file */
|
||||
uint8 *buf; /* Buffer for data */
|
||||
hsize_t elements[5][3]; /* Dataspace elements selected */
|
||||
hsize_t curr_dims[3]={13,14,15}; /* Dimensions of the dataset */
|
||||
|
||||
/* Create file */
|
||||
file = H5Fcreate("example3.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
|
||||
|
||||
/* Create dataspace for dataset in the file */
|
||||
/* Selection for dataspace defaults to entire space */
|
||||
file_space=H5Screate(H5S_SIMPLE);
|
||||
|
||||
/* Set the extent & type of the dataset's dataspace */
|
||||
H5Sset_extent_simple(file_space,3,curr_dims,curr_dims);
|
||||
|
||||
/* Set the elements for the selection in the file dataspace */
|
||||
elements[0]={0,2,4}; /* Yes, I know this won't compile.. :-) */
|
||||
elements[1]={3,4,1};
|
||||
elements[2]={9,8,3};
|
||||
elements[3]={7,2,0};
|
||||
elements[4]={6,5,8};
|
||||
H5Sselect_elements(file_space,H5S_SELECT_SET,5,elements);
|
||||
|
||||
/* Create the dataspace for the dataset in memory */
|
||||
/* Selection for dataspace defaults to entire space */
|
||||
mem_space=H5Screate(H5S_SIMPLE);
|
||||
|
||||
/* Set the extent & type of the memory dataspace */
|
||||
curr_dims={23,15,18}; /* This won't compile either :-) */
|
||||
H5Sset_extent_simple(mem_space,3,curr_dims,curr_dims);
|
||||
|
||||
/* Set the elements for the selection in the file dataspace */
|
||||
elements[0]={9,2,1};
|
||||
elements[1]={13,1,12};
|
||||
elements[2]={4,1,7};
|
||||
elements[3]={0,12,0};
|
||||
elements[4]={20,10,17};
|
||||
H5Sselect_elements(mem_space,H5S_SELECT_SET,5,elements);
|
||||
|
||||
/* Create the dataset on disk */
|
||||
dataset=H5Dcreate(file,"Dataset",H5T_NATIVE_UINT8,file_space,H5P_DEFAULT);
|
||||
|
||||
/* Write the hyperslab to the file */
|
||||
H5Dwrite(dataset,H5T_NATIVE_UINT8,mem_space,file_space,H5P_DEFAULT,buf);
|
||||
|
||||
/* Close dataspaces */
|
||||
H5Sclose(mem_space);
|
||||
H5Sclose(file_space);
|
||||
|
||||
/* Close dataset & file */
|
||||
H5Dclose(dataset);
|
||||
H5Fclose(file);
|
||||
}
|
||||
|
||||
|
||||
Example 4: Create a simple fixed size 3-D dataspace in memory and on disk and
|
||||
build up selection hyperslab selections to copy from memory to disk. The
|
||||
selection is the same for both dataspaces, but a different offset is used,
|
||||
to illustrate the selection offsets.
|
||||
|
||||
{
|
||||
hid_t file; /* File ID */
|
||||
hid_t dataset; /* Dataset ID */
|
||||
hid_t mem_space, file_space; /* Dataspaces for memory and the file */
|
||||
uint8 *buf; /* Buffer for data */
|
||||
hssize_t start[3]; /* Start of hyperslab */
|
||||
hsize_t stride[3]; /* Stride for hyperslab */
|
||||
hsize_t count[3]; /* Hyperslab block count in each dimension */
|
||||
hsize_t block[3]; /* Hyperslab block size in each dimension */
|
||||
hssize_t offset[3]; /* Selection offset */
|
||||
hsize_t curr_dims[3]={13,14,15}; /* Dimensions of the dataset */
|
||||
|
||||
/* Create file */
|
||||
file = H5Fcreate("example4.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
|
||||
|
||||
/* Create dataspace for dataset in the file */
|
||||
/* Selection for dataspace defaults to entire space */
|
||||
file_space=H5Screate(H5S_SIMPLE);
|
||||
|
||||
/* Set the extent & type of the dataset's dataspace */
|
||||
H5Sset_extent_simple(file_space,3,curr_dims,curr_dims);
|
||||
|
||||
/* Build up the selection with a series of hyperslab selections */
|
||||
start={0,2,4}; /* Again, this won't compile.. :-) */
|
||||
stride={1,1,1};
|
||||
count={6,5,8};
|
||||
block={1,1,1};
|
||||
|
||||
/* Set the first selection, union the rest in */
|
||||
H5Sselect_hyperslab(file_space,H5S_SELECT_SET,start,stride,count,block);
|
||||
|
||||
/* initialize the second hyperslab */
|
||||
start={10,9,1}; /* Again, this won't compile.. :-) */
|
||||
stride={1,1,1};
|
||||
count={2,3,10};
|
||||
block={1,1,1};
|
||||
|
||||
/* Union the second hyperslab into the file dataspace's selection */
|
||||
H5Sselect_hyperslab(file_space,H5S_SELECT_UNION,start,stride,count,block);
|
||||
|
||||
/* initialize the third hyperslab */
|
||||
start={3,10,5}; /* Again, this won't compile.. :-) */
|
||||
stride={1,1,1};
|
||||
count={8,2,6};
|
||||
block={1,1,1};
|
||||
|
||||
/* Union the final hyperslab into the file dataspace's selection */
|
||||
H5Sselect_hyperslab(file_space,H5S_SELECT_UNION,start,stride,count,block);
|
||||
|
||||
/* Create the dataspace for the dataset in memory */
|
||||
/* Selection for dataspace defaults to entire space */
|
||||
mem_space=H5Screate(H5S_SIMPLE);
|
||||
|
||||
/* Set the extent & type of the memory dataspace */
|
||||
curr_dims={23,15,18}; /* This won't compile either :-) */
|
||||
H5Sset_extent_simple(mem_space,3,curr_dims,curr_dims);
|
||||
|
||||
/* Copy the selection from the file dataspace */
|
||||
H5Sselect_op(mem_space,H5S_SELECT_COPY,file_space);
|
||||
|
||||
/* Adjust the offset of the selection in the memory dataspace */
|
||||
offset={1,1,1};
|
||||
H5Soffset_simple(mem_space,offset);
|
||||
|
||||
/* Create the dataset on disk */
|
||||
dataset=H5Dcreate(file,"Dataset",H5T_NATIVE_UINT8,file_space,H5P_DEFAULT);
|
||||
|
||||
/* Write the hyperslab to the file */
|
||||
H5Dwrite(dataset,H5T_NATIVE_UINT8,mem_space,file_space,H5P_DEFAULT,buf);
|
||||
|
||||
/* Close dataspaces */
|
||||
H5Sclose(mem_space);
|
||||
H5Sclose(file_space);
|
||||
|
||||
/* Close dataset & file */
|
||||
H5Dclose(dataset);
|
||||
H5Fclose(file);
|
||||
}
|
||||
|
||||
|
||||
Example 5: Same as example 1 (create a simple fixed size 3-D dataspace in memory and on disk and
|
||||
copy the entire dataset to disk), except that the selection order is changed
|
||||
for the memory dataspace, to change between FORTRAN and C array ordering.
|
||||
|
||||
{
|
||||
hid_t file; /* File ID */
|
||||
hid_t dataset; /* Dataset ID */
|
||||
hid_t mem_space, file_space; /* Dataspaces for memory and the file */
|
||||
uint8 *buf; /* Buffer for data */
|
||||
hsize_t order[3]; /* Dimension ordering for selection */
|
||||
hsize_t curr_dims[3]={3,4,5}; /* Dimensions of the dataset */
|
||||
|
||||
/* Create file */
|
||||
file = H5Fcreate("example5.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
|
||||
|
||||
/* Create dataspace for dataset in the file */
|
||||
/* Selection for dataspace defaults to entire space and C array order */
|
||||
file_space=H5Screate(H5S_SIMPLE);
|
||||
|
||||
/* Set the extent & type of the dataset's dataspace */
|
||||
H5Sset_extent_simple(file_space,3,curr_dims,curr_dims);
|
||||
|
||||
/* Create the dataspace for the dataset in memory */
|
||||
/* Selection for dataspace defaults to entire space and C array order */
|
||||
mem_space=H5Screate(H5S_SIMPLE);
|
||||
|
||||
/* Set the extent & type of the memory dataspace */
|
||||
H5Sset_extent_simple(mem_space,3,curr_dims,curr_dims);
|
||||
|
||||
/* Change selection ordering to FORTRAN order for memory dataspace */
|
||||
order={0,1,2};
|
||||
H5Sselect_order(mem_space,order);
|
||||
|
||||
/* Create the dataset on disk */
|
||||
dataset=H5Dcreate(file,"Dataset",H5T_NATIVE_UINT8,file_space,H5P_DEFAULT);
|
||||
|
||||
/* Write the dataset to the file */
|
||||
H5Dwrite(dataset,H5T_NATIVE_UINT8,mem_space,file_space,H5P_DEFAULT,buf);
|
||||
|
||||
/* Close dataspaces */
|
||||
H5Sclose(mem_space);
|
||||
H5Sclose(file_space);
|
||||
|
||||
/* Close dataset & file */
|
||||
H5Dclose(dataset);
|
||||
H5Fclose(file);
|
||||
}
|
||||
|
||||
|
||||
Example 6: Create a stored dataspace on disk and use the H5Ssubspace function
|
||||
create a dataspace located within that space.
|
||||
|
||||
{
|
||||
hid_t file; /* File ID */
|
||||
hid_t space1, space2; /* Dataspace IDs */
|
||||
hssize_t start[3]; /* Start of hyperslab */
|
||||
hsize_t count[3]; /* Hyperslab block count in each dimension */
|
||||
hsize_t curr_dims[3]={13,14,15};/* Dimensions of the dataset */
|
||||
|
||||
/* Create file */
|
||||
file = H5Fcreate("example6.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
|
||||
|
||||
/* Create dataspace #1 */
|
||||
space1=H5Screate(H5S_SIMPLE);
|
||||
|
||||
/* Set the extent & type of dataspace #1 */
|
||||
H5Sset_extent_simple(space1,3,curr_dims,curr_dims);
|
||||
|
||||
/* Store dataspace #1 on disk */
|
||||
H5Scommit(file,"/Dataspaces/Dataspace #1",space1);
|
||||
|
||||
/* Select a contiguous hyperslab in dataspace #1 to create dataspace #2 with */
|
||||
start={0,2,4};
|
||||
count={6,5,8};
|
||||
|
||||
/*
|
||||
* Use stride and block set to NULL to get contiguous, single element sized
|
||||
* hyperslab. The stride and block parameters could also be set to all
|
||||
* 1's, but this is simpler and easier.
|
||||
*/
|
||||
H5Sselect_hyperslab(space1,H5S_SELECT_SET,start,NULL,count,NULL);
|
||||
|
||||
/* Create dataspace #2 as a dataspace located within dataspace #1 */
|
||||
space2=H5Ssubspace(space1);
|
||||
|
||||
/* Store dataspace #2 on disk also */
|
||||
H5Scommit(file,"/Dataspaces/Dataspace #2",space2);
|
||||
|
||||
/*
|
||||
* space1 & space2 can be used to create datasets, etc. Any datasets
|
||||
* created with space2 can have their dataspace queried to find the parent
|
||||
* dataspace and the location within the parent dataspace
|
||||
*/
|
||||
|
||||
/* Close dataspaces */
|
||||
H5Sclose(space1);
|
||||
H5Sclose(space2);
|
||||
|
||||
/* Close file */
|
||||
H5Fclose(file);
|
||||
}
|
72
doc/html/heap.txt
Normal file
@ -0,0 +1,72 @@
|
||||
HEAP MANAGEMENT IN HDF5
|
||||
------------------------
|
||||
|
||||
Heap functions are in the H5H package.
|
||||
|
||||
|
||||
off_t
|
||||
H5H_new (hdf5_file_t *f, size_t size_hint, size_t realloc_hint);
|
||||
|
||||
Creates a new heap in the specified file which can efficiently
|
||||
store at least SIZE_HINT bytes. The heap can store more than
|
||||
that, but doing so may cause the heap to become less efficient
|
||||
(for instance, a heap implemented as a B-tree might become
|
||||
discontigous). The REALLOC_HINT is the minimum number of bytes
|
||||
by which the heap will grow when it must be resized. The hints
|
||||
may be zero in which case reasonable (but probably not
|
||||
optimal) values will be chosen.
|
||||
|
||||
The return value is the address of the new heap relative to
|
||||
the beginning of the file boot block.
|
||||
|
||||
off_t
|
||||
H5H_insert (hdf5_file_t *f, off_t addr, size_t size, const void *buf);
|
||||
|
||||
Copies SIZE bytes of data from BUF into the heap whose address
|
||||
is ADDR in file F. BUF must be the _entire_ heap object. The
|
||||
return value is the byte offset of the new data in the heap.
|
||||
|
||||
void *
|
||||
H5H_read (hdf5_file_t *f, off_t addr, off_t offset, size_t size, void *buf);
|
||||
|
||||
Copies SIZE bytes of data from the heap whose address is ADDR
|
||||
in file F into BUF and then returns the address of BUF. If
|
||||
BUF is the null pointer then a new buffer will be malloc'd by
|
||||
this function and its address is returned.
|
||||
|
||||
Returns buffer address or null.
|
||||
|
||||
const void *
|
||||
H5H_peek (hdf5_file_t *f, off_t addr, off_t offset)
|
||||
|
||||
A more efficient version of H5H_read that returns a pointer
|
||||
directly into the cache; the data is not copied from the cache
|
||||
to a buffer. The pointer is valid until the next call to an
|
||||
H5AC function directly or indirectly.
|
||||
|
||||
Returns a pointer or null. Do not free the pointer.
|
||||
|
||||
void *
|
||||
H5H_write (hdf5_file_t *f, off_t addr, off_t offset, size_t size,
|
||||
const void *buf);
|
||||
|
||||
Modifies (part of) an object in the heap at address ADDR of
|
||||
file F by copying SIZE bytes from the beginning of BUF to the
|
||||
file. OFFSET is the address withing the heap where the output
|
||||
is to occur.
|
||||
|
||||
This function can fail if the combination of OFFSET and SIZE
|
||||
would write over a boundary between two heap objects.
|
||||
|
||||
herr_t
|
||||
H5H_remove (hdf5_file_t *f, off_t addr, off_t offset, size_t size);
|
||||
|
||||
Removes an object or part of an object which begins at byte
|
||||
OFFSET within a heap whose address is ADDR in file F. SIZE
|
||||
bytes are returned to the free list. Removing the middle of
|
||||
an object has the side effect that one object is now split
|
||||
into two objects.
|
||||
|
||||
Returns success or failure.
|
||||
|
||||
|
40
doc/html/index.html
Normal file
@ -0,0 +1,40 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
HDF5 - The Next Generation of the HDF library & tools
|
||||
</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<center><h1>HDF5 - A New Generation of HDF</h1></center>
|
||||
<UL>
|
||||
<LI><A HREF="H5.intro.html">An Introduction to HDF5</A> - A brief overview of
|
||||
the design goals behind the HDF5 library & file format
|
||||
</LI>
|
||||
<LI><A HREF="H5.api.html">HDF5 Reference Manual</A> - A complete reference
|
||||
manual for the HDF5 API
|
||||
</LI>
|
||||
<LI><A HREF="H5.user.html">HDF5 User Guide</A> - A collection of chapters on
|
||||
each of the main HDF5 APIs as well as other supporting information
|
||||
</LI>
|
||||
<LI><A HREF="H5.format.html">HDF5 Format Specification</A> - The complete
|
||||
specification of the HDF5 file format
|
||||
</LI>
|
||||
<LI><A HREF="ph5design.html">Parallel HDF5 Design</A> - The design
|
||||
specification of the parallel HDF5 API and an example program
|
||||
</LI>
|
||||
<LI><A HREF="ph5implement.txt">Parallel HDF5 Implementation</A> - The
|
||||
current status of implmentation of the parallel HDF5 API
|
||||
</LI>
|
||||
</UL>
|
||||
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:koziol@ncsa.uiuc.edu">Quincey Koziol</a></address>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- hhmts start -->
|
||||
Last modified: Feb 16, 1998
|
||||
<!-- hhmts end -->
|
||||
|
||||
</body>
|
||||
</html>
|
66
doc/html/move.html
Normal file
@ -0,0 +1,66 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>How to Relocate a File Data Structure</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>How to Relocate a File Data Structure</h1>
|
||||
|
||||
<p>Since file data structures can be cached in memory by the H5AC
|
||||
package it becomes problematic to move such a data structure in
|
||||
the file. One cannot just copy a portion of the file from one
|
||||
location to another because:
|
||||
|
||||
<ol>
|
||||
<li>the file might not contain the latest information, and</li>
|
||||
<li>the H5AC package might not realize that the object's
|
||||
address has changed and attempt to write the object to disk
|
||||
at the old address.</li>
|
||||
</ol>
|
||||
|
||||
<p>Here's a correct method to move data from one location to
|
||||
another. The example code assumes that one is moving a B-link
|
||||
tree node from <code>old_addr</code> to <code>new_addr</code>.
|
||||
|
||||
<ol>
|
||||
<li>Make sure the disk is up-to-date with respect to the
|
||||
cache. There is no need to remove the item from the cache,
|
||||
hence the final argument to <code>H5AC_flush</code> is
|
||||
<code>FALSE</code>.
|
||||
<br><br>
|
||||
<code>
|
||||
H5AC_flush (f, H5AC_BT, old_addr, FALSE);<br>
|
||||
</code>
|
||||
<br>
|
||||
</li>
|
||||
|
||||
<li>Read the data from the old address and write it to the new
|
||||
address.
|
||||
<br><br>
|
||||
<code>
|
||||
H5F_block_read (f, old_addr, size, buf);<br>
|
||||
H5F_block_write (f, new_addr, size, buf);<br>
|
||||
</code>
|
||||
<br>
|
||||
</li>
|
||||
|
||||
<li>Notify the cache that the address of the object changed.
|
||||
<br><br>
|
||||
<code>
|
||||
H5AC_rename (f, H5AC_BT, old_addr, new_addr);<br>
|
||||
</code>
|
||||
<br>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:robb@maya.nuance.com">Robb Matzke</a></address>
|
||||
<!-- Created: Mon Jul 14 15:09:06 EST 1997 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Mon Jul 14 15:38:29 EST
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
77
doc/html/ph5design.html
Normal file
@ -0,0 +1,77 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
|
||||
<META NAME="Generator" CONTENT="Microsoft Word 97">
|
||||
<TITLE>new</TITLE>
|
||||
<META NAME="Template" CONTENT="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
||||
</HEAD>
|
||||
<BODY LINK="#0000ff" VLINK="#800080">
|
||||
|
||||
<B><FONT SIZE=6><P ALIGN="CENTER">Parallel HDF5 Design</P>
|
||||
</B></FONT><P ALIGN="CENTER"> </P>
|
||||
<H1>1. Design Overview</H1>
|
||||
<P>In this section, I first describe the function requirements of the Parallel HDF5 (PHDF5) software and the assumed system requirements. Section 2 describes the programming model of the PHDF5 interface. Section 3 shows an example PHDF5 program. </P>
|
||||
<H2>1.1. Function requirements</H2>
|
||||
|
||||
<UL>
|
||||
<LI>An API to support parallel file access for HDF5 files in a message passing environment. </LI>
|
||||
<LI>Fast parallel I/O to large datasets through standard parallel I/O interface.</LI>
|
||||
<LI>Processes are required to do collective API calls only when structural changes are needed for the HDF5 file. </LI>
|
||||
<LI>Each process may do independent I/O requests to different datasets in the same or different HDF5 files. </LI>
|
||||
<LI>Supports collective I/O requests for datasets (to be included in next version). </LI>
|
||||
<LI>Minimize diviation from HDF5 interface.</LI>
|
||||
</UL>
|
||||
|
||||
<H2>1.2. System requirements</H2>
|
||||
|
||||
<UL>
|
||||
<LI>C language interface is the initial requirement. Fortran77 interface will be added later. </LI>
|
||||
<LI>Use Message Passing Interface (MPI) for interprocess communication. </LI>
|
||||
<LI>Use MPI-IO calls for parallel file accesses. </LI>
|
||||
<LI>Initial platforms—IBM SP2, Intel TFLOPS and SGI Origin 2000. </LI></UL>
|
||||
|
||||
<H1>2. Programming Model</H1>
|
||||
<P>HDF5 uses optional access template object to control the file access
|
||||
mechanism. The general model in accessing an HDF5 file in parallel
|
||||
contains the following steps: </P>
|
||||
|
||||
<UL>
|
||||
<LI>Setup access template</LI>
|
||||
<LI>File open </LI>
|
||||
<LI>Dataset open </LI>
|
||||
<LI>Dataset data access (zero or more) </LI>
|
||||
<LI>Dataset close </LI>
|
||||
<LI>File close </LI></UL>
|
||||
|
||||
<H2>2.1. Setup access template</H2>
|
||||
<P>Each processes of the MPI communicator creates an access template and sets
|
||||
it up with MPI parallel access information (communicator, info object,
|
||||
access-mode). </P>
|
||||
<H2>2.1. File open</H2>
|
||||
<P>All processes of the MPI communicator open an HDF5 file by a collective call
|
||||
(H5FCreate or H5Fopen) with the access template. </P>
|
||||
<H2>2.2. Dataset open</H2>
|
||||
<P>All processes of the MPI communicator open a dataset by a collective call (H5Dcreate or H5Dopen). This version supports only collective dataset open. Future version may support datasets open by a subset of the processes that have opened the file. </P>
|
||||
<H2>2.3. Dataset access</H2>
|
||||
<H3>2.3.1. Independent dataset access</H3>
|
||||
<P>Each process may do independent and arbitrary number of data I/O access by independent calls (H5Dread or H5Dwrite) to the dataset with the transfer template set for independent access. (The default transfer mode is independent transfer). If the dataset is an unlimited dimension one and if the H5Dwrite is writing data beyond the current dimension size of the dataset, all processes that have opened the dataset must make a collective call (H5Dallocate) to allocate more space for the dataset BEFORE the independent H5Dwrite call. </P>
|
||||
<H3>2.3.2. Collective dataset access</H3>
|
||||
<P>All processes that have opened the dataset may do collective data I/O access by collective calls (H5Dread or H5Dwrite) to the dataset with the transfer template set for collective access. Pre-allocation (H5Dallocate) is not needed for unlimited dimension datasets since the H5Dallocate call, if needed, is done internally by the collective data access call. </P>
|
||||
<H3>2.3.3. Dataset attributes access</H3>
|
||||
<P>Changes to attributes can only occur at the <I>"main process" </I>(process 0). Read only access to attributes can occur independent in each process that has opened the dataset. (API to be defined later.) <BR>
|
||||
</P>
|
||||
<H2>2.4. Dataset close</H2>
|
||||
<P>All processes that have opened the dataset must close the dataset by a collective call (H5Dclose). </P>
|
||||
<H2>2.5. File close</H2>
|
||||
<P>All processes that have opened the file must close the file by a collective call (H5Fclose). <BR>
|
||||
</P>
|
||||
<H1>3. Parallel HDF5 Example</H1>
|
||||
<PRE>
|
||||
<CODE>
|
||||
</CODE><A HREF="ph5example.c">Example code</A>
|
||||
</PRE>
|
||||
<P><HR></P>
|
||||
<P>Send comments to <BR>
|
||||
<A HREF="mailto:hdfparallel@ncsa.uiuc.edu">hdfparallel@ncsa.uiuc.edu</A> </P>
|
||||
<H6>Last Modified: Feb 16, 1998</H6></BODY>
|
||||
</HTML>
|
1003
doc/html/ph5example.c
Normal file
27
doc/html/ph5implement.txt
Normal file
@ -0,0 +1,27 @@
|
||||
Release information for parallel HDF5
|
||||
-------------------------------------
|
||||
|
||||
+) Current release supports independent access to fixed dimension datasets
|
||||
only.
|
||||
|
||||
+) The comm and info arguments of H5Pset_mpi are not used. All parallel
|
||||
I/O are done via MPI_COMM_WORLD. Access_mode for H5Pset_mpi can be
|
||||
H5ACC_INDEPENDENT only.
|
||||
|
||||
+) This release of parallel HDF5 has been tested on IBM SP2 and SGI
|
||||
Origin 2000 systems. It uses the ROMIO version of MPIO interface
|
||||
for parallel I/O supports.
|
||||
|
||||
+) Useful URL's.
|
||||
Parallel HDF webpage: "http://hdf.ncsa.uiuc.edu/Parallel_HDF/"
|
||||
ROMIO webpage: "http://www.mcs.anl.gov/home/thakur/romio/"
|
||||
|
||||
+) Some to-do items for future releases
|
||||
support for Intel Teraflop platform.
|
||||
support for unlimited dimension datasets.
|
||||
support for file access via a communicator besides MPI_COMM_WORLD.
|
||||
support for collective access to datasets.
|
||||
support for independent create/open of datasets.
|
||||
|
||||
----
|
||||
Last updated: Feb 16, 1998.
|
BIN
doc/html/pipe1.gif
Normal file
After ![]() (image error) Size: 9.9 KiB |
136
doc/html/pipe1.obj
Normal file
@ -0,0 +1,136 @@
|
||||
%TGIF 3.0-p5
|
||||
state(1,33,100,0,0,0,8,1,9,1,1,0,0,0,0,1,1,'Helvetica',0,17,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1408,1088,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
box('black',64,64,128,256,0,1,1,22,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',80,96,112,224,26,1,1,23,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
128,160,912,160],1,2,1,24,0,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
160,160,144,224,160,272,176,224,160,160],1,2,1,25,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
848,160,832,224,848,272,864,224,848,160],1,2,1,34,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
box('black',464,192,496,256,26,1,1,39,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
160,224,464,224],1,2,1,40,0,26,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
496,224,848,224],1,2,1,41,0,26,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
192,224,176,288,192,336,208,288,192,224],1,2,1,42,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
432,224,416,288,432,336,448,288,432,224],1,2,1,43,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
192,288,432,288],1,2,1,44,0,26,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
box('black',464,352,496,416,26,1,1,45,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',5,[
|
||||
528,224,512,288,528,336,544,288,528,224],1,2,1,46,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
816,224,800,288,816,336,832,288,816,224],1,2,1,47,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
528,288,816,288],1,2,1,48,0,26,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
464,256,456,304,464,328,488,304,488,256],1,2,1,62,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
480,352,488,304],2,2,1,85,0,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
box('black',912,64,976,256,0,1,1,87,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',928,96,960,224,26,1,1,88,0,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',96,48,'Helvetica',0,17,1,1,0,1,21,15,89,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"File"]).
|
||||
text('black',944,48,'Helvetica',0,17,1,1,0,1,64,15,93,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Application"]).
|
||||
text('black',480,144,'Helvetica',0,17,1,1,0,1,65,15,99,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5D_read()"]).
|
||||
text('black',480,128,'Helvetica',0,17,1,1,0,1,58,15,108,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5Dread()"]).
|
||||
text('black',304,208,'Helvetica',0,17,1,1,0,1,86,15,115,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_arr_read()"]).
|
||||
text('black',304,192,'Helvetica',0,17,1,1,0,1,99,15,119,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5S_simp_fgath()"]).
|
||||
text('black',296,288,'Helvetica',0,17,1,1,0,1,101,15,125,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_block_read()"]).
|
||||
text('black',296,304,'Helvetica',0,17,1,1,0,1,90,15,132,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_low_read()"]).
|
||||
text('black',296,320,'Helvetica',0,17,1,1,0,1,98,15,136,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_sec2_read()"]).
|
||||
text('black',296,336,'Helvetica',0,17,1,1,0,1,33,15,140,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"read()"]).
|
||||
text('black',664,208,'Helvetica',0,17,1,1,0,1,106,15,146,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5V_stride_copy()"]).
|
||||
text('black',664,176,'Helvetica',0,17,1,1,0,1,104,15,150,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5S_simp_mscat()"]).
|
||||
text('black',664,272,'Helvetica',0,17,1,1,0,1,54,15,154,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"memcpy()"]).
|
||||
text('black',384,392,'Helvetica',0,17,1,1,0,1,105,15,170,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5T_conv_struct()"]).
|
||||
poly('black',4,[
|
||||
392,384,400,352,440,368,456,336],1,1,1,172,1,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"6",[
|
||||
]).
|
||||
text('black',480,176,'Helvetica',0,17,1,1,0,1,44,15,176,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"TCONV"]).
|
||||
text('black',480,416,'Helvetica',0,17,1,1,0,1,25,15,182,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"BKG"]).
|
||||
box('black',48,32,992,512,0,1,1,186,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',5,[
|
||||
72,392,56,456,72,504,88,456,72,392],1,2,1,188,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
text('black',96,448,'Helvetica',0,17,1,0,0,1,46,15,189,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"== Loop"]).
|
||||
poly('black',3,[
|
||||
48,384,152,384,152,512],0,1,1,191,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
text('black',480,40,'Helvetica',0,24,1,1,0,1,380,29,197,0,24,5,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Fig 1: Internal Contiguous Storage"]).
|
||||
text('black',136,144,'Helvetica',0,17,1,1,0,1,9,15,201,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"A"]).
|
||||
text('black',160,208,'Helvetica',0,17,1,1,0,1,8,15,207,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"B"]).
|
||||
text('black',192,272,'Helvetica',0,17,1,1,0,1,9,15,211,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"C"]).
|
||||
text('black',504,208,'Helvetica',0,17,1,1,0,1,8,15,215,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"E"]).
|
||||
text('black',528,272,'Helvetica',0,17,1,1,0,1,8,15,223,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"F"]).
|
||||
text('black',464,304,'Helvetica',0,17,1,1,0,1,9,15,231,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"D"]).
|
||||
text('black',664,192,'Helvetica',0,17,1,1,0,1,107,15,324,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5V_hyper_copy()"]).
|
BIN
doc/html/pipe2.gif
Normal file
After ![]() (image error) Size: 11 KiB |
168
doc/html/pipe2.obj
Normal file
@ -0,0 +1,168 @@
|
||||
%TGIF 3.0-p5
|
||||
state(1,33,100,0,0,0,8,1,9,1,1,1,1,0,0,1,1,'Helvetica',0,17,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1408,1088,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
box('black',64,64,128,256,0,1,1,22,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',80,96,112,224,26,1,1,23,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
128,160,912,160],1,2,1,24,0,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
160,160,144,224,160,272,176,224,160,160],1,2,1,25,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
848,160,832,224,848,272,864,224,848,160],1,2,1,34,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
box('black',464,192,496,256,26,1,1,39,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
160,224,464,224],1,2,1,40,0,26,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
496,224,848,224],1,2,1,41,0,26,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
192,224,176,288,192,336,208,288,192,224],1,2,1,42,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
432,224,416,288,432,336,448,288,432,224],1,2,1,43,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
192,288,432,288],1,2,1,44,0,26,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
box('black',464,352,496,416,26,1,1,45,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',5,[
|
||||
528,224,512,288,528,336,544,288,528,224],1,2,1,46,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
816,224,800,288,816,336,832,288,816,224],1,2,1,47,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
528,288,816,288],1,2,1,48,0,26,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
848,240,848,352,832,384,800,384,496,384],1,2,1,55,1,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"70",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
528,384,512,448,528,496,544,448,528,384],1,2,1,57,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
800,384,784,448,800,496,816,448,800,384],1,2,1,58,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
800,448,528,448],1,2,1,61,0,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
464,256,456,304,464,328,488,304,488,256],1,2,1,62,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
480,352,488,304],0,2,1,85,0,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
box('black',912,64,976,256,0,1,1,87,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',928,96,960,224,26,1,1,88,0,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',96,48,'Helvetica',0,17,1,1,0,1,21,15,89,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"File"]).
|
||||
text('black',944,48,'Helvetica',0,17,1,1,0,1,64,15,93,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Application"]).
|
||||
text('black',480,144,'Helvetica',0,17,1,1,0,1,65,15,99,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5D_read()"]).
|
||||
text('black',480,128,'Helvetica',0,17,1,1,0,1,58,15,108,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5Dread()"]).
|
||||
text('black',304,208,'Helvetica',0,17,1,1,0,1,86,15,115,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_arr_read()"]).
|
||||
text('black',304,192,'Helvetica',0,17,1,1,0,1,99,15,119,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5S_simp_fgath()"]).
|
||||
text('black',296,288,'Helvetica',0,17,1,1,0,1,101,15,125,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_block_read()"]).
|
||||
text('black',296,304,'Helvetica',0,17,1,1,0,1,90,15,132,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_low_read()"]).
|
||||
text('black',296,320,'Helvetica',0,17,1,1,0,1,98,15,136,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_sec2_read()"]).
|
||||
text('black',296,336,'Helvetica',0,17,1,1,0,1,33,15,140,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"read()"]).
|
||||
text('black',664,208,'Helvetica',0,17,1,1,0,1,106,15,146,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5V_stride_copy()"]).
|
||||
text('black',664,176,'Helvetica',0,17,1,1,0,1,104,15,150,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5S_simp_mscat()"]).
|
||||
text('black',664,272,'Helvetica',0,17,1,1,0,1,54,15,154,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"memcpy()"]).
|
||||
text('black',672,368,'Helvetica',0,17,1,1,0,1,106,15,158,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5V_stride_copy()"]).
|
||||
text('black',672,336,'Helvetica',0,17,1,1,0,1,105,15,162,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5S_simp_mgath()"]).
|
||||
text('black',672,432,'Helvetica',0,17,1,1,0,1,54,15,166,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"memcpy()"]).
|
||||
text('black',384,392,'Helvetica',0,17,1,1,0,1,105,15,170,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5T_conv_struct()"]).
|
||||
poly('black',4,[
|
||||
392,384,400,352,440,368,456,336],1,1,1,172,1,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"6",[
|
||||
]).
|
||||
text('black',480,176,'Helvetica',0,17,1,1,0,1,44,15,176,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"TCONV"]).
|
||||
text('black',480,416,'Helvetica',0,17,1,1,0,1,25,15,182,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"BKG"]).
|
||||
box('black',48,32,992,512,0,1,1,186,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',5,[
|
||||
72,392,56,456,72,504,88,456,72,392],1,2,1,188,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
text('black',96,448,'Helvetica',0,17,1,0,0,1,46,15,189,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"== Loop"]).
|
||||
poly('black',3,[
|
||||
48,384,152,384,152,512],0,1,1,191,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
text('black',480,40,'Helvetica',0,24,1,1,0,1,404,29,197,0,24,5,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Fig 2: Partially Initialized Destination"]).
|
||||
text('black',136,144,'Helvetica',0,17,1,1,0,1,9,15,201,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"A"]).
|
||||
text('black',160,208,'Helvetica',0,17,1,1,0,1,8,15,207,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"B"]).
|
||||
text('black',192,272,'Helvetica',0,17,1,1,0,1,9,15,211,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"C"]).
|
||||
text('black',504,208,'Helvetica',0,17,1,1,0,1,8,15,215,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"E"]).
|
||||
text('black',528,272,'Helvetica',0,17,1,1,0,1,8,15,223,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"F"]).
|
||||
text('black',856,288,'Helvetica',0,17,1,1,0,1,9,15,225,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"G"]).
|
||||
text('black',800,432,'Helvetica',0,17,1,1,0,1,9,15,229,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H"]).
|
||||
text('black',464,304,'Helvetica',0,17,1,1,0,1,9,15,231,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"D"]).
|
||||
poly('black',4,[
|
||||
848,240,848,224,864,224,904,224],0,2,1,318,1,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"6",[
|
||||
]).
|
||||
text('black',664,192,'Helvetica',0,17,1,1,0,1,107,15,326,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5V_hyper_copy()"]).
|
||||
text('black',672,352,'Helvetica',0,17,1,1,0,1,107,15,334,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5V_hyper_copy()"]).
|
BIN
doc/html/pipe3.gif
Normal file
After ![]() (image error) Size: 6.8 KiB |
70
doc/html/pipe3.obj
Normal file
@ -0,0 +1,70 @@
|
||||
%TGIF 3.0-p5
|
||||
state(1,33,100,0,0,0,8,1,9,1,1,0,0,0,0,1,1,'Helvetica',0,17,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1408,1088,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
box('black',64,64,128,256,0,1,1,22,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',80,96,112,224,26,1,1,23,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
128,160,912,160],1,2,1,24,0,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
box('black',912,64,976,256,0,1,1,87,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',928,96,960,224,26,1,1,88,0,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',96,48,'Helvetica',0,17,1,1,0,1,21,15,89,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"File"]).
|
||||
text('black',944,48,'Helvetica',0,17,1,1,0,1,64,15,93,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Application"]).
|
||||
text('black',480,104,'Helvetica',0,17,1,1,0,1,65,15,99,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5D_read()"]).
|
||||
text('black',480,88,'Helvetica',0,17,1,1,0,1,58,15,108,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5Dread()"]).
|
||||
box('black',48,32,992,512,0,1,1,186,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',5,[
|
||||
72,392,56,456,72,504,88,456,72,392],1,2,1,188,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
text('black',96,448,'Helvetica',0,17,1,0,0,1,46,15,189,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"== Loop"]).
|
||||
poly('black',3,[
|
||||
48,384,152,384,152,512],0,1,1,191,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
text('black',480,40,'Helvetica',0,24,1,1,0,1,295,29,197,0,24,5,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Fig 3: No Type Conversion"]).
|
||||
text('black',136,144,'Helvetica',0,17,1,1,0,1,9,15,201,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"A"]).
|
||||
poly('black',5,[
|
||||
152,160,136,224,152,272,168,224,152,160],1,2,1,273,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
text('black',480,120,'Helvetica',0,17,1,1,0,1,96,15,277,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5S_simp_read()"]).
|
||||
text('black',480,136,'Helvetica',0,17,1,1,0,1,86,15,281,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_arr_read()"]).
|
||||
poly('black',5,[
|
||||
880,160,864,224,880,272,896,224,880,160],1,2,1,283,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
152,224,880,224],1,2,1,286,0,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
text('black',480,232,'Helvetica',0,17,1,1,0,1,101,15,291,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_block_read()"]).
|
||||
text('black',480,248,'Helvetica',0,17,1,1,0,1,90,15,293,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_low_read()"]).
|
||||
text('black',480,264,'Helvetica',0,17,1,1,0,1,98,15,309,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_sec2_read()"]).
|
||||
text('black',480,280,'Helvetica',0,17,1,1,0,1,33,15,311,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"read()"]).
|
||||
text('black',176,208,'Helvetica',0,17,1,1,0,1,8,15,418,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"B"]).
|
BIN
doc/html/pipe4.gif
Normal file
After ![]() (image error) Size: 8.2 KiB |
92
doc/html/pipe4.obj
Normal file
@ -0,0 +1,92 @@
|
||||
%TGIF 3.0-p5
|
||||
state(1,33,100,0,0,0,8,1,9,1,1,1,2,1,0,1,0,'Helvetica',0,17,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1408,1088,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
box('black',64,64,128,256,0,1,1,22,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',80,96,112,224,26,1,1,23,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
128,160,912,160],1,2,1,24,0,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
box('black',912,96,944,224,26,1,1,88,0,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',96,48,'Helvetica',0,17,1,1,0,1,21,15,89,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"File"]).
|
||||
text('black',928,72,'Helvetica',0,17,1,1,0,1,32,15,93,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Buffer"]).
|
||||
box('black',48,32,992,512,0,1,1,186,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',5,[
|
||||
72,392,56,456,72,504,88,456,72,392],1,2,1,188,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
text('black',96,448,'Helvetica',0,17,1,0,0,1,46,15,189,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"== Loop"]).
|
||||
poly('black',3,[
|
||||
48,384,152,384,152,512],0,1,1,191,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
text('black',480,40,'Helvetica',0,24,1,1,0,1,372,29,197,0,24,5,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Fig 4: Regularly Chunked Storage"]).
|
||||
text('black',136,144,'Helvetica',0,17,1,1,0,1,9,15,201,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"A"]).
|
||||
text('black',480,104,'Helvetica',0,17,1,1,0,1,86,15,281,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_arr_read()"]).
|
||||
text('black',480,120,'Helvetica',0,17,1,1,0,1,102,15,349,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_istore_read()"]).
|
||||
text('black',480,136,'Helvetica',0,17,1,1,0,1,167,15,351,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_istore_copy_hyperslab()"]).
|
||||
poly('black',5,[
|
||||
160,160,144,224,160,272,176,224,160,160],1,2,1,362,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
poly('black',5,[
|
||||
880,160,864,224,880,272,896,224,880,160],1,2,1,363,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
box('black',448,192,512,256,26,1,1,364,0,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',480,176,'Helvetica',0,17,1,1,0,1,43,15,367,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"CHUNK"]).
|
||||
poly('black',2,[
|
||||
160,224,448,224],1,2,1,372,0,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
512,224,880,224],1,2,1,373,0,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
text('black',288,224,'Helvetica',0,17,1,1,0,1,101,15,385,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_block_read()"]).
|
||||
text('black',288,240,'Helvetica',0,17,1,1,0,1,90,15,387,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_low_read()"]).
|
||||
text('black',288,256,'Helvetica',0,17,1,1,0,1,98,15,391,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_sec2_read()"]).
|
||||
text('black',288,272,'Helvetica',0,17,1,1,0,1,33,15,395,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"read()"]).
|
||||
poly('black',5,[
|
||||
456,256,448,296,480,320,512,296,504,256],1,2,1,401,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
text('black',184,208,'Helvetica',0,17,1,1,0,1,8,15,422,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"B"]).
|
||||
text('black',520,208,'Helvetica',0,17,1,1,0,1,9,15,434,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"D"]).
|
||||
text('black',440,272,'Helvetica',0,17,1,1,0,1,9,15,440,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"C"]).
|
||||
text('black',480,320,'Helvetica',0,17,1,1,0,1,107,15,444,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5Z_uncompress()"]).
|
||||
text('black',672,224,'Helvetica',0,17,1,1,0,1,107,15,454,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5V_hyper_copy()"]).
|
||||
text('black',672,240,'Helvetica',0,17,1,1,0,1,106,15,464,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5V_stride_copy()"]).
|
||||
text('black',672,256,'Helvetica',0,17,1,1,0,1,54,15,466,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"memcpy()"]).
|
||||
text('black',168,488,'Helvetica',0,17,1,0,0,1,282,15,471,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"NOTE: H5Z_uncompress() is not implemented yet."]).
|
BIN
doc/html/pipe5.gif
Normal file
After ![]() (image error) Size: 6.1 KiB |
52
doc/html/pipe5.obj
Normal file
@ -0,0 +1,52 @@
|
||||
%TGIF 3.0-p5
|
||||
state(1,33,100,0,0,0,8,1,9,1,1,1,2,1,0,1,0,'Helvetica',0,17,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1408,1088,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
box('black',64,64,128,256,0,1,1,22,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',80,96,112,224,26,1,1,23,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
128,160,912,160],1,2,1,24,0,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"0",[
|
||||
]).
|
||||
box('black',912,96,944,224,26,1,1,88,0,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',96,48,'Helvetica',0,17,1,1,0,1,21,15,89,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"File"]).
|
||||
text('black',928,72,'Helvetica',0,17,1,1,0,1,32,15,93,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Buffer"]).
|
||||
box('black',48,32,992,512,0,1,1,186,0,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',480,40,'Helvetica',0,24,1,1,0,1,333,29,197,0,24,5,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Fig 5: Reading a Single Chunk"]).
|
||||
text('black',136,144,'Helvetica',0,17,1,1,0,1,9,15,201,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"A"]).
|
||||
text('black',480,112,'Helvetica',0,17,1,1,0,1,86,15,281,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_arr_read()"]).
|
||||
text('black',480,128,'Helvetica',0,17,1,1,0,1,102,15,349,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_istore_read()"]).
|
||||
text('black',480,144,'Helvetica',0,17,1,1,0,1,167,15,351,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_istore_copy_hyperslab()"]).
|
||||
text('black',480,160,'Helvetica',0,17,1,1,0,1,101,15,385,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_block_read()"]).
|
||||
text('black',480,176,'Helvetica',0,17,1,1,0,1,90,15,387,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_low_read()"]).
|
||||
text('black',480,192,'Helvetica',0,17,1,1,0,1,98,15,391,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5F_sec2_read()"]).
|
||||
text('black',480,208,'Helvetica',0,17,1,1,0,1,33,15,395,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"read()"]).
|
||||
text('black',864,240,'Helvetica',0,17,1,1,0,1,107,15,444,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"H5Z_uncompress()"]).
|
||||
text('black',56,488,'Helvetica',0,17,1,0,0,1,282,15,471,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"NOTE: H5Z_uncompress() is not implemented yet."]).
|
||||
poly('black',5,[
|
||||
912,176,864,176,840,208,872,232,912,216],1,2,1,490,2,0,0,0,10,4,0,0,0,'2','10','4',
|
||||
"",[
|
||||
]).
|
||||
text('black',896,184,'Helvetica',0,17,1,0,0,1,8,15,491,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"B"]).
|
283
doc/html/review1.html
Normal file
@ -0,0 +1,283 @@
|
||||
<html><head><title>
|
||||
HDF5 Draft Revised API Example Code
|
||||
</title></head><body>
|
||||
|
||||
<center>
|
||||
<h1>HDF5: Revised API Example Code</h1>
|
||||
</center>
|
||||
|
||||
<P>Example programs/sections of code below:
|
||||
<dl COMPACT>
|
||||
<dt><a href="#Example1">#1</a>
|
||||
<dd>A simple example showing how to create a file.
|
||||
<dt><a href="#Example2">#2</a>
|
||||
<dd>A example showing how to check if a file is an HDF5 file and list it's contents.
|
||||
<dt><a href="#Example3">#3</a>
|
||||
<dd>A example showing how to create a homogenous multi-dimensional dataset.
|
||||
<dt><a href="#Example4">#4</a>
|
||||
<dd>A example showing how to create a compound 1-D dataset.
|
||||
<dt><a href="#Example5">#5</a>
|
||||
<dd>A example showing how to create a compound multi-dimensional dataset.
|
||||
<dt><a href="#Example6">#6</a>
|
||||
<dd>A example showing how to read a generic dataset.
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example1">Simple Example showing how to create a file.</a></h2>
|
||||
|
||||
<P>Notes:<br>
|
||||
This example creates a new HDF5 file and allows write access.
|
||||
If the file exists already, the H5F_ACC_TRUNC flag would also be necessary to
|
||||
overwrite the previous file's information.
|
||||
|
||||
<P>Code:
|
||||
|
||||
<code> <pre>
|
||||
hid_t file_id;
|
||||
|
||||
file_id=<A HREF="H5.apiv3.html#File-Create">H5Fcreate</a>("example1.h5",0);
|
||||
|
||||
<A HREF="H5.apiv3.html#File-Close">H5Fclose</a>(file_id);
|
||||
|
||||
</pre> </code>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example2">Example showing how check if a file is an HDF5 file and list it's contents.</a></h2>
|
||||
|
||||
<P>Notes:<br>
|
||||
This example checks if a file is an HDF5 file and lists the contents of the top
|
||||
level (file level) group.
|
||||
|
||||
<P>Code:
|
||||
|
||||
<code> <pre>
|
||||
hid_t file_id; /* File ID */
|
||||
uint32 num_items; /* number of items in top-level group */
|
||||
intn i; /* counter */
|
||||
char *obj_name; /* object's name as string atom */
|
||||
uintn name_len; /* object name's length in chars */
|
||||
uintn buf_len=0; /* buffer length for names */
|
||||
char *buf=NULL; /* buffer for names */
|
||||
|
||||
if(<A HREF="H5.apiv3.html#File-IsHDF5">H5Fis_hdf5</a>("example2.h5")==TRUE)
|
||||
{
|
||||
file_id=<A HREF="H5.apiv3.html#File-Open">H5Fopen</a>("example2.h5",H5F_ACC_RDWR|H5ACC_CREATE);
|
||||
num_items=<A HREF="H5.apiv3.html#Group-GetNumContents">H5GgetNumContents</a>(file_id);
|
||||
for(i=0; i<num_items; i++)
|
||||
{
|
||||
obj_name=<A HREF="H5.apiv3.html#Group-GetNameByIndex">H5GgetNameByIndex</a>(file_id,i,NULL,0);
|
||||
printf("object #%d is: %s\n",i,buf);
|
||||
HDfree(obj_name);
|
||||
}
|
||||
<A HREF="H5.apiv3.html#File-Close">H5Fclose</a>(file_id);
|
||||
}
|
||||
|
||||
</pre> </code>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example3">Example showing how create a homogenous multi-dimensional dataset.</a></h2>
|
||||
|
||||
<P>Notes:<br>
|
||||
This example creates a 4-dimensional dataset of 32-bit floating-point
|
||||
numbers, corresponding to the current Scientific Dataset functionality.
|
||||
This example assumes that the datatype and dataspace of the dataset will not
|
||||
be re-used.
|
||||
|
||||
<P>Code:
|
||||
|
||||
<code> <pre>
|
||||
hid_t file_id; /* File's ID */
|
||||
uint32 dims[4]={6,5,4,3}; /* the size of each dimension */
|
||||
hid_t dataset_id; /* new object's ID */
|
||||
float32 obj_data[6][5][4][3]; /* storage for the dataset's data */
|
||||
|
||||
if((file_id=<A HREF="H5.apiv3.html#File-Create">H5Fcreate</a>("example3.h5",H5F_ACC_TRUNC))>=0)
|
||||
{
|
||||
/* Create & initialize the dataset object */
|
||||
dataset_id=<A HREF="H5.apiv3.html#Meta-Create">H5Mcreate</a>(file_id,H5OBJ_DATASET,"Simple Object");
|
||||
|
||||
/* Create & initialize a datatype object */
|
||||
<A HREF="H5.apiv3.html#Datatype-SetType">H5TsetType</a>(dataset_id,H5TYPE_FLOAT,4,H5T_BIGENDIAN);
|
||||
|
||||
/* Initialize dimensionality of dataset */
|
||||
<A HREF="H5.apiv3.html#Dimensionality-SetSpace">H5SsetSpace</a>(dataset_id,rank,dims);
|
||||
|
||||
<initialize data array>
|
||||
|
||||
/* Write the entire dataset out */
|
||||
<A HREF="H5.apiv3.html#Dataset-Write">H5Dwrite</a>(dataset_id,H5S_SCALAR,data);
|
||||
<or>
|
||||
<A HREF="H5.apiv3.html#Dataset-Write">H5Dwrite</a>(dataset_id,dataset_id,data);
|
||||
|
||||
/* Release the atoms we've created */
|
||||
<A HREF="H5.apiv3.html#Meta-Release">H5Mrelease</a>(dataset_id);
|
||||
|
||||
/* close the file */
|
||||
<A HREF="H5.apiv3.html#File-Close">H5Fclose</a>(file_id);
|
||||
}
|
||||
</pre> </code>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example4">Example showing how create a compound 1-D dataset.</a></h2>
|
||||
|
||||
<P>Notes:<br>
|
||||
This example creates a 1-dimensional dataset of compound datatype records,
|
||||
corresponding to the current Vdata functionality. This example also assumes
|
||||
that the datatype and dataspace will not be re-used.
|
||||
|
||||
<P>Code:
|
||||
|
||||
<code> <pre>
|
||||
hid_t file_id; /* File's ID */
|
||||
uint32 dims[1]={45}; /* the size of the dimension */
|
||||
hid_t dataset_id; /* object's ID */
|
||||
void *obj_data; /* pointer to the dataset's data */
|
||||
|
||||
if((file_id=<A HREF="H5.apiv3.html#File-Create">H5Fcreate</a>("example4.h5",H5F_ACC_TRUNC))>=0)
|
||||
{
|
||||
/* Create & initialize the dataset object */
|
||||
dataset_id=<A HREF="H5.apiv3.html#Meta-Create">H5Mcreate</a>(file_id,H5OBJ_DATASET,"Compound Object");
|
||||
|
||||
/* Initialize datatype */
|
||||
<A HREF="H5.apiv3.html#Datatype-SetType">H5TsetType</a>(dataset_id,H5TYPE_STRUCT);
|
||||
<A HREF="H5.apiv3.html#Datatype-AddField">H5TaddField</a>(dataset_id,H5TYPE_FLOAT32,"Float32 Scalar Field",H5SPACE_SCALAR);
|
||||
<A HREF="H5.apiv3.html#Datatype-AddField">H5TaddField</a>(dataset_id,H5TYPE_CHAR,"Char Field",H5SPACE_SCALAR);
|
||||
<A HREF="H5.apiv3.html#Datatype-AddField">H5TaddField</a>(dataset_id,H5TYPE_UINT16,"UInt16 Field",H5SPACE_SCALAR);
|
||||
<A HREF="H5.apiv3.html#Datatype-EndDefine">H5TendDefine</a>(dataset_id);
|
||||
|
||||
/* Initialize dimensionality */
|
||||
<A HREF="H5.apiv3.html#Dimensionality-SetSpace">H5SsetSpace</a>(dataset_id,1,dims);
|
||||
|
||||
<initialize data array>
|
||||
|
||||
/* Write the entire dataset out */
|
||||
<A HREF="H5.apiv3.html#Dataset-Write">H5Dwrite</a>(dataset_id,H5S_SCALAR,data);
|
||||
|
||||
/* Release the atoms we've created */
|
||||
<A HREF="H5.apiv3.html#Meta-Release">H5Mrelease</a>(dataset_id);
|
||||
|
||||
/* close the file */
|
||||
<A HREF="H5.apiv3.html#File-Close">H5Fclose</a>(file_id);
|
||||
}
|
||||
</pre> </code>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example5">Example showing how create a compound multi-dimensional dataset.</a></h2>
|
||||
|
||||
<P>Notes:<br>
|
||||
This example creates a 3-dimensional dataset of compound datatype records,
|
||||
roughly corresponding to a multi-dimensional Vdata functionality. This
|
||||
example also shows the use of multi-dimensional fields in the compound datatype.
|
||||
This example uses "stand-alone" datatypes and dataspaces.
|
||||
|
||||
<P>Code:
|
||||
|
||||
<code> <pre>
|
||||
hid_t file_id; /* File's ID */
|
||||
hid_t type_id; /* datatype's ID */
|
||||
hid_t dim_id; /* dimensionality's ID */
|
||||
uint32 dims[3]={95,67,5}; /* the size of the dimensions */
|
||||
hid_t field_dim_id; /* dimensionality ID for fields in the structure */
|
||||
uint32 field_dims[4]; /* array for field dimensions */
|
||||
hid_t dataset_id; /* object's ID */
|
||||
void *obj_data; /* pointer to the dataset's data */
|
||||
|
||||
if((file_id=<A HREF="H5.apiv3.html#File-Create">H5Fcreate</a>("example5.h5",H5F_ACC_TRUNC))>=0)
|
||||
{
|
||||
/* Create & initialize a datatype object */
|
||||
type_id=<A HREF="H5.apiv3.html#Meta-Create">H5Mcreate</a>(file_id,H5OBJ_DATATYPE,"Compound Type #1");
|
||||
<A HREF="H5.apiv3.html#Datatype-SetType">H5TsetType</a>(type_id,H5TYPE_STRUCT);
|
||||
|
||||
/* Create each multi-dimensional field in structure */
|
||||
field_dim_id=<A HREF="H5.apiv3.html#Meta-Create">H5Mcreate</a>(file_id,H5OBJ_DATASPACE,"Lat/Long Dims");
|
||||
field_dims[0]=360;
|
||||
field_dims[1]=720;
|
||||
<A HREF="H5.apiv3.html#Dimensionality-SetSpace">H5SsetSpace</a>(field_dim_id,2,field_dims);
|
||||
<A HREF="H5.apiv3.html#Datatype-AddField">H5TaddField</a>(type_id,H5TYPE_FLOAT32,"Lat/Long Locations",field_dim_id);
|
||||
<A HREF="H5.apiv3.html#Meta-Release">H5Mrelease</a>(field_dim_id);
|
||||
|
||||
field_dim_id=<A HREF="H5.apiv3.html#Meta-Create">H5Mcreate</a>(file_id,H5OBJ_DATASPACE,"Browse Dims");
|
||||
field_dims[0]=40;
|
||||
field_dims[1]=40;
|
||||
<A HREF="H5.apiv3.html#Dimensionality-SetSpace">H5SsetSpace</a>(field_dim_id,2,field_dims);
|
||||
<A HREF="H5.apiv3.html#Datatype-AddField">H5TaddField</a>(type_id,H5TYPE_CHAR,"Browse Image",field_dim_id);
|
||||
<A HREF="H5.apiv3.html#Meta-Release">H5Mrelease</a>(field_dim_id);
|
||||
|
||||
field_dim_id=<A HREF="H5.apiv3.html#Meta-Create">H5Mcreate</a>(file_id,H5OBJ_DATASPACE,"Multispectral Dims");
|
||||
field_dims[0]=80;
|
||||
field_dims[1]=60;
|
||||
field_dims[2]=40;
|
||||
<A HREF="H5.apiv3.html#Dimensionality-SetSpace">H5SsetSpace</a>(field_dim_id,3,field_dims);
|
||||
<A HREF="H5.apiv3.html#Datatype-AddField">H5TaddField</a>(type_id,H5TYPE_UINT16,"Multispectral Scans",field_dim_id);
|
||||
<A HREF="H5.apiv3.html#Meta-Release">H5Mrelease</a>(field_dim_id);
|
||||
<A HREF="H5.apiv3.html#Datatype-EndDefine">H5TendDefine</a>(type_id);
|
||||
|
||||
/* Create & initialize a dimensionality object */
|
||||
dim_id=<A HREF="H5.apiv3.html#Meta-Create">H5Mcreate</a>(file_id,H5OBJ_DATASPACE,"3-D Dim");
|
||||
<A HREF="H5.apiv3.html#Dimensionality-SetSpace">H5SsetSpace</a>(dim_id,3,dims);
|
||||
|
||||
/* Create & initialize the dataset object */
|
||||
dataset_id=<A HREF="H5.apiv3.html#Meta-Create">H5Mcreate</a>(file_id,H5OBJ_DATASET,"Compound Multi-Dim Object");
|
||||
<A HREF="H5.apiv3.html#Dataset-SetInfo">H5DsetInfo</a>(dataset_id,type_id,dim_id);
|
||||
|
||||
<initialize data array>
|
||||
|
||||
/* Write the entire dataset out */
|
||||
<A HREF="H5.apiv3.html#Dataset-Write">H5Dwrite</a>(dataset_id,H5S_SCALAR,data);
|
||||
|
||||
/* Release the atoms we've created */
|
||||
<A HREF="H5.apiv3.html#Meta-Release">H5Mrelease</a>(type_id);
|
||||
<A HREF="H5.apiv3.html#Meta-Release">H5Mrelease</a>(dim_id);
|
||||
<A HREF="H5.apiv3.html#Meta-Release">H5Mrelease</a>(dataset_id);
|
||||
|
||||
/* close the file */
|
||||
<A HREF="H5.apiv3.html#File-Close">H5Fclose</a>(file_id);
|
||||
}
|
||||
</pre> </code>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example6">Example showing how read a generic dataset.</a></h2>
|
||||
|
||||
<P>Notes:<br>
|
||||
This example shows how to get the information for and display a generic
|
||||
dataset.
|
||||
|
||||
<P>Code:
|
||||
|
||||
<code> <pre>
|
||||
hid_t file_id; /* File's ID */
|
||||
hid_t dataset_id; /* dataset's ID in memory */
|
||||
uintn elem_size; /* size of each element */
|
||||
uintn nelems; /* number of elements in array */
|
||||
void *obj_data; /* pointer to the dataset's data */
|
||||
|
||||
if((file_id=<A HREF="H5.apiv3.html#File-Open">H5Fopen</a>("example6.h5",0))>=0)
|
||||
{
|
||||
/* Attach to a datatype object */
|
||||
dataset_id=<A HREF="H5.apiv3.html#Meta-Access">H5MaccessByIndex</a>(obj_oid,0);
|
||||
|
||||
if(<A HREF="H5.apiv3.html#Datatype-BaseType">H5TbaseType</a>(dataset_id)==H5T_COMPOUND)
|
||||
{
|
||||
<set up for compound object>
|
||||
}
|
||||
else
|
||||
{
|
||||
<set up for homogenous object>
|
||||
}
|
||||
|
||||
elem_size=<A HREF="H5.apiv3.html#Datatype-Size">H5Tsize</a>(dataset_id);
|
||||
nelems=<A HREF="H5.apiv3.html#Dataspace-NElem">H5Snelem</a>(dataset_id);
|
||||
<allocate space based on element size and number of elements >
|
||||
|
||||
/* Read in the dataset */
|
||||
<A HREF="H5.apiv3.html#Dataset-Read">H5Dwrite</a>(dataset_id,H5S_SCALAR,data);
|
||||
<or>
|
||||
<A HREF="H5.apiv3.html#Dataset-Read">H5Dwrite</a>(dataset_id,dataset_id,data);
|
||||
|
||||
/* Release the atoms we've accessed */
|
||||
<A HREF="H5.apiv3.html#Meta-Release">H5Mrelease</a>(dataset_id);
|
||||
|
||||
/* close the file */
|
||||
<A HREF="H5.apiv3.html#File-Close">H5Fclose</a>(file_id);
|
||||
}
|
||||
</pre> </code>
|
252
doc/html/review1a.html
Normal file
@ -0,0 +1,252 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Group Examples</title>
|
||||
</head>
|
||||
<body>
|
||||
<center><h1>Group Examples</h1></center>
|
||||
|
||||
<hr>
|
||||
<h1>Background</h1>
|
||||
|
||||
<p>Directories (or now <i>Groups</i>) are currently implemented as
|
||||
a directed graph with a single entry point into the graph which
|
||||
is the <i>Root Object</i>. The root object is usually a
|
||||
group. All objects have at least one predecessor (the <i>Root
|
||||
Object</i> always has the HDF5 file boot block as a
|
||||
predecessor). The number of predecessors of a group is also
|
||||
known as the <i>hard link count</i> or just <i>link count</i>.
|
||||
Unlike Unix directories, HDF5 groups have no ".." entry since
|
||||
any group can have multiple predecessors. Given the handle or
|
||||
id of some object and returning a full name for that object
|
||||
would be an expensive graph traversal.
|
||||
|
||||
<p>A special optimization is that a file may contain a single
|
||||
non-group object and no group(s). The object has one
|
||||
predecessor which is the file boot block. However, once a root
|
||||
group is created it never dissappears (although I suppose it
|
||||
could if we wanted).
|
||||
|
||||
<p>A special object called a <i>Symbolic Link</i> is simply a
|
||||
name. Usually the name refers to some (other) object, but that
|
||||
object need not exist. Symbolic links in HDF5 will have the
|
||||
same semantics as symbolic links in Unix.
|
||||
|
||||
<p>The symbol table graph contains "entries" for each name. An
|
||||
entry contains the file address for the object header and
|
||||
possibly certain messages cached from the object header.
|
||||
|
||||
<p>The H5G package understands the notion of <i>opening</i> and object
|
||||
which means that given the name of the object, a handle to the
|
||||
object is returned (this isn't an API function). Objects can be
|
||||
opened multiple times simultaneously through the same name or,
|
||||
if the object has hard links, through other names. The name of
|
||||
an object cannot be removed from a group if the object is opened
|
||||
through that group (although the name can change within the
|
||||
group).
|
||||
|
||||
<p>Below the API, object attributes can be read without opening
|
||||
the object; object attributes cannot change without first
|
||||
opening that object. The one exception is that the contents of a
|
||||
group can change without opening the group.
|
||||
|
||||
<hr>
|
||||
<h1>Building a hierarchy from a flat namespace</h1>
|
||||
|
||||
<p>Assuming we have a flat name space (that is, the root object is
|
||||
a group which contains names for all other objects in the file
|
||||
and none of those objects are groups), then we can build a
|
||||
hierarchy of groups that also refer to the objects.
|
||||
|
||||
<p>The file initially contains `foo' `bar' `baz' in the root
|
||||
group. We wish to add groups `grp1' and `grp2' so that `grp1'
|
||||
contains objects `foo' and `baz' and `grp2' contains objects
|
||||
`bar' and `baz' (so `baz' appears in both groups).
|
||||
|
||||
<p>In either case below, one might want to move the flat objects
|
||||
into some other group (like `flat') so their names don't
|
||||
interfere with the rest of the hierarchy (or move the hierarchy
|
||||
into a directory called `/hierarchy').
|
||||
|
||||
<h2>with symbolic links</h2>
|
||||
|
||||
<p>Create group `grp1' and add symbolic links called `foo' whose
|
||||
value is `/foo' and `baz' whose value is `/baz'. Similarly for
|
||||
`grp2'.
|
||||
|
||||
<p>Accessing `grp1/foo' involves searching the root group for
|
||||
the name `grp1', then searching that group for `foo', then
|
||||
searching the root directory for `foo'. Alternatively, one
|
||||
could change working groups to the grp1 group and then ask for
|
||||
`foo' which searches `grp1' for the name `foo', then searches
|
||||
the root group for the name `foo'.
|
||||
|
||||
<p>Deleting `/grp1/foo' deletes the symbolic link without
|
||||
affecting the `/foo' object. Deleting `/foo' leaves the
|
||||
`/grp1/foo' link dangling.
|
||||
|
||||
<h2>with hard links</h2>
|
||||
|
||||
<p>Creating the hierarchy is the same as with symbolic links.
|
||||
|
||||
<p>Accessing `/grp1/foo' searches the root group for the name
|
||||
`grp1', then searches that group for the name `foo'. If the
|
||||
current working group is `/grp1' then we just search for the
|
||||
name `foo'.
|
||||
|
||||
<p>Deleting `/grp1/foo' leaves `/foo' and vice versa.
|
||||
|
||||
<h2>the code</h2>
|
||||
|
||||
<p>Depending on the eventual API...
|
||||
|
||||
<code><pre>
|
||||
H5Gcreate (file_id, "/grp1");
|
||||
H5Glink (file_id, H5G_HARD, "/foo", "/grp1/foo");
|
||||
</pre></code>
|
||||
|
||||
or
|
||||
|
||||
<code><pre>
|
||||
group_id = H5Gcreate (root_id, "grp1");
|
||||
H5Glink (file_id, H5G_HARD, root_id, "foo", group_id, "foo");
|
||||
H5Gclose (group_id);
|
||||
</pre></code>
|
||||
|
||||
|
||||
<hr>
|
||||
<h1>Building a flat namespace from a hierarchy</h1>
|
||||
|
||||
<p>Similar to abvoe, but in this case we have to watch out that
|
||||
we don't get two names which are the same: what happens to
|
||||
`/grp1/baz' and `/grp2/baz'? If they really refer to the same
|
||||
object then we just have `/baz', but if they point to two
|
||||
different objects what happens?
|
||||
|
||||
<p>The other thing to watch out for cycles in the graph when we
|
||||
traverse it to build the flat namespace.
|
||||
|
||||
<hr>
|
||||
<h1>Listing the Group Contents</h1>
|
||||
|
||||
<p>Two things to watch out for are that the group contents don't
|
||||
appear to change in a manner which would confuse the
|
||||
application, and that listing everything in a group is as
|
||||
efficient as possible.
|
||||
|
||||
<h2>Method A</h2>
|
||||
|
||||
<p>Query the number of things in a group and then query each item
|
||||
by index. A trivial implementation would be O(n*n) and wouldn't
|
||||
protect the caller from changes to the directory which move
|
||||
entries around and therefore change their indices.
|
||||
|
||||
<code><pre>
|
||||
n = H5GgetNumContents (group_id);
|
||||
for (i=0; i<n; i++) {
|
||||
H5GgetNameByIndex (group_id, i, ...); /*don't worry about args yet*/
|
||||
}
|
||||
</pre></code>
|
||||
|
||||
<h2>Method B</h2>
|
||||
|
||||
<p>The API contains a single function that reads all information
|
||||
from the specified group and returns that info through an array.
|
||||
The caller is responsible for freeing the array allocated by the
|
||||
query and the things to which it points. This also makes it
|
||||
clear the the returned value is a snapshot of the group which
|
||||
doesn't change if the group is modified.
|
||||
|
||||
<code><pre>
|
||||
n = H5Glist (file_id, "/grp1", info, ...);
|
||||
for (i=0; i<n; i++) {
|
||||
printf ("name = %s\n", info[i].name);
|
||||
free (info[i].name); /*and maybe other fields too?*/
|
||||
}
|
||||
free (info);
|
||||
</pre></code>
|
||||
|
||||
Notice that it would be difficult to expand the info struct since
|
||||
its definition is part of the API.
|
||||
|
||||
<h2>Method C</h2>
|
||||
|
||||
<p>The caller asks for a snapshot of the group and then accesses
|
||||
items in the snapshot through various query-by-index API
|
||||
functions. When finished, the caller notifies the library that
|
||||
it's done with the snapshot. The word "snapshot" makes it clear
|
||||
that subsequent changes to the directory will not be reflected in
|
||||
the shapshot_id.
|
||||
|
||||
<code><pre>
|
||||
snapshot_id = H5Gsnapshot (group_id); /*or perhaps group_name */
|
||||
n = H5GgetNumContents (snapshot_id);
|
||||
for (i=0; i<n; i++) {
|
||||
H5GgetNameByIndex (shapshot_id, i, ...);
|
||||
}
|
||||
H5Grelease (shapshot_id);
|
||||
</pre></code>
|
||||
|
||||
In fact, we could allow the user to leave off the H5Gsnapshot and
|
||||
H5Grelease and use group_id in the H5GgetNumContents and
|
||||
H5GgetNameByIndex so they can choose between Method A and Method
|
||||
C.
|
||||
|
||||
<hr>
|
||||
<h1>An implementation of Method C</h1>
|
||||
|
||||
<dl>
|
||||
<dt><code>hid_t H5Gshapshot (hid_t group_id)</code>
|
||||
<dd>Opens every object in the specified group and stores the
|
||||
handles in an array managed by the library (linear-time
|
||||
operation). Open object handles are essentialy symbol table
|
||||
entries with a little extra info (symbol table entries cache
|
||||
certain things about the object which are also found in the
|
||||
object header). Because the objects are open (A) they cannot be
|
||||
removed from the group, (B) querying the object returns the
|
||||
latest info even if something else has that object open, (C)
|
||||
if the object is renamed within the group then its name with
|
||||
<code>H5GgetNameByIndex</code> is changed. Adding new entries
|
||||
to a group doesn't affect the snapshot.
|
||||
|
||||
<dt><code>char *H5GgetNameByIndex (hid_t shapshot_id, int
|
||||
index)</code>
|
||||
<dd>Uses the open object handle from entry <code>index</code> of
|
||||
the snapshot array to get the object name. This is a
|
||||
constant-time operation. The name is updated automatically if
|
||||
the object is renamed within the group.
|
||||
|
||||
<dt><code>H5Gget<whatever>ByIndex...()</code>
|
||||
<dd>Uses the open object handle from entry <code>index</code>,
|
||||
which is just a symbol table entry, and reads the appropriate
|
||||
object header message(s) which might be cached in the symbol
|
||||
table entry. This is a constant-time operation if cached,
|
||||
linear in the number of messages if not cached.
|
||||
|
||||
<dt><code>H5Grelease (hid_t snapshot_id)</code>
|
||||
<dd>Closes each object refered to by the snapshot and then frees
|
||||
the snapshot array. This is a linear-time operation.
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<h1>To return <code>char*</code> or some HDF5 string type.</h1>
|
||||
|
||||
<p>In either case, the caller has to release resources associated
|
||||
with the return value, calling free() or some HDF5 function.
|
||||
|
||||
<p>Names in the current implementation of the H5G package don't
|
||||
contain embedded null characters and are always null terminated.
|
||||
|
||||
<p>Eventually the caller probably wants a <code>char*</code> so it
|
||||
can pass it to some non-HDF5 function, does that require
|
||||
strdup'ing the string again? Then the caller has to free() the
|
||||
the char* <i>and</i> release the DHF5 string.
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Fri Sep 26 12:03:20 EST 1997 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Fri Oct 3 09:32:10 EST 1997
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
274
doc/html/storage.html
Normal file
@ -0,0 +1,274 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Raw Data Storage in HDF5</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Raw Data Storage in HDF5</h1>
|
||||
|
||||
<p>This document describes the various ways that raw data is
|
||||
stored in an HDF5 file and the object header messages which
|
||||
contain the parameters for the storage.
|
||||
|
||||
<p>Raw data storage has three components: the mapping from some
|
||||
logical multi-dimensional element space to the linear address
|
||||
space of a file, compression of the raw data on disk, and
|
||||
striping of raw data across multiple files. These components
|
||||
are orthogonal.
|
||||
|
||||
<p>Some goals of the storage mechanism are to be able to
|
||||
efficently store data which is:
|
||||
|
||||
<dl>
|
||||
<dt>Small
|
||||
<dd>Small pieces of raw data can be treated as meta data and
|
||||
stored in the object header. This will be achieved by storing
|
||||
the raw data in the object header with message 0x0006.
|
||||
Compression and striping are not supported in this case.
|
||||
|
||||
<dt>Complete Large
|
||||
<dd>The library should be able to store large arrays
|
||||
contiguously in the file provided the user knows the final
|
||||
array size a priori. The array can then be read/written in a
|
||||
single I/O request. This is accomplished by describing the
|
||||
storage with object header message 0x0005. Compression and
|
||||
striping are not supported in this case.
|
||||
|
||||
<dt>Sparse Large
|
||||
<dd>A large sparse raw data array should be stored in a manner
|
||||
that is space-efficient but one in which any element can still
|
||||
be accessed in a reasonable amount of time. Implementation
|
||||
details are below.
|
||||
|
||||
<dt>Dynamic Size
|
||||
<dd>One often doesn't have prior knowledge of the size of an
|
||||
array. It would be nice to allow arrays to grow dynamically in
|
||||
any dimension. It might also be nice to allow the array to
|
||||
grow in the negative dimension directions if convenient to
|
||||
implement. Implementation details are below.
|
||||
|
||||
<dt>Subslab Access
|
||||
<dd>Some multi-dimensional arrays are almost always accessed by
|
||||
subslabs. For instance, a 2-d array of pixels might always be
|
||||
accessed as smaller 1k-by-1k 2-d arrays always aligned on 1k
|
||||
index values. We should be able to store the array in such a
|
||||
way that striding though the entire array is not necessary.
|
||||
Subslab access might also be useful with compression
|
||||
algorithms where each storage slab can be compressed
|
||||
independently of the others. Implementation details are below.
|
||||
|
||||
<dt>Compressed
|
||||
<dd>Various compression algorithms can be applied to the entire
|
||||
array. We're not planning to support separate algorithms (or a
|
||||
single algorithm with separate parameters) for each chunk
|
||||
although it would be possible to implement that in a manner
|
||||
similar to the way striping across files is
|
||||
implemented.
|
||||
|
||||
<dt>Striped Across Files
|
||||
<dd>The array access functions should support arrays stored
|
||||
discontiguously across a set of files.
|
||||
</dl>
|
||||
|
||||
<h1>Implementation of Indexed Storage</h1>
|
||||
|
||||
<p>The Sparse Large, Dynamic Size, and Subslab Access methods
|
||||
share so much code that they can be described with a single
|
||||
message. The new Indexed Storage Message (<code>0x0008</code>)
|
||||
will replace the old Chunked Object (<code>0x0009</code>) and
|
||||
Sparse Object (<code>0x000A</code>) Messages.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border cellpadding=4 width="60%">
|
||||
<caption align=bottom>
|
||||
<b>The Format of the Indexed Storage Message</b>
|
||||
</caption>
|
||||
<tr align=center>
|
||||
<th width="25%">byte</th>
|
||||
<th width="25%">byte</th>
|
||||
<th width="25%">byte</th>
|
||||
<th width="25%">byte</th>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td colspan=4><br>Address of B-tree<br><br></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>Number of Dimensions</td>
|
||||
<td>Reserved</td>
|
||||
<td>Reserved</td>
|
||||
<td>Reserved</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>Reserved (4 bytes)</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>Alignment for Dimension 0 (4 bytes)</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>Alignment for Dimension 1 (4 bytes)</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>...</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>Alignment for Dimension N (4 bytes)</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>The alignment fields indicate the alignment in logical space to
|
||||
use when allocating new storage areas on disk. For instance,
|
||||
writing every other element of a 100-element one-dimensional
|
||||
array (using one HDF5 I/O partial write operation per element)
|
||||
that has unit storage alignment would result in 50
|
||||
single-element, discontiguous storage segments. However, using
|
||||
an alignment of 25 would result in only four discontiguous
|
||||
segments. The size of the message varies with the number of
|
||||
dimensions.
|
||||
|
||||
<p>A B-tree is used to point to the discontiguous portions of
|
||||
storage which has been allocated for the object. All keys of a
|
||||
particular B-tree are the same size and are a function of the
|
||||
number of dimensions. It is therefore not possible to change the
|
||||
dimensionality of an indexed storage array after its B-tree is
|
||||
created.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border cellpadding=4 width="60%">
|
||||
<caption align=bottom>
|
||||
<b>The Format of a B-Tree Key</b>
|
||||
</caption>
|
||||
<tr align=center>
|
||||
<th width="25%">byte</th>
|
||||
<th width="25%">byte</th>
|
||||
<th width="25%">byte</th>
|
||||
<th width="25%">byte</th>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td colspan=4>External File Number or Zero (4 bytes)</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>Chunk Offset in Dimension 0 (4 bytes)</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>Chunk Offset in Dimension 1 (4 bytes)</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>...</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>Chunk Offset in Dimension N (4 bytes)</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>The keys within a B-tree obey an ordering based on the chunk
|
||||
offsets. If the offsets in dimension-0 are equal, then
|
||||
dimension-1 is used, etc. The External File Number field
|
||||
contains a 1-origin offset into the External File List message
|
||||
which contains the name of the external file in which that chunk
|
||||
is stored.
|
||||
|
||||
<h1>Implementation of Striping</h1>
|
||||
|
||||
<p>The indexed storage will support arbitrary striping at the
|
||||
chunk level; each chunk can be stored in any file. This is
|
||||
accomplished by using the External File Number field of an
|
||||
indexed storage B-tree key as a 1-origin offset into an External
|
||||
File List Message (0x0009) which takes the form:
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border cellpadding=4 width="60%">
|
||||
<caption align=bottom>
|
||||
<b>The Format of the External File List Message</b>
|
||||
</caption>
|
||||
<tr align=center>
|
||||
<th width="25%">byte</th>
|
||||
<th width="25%">byte</th>
|
||||
<th width="25%">byte</th>
|
||||
<th width="25%">byte</th>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td colspan=4><br>Name Heap Address<br><br></td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>Number of Slots Allocated (4 bytes)</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>Number of File Names (4 bytes)</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>Byte Offset of Name 1 in Heap (4 bytes)</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>Byte Offset of Name 2 in Heap (4 bytes)</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4>...</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td colspan=4><br>Unused Slot(s)<br><br></td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<p>Each indexed storage array that has all or part of its data
|
||||
stored in external files will contain a single external file
|
||||
list message. The size of the messages is determined when the
|
||||
message is created, but it may be possible to enlarge the
|
||||
message on demand by moving it. At this time, it's not possible
|
||||
for multiple arrays to share a single external file list
|
||||
message.
|
||||
|
||||
<dl>
|
||||
<dt><code>
|
||||
H5O_efl_t *H5O_efl_new (H5G_entry_t *object, intn
|
||||
nslots_hint, intn heap_size_hint)
|
||||
</code>
|
||||
<dd>Adds a new, empty external file list message to an object
|
||||
header and returns a pointer to that message. The message
|
||||
acts as a cache for file descriptors of external files that
|
||||
are open.
|
||||
|
||||
<p><dt><code>
|
||||
intn H5O_efl_index (H5O_efl_t *efl, const char *filename)
|
||||
</code>
|
||||
<dd>Gets the external file index number for a particular file name.
|
||||
If the name isn't in the external file list then it's added to
|
||||
the H5O_efl_t struct and immediately written to the object
|
||||
header to which the external file list message belongs. Name
|
||||
comparison is textual. Each name should be relative to the
|
||||
directory which contains the HDF5 file.
|
||||
|
||||
<p><dt><code>
|
||||
H5F_low_t *H5O_efl_open (H5O_efl_t *efl, intn index, uintn mode)
|
||||
</code>
|
||||
<dd>Gets a low-level file descriptor for an external file. The
|
||||
external file list caches file descriptors because we might
|
||||
have many more external files than there are file descriptors
|
||||
available to this process. The caller should not close this file.
|
||||
|
||||
<p><dt><code>
|
||||
herr_t H5O_efl_release (H5O_efl_t *efl)
|
||||
</code>
|
||||
<dd>Releases an external file list, closes all files
|
||||
associated with that list, and if the list has been modified
|
||||
since the call to <code>H5O_efl_new</code> flushes the message
|
||||
to disk.
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:robb@arborea.spizella.com">Robb Matzke</a></address>
|
||||
<!-- Created: Fri Oct 3 09:52:32 EST 1997 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Tue Nov 25 12:36:50 EST 1997
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
172
doc/html/study.html
Normal file
@ -0,0 +1,172 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Testing the chunked layout of HDF5</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Testing the chunked layout of HDF5</h1>
|
||||
|
||||
<p>This is the results of studying the chunked layout policy in
|
||||
HDF5. A 1000 by 1000 array of integers was written to a file
|
||||
dataset extending the dataset with each write to create, in the
|
||||
end, a 5000 by 5000 array of 4-byte integers for a total data
|
||||
storage size of 100 million bytes.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<img alt="Order that data was written" src="study_p1.gif">
|
||||
<br><b>Fig 1: Write-order of Output Blocks</b>
|
||||
</center>
|
||||
|
||||
<p>After the array was written, it was read back in blocks that
|
||||
were 500 by 500 bytes in row major order (that is, the top-left
|
||||
quadrant of output block one, then the top-right quadrant of
|
||||
output block one, then the top-left quadrant of output block 2,
|
||||
etc.).
|
||||
|
||||
<p>I tried to answer two questions:
|
||||
<ul>
|
||||
<li>How does the storage overhead change as the chunk size
|
||||
changes?
|
||||
<li>What does the disk seek pattern look like as the chunk size
|
||||
changes?
|
||||
</ul>
|
||||
|
||||
<p>I started with chunk sizes that were multiples of the read
|
||||
block size or k*(500, 500).
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border>
|
||||
<caption align=bottom>
|
||||
<b>Table 1: Total File Overhead</b>
|
||||
</caption>
|
||||
<tr>
|
||||
<th>Chunk Size (elements)</th>
|
||||
<th>Meta Data Overhead (ppm)</th>
|
||||
<th>Raw Data Overhead (ppm)</th>
|
||||
</tr>
|
||||
|
||||
<tr align=center>
|
||||
<td>500 by 500</td>
|
||||
<td>85.84</td>
|
||||
<td>0.00</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>1000 by 1000</td>
|
||||
<td>23.08</td>
|
||||
<td>0.00</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>5000 by 1000</td>
|
||||
<td>23.08</td>
|
||||
<td>0.00</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>250 by 250</td>
|
||||
<td>253.30</td>
|
||||
<td>0.00</td>
|
||||
</tr>
|
||||
<tr align=center>
|
||||
<td>499 by 499</td>
|
||||
<td>85.84</td>
|
||||
<td>205164.84</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<center>
|
||||
<img alt="500x500" src="study_500x500.gif">
|
||||
<br><b>Fig 2: Chunk size is 500x500</b>
|
||||
</center>
|
||||
|
||||
<p>The first half of Figure 2 shows output to the file while the
|
||||
second half shows input. Each dot represents a file-level I/O
|
||||
request and the lines that connect the dots are for visual
|
||||
clarity. The size of the request is not indicated in the
|
||||
graph. The output block size is four times the chunk size which
|
||||
results in four file-level write requests per block for a total
|
||||
of 100 requests. Since file space for the chunks was allocated
|
||||
in output order, and the input block size is 1/4 the output
|
||||
block size, the input shows a staircase effect. Each input
|
||||
request results in one file-level read request. The downward
|
||||
spike at about the 60-millionth byte is probably the result of a
|
||||
cache miss for the B-tree and the downward spike at the end is
|
||||
probably a cache flush or file boot block update.
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<center>
|
||||
<img alt="1000x1000" src="study_1000x1000.gif">
|
||||
<br><b>Fig 2: Chunk size is 1000x1000</b>
|
||||
</center>
|
||||
|
||||
<p>In this test I increased the chunk size to match the output
|
||||
chunk size and one can see from the first half of the graph that
|
||||
25 file-level write requests were issued, one for each output
|
||||
block. The read half of the test shows that four times the
|
||||
amount of data was read as written. This results from the fact
|
||||
that HDF5 must read the entire chunk for any request that falls
|
||||
within that chunk, which is done because (1) if the data is
|
||||
compressed the entire chunk must be decompressed, and (2) the
|
||||
library assumes that a chunk size was chosen to optimize disk
|
||||
performance.
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<center>
|
||||
<img alt="5000x1000" src="study_5000x1000.gif">
|
||||
<br><b>Fig 3: Chunk size is 5000x1000</b>
|
||||
</center>
|
||||
|
||||
<p>Increasing the chunk size further results in even worse
|
||||
performance since both the read and write halves of the test are
|
||||
re-reading and re-writing vast amounts of data. This proves
|
||||
that one should be careful that chunk sizes are not much larger
|
||||
than the typical partial I/O request.
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<center>
|
||||
<img alt="250x250" src="study_250x250.gif">
|
||||
<br><b>Fig 4: Chunk size is 250x250</b>
|
||||
</center>
|
||||
|
||||
<p>If the chunk size is decreased then the amount of data
|
||||
transfered between the disk and library is optimal for no
|
||||
caching, but the amount of meta data required to describe the
|
||||
chunk locations increases to 250 parts per million. One can
|
||||
also see that the final downward spike contains more file-level
|
||||
write requests as the meta data is flushed to disk just before
|
||||
the file is closed.
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<center>
|
||||
<img alt="499x499" src="study_499x499.gif">
|
||||
<br><b>Fig 4: Chunk size is 499x499</b>
|
||||
</center>
|
||||
|
||||
<p>This test shows the result of choosing a chunk size which is
|
||||
close to the I/O block size. Because the total size of the
|
||||
array isn't a multiple of the chunk size, the library allocates
|
||||
an extra zone of chunks around the top and right edges of the
|
||||
array which are only partially filled. This results in
|
||||
20,516,484 extra bytes of storage, a 20% increase in the total
|
||||
raw data storage size. But the amount of meta data overhead is
|
||||
the same as for the 500 by 500 test. In addition, the mismatch
|
||||
causes entire chunks to be read in order to update a few
|
||||
elements along the edge or the chunk which results in a 3.6-fold
|
||||
increase in the amount of data transfered.
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Fri Jan 30 21:04:49 EST 1998 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Fri Jan 30 23:51:31 EST 1998
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
BIN
doc/html/study_1000x1000.gif
Normal file
After ![]() (image error) Size: 6.4 KiB |
BIN
doc/html/study_250x250.gif
Normal file
After ![]() (image error) Size: 6.8 KiB |
BIN
doc/html/study_499x499.gif
Normal file
After ![]() (image error) Size: 10 KiB |
BIN
doc/html/study_5000x1000.gif
Normal file
After ![]() (image error) Size: 10 KiB |
BIN
doc/html/study_500x500.gif
Normal file
After ![]() (image error) Size: 6.7 KiB |
BIN
doc/html/study_p1.gif
Normal file
After ![]() (image error) Size: 6.4 KiB |
113
doc/html/study_p1.obj
Normal file
@ -0,0 +1,113 @@
|
||||
%TGIF 3.0-p5
|
||||
state(0,33,100,0,0,0,16,1,9,1,1,0,0,3,7,1,1,'Helvetica',0,24,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1088,1408,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
box('black',64,64,384,384,0,1,1,22,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',2,[
|
||||
128,64,128,384],0,1,1,23,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
192,64,192,384],0,1,1,24,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
256,64,256,384],0,1,1,25,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
320,64,320,384],0,1,1,26,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
64,128,384,128],0,1,1,27,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
64,192,384,192],0,1,1,28,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
64,256,384,256],0,1,1,29,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
64,320,384,320],0,1,1,30,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
text('black',96,80,'Courier',0,17,1,1,0,1,7,14,37,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1"]).
|
||||
text('black',160,80,'Courier',0,17,1,1,0,1,7,14,39,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"2"]).
|
||||
text('black',224,80,'Courier',0,17,1,1,0,1,7,14,41,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"3"]).
|
||||
text('black',288,80,'Courier',0,17,1,1,0,1,7,14,43,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"4"]).
|
||||
text('black',352,80,'Courier',0,17,1,1,0,1,7,14,47,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"5"]).
|
||||
text('black',96,144,'Courier',0,17,1,1,0,1,7,14,51,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"6"]).
|
||||
text('black',160,144,'Courier',0,17,1,1,0,1,7,14,53,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"7"]).
|
||||
text('black',224,144,'Courier',0,17,1,1,0,1,7,14,55,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"8"]).
|
||||
text('black',288,144,'Courier',0,17,1,1,0,1,7,14,57,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"9"]).
|
||||
text('black',352,144,'Courier',0,17,1,1,0,1,14,14,59,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"10"]).
|
||||
text('black',96,208,'Courier',0,17,1,1,0,1,14,14,61,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"11"]).
|
||||
text('black',160,208,'Courier',0,17,1,1,0,1,14,14,63,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"12"]).
|
||||
text('black',224,208,'Courier',0,17,1,1,0,1,14,14,65,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"13"]).
|
||||
text('black',288,208,'Courier',0,17,1,1,0,1,14,14,67,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"14"]).
|
||||
text('black',352,208,'Courier',0,17,1,1,0,1,14,14,71,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"15"]).
|
||||
text('black',96,272,'Courier',0,17,1,1,0,1,14,14,75,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"16"]).
|
||||
text('black',160,272,'Courier',0,17,1,1,0,1,14,14,77,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"17"]).
|
||||
text('black',224,272,'Courier',0,17,1,1,0,1,14,14,79,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"18"]).
|
||||
text('black',288,272,'Courier',0,17,1,1,0,1,14,14,81,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"19"]).
|
||||
text('black',352,272,'Courier',0,17,1,1,0,1,14,14,83,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"20"]).
|
||||
text('black',96,336,'Courier',0,17,1,1,0,1,14,14,87,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"21"]).
|
||||
text('black',160,336,'Courier',0,17,1,1,0,1,14,14,89,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"22"]).
|
||||
text('black',224,336,'Courier',0,17,1,1,0,1,14,14,91,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"23"]).
|
||||
text('black',288,336,'Courier',0,17,1,1,0,1,14,14,93,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"24"]).
|
||||
text('black',352,336,'Courier',0,17,1,1,0,1,14,14,95,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"25"]).
|
||||
poly('black',2,[
|
||||
416,64,416,384],3,1,1,100,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
64,416,384,416],3,1,1,101,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
text('black',390,228,'Courier',0,17,1,0,0,1,14,35,102,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,1,0,[
|
||||
390,228,390,228,425,242,0,-1000,1000,0,34,18,389,227,426,243],[
|
||||
"5,000"]).
|
||||
text('black',224,432,'Courier',0,17,1,1,0,1,35,14,116,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"5,000"]).
|
||||
text('black',160,512,'Courier',0,17,1,0,0,1,105,14,131,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"= 1,000 x 1,000"]).
|
||||
box('black',80,480,144,544,7,1,1,134,0,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',224,16,'Helvetica',0,24,1,1,0,1,296,29,144,0,24,5,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Order that data was written"]).
|
||||
box('black',32,0,464,576,0,1,1,149,0,0,0,0,0,'1',[
|
||||
]).
|
313
doc/html/symtab
Normal file
@ -0,0 +1,313 @@
|
||||
A number of issues involving caching of object header messages in
|
||||
symbol table entries must be resolved.
|
||||
|
||||
What is the motivation for these changes?
|
||||
|
||||
If we make objects completely independent of object name it allows
|
||||
us to refer to one object by multiple names (a concept called hard
|
||||
links in Unix file systems), which in turn provides an easy way to
|
||||
share data between datasets.
|
||||
|
||||
Every object in an HDF5 file has a unique, constant object header
|
||||
address which serves as a handle (or OID) for the object. The
|
||||
object header contains messages which describe the object.
|
||||
|
||||
HDF5 allows some of the object header messages to be cached in
|
||||
symbol table entries so that the object header doesn't have to be
|
||||
read from disk. For instance, an entry for a directory caches the
|
||||
directory disk addresses required to access that directory, so the
|
||||
object header for that directory is seldom read.
|
||||
|
||||
If an object has multiple names (that is, a link count greater than
|
||||
one), then it has multiple symbol table entries which point to it.
|
||||
All symbol table entries must agree on header messages. The
|
||||
current mechanism is to turn off the caching of header messages in
|
||||
symbol table entries when the header link count is more than one,
|
||||
and to allow caching once the link count returns to one.
|
||||
|
||||
However, in the current implementation, a package is allowed to
|
||||
copy a symbol table entry and use it as a private cache for the
|
||||
object header. This doesn't work for a number of reasons (all but
|
||||
one require a `delete symbol entry' operation).
|
||||
|
||||
1. If two packages hold copies of the same symbol table entry,
|
||||
they don't notify each other of changes to the symbol table
|
||||
entry. Eventually, one package reads a cached message and
|
||||
gets the wrong value because the other package changed the
|
||||
message in the object header.
|
||||
|
||||
2. If one package holds a copy of the symbol table entry and
|
||||
some other part of HDF5 removes the object and replaces it
|
||||
with some other object, then the original package will
|
||||
continue to access the non-existent object using the new
|
||||
object header.
|
||||
|
||||
3. If one package holds a copy of the symbol table entry and
|
||||
some other part of HDF5 (re)moves the directory which
|
||||
contains the object, then the package will be unable to
|
||||
update the symbol table entry with the new cached
|
||||
data. Packages that refer to the object by the new name will
|
||||
use old cached data.
|
||||
|
||||
|
||||
The basic problem is that there may be multiple copies of the object
|
||||
symbol table entry floating around in the code when there should
|
||||
really be at most one per hard link.
|
||||
|
||||
Level 0: A copy may exist on disk as part of a symbol table node, which
|
||||
is a small 1d array of symbol table entries.
|
||||
|
||||
Level 1: A copy may be cached in memory as part of a symbol table node
|
||||
in the H5Gnode.c file by the H5AC layer.
|
||||
|
||||
Level 2a: Another package may be holding a copy so it can perform
|
||||
fast lookup of any header messages that might be cached in
|
||||
the symbol table entry. It can't point directly to the
|
||||
cached symbol table node because that node can dissappear
|
||||
at any time.
|
||||
|
||||
Level 2b: Packages may hold more than one copy of a symbol table
|
||||
entry. For instance, if H5D_open() is called twice for
|
||||
the same name, then two copies of the symbol table entry
|
||||
for the dataset exist in the H5D package.
|
||||
|
||||
How can level 2a and 2b be combined?
|
||||
|
||||
If package data structures contained pointers to symbol table
|
||||
entries instead of copies of symbol table entries and if H5G
|
||||
allocated one symbol table entry per hard link, then it's trivial
|
||||
for Level 2a and 2b to benefit from one another's actions since
|
||||
they share the same cache.
|
||||
|
||||
How does this work conceptually?
|
||||
|
||||
Level 2a and 2b must notify Level 1 of their intent to use (or stop
|
||||
using) a symbol table entry to access an object header. The
|
||||
notification of the intent to access an object header is called
|
||||
`opening' the object and releasing the access is `closing' the
|
||||
object.
|
||||
|
||||
Opening an object requires an object name which is used to locate
|
||||
the symbol table entry to use for caching of object header
|
||||
messages. The return value is a handle for the object. Figure 1
|
||||
shows the state after Dataset1 opens Object with a name that maps
|
||||
through Entry1. The open request created a copy of Entry1 called
|
||||
Shadow1 which exists even if SymNode1 is preempted from the H5AC
|
||||
layer.
|
||||
|
||||
______
|
||||
Object / \
|
||||
SymNode1 +--------+ |
|
||||
+--------+ _____\ | Header | |
|
||||
| | / / +--------+ |
|
||||
+--------+ +---------+ \______/
|
||||
| Entry1 | | Shadow1 | /____
|
||||
+--------+ +---------+ \ \
|
||||
: : \
|
||||
+--------+ +----------+
|
||||
| Dataset1 |
|
||||
+----------+
|
||||
FIGURE 1
|
||||
|
||||
|
||||
|
||||
The SymNode1 can appear and disappear from the H5AC layer at any
|
||||
time without affecting the Object Header data cached in the Shadow.
|
||||
The rules are:
|
||||
|
||||
* If the SymNode1 is present and is about to disappear and the
|
||||
Shadow1 dirty bit is set, then Shadow1 is copied over Entry1, the
|
||||
Entry1 dirty bit is set, and the Shadow1 dirty bit is cleared.
|
||||
|
||||
* If something requests a copy of Entry1 (for a read-only peek
|
||||
request), and Shadow1 exists, then a copy (not pointer) of Shadow1
|
||||
is returned instead.
|
||||
|
||||
* Entry1 cannot be deleted while Shadow1 exists.
|
||||
|
||||
* Entry1 cannot change directly if Shadow1 exists since this means
|
||||
that some other package has opened the object and may be modifying
|
||||
it. I haven't decided if it's useful to ever change Entry1
|
||||
directly (except of course within the H5G layer itself).
|
||||
|
||||
* Shadow1 is created when Dataset1 `opens' the object through
|
||||
Entry1. Dataset1 is given a pointer to Shadow1 and Shadow1's
|
||||
reference count is incremented.
|
||||
|
||||
* When Dataset1 `closes' the Object the Shadow1 reference count is
|
||||
decremented. When the reference count reaches zero, if the
|
||||
Shadow1 dirty bit is set, then Shadow1's contents are copied to
|
||||
Entry1, and the Entry1 dirty bit is set. Shadow1 is then deleted
|
||||
if its reference count is zero. This may require reading SymNode1
|
||||
back into the H5AC layer.
|
||||
|
||||
What happens when another Dataset opens the Object through Entry1?
|
||||
|
||||
If the current state is represented by the top part of Figure 2,
|
||||
then Dataset2 will be given a pointer to Shadow1 and the Shadow1
|
||||
reference count will be incremented to two. The Object header link
|
||||
count remains at one so Object Header messages continue to be cached
|
||||
by Shadow1. Dataset1 and Dataset2 benefit from one another
|
||||
actions. The resulting state is represented by Figure 2.
|
||||
|
||||
_____
|
||||
SymNode1 Object / \
|
||||
+--------+ _____\ +--------+ |
|
||||
| | / / | Header | |
|
||||
+--------+ +---------+ +--------+ |
|
||||
| Entry1 | | Shadow1 | /____ \_____/
|
||||
+--------+ +---------+ \ \
|
||||
: : _ \
|
||||
+--------+ |\ +----------+
|
||||
\ | Dataset1 |
|
||||
\________ +----------+
|
||||
\ \
|
||||
+----------+ |
|
||||
| Dataset2 | |- New Dataset
|
||||
+----------+ |
|
||||
/
|
||||
FIGURE 2
|
||||
|
||||
|
||||
What happens when the link count for Object increases while Dataset
|
||||
has the Object open?
|
||||
|
||||
SymNode2
|
||||
+--------+
|
||||
SymNode1 Object | |
|
||||
+--------+ ____\ +--------+ /______ +--------+
|
||||
| | / / | header | \ `| Entry2 |
|
||||
+--------+ +---------+ +--------+ +--------+
|
||||
| Entry1 | | Shadow1 | /____ : :
|
||||
+--------+ +---------+ \ \ +--------+
|
||||
: : \
|
||||
+--------+ +----------+ \________________/
|
||||
| Dataset1 | |
|
||||
+----------+ New Link
|
||||
|
||||
FIGURE 3
|
||||
|
||||
The current state is represented by the left part of Figure 3. To
|
||||
create a new link the Object Header had to be located by traversing
|
||||
through Entry1/Shadow1. On the way through, the Entry1/Shadow1
|
||||
cache is invalidated and the Object Header link count is
|
||||
incremented. Entry2 is then added to SymNode2.
|
||||
|
||||
Since the Object Header link count is greater than one, Object
|
||||
header data will not be cached in Entry1/Shadow1.
|
||||
|
||||
If the initial state had been all of Figure 3 and a third link is
|
||||
being added and Object is open by Entry1 and Entry2, then creation
|
||||
of the third link will invalidate the cache in Entry1 or Entry2. It
|
||||
doesn't matter which since both caches are already invalidated
|
||||
anyway.
|
||||
|
||||
What happens if another Dataset opens the same object by another name?
|
||||
|
||||
If the current state is represented by Figure 3, then a Shadow2 is
|
||||
created and associated with Entry2. However, since the Object
|
||||
Header link count is more than one, nothing gets cached in Shadow2
|
||||
(or Shadow1).
|
||||
|
||||
What happens if the link count decreases?
|
||||
|
||||
If the current state is represented by all of Figure 3 then it isn't
|
||||
possible to delete Entry1 because the object is currently open
|
||||
through that entry. Therefore, the link count must have
|
||||
decreased because Entry2 was removed.
|
||||
|
||||
As Dataset1 reads/writes messages in the Object header they will
|
||||
begin to be cached in Shadow1 again because the Object header link
|
||||
count is one.
|
||||
|
||||
What happens if the object is removed while it's open?
|
||||
|
||||
That operation is not allowed.
|
||||
|
||||
What happens if the directory containing the object is deleted?
|
||||
|
||||
That operation is not allowed since deleting the directory requires
|
||||
that the directory be empty. The directory cannot be emptied
|
||||
because the open object cannot be removed from the directory.
|
||||
|
||||
What happens if the object is moved?
|
||||
|
||||
Moving an object is a process consisting of creating a new
|
||||
hard-link with the new name and then deleting the old name.
|
||||
This will fail if the object is open.
|
||||
|
||||
What happens if the directory containing the entry is moved?
|
||||
|
||||
The entry and the shadow still exist and are associated with one
|
||||
another.
|
||||
|
||||
What if a file is flushed or closed when objects are open?
|
||||
|
||||
Flushing a symbol table with open objects writes correct information
|
||||
to the file since Shadow is copied to Entry before the table is
|
||||
flushed.
|
||||
|
||||
Closing a file with open objects will create a valid file but will
|
||||
return failure.
|
||||
|
||||
How is the Shadow associated with the Entry?
|
||||
|
||||
A symbol table is composed of one or more symbol nodes. A node is a
|
||||
small 1-d array of symbol table entries. The entries can move
|
||||
around within a node and from node-to-node as entries are added or
|
||||
removed from the symbol table and nodes can move around within a
|
||||
symbol table, being created and destroyed as necessary.
|
||||
|
||||
Since a symbol table has an object header with a unique and constant
|
||||
file offset, and since H5G contains code to efficiently locate a
|
||||
symbol table entry given it's name, we use these two values as a key
|
||||
within a shadow to associate the shadow with the symbol table
|
||||
entry.
|
||||
|
||||
struct H5G_shadow_t {
|
||||
haddr_t stab_addr; /*symbol table header address*/
|
||||
char *name; /*entry name wrt symbol table*/
|
||||
hbool_t dirty; /*out-of-date wrt stab entry?*/
|
||||
H5G_entry_t ent; /*my copy of stab entry */
|
||||
H5G_entry_t *main; /*the level 1 entry or null */
|
||||
H5G_shadow_t *next, *prev; /*other shadows for this stab*/
|
||||
};
|
||||
|
||||
The set of shadows will be organized in a hash table of linked
|
||||
lists. Each linked list will contain the shadows associated with a
|
||||
particular symbol table header address and the list will be sorted
|
||||
lexicographically.
|
||||
|
||||
Also, each Entry will have a pointer to the corresponding Shadow or
|
||||
null if there is no shadow.
|
||||
|
||||
When a symbol table node is loaded into the main cache, we look up
|
||||
the linked list of shadows in the shadow hash table based on the
|
||||
address of the symbol table object header. We then traverse that
|
||||
list matching shadows with symbol table entries.
|
||||
|
||||
We assume that opening/closing objects will be a relatively
|
||||
infrequent event compared with loading/flushing symbol table
|
||||
nodes. Therefore, if we keep the linked list of shadows sorted it
|
||||
costs O(N) to open and close objects where N is the number of open
|
||||
objects in that symbol table (instead of O(1)) but it costs only
|
||||
O(N) to load a symbol table node (instead of O(N^2)).
|
||||
|
||||
What about the root symbol entry?
|
||||
|
||||
Level 1 storage for the root symbol entry is always available since
|
||||
it's stored in the hdf5_file_t struct instead of a symbol table
|
||||
node. However, the contents of that entry can move from the file
|
||||
handle to a symbol table node by H5G_mkroot(). Therefore, if the
|
||||
root object is opened, we keep a shadow entry for it whose
|
||||
`stab_addr' field is zero and whose `name' is null.
|
||||
|
||||
For this reason, the root object should always be read through the
|
||||
H5G interface.
|
||||
|
||||
One more key invariant: The H5O_STAB message in a symbol table header
|
||||
never changes. This allows symbol table entries to cache the H5O_STAB
|
||||
message for the symbol table to which it points without worrying about
|
||||
whether the cache will ever be invalidated.
|
||||
|
||||
|
192
doc/html/tracing.html
Normal file
@ -0,0 +1,192 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>API Tracing</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>API Tracing</h1>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
<p>The HDF5 library is now able to 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>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=top><b>Sample Output</b></caption>
|
||||
<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>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<h2>Configuation</h2>
|
||||
|
||||
<p>This all happens with some magic in the configuration script,
|
||||
the makefiles, and macros. First, from the end-user point of
|
||||
view, the library must be configured with the
|
||||
<code>--enable-tracing</code> switch. This causes the library to
|
||||
include the support necessary for API tracing.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=top><b>Configuration</b></caption>
|
||||
<tr>
|
||||
<td>
|
||||
<code><pre>
|
||||
$ make distclean
|
||||
$ sh configure --enable-tracing
|
||||
$ make
|
||||
</pre></code>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<h2>Execution</h2>
|
||||
|
||||
<p>In order to actually get tracing output one must turn tracing
|
||||
on and specify a file descriptor where the tracing output should
|
||||
be written. This is done by assigning a file descriptor number
|
||||
to the <code>HDF5_TRACE</code> environment variable.
|
||||
|
||||
<p>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=top><b>Execution Examples</b></caption>
|
||||
<tr>
|
||||
<td>To display the trace on the standard error stream:
|
||||
<code><pre>
|
||||
$ export HDF5_TRACE=2
|
||||
$ a.out
|
||||
</pre></code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>To send the trace to a file:
|
||||
<code><pre>
|
||||
$ export HDF5_TRACE=255
|
||||
$ a.out 255>trace-output
|
||||
</pre></code>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
|
||||
<h2>Performance</h2>
|
||||
|
||||
<p>If the library was not configured for tracing then there is no
|
||||
unnecessary overhead since all tracing code is
|
||||
excluded.
|
||||
|
||||
<p>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>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.
|
||||
|
||||
<h2>Safety</h2>
|
||||
|
||||
<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.
|
||||
|
||||
<h2>Completeness</h2>
|
||||
|
||||
<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>On the other hand, a number of API functions are called during
|
||||
library initialization and they print tracing information.
|
||||
|
||||
<h2>Implementation</h2>
|
||||
|
||||
<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>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>
|
||||
<center>
|
||||
<table border align=center width="100%">
|
||||
<caption align=top><b>Explicit Instrumentation</b></caption>
|
||||
<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>
|
||||
</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>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.
|
||||
|
||||
|
||||
<hr>
|
||||
<address><a href="mailto:matzke@llnl.gov">Robb Matzke</a></address>
|
||||
<!-- Created: Wed Jun 17 12:29:12 EDT 1998 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Wed Jun 17 15:45:50 EDT 1998
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
BIN
doc/html/version.gif
Normal file
After ![]() (image error) Size: 4.7 KiB |
96
doc/html/version.obj
Normal file
@ -0,0 +1,96 @@
|
||||
%TGIF 3.0-p5
|
||||
state(0,33,100,0,0,0,8,1,9,1,1,0,2,1,0,1,0,'Courier',0,17,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,0,1088,1408,0,0,2880).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
page(1,"",1).
|
||||
poly('black',2,[
|
||||
128,128,128,448],0,3,1,0,0,0,0,0,12,5,0,0,0,'3','12','5',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
128,128,128,64],0,3,1,1,0,0,2,0,12,5,0,0,0,'3','12','5',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
128,448,128,512],0,3,1,4,0,0,2,0,12,5,0,0,0,'3','12','5',
|
||||
"0",[
|
||||
]).
|
||||
text('black',144,112,'Courier',0,17,1,0,0,1,42,14,22,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.3.30"]).
|
||||
text('black',144,144,'Courier',0,17,1,0,0,1,42,14,30,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.3.31"]).
|
||||
text('black',144,176,'Courier',0,17,1,0,0,1,42,14,32,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.3.32"]).
|
||||
poly('black',2,[
|
||||
256,208,256,448],0,3,1,34,0,0,0,0,12,5,0,0,0,'3','12','5',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
256,448,256,512],0,3,1,36,0,0,2,0,12,5,0,0,0,'3','12','5',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
128,192,256,208],1,1,1,37,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
text('black',144,224,'Courier',0,17,1,0,0,1,42,14,41,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.3.33"]).
|
||||
text('black',144,256,'Courier',0,17,1,0,0,1,42,14,43,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.3.34"]).
|
||||
text('black',272,224,'Courier',0,17,1,0,0,1,35,14,45,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.5.0"]).
|
||||
text('black',272,256,'Courier',0,17,1,0,0,1,35,14,47,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.5.1"]).
|
||||
text('black',272,288,'Courier',0,17,1,0,0,1,35,14,49,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.5.2"]).
|
||||
text('black',272,320,'Courier',0,17,1,0,0,1,35,14,51,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.5.3"]).
|
||||
text('black',144,288,'Courier',0,17,1,0,0,1,42,14,53,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.3.35"]).
|
||||
text('black',144,320,'Courier',0,17,1,0,0,1,35,14,57,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.4.0"]).
|
||||
text('black',144,368,'Courier',0,17,1,0,0,1,35,14,59,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.4.1"]).
|
||||
text('black',272,192,'Helvetica',0,17,1,0,0,1,144,15,67,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"New development branch"]).
|
||||
text('black',144,64,'Helvetica',0,17,1,0,0,1,163,15,69,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Original development branch"]).
|
||||
text('black',16,208,'Helvetica',0,17,2,0,0,1,87,30,71,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Feature Freeze",
|
||||
"at this point."]).
|
||||
text('black',16,320,'Helvetica',0,17,2,0,0,1,84,30,73,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Public Release",
|
||||
"at this point."]).
|
||||
poly('black',2,[
|
||||
104,208,128,208],1,1,1,77,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
104,320,128,320],1,1,1,78,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
poly('black',2,[
|
||||
256,336,128,352],1,1,1,79,0,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"0",[
|
||||
]).
|
||||
text('black',320,368,'Helvetica',0,17,3,0,0,1,137,45,82,0,12,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"Merge a bug fix from the",
|
||||
"development branch to",
|
||||
"the release branch."]).
|
||||
box('black',312,368,464,416,0,1,1,87,0,0,0,0,0,'1',[
|
||||
]).
|
||||
poly('black',4,[
|
||||
312,392,240,384,296,344,232,344],1,1,1,90,1,0,0,0,8,3,0,0,0,'1','8','3',
|
||||
"6",[
|
||||
]).
|
||||
box('black',8,208,104,240,0,1,1,95,0,0,0,0,0,'1',[
|
||||
]).
|
||||
box('black',8,320,104,352,0,1,1,98,0,0,0,0,0,'1',[
|
||||
]).
|
||||
text('black',144,408,'Courier',0,17,1,0,0,1,35,14,102,0,11,3,0,0,0,0,0,2,0,0,0,0,"",0,0,0,[
|
||||
"1.4.2"]).
|
||||
box('black',0,40,480,528,0,1,1,104,0,0,0,0,0,'1',[
|
||||
]).
|