diff --git a/README.md b/README.md
index 1f3c6444a1c..4aa6ff84a10 100644
--- a/README.md
+++ b/README.md
@@ -89,7 +89,7 @@ are tentative.
| Release | New Features |
| ------- | ------------ |
-| 2.0.0 | Drop Autotools support, drop the C++ API, drop the HDF5 <--> GIF tools, add complex number support, update library defaults (cache sizes, etc.), use semantic versioning |
+| 2.0.0 | Drop Autotools support, drop the HDF5 <--> GIF tools, add complex number support, update library defaults (cache sizes, etc.), use semantic versioning |
| FUTURE | Multi-threaded HDF5, crashproofing / metadata journaling, Full (VFD) SWMR, encryption, digital signatures, sparse datasets, improved storage for variable-length datatypes, better Unicode support (especially on Windows) |
NOTE: In the March 2025 release we will begin using semantic versioning (https://semver.org/) and the previously announced 1.16.0 version will instead be numbered 2.0.0.
diff --git a/bin/make_vers b/bin/make_vers
index ba335cae27e..6f93b20510d 100755
--- a/bin/make_vers
+++ b/bin/make_vers
@@ -3,20 +3,49 @@ require 5.003;
use warnings;
# Global settings
-# (The max_idx parameter is the only thing that needs to be changed when adding
-# support for a new major release. If support for a prior major release
-# is added (like support for 1.4, etc), the min_sup_idx parameter will
-# need to be decremented.)
-# Max. library "index" (0 = v1.0, 1 = 1.2, 2 = 1.4, 3 = 1.6, 4 = 1.8, 5 = 1.10, 6 = 1.12, 7 = 1.14, 8 = 2.0, etc)
-$max_idx = 8;
-
-# Min. supported previous library version "index" (0 = v1.0, 1 = 1.2, etc)
-$min_sup_idx = 3;
+# Supported version strings. "16" = HDF5 1.6.0, "200" = HDF5 2.0.0, etc.
+#
+# Note that the scheme changed with 2.0.0, when we went to semantic versioning.
+# We use 200 instead of 20 so that HDF5 11.0.0 will get 1100 instead of 110,
+# which would conflict with HDF5 1.10.
+#
+# Also, note that this scheme started at the 1.6/1.8 transition, so earlier
+# versions of the API aren't versioned.
+@versions = ("16", "18", "110", "112", "114", "200");
# Number of spaces to indent preprocessor commands inside ifdefs
$indent = 2;
+# Global hash of functions ==> # symbol versions parsed from H5vers.txt
+$functions = {};
+
+# Global hash of functions ==> versioned function params parsed from H5vers.txt
+$func_params = {};
+
+# Global hash of typedefs ==> # symbol versions parsed from H5vers.txt
+$typedefs = {};
+
+# Hash of API versions to a hash of (API call name --> symbol version)
+#
+# There is one hash for each version in @versions and the (API call name
+# --> symbol version) hash maps an API name like H5Dopen to the symbol version
+# (e.g. H5Dopen --> 1 or 2).
+#
+# So...
+#
+# 200 --> {H5Dopen --> 2, H5Iregister_type --> 2, etc.}
+my %api_vers_to_function_vers;
+foreach my $key (@versions) {
+ $api_vers_to_function_vers{$key} = {};
+}
+
+# Hash of API versions to a hash of (typedef name --> symbol version)
+my %api_vers_to_type_vers;
+foreach my $key (@versions) {
+ $api_vers_to_type_vers{$key} = {};
+}
+
#
# Copyright by The HDF Group.
# All rights reserved.
@@ -83,7 +112,6 @@ sub print_startprotect ($$) {
#
sub print_checkoptions ($) {
my $fh = shift; # File handle for output file
- my $curr_idx; # Current API version index
# Print the option checking
print $fh "\n\n/* Issue error if contradicting macros have been defined. */\n";
@@ -91,9 +119,12 @@ sub print_checkoptions ($) {
# Print the #ifdef
print $fh "#if (";
- for $curr_idx ($min_sup_idx .. ($max_idx - 1)) {
- print $fh "defined(H5_USE_1", ($curr_idx * 2), "_API)";
- if($curr_idx < ($max_idx - 1)) {
+ for my $i (0 .. $#versions - 1) {
+ print $fh "defined(H5_USE_", $versions[$i], "_API)";
+
+ # -2 because we're ignoring the last version in the array, and the
+ # last version we DO write out can't have an || after it
+ if ($i < @versions - 2) {
print $fh " || ";
}
}
@@ -104,9 +135,10 @@ sub print_checkoptions ($) {
# Print the #endif
print $fh "#endif /* (";
- for $curr_idx ($min_sup_idx .. ($max_idx - 1)) {
- print $fh "defined(H5_USE_1", ($curr_idx * 2), "_API)";
- if($curr_idx < ($max_idx - 1)) {
+ for my $i (0 .. $#versions - 1) {
+ print $fh "defined(H5_USE_", $versions[$i], "_API)";
+
+ if ($i < @versions - 2) {
print $fh " || ";
}
}
@@ -118,7 +150,6 @@ sub print_checkoptions ($) {
#
sub print_globalapidefvers ($) {
my $fh = shift; # File handle for output file
- my $curr_idx; # Current API version index
# Print the descriptive comment
print $fh "\n\n/* If a particular default \"global\" version of the library's interfaces is\n";
@@ -126,13 +157,13 @@ sub print_globalapidefvers ($) {
print $fh " *\n";
print $fh " */\n";
- for $curr_idx ($min_sup_idx .. ($max_idx - 1)) {
+ for my $api_vers (@versions) {
# Print API version ifdef
- print $fh "\n#if defined(H5_USE_1", ($curr_idx * 2), "_API_DEFAULT) && !defined(H5_USE_1", ($curr_idx * 2), "_API)\n";
+ print $fh "\n#if defined(H5_USE_", $api_vers, "_API_DEFAULT) && !defined(H5_USE_", $api_vers, "_API)\n";
# Print API version definition
- print $fh " " x $indent, "#define H5_USE_1", ($curr_idx * 2), "_API 1\n";
+ print $fh " " x $indent, "#define H5_USE_", $api_vers, "_API 1\n";
# Print API version endif
- print $fh "#endif /* H5_USE_1", ($curr_idx * 2), "_API_DEFAULT && !H5_USE_1", ($curr_idx * 2), "_API */\n";
+ print $fh "#endif /* H5_USE_", $api_vers, "_API_DEFAULT && !H5_USE_", $api_vers, "_API */\n";
}
}
@@ -141,7 +172,6 @@ sub print_globalapidefvers ($) {
#
sub print_globalapisymbolvers ($) {
my $fh = shift; # File handle for output file
- my $curr_idx; # Current API version index
# Print the descriptive comment
print $fh "\n\n/* If a particular \"global\" version of the library's interfaces is chosen,\n";
@@ -152,18 +182,18 @@ sub print_globalapisymbolvers ($) {
print $fh " */\n";
# Loop over supported older library APIs and define the appropriate macros
- for $curr_idx ($min_sup_idx .. ($max_idx - 1)) {
+ foreach my $api_vers (@versions) {
# Print API version ifdef
- print $fh "\n#ifdef H5_USE_1", ($curr_idx * 2), "_API\n";
+ print $fh "\n#ifdef H5_USE_", $api_vers, "_API\n";
# Print the version macro info for each function that is defined for
# this API version
print $fh "\n/*************/\n";
print $fh "/* Functions */\n";
print $fh "/*************/\n";
- for $name (sort keys %{$func_vers[$curr_idx]}) {
+ for $name (sort keys %{$api_vers_to_function_vers{$api_vers}}) {
print $fh "\n#if !defined(", $name, "_vers)\n";
- print $fh " " x $indent, "#define ", $name, "_vers $func_vers[$curr_idx]{$name}\n";
+ print $fh " " x $indent, "#define ", $name, "_vers $api_vers_to_function_vers{$api_vers}{$name}\n";
print $fh "#endif /* !defined(", $name, "_vers) */\n";
}
@@ -172,14 +202,14 @@ sub print_globalapisymbolvers ($) {
print $fh "\n/************/\n";
print $fh "/* Typedefs */\n";
print $fh "/************/\n";
- for $name (sort keys %{$type_vers[$curr_idx]}) {
+ for $name (sort keys %{$api_vers_to_type_vers{$api_vers}}) {
print $fh "\n#if !defined(", $name, "_t_vers)\n";
- print $fh " " x $indent, "#define ", $name, "_t_vers $type_vers[$curr_idx]{$name}\n";
+ print $fh " " x $indent, "#define ", $name, "_t_vers $api_vers_to_type_vers{$api_vers}{$name}\n";
print $fh "#endif /* !defined(", $name, "_t_vers) */\n";
}
# Print API version endif
- print $fh "\n#endif /* H5_USE_1", ($curr_idx * 2), "_API */\n";
+ print $fh "\n#endif /* H5_USE_", $api_vers, "_API */\n";
}
}
@@ -222,7 +252,7 @@ sub print_defaultapivers ($) {
print $fh " " x $indent, "#define $curr_name $curr_name$curr_vers\n";
# Print function's dependent parameter types
- foreach(sort(@param_list)) {
+ foreach (sort (@param_list)) {
print $fh " " x $indent, "#define ${_}_t $_${curr_vers}_t\n";
}
@@ -233,7 +263,7 @@ sub print_defaultapivers ($) {
print $fh " " x $indent, "#define $curr_name $curr_name$curr_vers\n";
# Print function's dependent parameter types
- foreach(sort(@param_list)) {
+ foreach (sort (@param_list)) {
print $fh " " x $indent, "#define ${_}_t $_${curr_vers}_t\n";
}
@@ -267,7 +297,7 @@ sub print_defaultapivers ($) {
# Loop to print earlier version name mappings
$curr_vers--;
- while($curr_vers > 0) {
+ while ($curr_vers > 0) {
print $fh "#elif $curr_vers_name == $curr_vers\n";
print $fh " " x $indent, "#define ${curr_name}_t $curr_name${curr_vers}_t\n";
$curr_vers--;
@@ -293,6 +323,57 @@ sub print_endprotect ($$) {
print $fh "#endif /* ${file}_H */\n\n";
}
+##############################################################################
+# Validate a line from H5vers.txt
+#
+sub validate_line {
+ my $name = $_[0];
+ my $params = $_[1];
+ my $vers = $_[2];
+
+ my @vers_list; # Version strings ("v18", etc.)
+ my %sym_versions; # Versions already seen (for duplicate checks)
+
+ # Check if the name already exists in the list of symbols
+ if (exists ($functions{$name}) || exists($typedefs{$name})) {
+ die "duplicated symbol: $name";
+ }
+
+ # Check for no version info given
+ if ($vers eq "") {
+ die "no version information: $name";
+ }
+
+ # Separate the versions on commas (produces string elements like "v18")
+ @vers_list = split (/\s*,\s*/, $vers);
+
+ # Check for invalid version data
+ foreach (@vers_list) {
+ # Note: v111 is allowed because H5O functions were prematurely versioned
+ # in HDF5 1.10. Because users were affected by this, the versioning
+ # was rescinded but the H5O version 2 functions were kept to be
+ # called directly. Now that the version macros are added in 1.12,
+ # along with a 3rd version of the H5O functions, the H5O function
+ # version for default api=v110 should be version 1 to work correctly
+ # with 1.10 applications that were using unversioned H5O functions,
+ # and the H5O function version should be version 3 for default api=v112
+ # (the default api version for 1.12). Allowing a v111 entry allows
+ # a version 2 that is never accessed via the H5O function macros.
+ if (!( $_ =~ /v1[02468]/ || $_ =~ /v11[02468]/ || $_ =~ /v111/ || $_ =~ /v200/ )) {
+ die "bad version information: $name";
+ }
+
+ # Make sure we didn't specify duplicate versions on this line
+ if (exists($sym_versions{$_})) {
+ die "duplicate version information: $name";
+ }
+
+ # Store the versions for the function in a local hash table, indexed by the version
+ # (this is only used to check for duplicates)
+ $sym_versions{$_}=$_;
+ }
+}
+
##############################################################################
# Parse a meaningful line (not a comment or blank line) into the appropriate
# data structure
@@ -301,149 +382,67 @@ sub parse_line ($) {
my $line = shift; # Get the line to parse
# Parse API function lines
-#print "line=$line\n";
- if($line =~ /^\s*FUNCTION:/ || $line =~ /^\s*TYPEDEF:/) {
+#print "line=$line";
+ if ($line =~ /^\s*FUNCTION:/ || $line =~ /^\s*TYPEDEF:/) {
my $name; # The name of the function
my $params; # Typedefs for function parameters
- my $vers; # The version info for the function
- my @vers_list; # Version info, as a list
- my @vers_nums; # Version info, as a numeric list
- my $num_versions; # Number of versions for function
- my %sym_versions; # Versions for a symbol
- my $last_idx; # The previous version index seen for a function
- my $last_vers; # The previous version # seen for a function
+ my $vers_string; # The version info for the function
+ my @vers_list; # Version info, as a list (e.g., "112", "200", etc.
my $line_type; # Type of line we are parsing
# Determine the type of the line to parse
- if($line =~ /^\s*FUNCTION:/) {
+ if ($line =~ /^\s*FUNCTION:/) {
$line_type = 1;
# Get the function's name & version info
- ($name, $params, $vers) = ($line =~ /^\s*FUNCTION:\s*(\w*);\s*(.*?)\s*;\s*(.*?)\s*$/);
-#print "parse_line: name='$name', params='$params', vers='$vers'\n";
+ ($name, $params, $vers_string) = ($line =~ /^\s*FUNCTION:\s*(\w*);\s*(.*?)\s*;\s*(.*?)\s*$/);
+#print "parse_line: name='$name', params='$params', vers_string='$vers_string'\n";
}
- elsif($line =~ /^\s*TYPEDEF:/) {
+ elsif ($line =~ /^\s*TYPEDEF:/) {
$line_type = 2;
# Get the typedefs's name & version info
- ($name, $vers) = ($line =~ /^\s*TYPEDEF:\s*(\w*);\s*(.*?)\s*$/);
-#print "parse_line: name='$name', vers='$vers'\n";
+ ($name, $vers_string) = ($line =~ /^\s*TYPEDEF:\s*(\w*);\s*(.*?)\s*$/);
+#print "parse_line: name='$name', vers_string='$vers_string'\n";
+ } else {
+ die "unknown line type: $line";
}
#print "parse_line: line_type='$line_type'\n";
+ validate_line($name, $params, $vers_string);
- # Check if the name already exists in the list of symbols
- if(exists($functions{$name}) || exists($typedefs{$name})) {
- die "duplicated symbol: $name";
- }
-
- # Check for no version info given
- if($vers eq "") {
- die "no version information: $name";
- }
-
- # Split up version info
- @vers_list = split(/\s*,\s*/, $vers);
+ # Split the version info and strip off the leading "v"
+ @vers_list = split(/\s*,\s*/, $vers_string);
+ @vers_list = map { substr($_, 1) } @vers_list;
#print "parse_line: vers_list=(@vers_list)\n";
- # Parse the version list into numbers, checking for invalid input
- foreach(@vers_list) {
- my $vers_idx; # Index of version in array
-
- # Do some validation on the input
- # Note: v111 is allowed because H5O functions were prematurely versioned
- # in HDF5 1.10. Because users were affected by this, the versioning
- # was rescinded but the H5O version 2 functions were kept to be
- # called directly. Now that the version macros are added in 1.12,
- # along with a 3rd version of the H5O functions, the H5O function
- # version for default api=v110 should be version 1 to work correctly
- # with 1.10 applications that were using unversioned H5O functions,
- # and the H5O function version should be version 3 for default api=v112
- # (the default api version for 1.12). Allowing a v111 entry and
- # incrementing its index 13 lines below allows a version 2 that is
- # never accessed via the H5O function macros.
- if(!( $_ =~ /v1[02468]/ || $_ =~ /v11[02468]/ || $_ =~ /v111/ )) {
- die "bad version information: $name";
- }
- if(exists($sym_versions{$_})) {
- die "duplicate version information: $name";
- }
-
- # Store the versions for the function in a local hash table, indexed by the version
- $sym_versions{$_}=$_;
-
-#print "parse_line: _=$_\n";
- # Get the index of the version
- ($vers_idx) = ($_ =~ /v1(\d+)/);
- if($vers_idx == 11) {
- $vers_idx++;
- }
- $vers_idx /= 2;
-#print "parse_line: vers_idx='$vers_idx'\n";
- push(@vers_nums, $vers_idx);
- }
-#print "parse_line: vers_nums=(@vers_nums)\n";
-
- # Check for invalid version info given
- $last_idx = -1;
- $last_vers = 1;
- foreach(sort(@vers_nums)) {
-#print "parse_line: _=$_ last_idx='$last_idx'\n";
- # Update intermediate versions of the library that included the API routine
- if($last_idx >= 0) {
-#print "parse_line: name='$name'\n";
-#print "parse_line: last_vers='$last_vers'\n";
-#print "parse_line: last_idx='$last_idx'\n";
-
- # Add the function to the list of API routines available in
- # different versions of the library
- while($last_idx <= $_) {
- if($line_type == 1) {
- $func_vers[$last_idx]{$name} = $last_vers;
- } elsif($line_type == 2) {
- $type_vers[$last_idx]{$name} = $last_vers;
+ # Parse the version list into the hashes of version and type info
+ my $curr_sym_number = 1;
+ foreach my $vers (@vers_list) {
+ foreach my $hash_vers (@versions) {
+ if ($vers > $hash_vers) {
+ next;
+ } else {
+ if ($line_type == 1) {
+ $api_vers_to_function_vers{$hash_vers}{$name} = $curr_sym_number;
} else {
- die "unknown line type: $line";
+ $api_vers_to_type_vers{$hash_vers}{$name} = $curr_sym_number;
}
- $last_idx++;
}
-
- # Increment the version # of the function
- $last_vers++;
}
- # Keep track of last version index seen
- $last_idx = $_;
- }
-
- # Finish updating versions of the library that included the API routine
- if($last_idx >= 0) {
-#print "parse_line: max_idx='$max_idx'\n";
-
- # Add the function to the list of API routines available in
- # different versions of the library
- while($last_idx <= $max_idx) {
- if($line_type == 1) {
- $func_vers[$last_idx]{$name} = $last_vers;
- } elsif($line_type == 2) {
- $type_vers[$last_idx]{$name} = $last_vers;
- } else {
- die "unknown line type: $line";
- }
- $last_idx++;
- }
+ $curr_sym_number++;
}
# Store the number of symbol versions in a hash table, indexed by the name
- if($line_type == 1) {
+ if ($line_type == 1) {
$functions{$name} = $#vers_list + 1;
# Store the function's parameter types for later
$func_params{$name} = $params;
- } elsif($line_type == 2) {
+ } elsif ($line_type == 2) {
$typedefs{$name} = $#vers_list + 1;
- } else {
- die "unknown line type: $line";
}
+#print "\n";
}
# Unknown keyword
else {
@@ -488,7 +487,7 @@ for $file (@ARGV) {
#print "file = '$file'\n";
# Check for directory prefix on input file
- if($file =~ /\//) {
+ if ($file =~ /\//) {
($prefix) = ($file =~ /(^.*\/)/);
}
else {
@@ -497,9 +496,9 @@ for $file (@ARGV) {
#print "prefix = '$prefix'\n";
# Read in the entire file
open SOURCE, $file or die "$file: $!\n";
- while ( defined ($line=
+ *
+ *
+ * \image html H5DS_fig1.png "Figure 1. The relationship between a Dimension and a Dimension Scale."
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * \image html H5DS_fig2.png "Figure 2. The definition of a Dimension Scale and its attributes."
+ *
+ *
+ *
+ *
+ * \subsection subsec_dim_scales_concept_types What types of scales should be implemented?
+ * There seems to be good agreement that the model should accommodate scales that consist of a
+ * stored 1-D list of values, certain simple functions, and “no scale.” This specification also
+ * includes scales that are higher dimensional arrays, as well.
+ *
+ * The four types of scales are:
+ * \li No scale. Frequently no scale is needed, so it should not be required.
+ * In some of these cases, an axis label may still be needed, and should be available.
+ * In this case, the Datase * t defines a Dimension Scale label for a dimension, with no
+ * Dimension Scale dataset.
+ * \li 1-D array. Both fixed length and extendable arrays should be available.
+ * The size of the Dimension Scale is not required by HDF5 to conform to the size of the
+ * corresponding dimension(s), so that the number of scale values could be less than,
+ * equal to, or greater than the corresponding dimension size.
+ * \li Simple function. At a minimum, a linear scale of the form A + Bx
+ * should be available. This will be discussed in a future proposal.
+ * \li Higher dimensional arrays. This specification allows Dimension Scales
+ * to have any number of dimensions.
+ *
+ * A number of use cases have been proposed in which more than one scale is needed for a given dimension.
+ * This specification places no restrictions on the number of scales that can be associated with a dimension,
+ * nor on the number or identities of Dimensions that may share the same Dimension Scale.
+ *
+ * There are use cases for storing many types of data in a scale, including,
+ * but not limited to integers, floats, and strings. Therefore, this specification places no restrictions
+ * on the datatypes of scale values: a Dimension Scale can have any HDF5 Datatype. The
+ * interpretation of dimension scale values is left to applications.
+ *
+ * \subsection subsec_dim_scales_concept_limits Limitations of this Specification
+ * One-to-many mapping. When there are fewer values in a dimension scale than in the corresponding
+ * dimension, it is useful to have a mapping between the two. For example, mappings are used by
+ * HDF-EOS to map geolocation information to dimension, in order that, for example, every second
+ * point may have geolocation. On the other hand, the way that mappings are defined can be very
+ * idiosyncratic, and it would seem to be challenging to provide a mapping model that satisfied a
+ * large number of cases. These mappings are not included in the model specified here.
+ *
+ * Visibility and Integrity. Since Dimension Scales are a specialization of a Dataset, it is
+ * “visible” and accessible as a regular Dataset through the HDF5 API. This means that an application
+ * program could alter the values of or delete a Dimension Scale object or required attributes without
+ * regard to any of the semantics defined in this document.
+ *
+ * One advantage it that the implementation requires no changes to the base library, which reduces
+ * the complexity of the code and the risk of side-effects. The implementation builds on existing
+ * functions, which should improve the quality and reliability of the code. Also, this approach leaves
+ * most of the semantics of dimension scales to applications and communities, who can use the
+ * specification in any way they need.
+ *
+ * An important disadvantage is that the core HDF5 library will not manage the semantics of
+ * Dimension Scales. In particular, applications or other software must implement:
+ * \li Naming – the HDF5 library will impose no rules on the names of Dimension Scales
+ * \li Consistency of references – e.g., if a Dataset (Dimension Scale) is deleted (e.g.,
+ * with #H5Ldelete, any Dimension Scales (Datasets) that it refers to (refer to it)
+ * will not be updated by the HDF5 library.
+ * \li Consistency of extents – the HDF5 library will not assure that a Dimension and
+ * associated Dimension Scale have the same extent (number of elements), nor that shared
+ * objects are consistent with each other. As in the case of delete, if a Dimension or
+ * Dimension Scale is extended (e.g., H5S…), any associated objects will not be
+ * automatically extended.
+ *
+ * These are briefly summarized here.
+ * \li Naming and Name Spaces. There are many potential schemes for naming dimensions, each
+ * suited for different uses. This specification does not impose any specific approach,
+ * so it may be used by different applications. However, the lack of restrictions has
+ * disadvantages as well. For some purposes, it will be important to iterate through
+ * all the Dimension Scale objects in a file. The iterate operation is difficult to
+ * implement with the design specified here. This will be left to other software. For example,
+ * the HDF-EOS library has its own mechanism for managing a set of dimensions, and the
+ * netCDF4 library will implement this if it needs to.
+ * \li Automatically extending dataset dimensions. When a dimension of a dataset is
+ * extended, should the library automatically extend the corresponding dimension scale, or
+ * should this be left to the application? Since a dimension scale can be shared among many
+ * datasets, this raises a number of issues that are difficult to address in a general way.
+ * For instance, which dimension scale should be extended when only one dataset is extended,
+ * and what values are to be added? We have seen no compelling reason to implement an automatic
+ * extension of dimension scales when dataset dimensions are extended, so we suggest letting
+ * applications be responsible for this operation.
+ * \li Automatically deleting dimension scales. Should a dimension scale be deleted
+ * when all datasets that use it have been deleted? This is another case where different applications
+ * might have different requirements, so a general policy would be difficult to devise. Furthermore,
+ * enforcing a deletion policy, even a simple one, adds complexity to the library, and could also
+ * affect performance. Deletion policies seem best left to applications.
+ *
+ * Section \ref sec_dim_scales_api presents an API and programming model that implements some of these
+ * features. However, applications
+ * may ignore or bypass these APIs, to write or read the attributes directly.
+ *
+ * \section sec_dim_scales_spec The HDF5 Dimension Scale Specification
+ *
+ * \subsection subsec_dim_scales_spec_summary Brief Summary
+ * A Dimension Scale is stored as an HDF5 Dataset.
+ * \li A Dimension Scale is an object that is associated with a dimension of a Dataset.
+ * \li A Dimension Scale can have at most one name.
+ * \li A Dimension Scale may be associated with zero, one, or many different dimensions in any number of
+ * Datasets.
+ * \li Unless otherwise specified, a Dimension Scale inherits the properties of an HDF5 Dataset.
+ * \li There are no restrictions on the size, shape, or datatype of a Dimension Scale.
+ *
+ * A Dimension Scale can be associated with a dimension of an HDF5 dataset
+ * \li A dimension of a Dataset may have zero, one, or more Dimension Scales associated with it.
+ * \li Each scale is identified by an index value.
+ *
+ * A dimension may have a label without a scale, and may have a scale with no label.
+ * \li The label need not be the same as the name of any associated Dimension Scales.
+ *
+ * The implementation has two parts:
+ * \li A storage profile
+ * \li An API and programming model
+ *
+ * \subsection subsec_dim_scales_spec_store
+ * This section specifies the storage profile for Dimension Scale objects and the association between
+ * Dimensions and Dimension Scales.
+ *
+ * This profile is compatible with an earlier netcdf prototype and the HDF4 to HDF5 Mapping. This
+ * profile is also compatible with the netCDF4 proposal. This profile may be used to augment the
+ * HDF-EOS5 profile.
+ *
+ * See Appendix 2 for a discussion of how to store converted HDF4 objects. See Appendix 3 for a
+ * discussion of netCDF4 issues. See Appendix 4 for a discussion of HDF-EOS5.
+ *
+ * \subsubsection subsubsec_dim_scales_spec_store_dset
+ * A Dimension Scale dataset is stored as an HDF5 dataset. Table 1 summarizes the stored data, i.e.,
+ * the values of the scale. There are no restrictions on the dataspace or datatype, or storage properties of
+ * the dataset.
+ *
+ * The scale may have any HDF5 datatype, and does not have to be the same as the datatype of
+ * the Dataset(s) that use the scale. E.g., an integer dataset might have dimension scales
+ * that are string or float values.
+ *
+ * The dataspace of the scale can be any rank and shape. A scale is not limited to one dimension,
+ * and is not restricted by the size of any dimension(s) associated with it. When a dimension is
+ * associated with a one dimensional scale, the scale may be a different size from the dimension.
+ * In this case, it is up to the application to interpret or resolve the difference. When a
+ * dimension is associated with a scale with a rank higher than 1, the interpretation of the
+ * association is up to the application.
+ *
+ * The Dimension Scale dataset can use any storage properties (including fill values, filters,
+ * and storage layout), not limited by the properties of any datasets that refer to it. When
+ * the Dimension Scale is extendible, it must be chunked.
+ *
+ * Table 2 defines the required and optional attributes of the Dimension Scale Dataset. The
+ * attribute REFERENCE_LIST is a list of (dataset, index) pairs. Each pair represents an
+ * association defined by ‘attach_scale’. These pairs are stored as an array of compound data.
+ * Table 3 defines this datatype.
+ *
+ * The Dimension Scale Dataset has an attribute called SUB_CLASS. This string is intended to
+ * be used to document particular specializations of this profile, e.g., a Dimension Scale
+ * created by netCDF4.
+ *
+ *
Table 1. The properties of the Dimension Scale dataset
+ *
+ *
Field
+ *
Datatype
+ *
Dataspace
+ *
Storage Properties
+ *
Notes
+ *
+ *
+ *
<data>
+ *
Any
+ *
Any
+ *
Any
+ *
These are the values of the Dimension Scale.
+ *
+ *
+ *
+ *
Table 2. Standard Attributes for a stored Dimension Scale dataset.
+ *
+ *
Attribute Name
+ *
Datatype and Dimensions
+ *
Value
+ *
Required / Optional
+ *
Notes
+ *
+ *
+ *
CLASS
+ *
#H5T_STRING length = 16
+ *
“DIMENSION_SCALE”
+ *
Required
+ *
This attribute distinguishes the dataset as a Dimension scale object. This is set by
+ * #H5DSset_scale
+ *
+ *
+ *
NAME
+ *
#H5T_STRING length = <user defined>
+ *
<user defined> The name does not have to be the same as the HDF5 path name for the dataset.
+ * The name does not have to be related to any labels. Several Dimension Scales may have the same name.
+ *
Optional, (Maximum of 1)
+ *
The user defined label of the Dimension Scale. This is set by #H5DSset_label
+ *
+ *
+ *
REFERENCE_LIST
+ *
Array of Dataset Reference Type (Compound Datatype), variable length.
+ *
[ {dataset1, ind1 }, …] [,…] ….]
+ *
Optional, required when scale is attached
+ *
See Table 3. This is set by #H5DSattach_scale.
+ *
+ *
+ *
SUB_CLASS
+ *
#H5T_STRING length = <profile defined>
+ *
“HDF4_DIMENSION”, “NC4_DIMENSION”,
+ *
Optional, defined by other profiles
+ *
This is used to indicate a specific profile was used.
+ *
+ *
+ *
<Other attributes>
+ *
+ *
+ *
Optional
+ *
For example, UNITS.
+ *
+ *
+ *
+ *
Table 3. Dataset Reference Type.
+ * This is a pair, <dataset_ref, index>. This is created when the Dimension Scale is attached to a
+ * Dataset.
+ *
+ *
Field
+ *
Datatype
+ *
Value
+ *
Notes
+ *
+ *
+ *
DATASET
+ *
Object Reference.
+ *
Pointer to a Dataset that refers to the scale
+ *
Set by #H5DSattach_scale. Removed by #H5DSdetach_scale.
+ *
+ *
+ *
INDEX
+ *
#H5T_NATIVE_INT
+ *
Index of the dimension the dataset pointed to by DATASET
+ *
Set by #H5DSattach_scale. Removed by #H5DSdetach_scale.
+ *
+ *
+ *
+ * \subsubsection subsubsec_dim_scales_spec_store_attr Attributes of a Dataset with a Dimension Scale
+ * A Dataset may have zero or more Dimension Scales associated with its dataspace. When present,
+ * these associations are represented by two attributes of the Dataset. Table 4 defines these attributes.
+ *
+ * The DIMENSION_LIST is a two dimensional array with one row for each dimension of the Dataset, and
+ * a variable number of entries in each row, one for each associated scale. This is stored as a one
+ * dimensional array, with the HDF5 Datatype variable length array of object references.
+ *
+ * When a dimension has more than one scale, the order of the scales in the DIMENSION_LIST attribute
+ * is not defined. A given Dimension Scale should appear in the list only once.
+ * (I.E., the DIMENSION_LIST is a “set”.)
+ *
+ * When a scale is shared by more than one dimension (of one or more Dataset), the order of
+ * the records in REFERENCE_LIST is not defined. The Dataset and Dimension should appear in the list only
+ * once.
+ *
+ *
Table 4. Standard Attributes of a Dataset with associated Dimension Scale.
+ *
+ *
Attribute Name
+ *
Datatype and Dimensions
+ *
Value
+ *
Required / Optional
+ *
Notes
+ *
+ *
+ *
DIMENSION_LIST
+ *
The HDF5 datatype is ARRAY of Variable Length #H5T_STD_REF_OBJ with rank of the dataspace.
Set by #H5DSattach_scale. Entries removed by #H5DSdetach_scale.
+ *
+ *
+ *
DIMENSION_LABELLIST
+ *
The HDF5 datatype is ARRAY of #H5T_STRING with rank of the dataspace.
+ *
[ <Label1>, <Label2>, …, <Label3>]
+ *
Optional, required for scales with a label
+ *
Set by #H5DSset_label.
+ *
+ *
+ *
+ * \subsection subsec_dim_scales_spec_lab Dimension Scale Names and Labels
+ * Dimension scales are often referred to by name, so Dimension Scales may have names.
+ * Since some applications do not wish to apply names to dimension scales, Dimension Scale
+ * names be optional. In addition, some applications will have a name but no associated data
+ * values for a dimension (i.e., just a label). To support this, each dimension may have a
+ * label, which may be but need not be the same as the name of an associated Dimension Scale.
+ *
+ * Dimension Scale Name. Associated with the Dimension Scale object. A Dimension Scale may
+ * have no name, or one name.
+ *
+ * Dimension Label. A optional label associated with a dimension of a Dataset.
+ *
+ * How is a name represented? Three options seem reasonable:
+ * \li Last link in the pathname. The h4toh5 mapping uses this approach [6], but there could be more
+ * than one path to a dataset, leading to ambiguities. This could be overcome by enforcing conventions.
+ * \li Attribute. This exposes this information at the top level, making it accessible to any viewer that
+ * can see attributes. It also makes it easy for applications to change the name, which could be
+ * dangerous, or valuable.
+ * \li Header message. This approach makes the name a little less available at the top level,
+ * but firmly pushes the concept into the base format and library. Since it also requires
+ * applications to change the name through a function call, it leaves open the possibility
+ * that the form of the name could be altered later without requiring application codes
+ * to change. On the other hand, if we treat names this way, it means that the “name”
+ * attribute is being treated differently from the “class” attribute, which could be confusing.
+ *
+ * Dimension Scale names are stored in attributes of the Dimension Scale or the Dataset that refers
+ * to a Dimension Scale.
+ *
+ * Should dimension scale names be unique among dimension scales within a file?
+ * We have seen a number of cases in which applications need more than one dimension scale with
+ * the same name. We have also seen applications where the opposite is true: dimension scale
+ * names are assumed to be unique within a file. This specification leaves it to applications
+ * to enforce a policy of uniqueness when they need it.
+ *
+ * Can a dimension have a label, without having an associated scale? Some
+ * applications may wish to name dimensions without having an associated scale. Therefore,
+ * a dataset may have a label for a dimension without having an associated Dimension Scale dataset.
+ *
+ * Can a dimension have a scale, without having an associated label? Some
+ * applications may wish to assign a dimension scale with no label. Therefore, a dataset
+ * may have one or more Dimension Scales for a dimension without having an associated label.
+ *
+ * Anonymous Dimensions. It is possible to have a Dimension Scale dataset
+ * with no name, and associate it with a dimension of a dataset with no label. This case
+ * associates an array of data values to the dimension, but no identifier.
+ *
+ * A dimension with a label and a name. A dimension of a dataset can be
+ * associated with a Dimension Scale that has a name, and assigned a label. In this case,
+ * the association has two “names”, the label and the dimension scale name. It is up to
+ * applications to interpret these names.
+ *
+ * Table 5 summarizes the six possible combinations of label and name.
+ *
+ *
Table 5. Labels and scales of a dimension.
+ *
+ *
+ *
No scale
+ *
Scale with no name
+ *
Scale with name
+ *
+ *
+ *
No label
+ *
Dimension has no label or scale (default)
+ *
Dimension has an anonymous scale
+ *
Dimension has scale, the scale is called “name”
+ *
+ *
+ *
Label
+ *
Dimension has label
+ *
Dimension has scale with a label.
+ *
Dimension has scale with both a label and name. A shared dimension has one name,
+ * but may have several labels
+ *
+ *
+ *
+ * \subsection subsec_dim_scales_spec_shared Shared Dimension Scales
+ * Given the design described above, datasets can share dimension scales. The following
+ * additional capabilities would seem to be useful.
+ * \li When a dimension scale is deleted, remove the reference to the dimension scale in
+ * all datasets that refer to it.
+ * \li Determine how many datasets are attached to a given dimension scale
+ * \li Determine what datasets are attached to a given dimension scale
+ *
+ * These capabilities can be provided in several ways:
+ * \li Back pointers. If every dimension scale contained a list of back pointers to all
+ * datasets that referenced it, then it would be relatively easy to open all of these
+ * datasets and remove the references, as well as to answer questions #2 and #3.
+ * This would require the library to update the back pointer list every time a link
+ * was made.
+ * \li Alternatively, such lists could be maintained in a separate table. Such a table
+ * could contain all information about a number of dimension scales, which might provide
+ * a convenient way for applications to gain information about a set of dimension scales.
+ * For instance, this table might correspond to the coordinate variable definitions in a netCDF file.
+ * \li If no such list were available, an HDF5 function could be available to search all datasets
+ * to determine which ones referenced a given dimension scale. This would be straightforward,
+ * but in some cases could be very time consuming.
+ *
+ * This specification defines attributes that maintain back pointers, which enable
+ * these kinds of cross referencing. Other software, such as NetCDF4, may well need a global table to
+ * track a set of dimensions. Such a table can be done in addition to the attributes defined here.
+ *
+ * \subsection subsec_dim_scales_spec_ex Example
+ * This section presents an example to illustrate the data structures defined above.
+ *
+ * Figure 3 shows a Dataset with a four dimensional Dataspace. The file also contains six Dimension
+ * Scale datasets. The Dimension Scale datasets are HDF5 objects, with path names such as “/DS1”.
+ *
+ * Figure 4 illustrates the use of dimension scales in this example. Each Dimension Scale Dataset
+ * has an optional NAME. For example, “/DS3” has been assigned the name “Scale3”.
+ *
+ * The dimensions of dataset D have been assigned zero or more scales and labels. Dimension 0
+ * has two scales, Dimension 1 has one scale, and so on. Dimension 2 has no scale associated with it.
+ *
+ * Some of the dimensions have labels as well. Note that dimension 2 has a label but no scale, and
+ * dimension 3 has scales but no label.
+ *
+ * Some of the Dimension Scales are shared. Dimension Scale DS1 is referenced by dimension 0 of D
+ * and by another unspecified dataset. Dimension Scale DS3 is referenced by dimension 1 and 3 of Dataset D.
+ *
+ * These relationships are represented in the file by attributes of the Dataset D and the Dimension
+ * Scale Datasets. Figure 5 shows the values that are stored for the DIMENSION_LIST attribute of
+ * Dataset D. This
+ *
+ *
+ *
+ * \image html UML_Attribute.jpg "The UML model for an HDF5 attribute"
+ *
+ *
+ *
+ * attribute is a one-dimensional array with the HDF5 datatype variable length
+ * #H5T_STD_REF_OBJ. Each row of the array is zero or more object references for Dimension Scale datasets.
+ *
+ * Table 6 shows the DIMENSION_LABELLIST for Dataset D. This is a one dimensional array with some empty
+ * values.
+ *
+ * Each of the Dimension Scale Datasets has a name and other attributes. The references are
+ * represented in the REFERENCE_LIST attributes. Table 7 – Table 10 show the values for these
+ * tables. Note that Dimension Scale DS4 and DS6 have no references to them in this diagram.
+ *
+ * The tables are stored as attributes of the Dimension Scale Dataset and the Datasets that
+ * refer to scales. Essentially, the association between a dimension of a Dataset and a Dimension
+ * Scale is represented by “pointers” (i.e., HDF5 Object References) in both of the associated
+ * objects. Since there can be multiple associations, there can be multiple pointers stored at
+ * each object, representing the endpoints of the associations. These will be stored in tables,
+ * i.e., as an attribute with an array of values.
+ *
+ * When dimension scales are attached or detached, the tables in the Dataset and the Dimension
+ * Scale must be updated. The arrays in the attributes can grow, and items can be deleted.
+ *
+ * The associations are identified by the object reference and dimension which is stored in a
+ * back pointer and returned from an API. The detach function needs to be careful how it deletes
+ * an item from the table, because the entries at both ends of the association must be updated
+ * at the same time.
+ *
+ *
+ *
+ *
+ * \image html H5DS_fig3.png "Figure 3. Example dataset and scales."
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * \image html H5DS_fig4.png "Figure 4. Example labels, names, and attached scales."
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * \image html H5DS_fig5.png "Figure 5. The table of dimension references, stored as an attribute of the
+ * Dataset."
+ *
+ *
+ *
+ *
+ *
Table 6. The table of dimension labels.
+ *
+ *
Dataset Dimension
+ *
Label
+ *
+ *
+ *
0
+ *
“LX”
+ *
+ *
+ *
1
+ *
“LZ”
+ *
+ *
+ *
2
+ *
“LQ”
+ *
+ *
+ *
3
+ *
“”
+ *
+ *
+ *
+ *
Table 7. The reference list for DS1.
+ *
+ *
Reference
+ *
Dataset Reference Record
+ *
+ *
+ *
0
+ *
{Object reference to Dataset D, 0}
+ *
+ *
+ *
1
+ *
{Object reference to other Dataset, ?}
+ *
+ *
+ *
+ *
Table 8. Reference list for DS2
+ *
+ *
Reference
+ *
Dataset Reference Record
+ *
+ *
+ *
0
+ *
{Object reference to Dataset D, 0}
+ *
+ *
+ *
+ *
Table 9. Reference list for DS3
+ *
+ *
Reference
+ *
Dataset Reference Record
+ *
+ *
+ *
0
+ *
{Object reference to Dataset D, 1}
+ *
+ *
+ *
1
+ *
{Object reference to Dataset D, 3}
+ *
+ *
+ *
+ *
Table 10. Reference List for DS5
+ *
+ *
Reference
+ *
Dataset Reference Record
+ *
+ *
+ *
0
+ *
{Object reference to Dataset D, 3}
+ *
+ *
+ *
+ * \section sec_dim_scales_api Programming Model and API
+ *
+ * \subsection subsec_dim_scales_api_model Programming Model
+ * Dimension Scales are HDF5 Datasets, so they may be created and accesses through any
+ * HDF5 API for datasets [10]. The HDF5 Dimension Scale API implements the specification
+ * defined in this document. The operations include:
+ * \li Convert dataset to scale (D) – convert dataset D to a dimension scale. D may be
+ * specified by an id or by a path name.
+ * \li Attach scale (D, S, i) – attach dimension scale S to the ith dimension of D. D
+ * and S may be specified by an id or path name
+ * \li Detach scale (D, i, scale) – detach scale from the ith dimension of D.
+ * \li Iterate through scales of (D, i) – get each scale attached.
+ * \li Get the number of scales of (D, i)
+ * \li Get the ith scale of D
+ * \li Set/Get name (S) – set/get the name about dimension scale S.
+ *
+ * The API also defines operations for dimension labels:
+ * \li Set/Get label (D, i) – set/get the label for ith dimension of D.
+ *
+ * \subsubsection subsubsec_dim_scales_api_model_create Create new Dimension Scale with Initial Values
+ * 1. Create dataset with for the Dimension Scale with H5Dcreate and other standard HDF5 calls.
+ * 2. Initialize the values of the Dimension Scale with H5Dwrite and other calls.
+ * 3. Convert the dataset to a Dimension Scale with H5DSmake_scale.
+ * 4. Close the Dimension Scale when finished with H5Dclose.
+ *
+ * \subsubsection subsubsec_dim_scales_api_model_attach Attach Dimension Scale to Dataset
+ * 1. Create or open the Dataset, D, with H5Dopen, etc.
+ * 2. Create or open the Dimension Scale dataset, S, with H5Dopen or as above.
+ * 3. Attach the Dimension Scale S to dimension j of Dataset D with H5DSattach_scale
+ * 4. When finished, close the Dimension Scale and Dataset with H5Dclose.
+ *
+ * \subsubsection subsubsec_dim_scales_api_model_read Read Dimension Scale values
+ * 1. Open the Dataset D, with H5Dopen
+ * 2. Get the number of dimensions of D with H5Dget_space.
+ * 3. Iterate through the scales of dimension i, locate the target scale, S (e.g., by its name).
+ * 4. Get the datatype, dataspace, etc. of S with H5Dget_space, H5Dget_type, H5Sget_ndims, etc.
+ * 5. Read the values of S into memory with H5Dread, e.g. into dscalebuff.
+ * 6. When finished, close the S and other objects with H5Dclose etc.
+ * 7. When finished, close the Dataset D with H5Dclose.
+ *
+ * \subsubsection subsubsec_dim_scales_api_model_write Write or Update Dimension Scale values
+ * 1. Open the Dimension Scale Dataset S with H5open
+ * 2. Get the datatype, dataspace, etc. of S with H5Dget_space, H5Dget_type, H5Sget_ndims, etc.
+ * 3. If needed, read the values of S into memory with H5Dread. Note, may read selected values using a
+ * selection.
+ * 4. Write updated values to S with H5Dwrite. Note, may write selected values using a selection.
+ * 5. When finished, close S and other objects with H5Dclose etc.
+ *
+ * \subsubsection subsubsec_dim_scales_api_model_label Create a label for a dimension
+ * 1. Open the Dataset D with H5open
+ * 2. Add write a label for dimension i of D, with H5DSset_label.
+ * 3. When finished, close the Dimension Scale Dataset and other objects with H5Dclose etc.
+ *
+ * \subsubsection subsubsec_dim_scales_api_model_extend Extending a Dimension with a Dimension Scale attached
+ * When an extendible Dataset has Dimension Scales, it is necessary to coordinate when the dimensions change
+ * size.
+ * 1. Open the Dataset to be extended, with H5Dopen.
+ * 2. Extend the dimension(s) with H5Dextend
+ * 3. Iterate through the scales of each extended dimension. For each scale
+ * a. Extend the scale to the new size of the dimension with H5Dextend
+ * b. Write new values to the extended scale with H5Dwrite, etc.
+ * c. Close the Dimension Scale Dataset with H5Dclose if necessary.
+ * 4. When finished, close the Dataset with H5Dclose
+ *
+ * \subsubsection subsubsec_dim_scales_api_model_detach Detach Dimension Scale from Dataset
+ * The detach operation removes an association between a dimension and a scale. It does not delete the
+ * Dimension Scale Dataset.
+ * 1. Open the Dataset, D, with H5Dopen.
+ * 2. Iterate through the scales of dimension i, locate the target scale, S (e.g., by its name).
+ * 3. Detach the Dimension Scale S to dimension j of Dataset D with H5DSdetach_scale
+ * 4. When finished, close the Dimension Scale and Dataset with H5Dclose.
+ *
+ * \subsubsection subsubsec_dim_scales_api_model_del Delete a Dimension Scale Dataset
+ * When it is necessary to delete a Dimension Scale Dataset, it is necessary to detach it from all dataset.
+ * This section outlines the necessary steps.
+ * 1. Open the Dimension Scale to be deleted.
+ * 2. Read the REFERENCE_LIST attribute into memory with H5Aread etc.
+ * 3. For each entry in the list:
+ * a. Dereference the dataset reference
+ * b. Detach the scale with H5DSdetach_scale
+ * c. Close the dataset reference
+ * 4. Delete the Dimension Scale Dataset
+ *
+ * \subsubsection subsubsec_dim_scales_api_model_clean Clean up Dimension Scales when deleting a Dataset
+ * When it is necessary to delete a dataset that has scales attached, it is necessary to delete all the
+ * scales before deleting the dataset. Here is a sketch of the steps.
+ * 1. Open the Dataset to be deleted, with H5Dopen.
+ * 2. Iterate through the scales of each dimension of D
+ * 3. For each scale, detach the Dimension Scale S from dimension j of Dataset D with H5DSdetach_scale
+ * 4. Delete the Dataset, with H5Gunlink.
+ *
+ * \subsection subsec_dim_scales_api_func Programming API: H5DS
+ * @see H5DS Reference Manual
+ *
* @todo Under Construction
*/
diff --git a/hl/src/H5PT.c b/hl/src/H5PT.c
index c8cefd3a324..89e6a20d69d 100644
--- a/hl/src/H5PT.c
+++ b/hl/src/H5PT.c
@@ -25,8 +25,6 @@ typedef struct {
static hsize_t H5PT_ptable_count = 0;
static H5I_type_t H5PT_ptable_id_type = H5I_UNINIT;
-#define H5PT_HASH_TABLE_SIZE 64
-
/* Packet Table private functions */
static herr_t H5PT_free_id(void *id, void **_ctx);
static herr_t H5PT_close(htbl_t *table);
@@ -73,8 +71,7 @@ H5PTcreate(hid_t loc_id, const char *dset_name, hid_t dtype_id, hsize_t chunk_si
/* Register the packet table ID type if this is the first table created */
if (H5PT_ptable_id_type < 0)
- if ((H5PT_ptable_id_type =
- H5Iregister_type((size_t)H5PT_HASH_TABLE_SIZE, 0, (H5I_free_t)H5PT_free_id)) < 0)
+ if ((H5PT_ptable_id_type = H5Iregister_type2(0, (H5I_free_t)H5PT_free_id)) < 0)
goto error;
/* Get memory for the table identifier */
@@ -187,8 +184,7 @@ H5PTcreate_fl(hid_t loc_id, const char *dset_name, hid_t dtype_id, hsize_t chunk
/* Register the packet table ID type if this is the first table created */
if (H5PT_ptable_id_type < 0)
- if ((H5PT_ptable_id_type =
- H5Iregister_type((size_t)H5PT_HASH_TABLE_SIZE, 0, (H5I_free_t)H5PT_free_id)) < 0)
+ if ((H5PT_ptable_id_type = H5Iregister_type2(0, (H5I_free_t)H5PT_free_id)) < 0)
goto error;
/* Get memory for the table identifier */
@@ -287,8 +283,7 @@ H5PTopen(hid_t loc_id, const char *dset_name)
/* Register the packet table ID type if this is the first table created */
if (H5PT_ptable_id_type < 0)
- if ((H5PT_ptable_id_type =
- H5Iregister_type((size_t)H5PT_HASH_TABLE_SIZE, 0, (H5I_free_t)H5PT_free_id)) < 0)
+ if ((H5PT_ptable_id_type = H5Iregister_type2(0, (H5I_free_t)H5PT_free_id)) < 0)
goto error;
table = (htbl_t *)malloc(sizeof(htbl_t));
diff --git a/java/src/hdf/hdf5lib/H5.java b/java/src/hdf/hdf5lib/H5.java
index fe475611bc8..fe51f4e511d 100644
--- a/java/src/hdf/hdf5lib/H5.java
+++ b/java/src/hdf/hdf5lib/H5.java
@@ -6306,7 +6306,7 @@ public synchronized static native void H5Iclear_type(int type_id, boolean force)
// hid_t H5Iregister(H5I_type_t type, const void *object);
// typedef herr_t (*H5I_free_t)(void *);
- // H5I_type_t H5Iregister_type(size_t hash_size, unsigned reserved, H5I_free_t free_func);
+ // H5I_type_t H5Iregister_type2(unsigned reserved, H5I_free_t free_func);
// void *H5Iremove_verify(hid_t id, H5I_type_t id_type);
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 8aab20fb543..c3e19ff3033 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -158,6 +158,24 @@ New Features
Library:
--------
+ - The H5Iregister_type() signature has changed
+
+ The hash_size parameter has not been used since early versions of HDF5
+ 1.8, so it has been removed and the API call has been versioned.
+
+ The old signature has been renamed to H5Iregister_type1() and is considered
+ deprecated:
+
+ H5I_type_t H5Iregister_type1(size_t hash_size, unsigned reserved, H5I_free_t free_func);
+
+ The new signature is H5Iregister_type2(). New code should use this
+ version:
+
+ H5I_type_t H5Iregister_type2(unsigned reserved, H5I_free_t free_func);
+
+ H5Iregister_type() will map to the new signature unless the library is
+ explicitly configured to use an older version of the API.
+
- H5F_LIBVER_LATEST is now an enum value
This was previously #defined to the latest H5F_libver_t API version, but
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2cdaa575c43..8900bae7528 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -387,6 +387,7 @@ IDE_GENERATED_PROPERTIES ("H5HL" "${H5HL_HDRS}" "${H5HL_SOURCES}" )
set (H5I_SOURCES
${HDF5_SRC_DIR}/H5I.c
${HDF5_SRC_DIR}/H5Idbg.c
+ ${HDF5_SRC_DIR}/H5Ideprec.c
${HDF5_SRC_DIR}/H5Iint.c
${HDF5_SRC_DIR}/H5Itest.c
)
diff --git a/src/H5I.c b/src/H5I.c
index 731f0f31c56..201a6fb8e83 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -73,16 +73,15 @@ static int H5I__iterate_pub_cb(void *obj, hid_t id, void *udata);
/*******************/
/*-------------------------------------------------------------------------
- * Function: H5Iregister_type
+ * Function: H5Iregister_type2
*
- * Purpose: Public interface to H5I_register_type. Creates a new type
+ * Purpose: Public interface to H5I_register_type2. Creates a new type
* of ID's to give out. A specific number (RESERVED) of type
* entries may be reserved to enable "constant" values to be handed
* out which are valid IDs in the type, but which do not map to any
- * data structures and are not allocated dynamically later. HASH_SIZE is
- * the minimum hash table size to use for the type. FREE_FUNC is
- * called with an object pointer when the object is removed from
- * the type.
+ * data structures and are not allocated dynamically later.
+ * FREE_FUNC is called with an object pointer when the object is
+ * removed from the type.
*
* Return: Success: Type ID of the new type
* Failure: H5I_BADID
@@ -90,65 +89,18 @@ static int H5I__iterate_pub_cb(void *obj, hid_t id, void *udata);
*-------------------------------------------------------------------------
*/
H5I_type_t
-H5Iregister_type(size_t H5_ATTR_UNUSED hash_size, unsigned reserved, H5I_free_t free_func)
+H5Iregister_type2(unsigned reserved, H5I_free_t free_func)
{
- H5I_class_t *cls = NULL; /* New ID class */
- H5I_type_t new_type = H5I_BADID; /* New ID type value */
- H5I_type_t ret_value = H5I_BADID; /* Return value */
+ H5I_type_t ret_value = H5I_BADID;
FUNC_ENTER_API(H5I_BADID)
- /* Generate a new H5I_type_t value */
-
- /* Increment the number of types */
- if (H5I_next_type_g < H5I_MAX_NUM_TYPES) {
- new_type = (H5I_type_t)H5I_next_type_g;
- H5I_next_type_g++;
- }
- else {
- bool done; /* Indicate that search was successful */
- int i;
-
- /* Look for a free type to give out */
- done = false;
- for (i = H5I_NTYPES; i < H5I_MAX_NUM_TYPES && done == false; i++) {
- if (NULL == H5I_type_info_array_g[i]) {
- /* Found a free type ID */
- new_type = (H5I_type_t)i;
- done = true;
- }
- }
-
- /* Verify that we found a type to give out */
- if (done == false)
- HGOTO_ERROR(H5E_ID, H5E_NOSPACE, H5I_BADID, "Maximum number of ID types exceeded");
- }
-
- /* Allocate new ID class */
- if (NULL == (cls = H5MM_calloc(sizeof(H5I_class_t))))
- HGOTO_ERROR(H5E_ID, H5E_CANTALLOC, H5I_BADID, "ID class allocation failed");
-
- /* Initialize class fields */
- cls->type = new_type;
- cls->flags = H5I_CLASS_IS_APPLICATION;
- cls->reserved = reserved;
- cls->free_func = free_func;
-
- /* Register the new ID class */
- if (H5I_register_type(cls) < 0)
+ if (H5I_BADID == (ret_value = H5I__register_type_common(reserved, free_func)))
HGOTO_ERROR(H5E_ID, H5E_CANTINIT, H5I_BADID, "can't initialize ID class");
- /* Set return value */
- ret_value = new_type;
-
done:
- /* Clean up on error */
- if (ret_value < 0)
- if (cls)
- cls = H5MM_xfree(cls);
-
FUNC_LEAVE_API(ret_value)
-} /* end H5Iregister_type() */
+} /* end H5Iregister_type2() */
/*-------------------------------------------------------------------------
* Function: H5Itype_exists
diff --git a/src/H5Ideprec.c b/src/H5Ideprec.c
new file mode 100644
index 00000000000..0d172f668bd
--- /dev/null
+++ b/src/H5Ideprec.c
@@ -0,0 +1,97 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the LICENSE file, which can be found at the root of the source code *
+ * distribution tree, or in https://www.hdfgroup.org/licenses. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Ideprec.c
+ *
+ * Purpose: Deprecated functions from the H5I interface. These
+ * functions are here for compatibility purposes and may be
+ * removed in the future. Applications should switch to the
+ * newer APIs.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#include "H5Imodule.h" /* This source code file is part of the H5I module */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Ipkg.h" /* File access */
+
+/****************/
+/* Local Macros */
+/****************/
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+/*-------------------------------------------------------------------------
+ * Function: H5Iregister_type1
+ *
+ * Purpose: Public interface to H5I_register_type. Creates a new type
+ * of ID's to give out. A specific number (RESERVED) of type
+ * entries may be reserved to enable "constant" values to be handed
+ * out which are valid IDs in the type, but which do not map to any
+ * data structures and are not allocated dynamically later. HASH_SIZE is
+ * the minimum hash table size to use for the type. FREE_FUNC is
+ * called with an object pointer when the object is removed from
+ * the type.
+ *
+ * Return: Success: Type ID of the new type
+ * Failure: H5I_BADID
+ *
+ *-------------------------------------------------------------------------
+ */
+H5I_type_t
+H5Iregister_type1(size_t H5_ATTR_UNUSED hash_size, unsigned reserved, H5I_free_t free_func)
+{
+ H5I_type_t ret_value = H5I_BADID;
+
+ FUNC_ENTER_API(H5I_BADID)
+
+ if (H5I_BADID == (ret_value = H5I__register_type_common(reserved, free_func)))
+ HGOTO_ERROR(H5E_ID, H5E_CANTINIT, H5I_BADID, "can't initialize ID class");
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Iregister_type1() */
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
diff --git a/src/H5Iint.c b/src/H5Iint.c
index 785dd9f0e86..21c4bfc280a 100644
--- a/src/H5Iint.c
+++ b/src/H5Iint.c
@@ -156,6 +156,76 @@ H5I_term_package(void)
FUNC_LEAVE_NOAPI(in_use)
} /* end H5I_term_package() */
+/*-------------------------------------------------------------------------
+ * Function: H5I__register_type_common
+ *
+ * Purpose: Common functionality for H5Iregister_type(1|2)
+ *
+ * Return: Success: Type ID of the new type
+ * Failure: H5I_BADID
+ *-------------------------------------------------------------------------
+ */
+H5I_type_t
+H5I__register_type_common(unsigned reserved, H5I_free_t free_func)
+{
+ H5I_class_t *cls = NULL; /* New ID class */
+ H5I_type_t new_type = H5I_BADID; /* New ID type value */
+ H5I_type_t ret_value = H5I_BADID; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Generate a new H5I_type_t value */
+
+ /* Increment the number of types */
+ if (H5I_next_type_g < H5I_MAX_NUM_TYPES) {
+ new_type = (H5I_type_t)H5I_next_type_g;
+ H5I_next_type_g++;
+ }
+ else {
+ bool done; /* Indicate that search was successful */
+ int i;
+
+ /* Look for a free type to give out */
+ done = false;
+ for (i = H5I_NTYPES; i < H5I_MAX_NUM_TYPES && done == false; i++) {
+ if (NULL == H5I_type_info_array_g[i]) {
+ /* Found a free type ID */
+ new_type = (H5I_type_t)i;
+ done = true;
+ }
+ }
+
+ /* Verify that we found a type to give out */
+ if (done == false)
+ HGOTO_ERROR(H5E_ID, H5E_NOSPACE, H5I_BADID, "Maximum number of ID types exceeded");
+ }
+
+ /* Allocate new ID class */
+ if (NULL == (cls = H5MM_calloc(sizeof(H5I_class_t))))
+ HGOTO_ERROR(H5E_ID, H5E_CANTALLOC, H5I_BADID, "ID class allocation failed");
+
+ /* Initialize class fields */
+ cls->type = new_type;
+ cls->flags = H5I_CLASS_IS_APPLICATION;
+ cls->reserved = reserved;
+ cls->free_func = free_func;
+
+ /* Register the new ID class */
+ if (H5I_register_type(cls) < 0)
+ HGOTO_ERROR(H5E_ID, H5E_CANTINIT, H5I_BADID, "can't initialize ID class");
+
+ /* Set return value */
+ ret_value = new_type;
+
+done:
+ /* Clean up on error */
+ if (ret_value == H5I_BADID)
+ if (cls)
+ cls = H5MM_xfree(cls);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I__register_type_common() */
+
/*-------------------------------------------------------------------------
* Function: H5I_register_type
*
diff --git a/src/H5Ipkg.h b/src/H5Ipkg.h
index 852ab151dc5..5393c3d2b39 100644
--- a/src/H5Ipkg.h
+++ b/src/H5Ipkg.h
@@ -106,6 +106,7 @@ H5_DLLVAR int H5I_next_type_g;
H5_DLL hid_t H5I__register(H5I_type_t type, const void *object, bool app_ref,
H5I_future_realize_func_t realize_cb, H5I_future_discard_func_t discard_cb);
+H5_DLL H5I_type_t H5I__register_type_common(unsigned reserved, H5I_free_t free_func);
H5_DLL int H5I__destroy_type(H5I_type_t type);
H5_DLL void *H5I__remove_verify(hid_t id, H5I_type_t type);
H5_DLL int H5I__inc_type_ref(H5I_type_t type);
diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h
index 9a28dac9094..0ccebda6da5 100644
--- a/src/H5Ipublic.h
+++ b/src/H5Ipublic.h
@@ -394,20 +394,14 @@ H5_DLL int H5Iget_ref(hid_t id);
*
* \brief Creates and returns a new ID type
*
- * \param[in] hash_size Minimum hash table size (in entries) used to store IDs
- * for the new type (unused in 1.8.13 and later)
* \param[in] reserved Number of reserved IDs for the new type
* \param[in] free_func Function used to deallocate space for a single ID
*
* \return Returns the type identifier on success, negative on failure.
*
- * \details H5Iregister_type() allocates space for a new ID type and returns an
+ * \details H5Iregister_type2() allocates space for a new ID type and returns an
* identifier for it.
*
- * The \p hash_size parameter indicates the minimum size of the hash
- * table used to store IDs in the new type. This parameter is unused
- * in 1.8.13 and later, when the implementation of ID storage changed.
- *
* The \p reserved parameter indicates the number of IDs in this new
* type to be reserved. Reserved IDs are valid IDs which are not
* associated with any storage within the library.
@@ -420,10 +414,10 @@ H5_DLL int H5Iget_ref(hid_t id);
* pointer which was passed in to the H5Iregister() function. The \p
* free_func function should return 0 on success and -1 on failure.
*
- * \since 1.8.0
+ * \since 2.0.0
*
*/
-H5_DLL H5I_type_t H5Iregister_type(size_t hash_size, unsigned reserved, H5I_free_t free_func);
+H5_DLL H5I_type_t H5Iregister_type2(unsigned reserved, H5I_free_t free_func);
/**
* \ingroup H5IUD
*
@@ -683,6 +677,51 @@ H5_DLL htri_t H5Itype_exists(H5I_type_t type);
*/
H5_DLL htri_t H5Iis_valid(hid_t id);
+/* Symbols defined for compatibility with previous versions of the HDF5 API.
+ *
+ * Use of these symbols is deprecated.
+ */
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+
+/**
+ * \ingroup H5IUD
+ *
+ * \brief Creates and returns a new ID type
+ *
+ * \param[in] hash_size Minimum hash table size (in entries) used to store IDs
+ * for the new type (unused in 1.8.13 and later)
+ * \param[in] reserved Number of reserved IDs for the new type
+ * \param[in] free_func Function used to deallocate space for a single ID
+ *
+ * \return Returns the type identifier on success, negative on failure.
+ *
+ * \details H5Iregister_type1() allocates space for a new ID type and returns an
+ * identifier for it.
+ *
+ * The \p hash_size parameter indicates the minimum size of the hash
+ * table used to store IDs in the new type. This parameter is unused
+ * in 1.8.13 and later, when the implementation of ID storage changed.
+ *
+ * The \p reserved parameter indicates the number of IDs in this new
+ * type to be reserved. Reserved IDs are valid IDs which are not
+ * associated with any storage within the library.
+ *
+ * The \p free_func parameter is a function pointer to a function
+ * which returns an herr_t and accepts a \c void*. The purpose of this
+ * function is to deallocate memory for a single ID. It will be called
+ * by H5Iclear_type() and H5Idestroy_type() on each ID. This function
+ * is NOT called by H5Iremove_verify(). The \c void* will be the same
+ * pointer which was passed in to the H5Iregister() function. The \p
+ * free_func function should return 0 on success and -1 on failure.
+ *
+ * \since 1.8.0
+ * \deprecated 2.0.0 Deprecated in favor of the function H5Iregister_type2()
+ *
+ */
+H5_DLL H5I_type_t H5Iregister_type1(size_t hash_size, unsigned reserved, H5I_free_t free_func);
+
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
#ifdef __cplusplus
}
#endif
diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h
index 34e4d76181f..be6ea9fe3d2 100644
--- a/src/H5Ppublic.h
+++ b/src/H5Ppublic.h
@@ -3913,8 +3913,7 @@ H5_DLL herr_t H5Pget_mdc_image_config(hid_t plist_id, H5AC_cache_image_config_t
* access property list, and H5Fget_mdc_logging_status() will return
* the current state of the logging flags.
*
- * The log format is described in the
- * Metadata Cache Logging document.
+ * The log format is described in the \ref_mdc_logging document.
*
* \since 1.10.0
*/
diff --git a/src/H5VLnative_private.h b/src/H5VLnative_private.h
index 15c9ae94e59..8d49a8ca871 100644
--- a/src/H5VLnative_private.h
+++ b/src/H5VLnative_private.h
@@ -47,7 +47,7 @@ H5_DLLVAR H5VL_connector_t *H5VL_NATIVE_conn_g;
H5_DLL void *H5VL__native_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name,
hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t aapl_id,
hid_t dxpl_id, void **req);
-void *H5VL__native_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name,
+H5_DLL void *H5VL__native_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_name,
hid_t aapl_id, hid_t dxpl_id, void **req);
H5_DLL herr_t H5VL__native_attr_read(void *attr, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req);
H5_DLL herr_t H5VL__native_attr_write(void *attr, hid_t dtype_id, const void *buf, hid_t dxpl_id, void **req);
diff --git a/src/H5vers.txt b/src/H5vers.txt
index c2b0a45886b..ce17f889c7b 100644
--- a/src/H5vers.txt
+++ b/src/H5vers.txt
@@ -39,7 +39,7 @@
# API function names
# (although not required, it's easier to compare this file with the headers
-# generated if the list below is in alphanumeric sort order - QAK)
+# generated if the list below is in alphanumeric sort order)
FUNCTION: H5Acreate; ; v10, v18
FUNCTION: H5Aiterate; H5A_operator; v10, v18
FUNCTION: H5Dcreate; ; v10, v18
@@ -53,6 +53,7 @@ FUNCTION: H5Ewalk; H5E_walk, H5E_error; v10, v18
FUNCTION: H5Fget_info; H5F_info; v18, v110
FUNCTION: H5Gcreate; ; v10, v18
FUNCTION: H5Gopen; ; v10, v18
+FUNCTION: H5Iregister_type; ; v18, v200
FUNCTION: H5Lget_info; H5L_info; v18, v112
FUNCTION: H5Lget_info_by_idx; H5L_info; v18, v112
FUNCTION: H5Literate; H5L_iterate; v18, v112
@@ -88,7 +89,7 @@ FUNCTION: H5Topen; ; v10, v18
# API typedefs
# (although not required, it's easier to compare this file with the headers
-# generated if the list below is in alphanumeric sort order - QAK)
+# generated if the list below is in alphanumeric sort order)
TYPEDEF: H5E_auto; v10, v18
TYPEDEF: H5O_info; v18, v112
TYPEDEF: H5O_iterate; v18, v112
diff --git a/src/H5version.h b/src/H5version.h
index 089e6e9f2de..9fe80159695 100644
--- a/src/H5version.h
+++ b/src/H5version.h
@@ -43,6 +43,10 @@
#define H5_USE_114_API 1
#endif /* H5_USE_114_API_DEFAULT && !H5_USE_114_API */
+#if defined(H5_USE_200_API_DEFAULT) && !defined(H5_USE_200_API)
+ #define H5_USE_200_API 1
+#endif /* H5_USE_200_API_DEFAULT && !H5_USE_200_API */
+
/* Issue error if contradicting macros have been defined. */
/* (Can't use an older (deprecated) API version if deprecated symbols have been disabled) */
@@ -224,6 +228,10 @@
#define H5Gopen_vers 2
#endif /* !defined(H5Gopen_vers) */
+#if !defined(H5Iregister_type_vers)
+ #define H5Iregister_type_vers 1
+#endif /* !defined(H5Iregister_type_vers) */
+
#if !defined(H5Lget_info_vers)
#define H5Lget_info_vers 1
#endif /* !defined(H5Lget_info_vers) */
@@ -392,6 +400,10 @@
#define H5Gopen_vers 2
#endif /* !defined(H5Gopen_vers) */
+#if !defined(H5Iregister_type_vers)
+ #define H5Iregister_type_vers 1
+#endif /* !defined(H5Iregister_type_vers) */
+
#if !defined(H5Lget_info_vers)
#define H5Lget_info_vers 1
#endif /* !defined(H5Lget_info_vers) */
@@ -564,6 +576,10 @@
#define H5Gopen_vers 2
#endif /* !defined(H5Gopen_vers) */
+#if !defined(H5Iregister_type_vers)
+ #define H5Iregister_type_vers 1
+#endif /* !defined(H5Iregister_type_vers) */
+
#if !defined(H5Lget_info_vers)
#define H5Lget_info_vers 2
#endif /* !defined(H5Lget_info_vers) */
@@ -736,6 +752,10 @@
#define H5Gopen_vers 2
#endif /* !defined(H5Gopen_vers) */
+#if !defined(H5Iregister_type_vers)
+ #define H5Iregister_type_vers 1
+#endif /* !defined(H5Iregister_type_vers) */
+
#if !defined(H5Lget_info_vers)
#define H5Lget_info_vers 2
#endif /* !defined(H5Lget_info_vers) */
@@ -850,6 +870,182 @@
#endif /* H5_USE_114_API */
+#ifdef H5_USE_200_API
+
+/*************/
+/* Functions */
+/*************/
+
+#if !defined(H5Acreate_vers)
+ #define H5Acreate_vers 2
+#endif /* !defined(H5Acreate_vers) */
+
+#if !defined(H5Aiterate_vers)
+ #define H5Aiterate_vers 2
+#endif /* !defined(H5Aiterate_vers) */
+
+#if !defined(H5Dcreate_vers)
+ #define H5Dcreate_vers 2
+#endif /* !defined(H5Dcreate_vers) */
+
+#if !defined(H5Dopen_vers)
+ #define H5Dopen_vers 2
+#endif /* !defined(H5Dopen_vers) */
+
+#if !defined(H5Eclear_vers)
+ #define H5Eclear_vers 2
+#endif /* !defined(H5Eclear_vers) */
+
+#if !defined(H5Eget_auto_vers)
+ #define H5Eget_auto_vers 2
+#endif /* !defined(H5Eget_auto_vers) */
+
+#if !defined(H5Eprint_vers)
+ #define H5Eprint_vers 2
+#endif /* !defined(H5Eprint_vers) */
+
+#if !defined(H5Epush_vers)
+ #define H5Epush_vers 2
+#endif /* !defined(H5Epush_vers) */
+
+#if !defined(H5Eset_auto_vers)
+ #define H5Eset_auto_vers 2
+#endif /* !defined(H5Eset_auto_vers) */
+
+#if !defined(H5Ewalk_vers)
+ #define H5Ewalk_vers 2
+#endif /* !defined(H5Ewalk_vers) */
+
+#if !defined(H5Fget_info_vers)
+ #define H5Fget_info_vers 2
+#endif /* !defined(H5Fget_info_vers) */
+
+#if !defined(H5Gcreate_vers)
+ #define H5Gcreate_vers 2
+#endif /* !defined(H5Gcreate_vers) */
+
+#if !defined(H5Gopen_vers)
+ #define H5Gopen_vers 2
+#endif /* !defined(H5Gopen_vers) */
+
+#if !defined(H5Iregister_type_vers)
+ #define H5Iregister_type_vers 2
+#endif /* !defined(H5Iregister_type_vers) */
+
+#if !defined(H5Lget_info_vers)
+ #define H5Lget_info_vers 2
+#endif /* !defined(H5Lget_info_vers) */
+
+#if !defined(H5Lget_info_by_idx_vers)
+ #define H5Lget_info_by_idx_vers 2
+#endif /* !defined(H5Lget_info_by_idx_vers) */
+
+#if !defined(H5Literate_vers)
+ #define H5Literate_vers 2
+#endif /* !defined(H5Literate_vers) */
+
+#if !defined(H5Literate_by_name_vers)
+ #define H5Literate_by_name_vers 2
+#endif /* !defined(H5Literate_by_name_vers) */
+
+#if !defined(H5Lvisit_vers)
+ #define H5Lvisit_vers 2
+#endif /* !defined(H5Lvisit_vers) */
+
+#if !defined(H5Lvisit_by_name_vers)
+ #define H5Lvisit_by_name_vers 2
+#endif /* !defined(H5Lvisit_by_name_vers) */
+
+#if !defined(H5Oget_info_vers)
+ #define H5Oget_info_vers 3
+#endif /* !defined(H5Oget_info_vers) */
+
+#if !defined(H5Oget_info_by_idx_vers)
+ #define H5Oget_info_by_idx_vers 3
+#endif /* !defined(H5Oget_info_by_idx_vers) */
+
+#if !defined(H5Oget_info_by_name_vers)
+ #define H5Oget_info_by_name_vers 3
+#endif /* !defined(H5Oget_info_by_name_vers) */
+
+#if !defined(H5Ovisit_vers)
+ #define H5Ovisit_vers 3
+#endif /* !defined(H5Ovisit_vers) */
+
+#if !defined(H5Ovisit_by_name_vers)
+ #define H5Ovisit_by_name_vers 3
+#endif /* !defined(H5Ovisit_by_name_vers) */
+
+#if !defined(H5Pencode_vers)
+ #define H5Pencode_vers 2
+#endif /* !defined(H5Pencode_vers) */
+
+#if !defined(H5Pget_filter_vers)
+ #define H5Pget_filter_vers 2
+#endif /* !defined(H5Pget_filter_vers) */
+
+#if !defined(H5Pget_filter_by_id_vers)
+ #define H5Pget_filter_by_id_vers 2
+#endif /* !defined(H5Pget_filter_by_id_vers) */
+
+#if !defined(H5Pinsert_vers)
+ #define H5Pinsert_vers 2
+#endif /* !defined(H5Pinsert_vers) */
+
+#if !defined(H5Pregister_vers)
+ #define H5Pregister_vers 2
+#endif /* !defined(H5Pregister_vers) */
+
+#if !defined(H5Rdereference_vers)
+ #define H5Rdereference_vers 2
+#endif /* !defined(H5Rdereference_vers) */
+
+#if !defined(H5Rget_obj_type_vers)
+ #define H5Rget_obj_type_vers 2
+#endif /* !defined(H5Rget_obj_type_vers) */
+
+#if !defined(H5Sencode_vers)
+ #define H5Sencode_vers 2
+#endif /* !defined(H5Sencode_vers) */
+
+#if !defined(H5Tarray_create_vers)
+ #define H5Tarray_create_vers 2
+#endif /* !defined(H5Tarray_create_vers) */
+
+#if !defined(H5Tcommit_vers)
+ #define H5Tcommit_vers 2
+#endif /* !defined(H5Tcommit_vers) */
+
+#if !defined(H5Tget_array_dims_vers)
+ #define H5Tget_array_dims_vers 2
+#endif /* !defined(H5Tget_array_dims_vers) */
+
+#if !defined(H5Topen_vers)
+ #define H5Topen_vers 2
+#endif /* !defined(H5Topen_vers) */
+
+/************/
+/* Typedefs */
+/************/
+
+#if !defined(H5E_auto_t_vers)
+ #define H5E_auto_t_vers 2
+#endif /* !defined(H5E_auto_t_vers) */
+
+#if !defined(H5O_info_t_vers)
+ #define H5O_info_t_vers 2
+#endif /* !defined(H5O_info_t_vers) */
+
+#if !defined(H5O_iterate_t_vers)
+ #define H5O_iterate_t_vers 2
+#endif /* !defined(H5O_iterate_t_vers) */
+
+#if !defined(H5Z_class_t_vers)
+ #define H5Z_class_t_vers 2
+#endif /* !defined(H5Z_class_t_vers) */
+
+#endif /* H5_USE_200_API */
+
/* Choose the correct version of each API symbol, defaulting to the latest
* version of each. The "best" name for API parameters/data structures
@@ -1012,6 +1208,17 @@
#error "H5Gopen_vers set to invalid value"
#endif /* H5Gopen_vers */
+#if !defined(H5Iregister_type_vers) || H5Iregister_type_vers == 2
+ #ifndef H5Iregister_type_vers
+ #define H5Iregister_type_vers 2
+ #endif /* H5Iregister_type_vers */
+ #define H5Iregister_type H5Iregister_type2
+#elif H5Iregister_type_vers == 1
+ #define H5Iregister_type H5Iregister_type1
+#else /* H5Iregister_type_vers */
+ #error "H5Iregister_type_vers set to invalid value"
+#endif /* H5Iregister_type_vers */
+
#if !defined(H5Lget_info_vers) || H5Lget_info_vers == 2
#ifndef H5Lget_info_vers
#define H5Lget_info_vers 2
diff --git a/src/Makefile.am b/src/Makefile.am
index a2166af110f..ae27987aa30 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -67,7 +67,7 @@ libhdf5_la_SOURCES= H5.c H5build_settings.c H5checksum.c H5dbg.c H5system.c \
H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \
H5HG.c H5HGcache.c H5HGdbg.c H5HGquery.c \
H5HL.c H5HLcache.c H5HLdbg.c H5HLint.c H5HLprfx.c H5HLdblk.c \
- H5I.c H5Idbg.c H5Iint.c H5Itest.c \
+ H5I.c H5Idbg.c H5Ideprec.c H5Iint.c H5Itest.c \
H5L.c H5Ldeprec.c H5Lexternal.c H5Lint.c \
H5M.c \
H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \
diff --git a/test/tid.c b/test/tid.c
index c4ec0d8ea40..f287f4e00d2 100644
--- a/test/tid.c
+++ b/test/tid.c
@@ -79,9 +79,9 @@ basic_id_test(void)
goto out;
/* Register a type */
- myType = H5Iregister_type((size_t)64, 0, free_wrapper);
+ myType = H5Iregister_type2(0, free_wrapper);
- CHECK(myType, H5I_BADID, "H5Iregister_type");
+ CHECK(myType, H5I_BADID, "H5Iregister_type2");
if (myType == H5I_BADID)
goto out;
@@ -173,9 +173,9 @@ basic_id_test(void)
H5E_END_TRY
/* Register another type and another object in that type */
- myType = H5Iregister_type((size_t)64, 0, free_wrapper);
+ myType = H5Iregister_type2(0, free_wrapper);
- CHECK(myType, H5I_BADID, "H5Iregister_type");
+ CHECK(myType, H5I_BADID, "H5Iregister_type2");
if (myType == H5I_BADID)
goto out;
@@ -246,6 +246,225 @@ basic_id_test(void)
return -1;
}
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+/* Test that H5Iregister_type1() works correctly (just a copy of the basic test) */
+static int
+H5Iregister_type1_test(void)
+{
+ H5I_type_t myType = H5I_BADID;
+ hid_t arrayID = H5I_INVALID_HID;
+ void *testObj = NULL;
+ void *testPtr = NULL;
+ char nameString[10];
+ hid_t testID;
+ ssize_t testSize = -1;
+ herr_t err;
+ int num_ref;
+ hsize_t num_members;
+
+ /* Try to register an ID with fictitious types */
+ H5E_BEGIN_TRY
+ arrayID = H5Iregister((H5I_type_t)420, testObj);
+ H5E_END_TRY
+
+ VERIFY(arrayID, H5I_INVALID_HID, "H5Iregister");
+ if (arrayID != H5I_INVALID_HID)
+ goto out;
+
+ H5E_BEGIN_TRY
+ arrayID = H5Iregister((H5I_type_t)-1, testObj);
+ H5E_END_TRY
+
+ VERIFY(arrayID, H5I_INVALID_HID, "H5Iregister");
+ if (arrayID != H5I_INVALID_HID)
+ goto out;
+
+ /* Try to access IDs with fictitious types */
+ H5E_BEGIN_TRY
+ testPtr = H5Iobject_verify((hid_t)100, (H5I_type_t)0);
+ H5E_END_TRY
+
+ CHECK_PTR_NULL(testPtr, "H5Iobject_verify");
+ if (testPtr != NULL)
+ goto out;
+
+ H5E_BEGIN_TRY
+ testPtr = H5Iobject_verify((hid_t)700, (H5I_type_t)700);
+ H5E_END_TRY
+
+ CHECK_PTR_NULL(testPtr, "H5Iobject_verify");
+ if (testPtr != NULL)
+ goto out;
+
+ /* Register a type */
+ myType = H5Iregister_type1(64, 0, free_wrapper);
+
+ CHECK(myType, H5I_BADID, "H5Iregister_type1");
+ if (myType == H5I_BADID)
+ goto out;
+
+ /* Register an ID and retrieve the object it points to.
+ * Once the ID has been registered, testObj will be freed when
+ * its ID type is destroyed.
+ */
+ testObj = malloc(7 * sizeof(int));
+ arrayID = H5Iregister(myType, testObj);
+
+ CHECK(arrayID, H5I_INVALID_HID, "H5Iregister");
+ if (arrayID == H5I_INVALID_HID) {
+ free(testObj);
+ goto out;
+ }
+
+ testPtr = (int *)H5Iobject_verify(arrayID, myType);
+
+ CHECK_PTR_EQ(testPtr, testObj, "H5Iobject_verify");
+ if (testPtr != testObj)
+ goto out;
+
+ /* Ensure that H5Iget_file_id and H5Iget_name() fail, since this
+ * is an hid_t for the wrong kind of object
+ */
+ H5E_BEGIN_TRY
+ testID = H5Iget_file_id(arrayID);
+ H5E_END_TRY
+
+ VERIFY(testID, H5I_INVALID_HID, "H5Iget_file_id");
+ if (testID != H5I_INVALID_HID)
+ goto out;
+
+ H5E_BEGIN_TRY
+ testSize = H5Iget_name(arrayID, nameString, (size_t)9);
+ H5E_END_TRY
+
+ VERIFY(testSize, -1, "H5Iget_name");
+ if (testSize != -1)
+ goto out;
+
+ /* Make sure H5Iremove_verify catches objects of the wrong type */
+ H5E_BEGIN_TRY
+ testPtr = (int *)H5Iremove_verify(arrayID, (H5I_type_t)0);
+ H5E_END_TRY
+
+ CHECK_PTR_NULL(testPtr, "H5Iremove_verify");
+ if (testPtr != NULL)
+ goto out;
+
+ H5E_BEGIN_TRY
+ testPtr = (int *)H5Iremove_verify(arrayID, (H5I_type_t)((int)myType - 1));
+ H5E_END_TRY
+
+ CHECK_PTR_NULL(testPtr, "H5Iremove_verify");
+ if (testPtr != NULL)
+ goto out;
+
+ /* Remove an ID and make sure we can't access it */
+ testPtr = (int *)H5Iremove_verify(arrayID, myType);
+
+ CHECK_PTR(testPtr, "H5Iremove_verify");
+ if (testPtr == NULL)
+ goto out;
+
+ H5E_BEGIN_TRY
+ testPtr = (int *)H5Iobject_verify(arrayID, myType);
+ H5E_END_TRY
+
+ CHECK_PTR_NULL(testPtr, "H5Iobject_verify");
+ if (testPtr != NULL)
+ goto out;
+
+ /* Delete the type and make sure we can't access objects within it */
+ arrayID = H5Iregister(myType, testObj);
+
+ err = H5Idestroy_type(myType);
+ VERIFY(err, 0, "H5Idestroy_type");
+ if (err != 0)
+ goto out;
+ VERIFY(H5Itype_exists(myType), 0, "H5Itype_exists");
+ if (H5Itype_exists(myType) != 0)
+ goto out;
+
+ H5E_BEGIN_TRY
+ VERIFY(H5Inmembers(myType, NULL), -1, "H5Inmembers");
+ if (H5Inmembers(myType, NULL) != -1)
+ goto out;
+ H5E_END_TRY
+
+ /* Register another type and another object in that type */
+ myType = H5Iregister_type1(64, 0, free_wrapper);
+
+ CHECK(myType, H5I_BADID, "H5Iregister_type1");
+ if (myType == H5I_BADID)
+ goto out;
+
+ /* The memory that testObj pointed to should already have been
+ * freed when the previous type was destroyed. Allocate new
+ * memory for it.
+ */
+ testObj = malloc(7 * sizeof(int));
+ arrayID = H5Iregister(myType, testObj);
+
+ CHECK(arrayID, H5I_INVALID_HID, "H5Iregister");
+ if (arrayID == H5I_INVALID_HID) {
+ free(testObj);
+ goto out;
+ }
+
+ err = H5Inmembers(myType, &num_members);
+ CHECK(err, -1, "H5Inmembers");
+ if (err < 0)
+ goto out;
+ VERIFY(num_members, 1, "H5Inmembers");
+ if (num_members != 1)
+ goto out;
+
+ /* Increment references to type and ensure that dec_type_ref
+ * doesn't destroy the type
+ */
+ num_ref = H5Iinc_type_ref(myType);
+ VERIFY(num_ref, 2, "H5Iinc_type_ref");
+ if (num_ref != 2)
+ goto out;
+ num_ref = H5Idec_type_ref(myType);
+ VERIFY(num_ref, 1, "H5Idec_type_ref");
+ if (num_ref != 1)
+ goto out;
+ err = H5Inmembers(myType, &num_members);
+ CHECK(err, -1, "H5Inmembers");
+ if (err < 0)
+ goto out;
+ VERIFY(num_members, 1, "H5Inmembers");
+ if (num_members != 1)
+ goto out;
+
+ /* This call to dec_type_ref should destroy the type */
+ num_ref = H5Idec_type_ref(myType);
+ VERIFY(num_ref, 0, "H5Idec_type_ref");
+ if (num_ref != 0)
+ goto out;
+ VERIFY(H5Itype_exists(myType), 0, "H5Itype_exists");
+ if (H5Itype_exists(myType) != 0)
+ goto out;
+
+ H5E_BEGIN_TRY
+ err = H5Inmembers(myType, &num_members);
+ if (err >= 0)
+ goto out;
+ H5E_END_TRY
+
+ return 0;
+
+out:
+ /* Clean up type if it has been allocated and free memory used
+ * by testObj
+ */
+ if (myType >= 0)
+ H5Idestroy_type(myType);
+
+ return -1;
+}
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
/* A dummy search function for the next test */
static int
test_search_func(void H5_ATTR_UNUSED *ptr1, hid_t H5_ATTR_UNUSED id, void H5_ATTR_UNUSED *ptr2)
@@ -508,47 +727,47 @@ test_id_type_list(void)
H5I_type_t testType;
int i; /* Just a counter variable */
- startType = H5Iregister_type((size_t)8, 0, free_wrapper);
- CHECK(startType, H5I_BADID, "H5Iregister_type");
+ startType = H5Iregister_type2(0, free_wrapper);
+ CHECK(startType, H5I_BADID, "H5Iregister_type2");
if (startType == H5I_BADID)
goto out;
/* Sanity check */
if ((int)startType >= H5I_MAX_NUM_TYPES || startType < H5I_NTYPES) {
/* Error condition, throw an error */
- ERROR("H5Iregister_type");
+ ERROR("H5Iregister_type2");
goto out;
}
/* Create types up to H5I_MAX_NUM_TYPES */
for (i = startType + 1; i < H5I_MAX_NUM_TYPES; i++) {
- currentType = H5Iregister_type((size_t)8, 0, free_wrapper);
- CHECK(currentType, H5I_BADID, "H5Iregister_type");
+ currentType = H5Iregister_type2(0, free_wrapper);
+ CHECK(currentType, H5I_BADID, "H5Iregister_type2");
if (currentType == H5I_BADID)
goto out;
}
/* Wrap around to low type ID numbers */
for (i = H5I_NTYPES; i < startType; i++) {
- currentType = H5Iregister_type((size_t)8, 0, free_wrapper);
- CHECK(currentType, H5I_BADID, "H5Iregister_type");
+ currentType = H5Iregister_type2(0, free_wrapper);
+ CHECK(currentType, H5I_BADID, "H5Iregister_type2");
if (currentType == H5I_BADID)
goto out;
}
/* There should be no room at the inn for a new ID type*/
H5E_BEGIN_TRY
- testType = H5Iregister_type((size_t)8, 0, free_wrapper);
+ testType = H5Iregister_type2(0, free_wrapper);
H5E_END_TRY
- VERIFY(testType, H5I_BADID, "H5Iregister_type");
+ VERIFY(testType, H5I_BADID, "H5Iregister_type2");
if (testType != H5I_BADID)
goto out;
/* Now delete a type and try to insert again */
H5Idestroy_type(H5I_NTYPES);
- testType = H5Iregister_type((size_t)8, 0, free_wrapper);
+ testType = H5Iregister_type2(0, free_wrapper);
- VERIFY(testType, H5I_NTYPES, "H5Iregister_type");
+ VERIFY(testType, H5I_NTYPES, "H5Iregister_type2");
if (testType != H5I_NTYPES)
goto out;
@@ -700,8 +919,8 @@ test_remove_clear_type(void)
herr_t ret; /* return value */
/* Register a user-defined type with our custom ID-deleting callback */
- obj_type = H5Iregister_type((size_t)8, 0, rct_free_cb);
- CHECK(obj_type, H5I_BADID, "H5Iregister_type");
+ obj_type = H5Iregister_type2(0, rct_free_cb);
+ CHECK(obj_type, H5I_BADID, "H5Iregister_type2");
if (obj_type == H5I_BADID)
goto error;
@@ -994,8 +1213,8 @@ test_future_ids(void)
herr_t ret; /* Return value */
/* Register a user-defined type with our custom ID-deleting callback */
- obj_type = H5Iregister_type((size_t)15, 0, free_actual_object);
- CHECK(obj_type, H5I_BADID, "H5Iregister_type");
+ obj_type = H5Iregister_type2(0, free_actual_object);
+ CHECK(obj_type, H5I_BADID, "H5Iregister_type2");
if (H5I_BADID == obj_type)
goto error;
@@ -1054,8 +1273,8 @@ test_future_ids(void)
goto error;
/* Re-register a user-defined type with our custom ID-deleting callback */
- obj_type = H5Iregister_type((size_t)15, 0, free_actual_object);
- CHECK(obj_type, H5I_BADID, "H5Iregister_type");
+ obj_type = H5Iregister_type2(0, free_actual_object);
+ CHECK(obj_type, H5I_BADID, "H5Iregister_type2");
if (H5I_BADID == obj_type)
goto error;
@@ -1094,8 +1313,8 @@ test_future_ids(void)
goto error;
/* Re-register a user-defined type with our custom ID-deleting callback */
- obj_type = H5Iregister_type((size_t)15, 0, free_actual_object);
- CHECK(obj_type, H5I_BADID, "H5Iregister_type");
+ obj_type = H5Iregister_type2(0, free_actual_object);
+ CHECK(obj_type, H5I_BADID, "H5Iregister_type2");
if (H5I_BADID == obj_type)
goto error;
@@ -1502,6 +1721,10 @@ test_ids(const void H5_ATTR_UNUSED *params)
if (basic_id_test() < 0)
TestErrPrintf("Basic ID test failed\n");
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+ if (H5Iregister_type1_test() < 0)
+ TestErrPrintf("H5Iregister_type1() test failed\n");
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
if (id_predefined_test() < 0)
TestErrPrintf("Predefined ID type test failed\n");
if (test_is_valid() < 0)