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=) ) { + while ( defined ($line = ) ) { # Skip blank lines and those lines whose first character is a '#' - if(!($line =~ /(^\s*#.*$)|(^\s*$)/)) { + if (!($line =~ /(^\s*#.*$)|(^\s*$)/)) { # Construct data structures for later printing parse_line($line); } @@ -509,20 +508,5 @@ for $file (@ARGV) { # Create header files print "Generating 'H5version.h'\n"; create_public($prefix); - -#for $name (sort keys %functions) { -# print "functions{$name} = $functions{$name}\n"; -#} - -#for $i (0 .. $#func_vers) { -# my $vers_name; # Name of indexed version -# $vers_name = "v1." . ($i * 2); -# print "$vers_name functions: "; -# for $name (sort keys %{$func_vers[$i]}) { -# print "$name$func_vers[$i]{$name} "; -# } -# print "\n"; -#} - } diff --git a/c++/src/C2Cppfunction_map.htm b/c++/src/C2Cppfunction_map.htm index 4ea67544efe..791892ee006 100644 --- a/c++/src/C2Cppfunction_map.htm +++ b/c++/src/C2Cppfunction_map.htm @@ -9992,7 +9992,7 @@ none;mso-border-top-alt:solid windowtext .5pt;mso-border-alt:solid windowtext .5pt; padding:0in 5.4pt 0in 5.4pt'>

H5Iregister_type

+ normal'>H5Iregister_type2

+ * + * + * \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
FieldDatatypeDataspaceStorage PropertiesNotes
<data>AnyAnyAnyThese are the values of the Dimension Scale.
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Table 2. Standard Attributes for a stored Dimension Scale dataset.
Attribute NameDatatype and DimensionsValueRequired / OptionalNotes
CLASS#H5T_STRING length = 16“DIMENSION_SCALE”RequiredThis 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_LISTArray of Dataset Reference Type (Compound Datatype), variable length.[ {dataset1, ind1 }, …] [,…] ….]Optional, required when scale is attachedSee Table 3. This is set by #H5DSattach_scale.
SUB_CLASS#H5T_STRING length = <profile defined>“HDF4_DIMENSION”,
“NC4_DIMENSION”,
Optional, defined by other profilesThis is used to indicate a specific profile was used.
<Other attributes>OptionalFor 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.
FieldDatatypeValueNotes
DATASETObject Reference.Pointer to a Dataset that refers to the scaleSet by #H5DSattach_scale.
Removed by #H5DSdetach_scale.
INDEX#H5T_NATIVE_INTIndex of the dimension the dataset pointed to by DATASETSet 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 NameDatatype and DimensionsValueRequired / OptionalNotes
DIMENSION_LISTThe HDF5 datatype is ARRAY of Variable Length #H5T_STD_REF_OBJ with rank of the dataspace.[[{object__ref1, object__ref2, … object__refn}, …] […] ..]Optional, required if scales are attachedSet by #H5DSattach_scale.
Entries removed by #H5DSdetach_scale.
DIMENSION_LABELLISTThe HDF5 datatype is ARRAY of #H5T_STRING with rank of the dataspace.[ <Label1>, <Label2>, …, <Label3>] Optional, required for scales with a labelSet 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 scaleScale with no nameScale with name
No labelDimension has no label or scale (default)Dimension has an anonymous scaleDimension has scale, the scale is called “name”
LabelDimension has labelDimension 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 DimensionLabel
0“LX”
1“LZ”
2“LQ”
3“”
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Table 7. The reference list for DS1.
ReferenceDataset Reference Record
0{Object reference to Dataset D, 0}
1{Object reference to other Dataset, ?}
+ * + * + * + * + * + * + * + * + * + * + *
Table 8. Reference list for DS2
ReferenceDataset Reference Record
0{Object reference to Dataset D, 0}
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Table 9. Reference list for DS3
ReferenceDataset Reference Record
0{Object reference to Dataset D, 1}
1{Object reference to Dataset D, 3}
+ * + * + * + * + * + * + * + * + * + * + *
Table 10. Reference List for DS5
ReferenceDataset 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)