[MOAB-dev] r2862 - MOAB/trunk
kraftche at cae.wisc.edu
kraftche at cae.wisc.edu
Thu Apr 30 16:02:48 CDT 2009
Author: kraftche
Date: 2009-04-30 16:02:48 -0500 (Thu, 30 Apr 2009)
New Revision: 2862
Modified:
MOAB/trunk/MBRange.hpp
MOAB/trunk/README.IO
MOAB/trunk/ReadHDF5.cpp
MOAB/trunk/ReadHDF5.hpp
Log:
add partial read capability for .h5m files
Modified: MOAB/trunk/MBRange.hpp
===================================================================
--- MOAB/trunk/MBRange.hpp 2009-04-30 21:01:58 UTC (rev 2861)
+++ MOAB/trunk/MBRange.hpp 2009-04-30 21:02:48 UTC (rev 2862)
@@ -277,6 +277,10 @@
const_iterator last,
MBEntityHandle val);
+ const_iterator lower_bound( MBEntityHandle val ) const
+ { return lower_bound( begin(), end(), val ); }
+ const_iterator upperbound( MBEntityHandle val ) const
+ { return upper_bound( begin(), end(), val ); }
const_iterator lower_bound( MBEntityType type ) const;
const_iterator upper_bound( MBEntityType type ) const;
std::pair<const_iterator, const_iterator> equal_range( MBEntityType type ) const;
Modified: MOAB/trunk/README.IO
===================================================================
--- MOAB/trunk/README.IO 2009-04-30 21:01:58 UTC (rev 2861)
+++ MOAB/trunk/README.IO 2009-04-30 21:02:48 UTC (rev 2862)
@@ -129,3 +129,30 @@
Force byte ordering of binary data. Default is BIG_ENDIAN for writing
and autodetection for reading (BIG_ENDIAN if autodetect fails).
+
+
+MOAB Native (HDF5-based MHDF) format
+------------------------------------
+
+ ELEMENTS={EXPLICIT|NODES}
+
+If reading only part of a file, specify which additional elements to read
+in addition to those contained in the specified set. The options are:
+ EXPLICIT - read only explicitly designated elements
+ NODES - read any element for which all the nodes are being read.
+Default is EXPLICIT unless only nodesa are explicitly specified, in which
+case NODES will be used.
+
+ CHILDREN={NONE|SETS|CONTENTS}
+
+If reading only part of a file, specify which whether or not child sets
+of input sets are to be read. The options are:
+ NONE - Do not read sets because they are children of designated sets.
+ SETS - Read all child sets of designated input sets.
+ CONTENTS - (Default). Read all child sets and any entities contained
+ in those sets.
+
+
+ BUFFER_SIZE=<BYTES>
+
+Reduce buffer size for debugging purposes.
Modified: MOAB/trunk/ReadHDF5.cpp
===================================================================
--- MOAB/trunk/ReadHDF5.cpp 2009-04-30 21:01:58 UTC (rev 2861)
+++ MOAB/trunk/ReadHDF5.cpp 2009-04-30 21:02:48 UTC (rev 2862)
@@ -44,6 +44,7 @@
#include <stdlib.h>
#include <string.h>
#include <limits>
+#include <functional>
#undef DEBUG
@@ -56,6 +57,32 @@
#define READ_HDF5_BUFFER_SIZE (40*1024*1024)
+// This function doesn't do anything useful. It's just a nice
+// place to set a break point to determine why the reader fails.
+static inline MBErrorCode error( MBErrorCode rval )
+ { return rval; }
+
+static void copy_sorted_file_ids( const MBEntityHandle* sorted_ids,
+ long num_ids,
+ MBRange& results )
+{
+ MBRange::iterator hint = results.begin();
+ long i = 0;
+ while (i < num_ids) {
+ MBEntityHandle start = sorted_ids[i];
+ for (++i; i < num_ids && sorted_ids[i] == 1+sorted_ids[i-1]; ++i);
+ hint = results.insert( hint, start, sorted_ids[i-1] );
+ }
+}
+
+static void intersect( const mhdf_EntDesc& group, const MBRange& range, MBRange& result )
+{
+ MBRange::const_iterator s, e;
+ s = MBRange::lower_bound( range.begin(), range.end(), group.start_id );
+ e = MBRange::lower_bound( s, range.end(), group.start_id + group.count );
+ result.merge( s, e );
+}
+
MBReaderIface* ReadHDF5::factory( MBInterface* iface )
{ return new ReadHDF5( iface ); }
@@ -64,6 +91,7 @@
dataBuffer( 0 ),
iFace( iface ),
filePtr( 0 ),
+ fileInfo( 0 ),
readUtil( 0 ),
handleType( 0 ),
ioProp( H5P_DEFAULT )
@@ -82,12 +110,12 @@
handleType = H5Tcopy( H5T_NATIVE_ULONG );
if (handleType < 0)
- return MB_FAILURE;
+ return error(MB_FAILURE);
if (H5Tset_size( handleType, sizeof(MBEntityHandle)) < 0)
{
H5Tclose( handleType );
- return MB_FAILURE;
+ return error(MB_FAILURE);
}
void* ptr = 0;
@@ -95,16 +123,12 @@
if (MB_SUCCESS != rval)
{
H5Tclose( handleType );
- return rval;
+ return error(rval);
}
readUtil = reinterpret_cast<MBReadUtilIface*>(ptr);
- setSet.first_id = 0;
- setSet.type2 = mhdf_set_type_handle();
- setSet.type = MBENTITYSET;
- nodeSet.first_id = 0;
- nodeSet.type2 = mhdf_node_type_handle();
- nodeSet.type = MBVERTEX;
+ idMap.clear();
+ fileInfo = 0;
return MB_SUCCESS;
}
@@ -123,24 +147,20 @@
MBEntityHandle& file_set,
const FileOptions& opts,
const char* name,
- const int*, const int )
+ const int* id_list,
+ const int num_ids )
{
MBErrorCode rval;
mhdf_Status status;
ioProp = H5P_DEFAULT;
- if (name) {
- readUtil->report_error( "Reading subset of files not supported for HDF5." );
- return MB_UNSUPPORTED_OPERATION;
- }
-
if (MB_SUCCESS != init())
- return MB_FAILURE;
+ return error(MB_FAILURE);
bool use_mpio = (MB_SUCCESS == opts.get_null_option("USE_MPIO"));
if (use_mpio) {
#ifndef HDF5_PARALLEL
- return MB_NOT_IMPLEMENTED;
+ return error(MB_NOT_IMPLEMENTED);
#else
int parallel_mode;
rval = opts.match_option( "PARALLEL",
@@ -148,7 +168,7 @@
parallel_mode );
if (MB_FAILURE == rval) {
readUtil->report_error("Unexpected value for 'PARALLEL' option\n");
- return MB_FAILURE;
+ return error(MB_FAILURE);
}
else if (MB_SUCCESS != rval ||
parallel_mode != ReadParallel::POPT_READ_DELETE) {
@@ -157,14 +177,26 @@
#endif
}
+ // This option is intended for testing purposes only, and thus
+ // is not documented anywhere. Decreasing the buffer size can
+ // expose bugs that would otherwise only be seen when reading
+ // very large files.
+ rval = opts.get_int_option( "BUFFER_SIZE", bufferSize );
+ if (MB_SUCCESS != rval) {
+ bufferSize = READ_HDF5_BUFFER_SIZE;
+ }
+ else if (bufferSize < (int)std::max( sizeof(MBEntityHandle), sizeof(void*) )) {
+ return error(MB_INVALID_SIZE);
+ }
+
dataBuffer = (char*)malloc( bufferSize );
if (!dataBuffer)
- return MB_MEMORY_ALLOCATION_FAILED;
+ return error(MB_MEMORY_ALLOCATION_FAILED);
rval = iFace->create_meshset( MESHSET_SET, file_set );
if (MB_SUCCESS != rval) {
free(dataBuffer);
- return rval;
+ return error(rval);
}
// Open the file
@@ -189,322 +221,836 @@
if (ioProp != H5P_DEFAULT)
H5Pclose( ioProp );
iFace->delete_entities( &file_set, 1 );
- return MB_FAILURE;
+ return error(MB_FAILURE);
}
-
-
- rval = load_file_impl( file_set, use_mpio );
+
+ // get file info
+ fileInfo = mhdf_getFileSummary( filePtr, handleType, &status );
+ if (is_error(status)) {
+ free( dataBuffer );
+ if (ioProp != H5P_DEFAULT)
+ H5Pclose( ioProp );
+ mhdf_closeFile( filePtr, &status );
+ iFace->delete_entities( &file_set, 1 );
+ return error(MB_FAILURE);
+ }
+
+ if (name)
+ rval = load_file_partial( file_set, name, id_list, num_ids, opts );
+ else
+ rval = load_file_impl( file_set, opts );
mhdf_closeFile( filePtr, &status );
filePtr = 0;
if (ioProp != H5P_DEFAULT)
H5Pclose( ioProp );
- if (mhdf_isError( &status )) {
- if (MB_SUCCESS == rval)
- rval = MB_FAILURE;
- readUtil->report_error( mhdf_message( &status ));
+ if (MB_SUCCESS == rval && is_error(status))
+ rval = MB_FAILURE;
+
+ if (file_set && MB_SUCCESS == rval) {
+ DEBUGOUT("Creating entity set for file contents\n")
+ MBRange range;
+ MBRange::iterator hint = range.begin();
+ for (IDMap::iterator j = idMap.begin(); j != idMap.end(); ++j)
+ hint = range.insert( hint, j->value, j->value + j->count - 1);
+ rval = iFace->add_entities( file_set, range );
}
// delete everything that was read in if read failed part-way through
if (MB_SUCCESS != rval) {
- iFace->delete_entities( &file_set, 1 );
- file_set = 0;
- iFace->delete_entities( setSet.range );
- for (std::list<ElemSet>::reverse_iterator rel_itor = elemList.rbegin();
- rel_itor != elemList.rend(); ++rel_itor)
- iFace->delete_entities( rel_itor->range );
- iFace->delete_entities( nodeSet.range );
+ MBRange range;
+ range.insert( file_set );
+ for (IDMap::iterator i = idMap.begin(); i != idMap.end(); ++i)
+ range.insert( i->value, i->value + i->count - 1 );
+ iFace->delete_entities( range );
}
- elemList.clear();
- nodeSet.range.clear();
- setSet.range.clear();
free( dataBuffer );
+ free( fileInfo );
return rval;
}
-MBErrorCode ReadHDF5::load_file_impl(
- MBEntityHandle file_set,
- bool use_mpio )
+MBErrorCode ReadHDF5::load_file_impl( MBEntityHandle file_set, const FileOptions& opts )
{
MBErrorCode rval;
mhdf_Status status;
std::string tagname;
- int num_tags = 0;
- char** tag_names = NULL;
- char** groups = NULL;
- std::list<ElemSet>::iterator el_itor;
- unsigned int i, num_groups;
- bool have_nodes = true;
+ int i;
DEBUGOUT("Reading Nodes.\n");
- rval = read_nodes();
- if (MB_FILE_WRITE_ERROR == rval) {
- DEBUGOUT("No nodes in file.!\n");
- have_nodes = false;
+ MBRange ids;
+ if (fileInfo->nodes.count) {
+ ids.insert( fileInfo->nodes.start_id,
+ fileInfo->nodes.start_id + fileInfo->nodes.count - 1);
+ rval = read_nodes( ids );
+ if (MB_SUCCESS != rval)
+ return error(rval);
}
- else if (MB_SUCCESS != rval)
- return rval;
DEBUGOUT("Reading element connectivity.\n");
- groups = mhdf_getElemHandles( filePtr, &num_groups, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ));
- return MB_FAILURE;
+ std::vector<int> polyhedra; // need to do these last so that faces are loaded
+ for (i = 0; i < fileInfo->num_elem_desc; ++i) {
+ if (MBCN::EntityTypeFromName(fileInfo->elems[i].type) == MBPOLYHEDRON) {
+ polyhedra.push_back(i);
+ continue;
+ }
+
+ rval = read_elems( i );
+ if (MB_SUCCESS != rval)
+ return error(rval);
}
-
- for (i = 0; i < num_groups; ++i)
- {
- int poly = mhdf_isPolyElement( filePtr, groups[i], &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ));
- free(groups);
- return MB_FAILURE;
+ for (std::vector<int>::iterator it = polyhedra.begin();
+ it != polyhedra.end(); ++it) {
+ rval = read_elems( *it );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+ }
+
+DEBUGOUT("Reading sets.\n");
+
+ ids.clear();
+ if (fileInfo->sets.count) {
+ ids.insert( fileInfo->sets.start_id,
+ fileInfo->sets.start_id + fileInfo->sets.count - 1);
+ rval = read_sets( ids );
+ if (rval != MB_SUCCESS) {
+ return error(rval);
}
+ }
+
+DEBUGOUT("Reading adjacencies.\n");
- if (poly)
- rval = read_poly( groups[i] );
- else
- rval = read_elems( groups[i] );
+ for (i = 0; i < fileInfo->num_elem_desc; ++i) {
+ if (!fileInfo->elems[i].have_adj)
+ continue;
+
+ long table_len;
+ hid_t table = mhdf_openAdjacency( filePtr,
+ fileInfo->elems[i].handle,
+ &table_len,
+ &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
- if (MB_SUCCESS != rval) {
- free( groups );
- return rval;
- }
+ rval = read_adjacencies( table, table_len );
+ mhdf_closeData( filePtr, table, &status );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+ if (is_error(status))
+ return error(MB_FAILURE);
}
+
+DEBUGOUT("Reading tags.\n");
-DEBUGOUT("Reading sets.\n");
+ for (i = 0; i < fileInfo->num_tag_desc; ++i) {
+ rval = read_tag( i );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+ }
- rval = read_sets();
- if (rval != MB_SUCCESS) {
- free( groups );
- return rval;
+DEBUGOUT("Finishing read.\n");
+ rval = read_qa( file_set );
+ return rval;
+}
+
+MBErrorCode ReadHDF5::load_file_partial( MBEntityHandle file_set,
+ const char* name,
+ const int* id_list,
+ int num_ids,
+ const FileOptions& opts )
+{
+ mhdf_Status status;
+
+DEBUGOUT( "RETREIVING TAGGED ENTITIES" );
+
+ int tag_index;
+ for (tag_index = 0; tag_index < fileInfo->num_tag_desc; ++tag_index)
+ if (!strcmp( name, fileInfo->tags[tag_index].name))
+ break;
+ if (tag_index == fileInfo->num_tag_desc) {
+ readUtil->report_error( "File does not contain subset tag '%s'", name );
+ return error(MB_TAG_NOT_FOUND);
}
+ if (fileInfo->tags[tag_index].type != mhdf_INTEGER ||
+ fileInfo->tags[tag_index].size != 1) {
+ readUtil->report_error( "Tag '%s' does not containa single integer value", name );
+ return error(MB_TYPE_OUT_OF_RANGE);
+ }
-DEBUGOUT("Reading adjacencies.\n");
+
+ MBErrorCode rval;
+ MBRange file_ids;
+ std::vector<int> ids( id_list, id_list+num_ids );
+ std::sort( ids.begin(), ids.end() );
+ rval = search_tag_values( tag_index, ids, file_ids );
+ if (MB_SUCCESS != rval) {
+ return error(rval);
+ }
- rval = read_adjacencies( nodeSet );
- if (rval != MB_SUCCESS) {
- free( groups );
- return rval;
+DEBUGOUT( "GATHERING ADDITIONAL ENTITIES" );
+
+ int set_mode;
+ const char* const set_opts[] = { "NONE", "SETS", "CONTENTS" };
+ rval = opts.match_option( "CHILDREN", set_opts, set_mode );
+ if (MB_ENTITY_NOT_FOUND == rval)
+ set_mode = 2;
+ else if (MB_SUCCESS != rval) {
+ readUtil->report_error( "Invalid value for 'CHILDREN' option" );
+ return error(rval);
}
- for (el_itor = elemList.begin(); el_itor != elemList.end(); ++el_itor) {
- rval = read_adjacencies( *el_itor );
- if (MB_SUCCESS != rval) {
- free( groups );
- return rval;
- }
+
+ MBRange sets;
+ intersect( fileInfo->sets, file_ids, sets );
+ if (set_mode == 2) {
+ rval = read_child_sets( sets );
+ if (MB_SUCCESS != rval)
+ return error(rval);
}
+
+ // get elements and vertices contained in sets
+ rval = get_set_contents( sets, file_ids );
+ if (MB_SUCCESS != rval)
+ return error(rval);
-DEBUGOUT("Reading tags.\n");
+
+DEBUGOUT( "READING NODES" );
- tag_names = mhdf_getTagNames( filePtr, &num_tags, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ));
- free( groups );
- return MB_FAILURE;
+ // if input contained any polyhedra, need to get faces
+ for (int i = 0; i < fileInfo->num_elem_desc; ++i) {
+ MBEntityType type = MBCN::EntityTypeFromName( fileInfo->elems[i].type );
+ if (type != MBPOLYHEDRON)
+ continue;
+
+ MBRange polyhedra;
+ intersect( fileInfo->elems[i].desc, file_ids, polyhedra );
+ rval = read_elems( i, polyhedra, file_ids );
+ if (MB_SUCCESS != rval)
+ return error(rval);
}
- for (int t = 0; t < num_tags; ++t)
- {
- rval = read_tag( tag_names[t] );
- free( tag_names[t] );
- if (MB_SUCCESS != rval) {
- for (; t < num_tags; ++t)
- free( tag_names[t] );
- free( tag_names );
- free( groups );
- return MB_FAILURE;
+ // get node file ids for all elements
+ MBRange nodes;
+ intersect( fileInfo->nodes, file_ids, nodes );
+ for (int i = 0; i < fileInfo->num_elem_desc; ++i) {
+ MBEntityType type = MBCN::EntityTypeFromName( fileInfo->elems[i].type );
+ if (type <= MBVERTEX || type >= MBENTITYSET) {
+ assert( false ); // for debug code die for unknown element tyoes
+ continue; // for release code, skip unknown element types
}
+ if (MBPOLYHEDRON == type)
+ continue;
+
+ MBRange subset;
+ intersect( fileInfo->elems[i].desc, file_ids, subset );
+ rval = read_elems( i, subset, nodes );
+ if (MB_SUCCESS != rval)
+ return error(rval);
}
- free( tag_names );
+
+ // Read node coordinates and create vertices in MOAB
+ // NOTE: This populates the RangeMap with node file ids,
+ // which is expected by read_node_adj_elems.
+ rval = read_nodes( nodes );
+ if (MB_SUCCESS != rval)
+ return error(rval);
- free( groups );
- if (file_set) {
- DEBUGOUT("Creating entity set for file contents\n")
- rval = iFace->add_entities( file_set, nodeSet.range );
+
+DEBUGOUT( "READING ELEMENTS" );
+
+ // decide if we need to read additional elements
+ int mode;
+ const char* const options[] = { "EXPLICIT", "ADJACENT", 0 };
+ rval = opts.match_option( "ELEMENTS", options, mode );
+ bool read_adjacent_elements;
+ if (MB_SUCCESS == rval) {
+ read_adjacent_elements = (mode == 1);
+ }
+ if (MB_ENTITY_NOT_FOUND == rval) {
+ // Chose default based on whether or not any elements have been
+ // specified.
+ MBRange tmp;
+ intersect( fileInfo->nodes, file_ids, tmp );
+ if (tmp.empty()) // can't do 'ADJACENT' mode if no nodes
+ read_adjacent_elements = false;
+ else { // check if we have any elements, default to 'ADJACENT' only if no
+ // explicitly specified elements
+ tmp.merge( sets );
+ MBRange elems = file_ids.subtract( tmp );
+ read_adjacent_elements = elems.empty();
+ }
+ }
+ else {
+ readUtil->report_error( "Invalid value for 'ELEMENTS' option" );
+ return error(rval);
+ }
+
+ if (read_adjacent_elements) {
+ for (int dim = 1; dim <= 3; ++dim) {
+ for (int i = 0; i < fileInfo->num_elem_desc; ++i) {
+ MBEntityType type = MBCN::EntityTypeFromName( fileInfo->elems[i].type );
+ if (MBCN::Dimension(type) == dim) {
+ rval = read_node_adj_elems( fileInfo->elems[i] );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+ }
+ }
+ }
+ }
+ else {
+ for (int dim = 1; dim <= 3; ++dim) {
+ for (int i = 0; i < fileInfo->num_elem_desc; ++i) {
+ MBEntityType type = MBCN::EntityTypeFromName( fileInfo->elems[i].type );
+ if (MBCN::Dimension(type) == dim) {
+ MBRange subset;
+ intersect( fileInfo->elems[i].desc, file_ids, subset );
+ rval = read_elems( fileInfo->elems[i], subset );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+ }
+ }
+ }
+ }
+
+DEBUGOUT( "READING SETS" );
+
+ // If reading child sets, but not all contents of child sets,
+ // need to get child sets after having read other entity types.
+ if (set_mode == 1) {
+ rval = read_child_sets( sets );
if (MB_SUCCESS != rval)
- return rval;
- for (el_itor = elemList.begin(); el_itor != elemList.end(); ++el_itor) {
- rval = iFace->add_entities( file_set, el_itor->range);
+ return error(rval);
+ }
+ // Append file IDs of sets containing any of the nodes or elements
+ // we've read up to this point.
+ rval = find_sets_containing( sets );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+ // Now actually read all set data and instantiate sets in MOAB.
+ // Get any contained sets out of file_ids.
+ MBEntityHandle first_set = fileInfo->sets.start_id;
+ sets.merge( file_ids.lower_bound( first_set ),
+ file_ids.lower_bound( first_set + fileInfo->sets.count ) );
+ rval = read_sets( sets );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+
+
+DEBUGOUT( "READING ADJACENCIES" );
+
+ for (int i = 0; i < fileInfo->num_elem_desc; ++i) {
+ if (fileInfo->elems[i].have_adj &&
+ idMap.intersects( fileInfo->elems[i].desc.start_id, fileInfo->elems[i].desc.count )) {
+ long len;
+ hid_t th = mhdf_openAdjacency( filePtr, fileInfo->elems[i].handle, &len, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+
+ rval = read_adjacencies( th, len );
+ mhdf_closeData( filePtr, th, &status );
if (MB_SUCCESS != rval)
- return rval;
+ return error(rval);
}
- rval = iFace->add_entities( file_set, setSet.range );
+ }
+
+DEBUGOUT( "READING TAGS" );
+
+ for (int i = 0; i < fileInfo->num_tag_desc; ++i) {
+ rval = read_tag( i );
if (MB_SUCCESS != rval)
- return rval;
+ return error(rval);
}
-DEBUGOUT("Finishing read.\n");
- rval = read_qa( file_set );
- return rval;
+ return MB_SUCCESS;
}
-MBErrorCode ReadHDF5::read_nodes()
+MBErrorCode ReadHDF5::search_tag_values( int tag_index,
+ const std::vector<int>& sorted_values,
+ MBRange& file_ids )
{
MBErrorCode rval;
mhdf_Status status;
- long count, first_id;
- int dim;
+ std::vector<long>::iterator iter;
+ const mhdf_TagDesc& tag = fileInfo->tags[tag_index];
+ long size;
+ long start_id;
+
+ // do dense data
+
+ hid_t table;
+ const char* name;
+ std::vector<long> indices;
+ // These are probably in order of dimension, so iterate
+ // in reverse order to make MBRange insertions more efficient.
+ std::vector<int> grp_indices( tag.dense_elem_indices, tag.dense_elem_indices+tag.num_dense_indices );
+ for (std::vector<int>::reverse_iterator i = grp_indices.rbegin(); i != grp_indices.rend(); ++i)
+ {
+ int idx = *i;
+ if (idx == -2) {
+ name = mhdf_set_type_handle();
+ start_id = fileInfo->sets.start_id;
+ }
+ else if (idx == -1) {
+ name = mhdf_node_type_handle();
+ start_id = fileInfo->nodes.start_id;
+ }
+ else {
+ if (idx < 0 || idx >= fileInfo->num_elem_desc)
+ return error(MB_FAILURE);
+ name = fileInfo->elems[idx].handle;
+ start_id = fileInfo->elems[idx].desc.start_id;
+ }
+ table = mhdf_openDenseTagData( filePtr, tag.name, name, &size, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ rval = search_tag_values( table, size, sorted_values, indices );
+ mhdf_closeData( filePtr, table, &status );
+ if (MB_SUCCESS != rval || is_error(status))
+ return error(MB_FAILURE);
+ // Convert from table indices to file IDs and add to result list
+ std::sort( indices.begin(), indices.end(), std::greater<long>() );
+ std::transform( indices.begin(), indices.end(), mb_range_inserter(file_ids),
+ std::bind1st( std::plus<long>(), start_id ) );
+ indices.clear();
+ }
+
+ if (!tag.have_sparse)
+ return MB_SUCCESS;
+
+ // do sparse data
+
+ hid_t tables[2];
+ long junk; // redundant value for non-variable-length tags
+ mhdf_openSparseTagData( filePtr, tag.name, &size, &junk, tables, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ rval = search_tag_values( tables[1], size, sorted_values, indices );
+ mhdf_closeData( filePtr, tables[1], &status );
+ if (MB_SUCCESS != rval || is_error(status)) {
+ mhdf_closeData( filePtr, tables[0], &status );
+ return error(MB_FAILURE);
+ }
+ // convert to ranges
+ std::sort( indices.begin(), indices.end() );
+ std::vector<long> ranges;
+ iter = indices.begin();
+ while (iter != indices.end()) {
+ ranges.push_back( *iter );
+ long last = *iter;
+ for (++iter; iter != indices.end() && (last + 1) == *iter; ++iter, ++last);
+ ranges.push_back( last );
+ }
+ // read file ids
+ iter = ranges.begin();
+ unsigned long offset = 0;
+ while (iter != ranges.end()) {
+ long begin = *iter; ++iter;
+ long end = *iter; ++iter;
+ mhdf_readSparseTagEntities( tables[0], begin, end - begin + 1,
+ H5T_NATIVE_LONG, &indices[offset], &status );
+ if (is_error(status)) {
+ mhdf_closeData( filePtr, tables[0], &status );
+ return error(MB_FAILURE);
+ }
+ offset += end - begin + 1;
+ }
+ mhdf_closeData( filePtr, tables[0], &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ assert( offset == indices.size() );
+ std::sort( indices.begin(), indices.end() );
+ copy_sorted_file_ids( (MBEntityHandle*)&indices[0], indices.size(), file_ids );
+
+ return MB_SUCCESS;
+}
+
+MBErrorCode ReadHDF5::search_tag_values( hid_t tag_table,
+ unsigned long table_size,
+ const std::vector<int>& sorted_values,
+ std::vector<long>& value_indices )
+{
+ mhdf_Status status;
+ size_t chunk_size = bufferSize / sizeof(unsigned);
+ unsigned * buffer = reinterpret_cast<unsigned*>(dataBuffer);
+ size_t remaining = table_size, offset = 0;
+ while (remaining) {
+ // Get a block of tag values
+ size_t count = std::min( chunk_size, remaining );
+ mhdf_readDenseTag( tag_table, offset, count, H5T_NATIVE_UINT, buffer, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+
+ // search tag values
+ for (size_t i = 0; i < count; ++i)
+ if (std::binary_search( sorted_values.begin(), sorted_values.end(), buffer[i] ))
+ value_indices.push_back( i + offset );
+
+ offset += count;
+ remaining -= count;
+ }
+
+ return MB_SUCCESS;
+}
+
+MBErrorCode ReadHDF5::read_nodes( const MBRange& node_file_ids )
+{
+ MBErrorCode rval;
+ mhdf_Status status;
+ const int dim = fileInfo->nodes.vals_per_ent;
MBRange range;
+ if (node_file_ids.empty())
+ return MB_SUCCESS;
+
int cdim;
rval = iFace->get_dimension( cdim );
if (MB_SUCCESS != rval)
- return rval;
+ return error(rval);
- hid_t data_id = mhdf_openNodeCoords( filePtr, &count, &dim, &first_id, &status );
- if (mhdf_isError( &status ))
- {
- //readUtil->report_error( mhdf_message( &status ));
- // Failed because no node data in file?
- nodeSet.range.clear();
- nodeSet.first_id = std::numeric_limits<long>::max();
- nodeSet.type = MBVERTEX;
- nodeSet.type2 = mhdf_node_type_handle();
- return MB_FILE_WRITE_ERROR;
- }
-
if (cdim < dim)
{
rval = iFace->set_dimension( dim );
if (MB_SUCCESS != rval)
- return rval;
+ return error(rval);
}
+ hid_t data_id = mhdf_openNodeCoordsSimple( filePtr, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+
+
MBEntityHandle handle;
std::vector<double*> arrays(dim);
- rval = readUtil->get_node_arrays( dim, (int)count, (int)first_id,
- handle, arrays );
+ rval = readUtil->get_node_arrays( dim, (int)node_file_ids.size(), 0, handle, arrays );
if (MB_SUCCESS != rval)
{
mhdf_closeData( filePtr, data_id, &status );
- return rval;
+ return error(rval);
}
- nodeSet.range.clear();
- nodeSet.range.insert( handle, handle + count - 1 );
- nodeSet.first_id = first_id;
- nodeSet.type = MBVERTEX;
- nodeSet.type2 = mhdf_node_type_handle();
- for (int i = 0; i < dim; i++)
+ // read blocks of coordinates
+ MBRange::const_pair_iterator p;
+ for (p = node_file_ids.const_pair_begin(); p != node_file_ids.const_pair_end(); ++p)
{
- mhdf_readNodeCoordWithOpt( data_id, 0, count, i, arrays[i], ioProp, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message(&status) );
+ long count = p->second - p->first + 1;
+ long offset = p->first - fileInfo->nodes.start_id;
+ for (int i = 0; i < dim; ++i) {
+ mhdf_readNodeCoord( data_id, offset, count, i, arrays[i], &status );
+ if (is_error(status)) {
+ mhdf_closeData( filePtr, data_id, &status );
+ return error(MB_FAILURE);
+ }
+ arrays[i] += count;
+ }
+ for (int i = dim; i < cdim; ++i) {
+ memset( arrays[i], 0, count*sizeof(double) );
+ arrays[i] += count;
+ }
+ IDMap::iterator ins = idMap.insert( p->first, handle, count );
+ if (ins == idMap.end()) {
mhdf_closeData( filePtr, data_id, &status );
- return MB_FAILURE;
+ return error(MB_FAILURE);
}
+ handle += count;
}
- for (int j = dim; j < cdim; j++)
- memset( arrays[j], 0, count * sizeof(double) );
mhdf_closeData( filePtr, data_id, &status );
if (mhdf_isError( &status ))
{
readUtil->report_error( mhdf_message(&status) );
- return MB_FAILURE;
+ return error(MB_FAILURE);
}
return MB_SUCCESS;
}
-MBErrorCode ReadHDF5::read_elems( const char* elem_group )
+MBErrorCode ReadHDF5::read_elems( int i )
{
- MBErrorCode rval;
+ MBRange ids;
+ ids.insert( fileInfo->elems[i].desc.start_id,
+ fileInfo->elems[i].desc.start_id + fileInfo->elems[i].desc.count - 1);
+ return read_elems( i, ids );
+}
+
+MBErrorCode ReadHDF5::read_elems( int i, const MBRange& file_ids )
+{
+ if (fileInfo->elems[i].desc.vals_per_ent < 0)
+ return read_poly( fileInfo->elems[i], file_ids );
+ else
+ return read_elems( fileInfo->elems[i], file_ids );
+}
+
+MBErrorCode ReadHDF5::read_elems( const mhdf_ElemDesc& elems, const MBRange& file_ids )
+{
+ MBErrorCode rval = MB_SUCCESS;
mhdf_Status status;
- char name[64];
- // Put elem set in list early so clean up code can
- // get rid of them if we fail.
- ElemSet empty_set;
- empty_set.type2 = elem_group;
- elemList.push_back( empty_set );
- std::list<ElemSet>::iterator it = elemList.end();
- --it;
- ElemSet& elems = *it;
-
- mhdf_getElemTypeName( filePtr, elem_group, name, sizeof(name), &status );
- if (mhdf_isError( &status ))
+ MBEntityType type = MBCN::EntityTypeFromName( elems.type );
+ if (type == MBMAXTYPE)
{
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
+ readUtil->report_error( "Unknown element type: \"%s\".\n", elems.type );
+ return error(MB_FAILURE);
}
- elems.type = MBCN::EntityTypeFromName( name );
- if (elems.type == MBMAXTYPE)
- {
- readUtil->report_error( "Unknown element type: \"%s\".\n", name );
- return MB_FAILURE;
+ const int nodes_per_elem = elems.desc.vals_per_ent;
+ const long first_id = elems.desc.start_id;
+ hid_t data_id = mhdf_openConnectivitySimple( filePtr, elems.handle, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+
+ MBRange::const_pair_iterator p;
+ for (p = file_ids.const_pair_begin(); p != file_ids.const_pair_end(); ++p) {
+ const long count = p->second - p->first + 1;
+
+ MBEntityHandle handle;
+ MBEntityHandle* array;
+ rval = readUtil->get_element_array( (int)count,
+ nodes_per_elem,
+ type,
+ 0,
+ handle,
+ array );
+ if (MB_SUCCESS != rval)
+ break;
+ IDMap::iterator ins = idMap.insert( p->first, handle, count );
+ if (ins == idMap.end())
+ { rval = MB_FAILURE; break; }
+
+ mhdf_readConnectivityWithOpt( data_id, p->first - first_id, count, handleType, array, ioProp, &status );
+ if (is_error(status))
+ break;
+
+ rval = convert_id_to_handle( array, (size_t)(nodes_per_elem*count) );
+ if (MB_SUCCESS != rval)
+ break;
+
+ // notify MOAB of the new elements
+ rval = readUtil->update_adjacencies(handle, count, nodes_per_elem, array);
+ if (MB_SUCCESS != rval)
+ break;
}
+
+
+ mhdf_closeData( filePtr, data_id, &status );
+ if (is_error(status) && MB_SUCCESS == rval)
+ rval = error(MB_FAILURE);
+ return rval;
+}
+
+MBErrorCode ReadHDF5::read_node_adj_elems( const mhdf_ElemDesc& group )
+{
+ mhdf_Status status;
+ MBErrorCode rval;
- int nodes_per_elem;
- long count, first_id;
- hid_t data_id = mhdf_openConnectivity( filePtr,
- elem_group,
- &nodes_per_elem,
- &count,
- &first_id,
- &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
- elems.first_id = first_id;
+ hid_t table = mhdf_openConnectivitySimple( filePtr, group.handle, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+
+ rval = read_node_adj_elems( group, table );
- MBEntityHandle handle;
- MBEntityHandle* array;
- rval = readUtil->get_element_array( (int)count,
- nodes_per_elem,
- elems.type,
- (int)first_id,
- handle,
- array );
- if (MB_SUCCESS != rval)
- {
- mhdf_closeData( filePtr, data_id, &status );
- return rval;
+ mhdf_closeData( filePtr, table, &status );
+ if (MB_SUCCESS == rval && is_error(status))
+ return error(rval = MB_FAILURE);
+ return rval;
+}
+
+MBErrorCode ReadHDF5::read_node_adj_elems( const mhdf_ElemDesc& group,
+ hid_t table_handle )
+{
+ mhdf_Status status;
+ MBErrorCode rval;
+
+ // copy data to local variables (makes other code clearer)
+ const int node_per_elem = group.desc.vals_per_ent;
+ long start_id = group.desc.start_id;
+ long remaining = group.desc.count;
+ const MBEntityType type = MBCN::EntityTypeFromName( group.type );
+
+ // figure out how many elements we can read in each pass
+ long* const buffer = reinterpret_cast<long*>( dataBuffer );
+ const long buffer_size = bufferSize / (node_per_elem * sizeof(buffer[0]));
+ // read all element connectivity in buffer_size blocks
+ long offset = 0;
+ while (remaining) {
+ // read a block of connectivity data
+ const long count = std::min( remaining, buffer_size );
+ mhdf_readConnectivity( table_handle, offset, count, H5T_NATIVE_LONG, buffer, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ offset += count;
+ remaining -= count;
+
+ // count the number of elements in the block that we want,
+ // zero connectivity for other elements
+ long num_elem = 0;
+ long* iter = buffer;
+ for (long i = 0; i < count; ++i) {
+ for (int j = 0; j < node_per_elem; ++j) {
+ iter[j] = (long)idMap.find( iter[j] );
+ if (!iter[j]) {
+ iter[0] = 0;
+ break;
+ }
+ }
+ if (iter[0])
+ ++num_elem;
+ iter += node_per_elem;
+ }
+
+ if (!num_elem) {
+ start_id += count;
+ continue;
+ }
+
+ // create elements
+ MBEntityHandle handle;
+ MBEntityHandle* array;
+ rval = readUtil->get_element_array( (int)num_elem,
+ node_per_elem,
+ type,
+ 0,
+ handle,
+ array );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+
+ // copy all non-zero connectivity values
+ iter = buffer;
+ MBEntityHandle* iter2 = array;
+ MBEntityHandle h = handle;
+ for (long i = 0; i < count; ++i) {
+ if (!*iter) {
+ iter += node_per_elem;
+ continue;
+ }
+ IDMap::iterator ins = idMap.insert( start_id + i, h++, 1 );
+ if (ins == idMap.end())
+ return error(MB_FAILURE);
+
+ long* const end = iter + node_per_elem;
+ for (; iter != end; ++iter, ++iter2)
+ *iter2 = (MBEntityHandle)*iter;
+ }
+ assert( iter2 - array == num_elem * node_per_elem );
+ start_id += count;
}
- elems.range.insert( handle, handle + count - 1 );
- mhdf_readConnectivityWithOpt( data_id, 0, count, handleType, array, ioProp, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, data_id, &status );
- return MB_FAILURE;
+ return MB_SUCCESS;
+}
+
+
+MBErrorCode ReadHDF5::read_elems( int i, const MBRange& elems_in, MBRange& nodes )
+{
+ MBEntityHandle* const buffer = reinterpret_cast<MBEntityHandle*>(dataBuffer);
+ const size_t buffer_size = bufferSize / sizeof(MBEntityHandle);
+ int node_per_elem = fileInfo->elems[i].desc.vals_per_ent;
+
+ if (elems_in.empty())
+ return MB_SUCCESS;
+
+ assert( (long)elems_in.front() >= fileInfo->elems[i].desc.start_id );
+ assert( (long)elems_in.back() - fileInfo->elems[i].desc.start_id < fileInfo->elems[i].desc.count );
+
+ // we don't support version 3 style poly element data
+ if (fileInfo->elems[i].desc.vals_per_ent <= 0)
+ return error(MB_TYPE_OUT_OF_RANGE);
+
+ mhdf_Status status;
+ hid_t table = mhdf_openConnectivitySimple( filePtr, fileInfo->elems[i].handle, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+
+ MBRange elements( elems_in );
+ while (!elements.empty()) {
+ MBEntityHandle file_id = elements.front();
+ long count = elements.const_pair_begin()->second - file_id + 1;
+ long offset = file_id - fileInfo->elems[i].desc.start_id;
+ if (count*node_per_elem > (long)buffer_size)
+ count = buffer_size/node_per_elem;
+ elements.erase( elements.begin(), elements.begin()+count );
+
+ // read element connectivity
+ mhdf_readConnectivity( table, offset, count, handleType, buffer, &status );
+ if (is_error(status)) {
+ mhdf_closeData( filePtr, table, &status );
+ return error(MB_FAILURE);
+ }
+
+ count *= node_per_elem;
+ std::sort( buffer, buffer + count );
+ count = std::unique( buffer, buffer + count ) - buffer;
+ copy_sorted_file_ids( buffer, count, nodes );
}
- mhdf_closeData( filePtr, data_id, &status );
- if (mhdf_isError( &status ))
+ mhdf_closeData( filePtr, table, &status );
+ return is_error(status) ? error(MB_FAILURE) : MB_SUCCESS;
+}
+
+MBErrorCode ReadHDF5::read_poly( const mhdf_ElemDesc& elems, const MBRange& file_ids )
+{
+ class PolyReader : public ContentReader {
+ private:
+ const MBEntityType type;
+ hid_t indexHandle, connHandle, handleType;
+ MBInterface *const mb;
+ IDMap& idMap;
+ public:
+ PolyReader( MBEntityType elem_type, hid_t idx, hid_t conn,
+ hid_t handle_type, MBInterface* iface, IDMap& id_map )
+ : type(elem_type), indexHandle(idx), connHandle(conn),
+ handleType(handle_type), mb(iface), idMap(id_map)
+ {}
+ void read_indices( long offset, long count, long* buffer, mhdf_Status& status )
+ { mhdf_readPolyConnIndices( indexHandle, offset, count, H5T_NATIVE_LONG, buffer, &status ); }
+ void read_contents( long offset, long count, MBEntityHandle* buffer, mhdf_Status& status )
+ { mhdf_readPolyConnIDs( connHandle, offset, count, handleType, buffer, &status ); }
+ MBErrorCode store_data( MBEntityHandle, long file_id, MBEntityHandle* conn, long len, bool )
+ {
+ size_t valid;
+ convert_id_to_handle( conn, len, valid, idMap );
+ if (valid != (size_t)len)
+ return error(MB_ENTITY_NOT_FOUND);
+ MBEntityHandle handle;
+ MBErrorCode rval = mb->create_element( type, conn, len, handle );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+ IDMap::iterator ins = idMap.insert( file_id, handle, 1 );
+ if (ins == idMap.end())
+ return error(MB_FAILURE);
+ return MB_SUCCESS;
+ }
+ };
+
+ MBEntityType type = MBCN::EntityTypeFromName( elems.type );
+ if (type == MBMAXTYPE)
{
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
+ readUtil->report_error( "Unknown element type: \"%s\".\n", elems.type );
+ return error(MB_FAILURE);
}
- if (elems.type == MBPOLYHEDRON)
- rval = convert_id_to_handle( array, (size_t)(nodes_per_elem*count) );
- else
- rval = convert_id_to_handle( nodeSet, array, (size_t)(nodes_per_elem*count) );
+ hid_t handles[2];
+ mhdf_Status status;
+ long num_poly, num_conn, first_id;
+ mhdf_openPolyConnectivity( filePtr, elems.handle, &num_poly, &num_conn, &first_id,
+ handles, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
- if (MB_SUCCESS != rval) return rval;
-
- // notify MOAB of the new elements
- MBErrorCode result = readUtil->update_adjacencies(handle, count,
- nodes_per_elem, array);
- if (MB_SUCCESS != result) return result;
+ PolyReader tool( type, handles[0], handles[1], handleType, iFace, idMap );
+ MBRange empty;
+ MBErrorCode rval = read_contents( tool, file_ids, first_id, 0, num_poly, num_conn, empty );
+ mhdf_closeData( filePtr, handles[0], &status );
+ if (MB_SUCCESS == rval && is_error(status))
+ rval = error(MB_FAILURE);
+ mhdf_closeData( filePtr, handles[1], &status );
+ if (MB_SUCCESS == rval && is_error(status))
+ rval = error(MB_FAILURE);
return rval;
}
-
+/*
MBErrorCode ReadHDF5::read_poly( const char* elem_group )
{
MBErrorCode rval;
@@ -515,7 +1061,7 @@
if (mhdf_isError( &status ))
{
readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
+ return error(MB_FAILURE);
}
MBEntityType type = MBCN::EntityTypeFromName( name );
@@ -526,7 +1072,7 @@
if (mhdf_isError( &status ))
{
readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
+ return error(MB_FAILURE);
}
ElemSet empty_set;
@@ -545,7 +1091,7 @@
readUtil->report_error( mhdf_message( &status ) );
mhdf_closeData( filePtr, handles[0], &status );
mhdf_closeData( filePtr, handles[1], &status );
- return MB_FAILURE;
+ return error(MB_FAILURE);
}
connectivity.resize( connend - prevend );
@@ -556,15 +1102,14 @@
readUtil->report_error( mhdf_message( &status ) );
mhdf_closeData( filePtr, handles[0], &status );
mhdf_closeData( filePtr, handles[1], &status );
- return MB_FAILURE;
+ return error(MB_FAILURE);
}
rval= convert_id_to_handle( &connectivity[0], connectivity.size() );
- if (MB_SUCCESS != rval)
- {
+ if (MB_SUCCESS != rval) {
mhdf_closeData( filePtr, handles[0], &status );
mhdf_closeData( filePtr, handles[1], &status );
- return rval;
+ return error(rval);
}
rval = iFace->create_element( type, &connectivity[0], connectivity.size(), h );
@@ -572,7 +1117,7 @@
{
mhdf_closeData( filePtr, handles[0], &status );
mhdf_closeData( filePtr, handles[1], &status );
- return rval;
+ return error(rval);
}
if (first || elemList.back().range.back() + 1 >= h) {
@@ -587,783 +1132,1045 @@
mhdf_closeData( filePtr, handles[0], &status );
if (mhdf_isError( &status )) {
readUtil->report_error( mhdf_message( &status ));
- result = MB_FAILURE;
+ result = error(MB_FAILURE);
}
mhdf_closeData( filePtr, handles[1], &status );
if (mhdf_isError( &status )) {
readUtil->report_error( mhdf_message( &status ));
- result = MB_FAILURE;
+ result = error(MB_FAILURE);
}
return result;
}
+*/
-template <typename T>
-class auto_array {
-private:
- T* data;
-public:
- auto_array( size_t s ) : data(new T[s]) {}
- auto_array() : data(0) {}
- ~auto_array() { delete [] data; }
- T* get () { return data; }
- const T* get () const { return data; }
- T& operator[]( size_t i ) { return data[i]; }
- const T& operator[]( size_t i ) const { return data[i]; }
- T& operator* () { return *data; }
- const T* operator* () const { return *data; }
- T* operator->() { return data; }
- const T* operator->() const { return data; }
-// auto_ptr-style destrutive assigment
- auto_array( auto_array<T>& c ) {
- data = c.data;
- const_cast<auto_array<T>&>(c).data = 0;
+MBErrorCode ReadHDF5::read_sets( const MBRange& file_ids )
+{
+ mhdf_Status status;
+ MBErrorCode rval;
+ if (fileInfo->sets.count == 0 || file_ids.empty()) {
+ assert(file_ids.empty());
+ return MB_SUCCESS;
}
- auto_array<T>& operator=( auto_array<T>& c ) {
- data = c.data;
- const_cast<auto_array<T>&>(c).data = 0;
+
+ hid_t meta_handle = mhdf_openSetMetaSimple( filePtr, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+
+
+ // create sets
+ MBRange ranged_set_ids;
+ MBEntityHandle start_handle;
+ rval = read_sets( file_ids, meta_handle, ranged_set_ids, start_handle );
+ if (MB_SUCCESS != rval) {
+ mhdf_closeData( filePtr, meta_handle, &status );
+ return error(rval);
}
-};
+
+ // read contents
+ if (fileInfo->have_set_contents) {
+ long len = 0;
+ hid_t handle = mhdf_openSetData( filePtr, &len, &status );
+ if (is_error(status)) {
+ mhdf_closeData( filePtr, meta_handle, &status );
+ return error(MB_FAILURE);
+ }
+
+ rval = read_contents( file_ids, start_handle, meta_handle, handle, len,
+ ranged_set_ids );
+ mhdf_closeData( filePtr, handle, &status );
+ if (MB_SUCCESS == rval && is_error(status))
+ rval = MB_FAILURE;
+ if (MB_SUCCESS != rval) {
+ mhdf_closeData( filePtr, meta_handle, &status );
+ return error(rval);
+ }
+ }
+ // read set child lists
+ if (fileInfo->have_set_children) {
+ long len = 0;
+ hid_t handle = mhdf_openSetChildren( filePtr, &len, &status );
+ if (is_error(status)) {
+ mhdf_closeData( filePtr, meta_handle, &status );
+ return error(MB_FAILURE);
+ }
+
+ rval = read_children( file_ids, start_handle, meta_handle, handle, len );
+ mhdf_closeData( filePtr, handle, &status );
+ if (MB_SUCCESS == rval && is_error(status))
+ rval = MB_FAILURE;
+ if (MB_SUCCESS != rval) {
+ mhdf_closeData( filePtr, meta_handle, &status );
+ return error(rval);
+ }
+ }
+
+ // read set parent lists
+ if (fileInfo->have_set_parents) {
+ long len = 0;
+ hid_t handle = mhdf_openSetParents( filePtr, &len, &status );
+ if (is_error(status)) {
+ mhdf_closeData( filePtr, meta_handle, &status );
+ return error(MB_FAILURE);
+ }
+
+ rval = read_parents( file_ids, start_handle, meta_handle, handle, len );
+ mhdf_closeData( filePtr, handle, &status );
+ if (MB_SUCCESS == rval && is_error(status))
+ rval = MB_FAILURE;
+ if (MB_SUCCESS != rval) {
+ mhdf_closeData( filePtr, meta_handle, &status );
+ return error(rval);
+ }
+ }
+
+ mhdf_closeData( filePtr, meta_handle, &status );
+ return is_error(status) ? error(MB_FAILURE) : MB_SUCCESS;
+}
-MBErrorCode ReadHDF5::read_set_contents( hid_t meta_id, hid_t data_id,
- const unsigned long data_len )
+MBErrorCode ReadHDF5::read_child_sets( MBRange& sets_in_out )
{
- MBErrorCode rval;
+ if (!fileInfo->have_set_children)
+ return MB_SUCCESS;
+
+ // open data tables
+ if (fileInfo->sets.count == 0) {
+ assert( sets_in_out.empty() );
+ return MB_SUCCESS;
+ }
+
mhdf_Status status;
+ hid_t meta_handle = mhdf_openSetMetaSimple( filePtr, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
- // create extra buffers for storing end indices and flags
- const unsigned long offset_size = bufferSize / sizeof(long);
- auto_array<long> offsets(offset_size);
- auto_array<unsigned short> flags(offset_size);
+ long child_len = 0;
+ hid_t child_handle = mhdf_openSetChildren( filePtr, &child_len, &status );
+ if (is_error(status)) {
+ mhdf_closeData( filePtr, meta_handle, &status );
+ return error(MB_FAILURE);
+ }
- MBEntityHandle* buffer = (MBEntityHandle*)dataBuffer;
- size_t chunk_size = bufferSize / sizeof(MBEntityHandle);
- if (chunk_size % 2)
- --chunk_size; // makes reading range data easier.
+ MBErrorCode rval = read_child_ids_recursive( sets_in_out, meta_handle, child_handle );
- unsigned long set_offset = 0; /* running offset into description table */
- unsigned long sets_remaining = setSet.range.size();
- unsigned long file_offset = 0; /* running offset into child table */
- MBRange::const_iterator set_iter = setSet.range.begin();
- while (sets_remaining) {
- // read end indices from meta data
- unsigned long set_count = sets_remaining < offset_size ? sets_remaining : offset_size;
- mhdf_readSetContentEndIndicesWithOpt( meta_id, set_offset, set_count,
- H5T_NATIVE_LONG, offsets.get(), ioProp, &status );
- if (mhdf_isError( &status )) {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
- mhdf_readSetFlagsWithOpt( meta_id, set_offset, set_count, H5T_NATIVE_USHORT,
- flags.get(), ioProp, &status );
- if (mhdf_isError( &status )) {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
-
- // now iterate over sets, reading set content lists
- unsigned long i, r = 0; // number of sets for which data has been read.
- while (r < set_count) {
- // figure out how many we can read at once
- for (i = r; i < set_count; ++i)
- if ((unsigned long)(offsets[i] + 1 - file_offset) > chunk_size)
- break;
-
- // special case: set content list for single set greater than buffer
- if (i == r) {
- // Check if set contents are stored as ranges or a simple list
- bool ranged = (0 != (flags[r] & (unsigned short)mhdf_SET_RANGE_BIT));
+ mhdf_closeData( filePtr, child_handle, &status );
+ if (MB_SUCCESS == rval && is_error(status))
+ rval = error(MB_FAILURE);
+ mhdf_closeData( filePtr, meta_handle, &status );
+ if (MB_SUCCESS == rval && is_error(status))
+ rval = error(MB_FAILURE);
+
+ return rval;
+}
- assert( set_iter != setSet.range.end() );
- MBEntityHandle h = *set_iter; ++set_iter;
- size_t remaining = offsets[r] + 1 - file_offset;
- if (remaining > data_len - file_offset) {
- readUtil->report_error( "Invalid set contents offset read from file." );
- return MB_FAILURE;
- }
- while (remaining)
- {
- size_t count = remaining > chunk_size ? chunk_size : remaining;
- remaining -= count;
- mhdf_readSetDataWithOpt( data_id, file_offset, count, handleType, buffer, ioProp, &status );
- if (mhdf_isError( &status )) {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
- file_offset += count;
+MBErrorCode ReadHDF5::find_sets_containing( MBRange& sets_out )
+{
+ MBErrorCode rval;
+ mhdf_Status status;
- // convert data from file ids to MBEntityHandles and add to set
- if (ranged)
- {
- if (count % 2 != 0) {
- readUtil->report_error( "Invalid ranged set contents spec." );
- return MB_FAILURE;
- }
- MBRange range;
- rval = convert_range_to_handle( buffer, count / 2, range );
- if (MB_SUCCESS != rval) {
- readUtil->report_error( "Invalid entities in set contents" );
- return rval;
- }
- rval = iFace->add_entities( h, range );
- if (MB_SUCCESS != rval)
- return rval;
- }
- else
- {
- rval = convert_id_to_handle( buffer, count );
- if (MB_SUCCESS != rval) {
- readUtil->report_error( "Invalid entities in set contents" );
- return rval;
- }
- rval = iFace->add_entities( h, buffer, count );
- if (MB_SUCCESS != rval)
- return rval;
- }
- } // while(remaining)
- ++r;
- } // end special case (really big set)
-
- // normal case - read data for several sets
- else {
-
- // read data for sets in [r,i)
-
- size_t count = offsets[i-1] + 1 - file_offset;
- if (count > data_len - file_offset) {
- readUtil->report_error( "Invalid set contents offset read from file." );
- return MB_FAILURE;
- }
-
- mhdf_readSetDataWithOpt( data_id, file_offset, count, handleType, buffer, ioProp, &status );
- if (mhdf_isError( &status )) {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
-
- // add contents to each set
- size_t mem_offset = 0;
- for (; r < i; ++r) {
- bool ranged = (0 != (flags[r] & (long)mhdf_SET_RANGE_BIT));
- count = offsets[r] + 1 - file_offset;
- assert( set_iter != setSet.range.end() );
- MBEntityHandle h = *set_iter; ++set_iter;
+ if (!fileInfo->have_set_contents)
+ return MB_SUCCESS;
+ assert( fileInfo->sets.count );
- if (ranged)
- {
- if (count % 2 != 0) {
- readUtil->report_error( "Invalid ranged set contenst spec." );
- return MB_FAILURE;
- }
- MBRange range;
- rval = convert_range_to_handle( buffer+mem_offset, count / 2, range );
- if (MB_SUCCESS != rval) {
- readUtil->report_error( "Invalid entities in set contents" );
- return rval;
- }
- rval = iFace->add_entities( h, range );
- if (MB_SUCCESS != rval)
- return rval;
- }
- else
- {
- rval = convert_id_to_handle( buffer+mem_offset, count );
- if (MB_SUCCESS != rval) {
- readUtil->report_error( "Invalid entities in set contents" );
- return rval;
- }
- rval = iFace->add_entities( h, buffer+mem_offset, count );
- if (MB_SUCCESS != rval)
- return rval;
- }
+ // open data tables
+ hid_t meta_handle = mhdf_openSetMetaSimple( filePtr, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ long content_len = 0;
+ hid_t content_handle = mhdf_openSetData( filePtr, &content_len, &status );
+ if (is_error(status)) {
+ mhdf_closeData( filePtr, meta_handle, &status );
+ return error(MB_FAILURE);
+ }
- file_offset += count;
- mem_offset += count;
- }
- }
- } // while(r < num_sets)
+ rval = find_sets_containing( meta_handle, content_handle, content_len, sets_out );
+
+ mhdf_closeData( filePtr, content_handle, &status );
+ if(MB_SUCCESS == rval && is_error(status))
+ rval = error(MB_FAILURE);
+ mhdf_closeData( filePtr, meta_handle, &status );
+ if(MB_SUCCESS == rval && is_error(status))
+ rval = error(MB_FAILURE);
- set_offset += set_count;
- sets_remaining -= set_count;
- } // while (sets_remaining)
+ return rval;
+}
- assert( set_iter == setSet.range.end() );
- return MB_SUCCESS;
+static bool set_map_intersect( unsigned short flags,
+ const long* contents,
+ int content_len,
+ const RangeMap<long,MBEntityHandle>& id_map )
+{
+ if (flags & mhdf_SET_RANGE_BIT) {
+ if (!content_len || id_map.empty())
+ return false;
+
+ const long* j = contents;
+ const long* const end = contents + content_len;
+ assert(content_len % 2 == 0);
+ while (j != end) {
+ long start = *(j++);
+ long count = *(j++);
+ if (id_map.intersects( start, count ))
+ return true;
+ }
+ }
+ else {
+ const long* const end = contents + content_len;
+ for (const long* i = contents; i != end; ++i)
+ if (id_map.exists( *i ))
+ return true;
+ }
+ return false;
}
-MBErrorCode ReadHDF5::read_parents_children( bool parents,
- hid_t meta_id,
- hid_t data_id,
- const unsigned long data_len )
+MBErrorCode ReadHDF5::find_sets_containing( hid_t meta_handle,
+ hid_t contents_handle,
+ long contents_len,
+ MBRange& file_ids )
{
- MBErrorCode rval;
+ const long avg_set_len = contents_len / fileInfo->sets.count;
+ long sets_per_buffer = bufferSize / (sizeof(short) + sizeof(long) * (2+avg_set_len));
+ // round to down multiple of 8 to avoid alignment issues
+ sets_per_buffer = 8 * (sets_per_buffer / 8);
+ if (sets_per_buffer < 10) // just in case there's one huge set
+ sets_per_buffer = 10;
+ unsigned short* flag_buffer = (unsigned short*)dataBuffer;
+ long* offset_buffer = (long*)(flag_buffer + sets_per_buffer);
+ long* content_buffer = offset_buffer + sets_per_buffer;
+ assert(bufferSize % sizeof(long) == 0);
+ long content_len = (long*)(dataBuffer + bufferSize) - content_buffer;
+ assert(dataBuffer + bufferSize >= (char*)(content_buffer + content_len));
+ // scan set table
mhdf_Status status;
-
- // create an extra buffer for storing offsets
- const unsigned long offset_size = bufferSize / sizeof(long);
- auto_array<long> offsets( offset_size );
- // use the existing buffer for storing set child lists
- MBEntityHandle* buffer = (MBEntityHandle*)dataBuffer;
- size_t chunk_size = bufferSize / sizeof(MBEntityHandle);
- const size_t total_sets = setSet.range.size();
-
- unsigned long set_offset = 0; /* running offset into description table */
- unsigned long sets_remaining = setSet.range.size();
- unsigned long file_offset = 0; /* running offset into child table */
- MBRange::const_iterator set_iter = setSet.range.begin();
- while (sets_remaining) {
- // read end indices from meta data
- unsigned long set_count = sets_remaining < offset_size ? sets_remaining : offset_size;
- if (parents)
- mhdf_readSetParentEndIndicesWithOpt( meta_id, set_offset, set_count,
- H5T_NATIVE_LONG, offsets.get(),
- ioProp, &status );
- else
- mhdf_readSetChildEndIndicesWithOpt( meta_id, set_offset, set_count,
- H5T_NATIVE_LONG, offsets.get(),
- ioProp, &status );
- if (mhdf_isError( &status )) {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
+ MBRange::iterator hint = file_ids.begin();
+ long remaining = fileInfo->sets.count;
+ long offset = 0;
+ long prev_idx = -1;
+ while (remaining) {
+ long count = std::min( remaining, sets_per_buffer );
+ mhdf_readSetFlags( meta_handle, offset, count, H5T_NATIVE_USHORT, flag_buffer, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ mhdf_readSetContentEndIndices( meta_handle, offset, count, H5T_NATIVE_LONG, offset_buffer, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
- // now iterate over sets, reading parent/child lists
- unsigned long i, r = 0; // number of sets for which data has been read.
- while (r < set_count) {
- // figure out how many we can read at once
- for (i = r; i < set_count; ++i)
- if ((unsigned long)(offsets[i] + 1 - file_offset) > chunk_size)
- break;
-
- // special case: children of one set greater than buffer
- if (i == r) {
- assert( set_iter != setSet.range.end() );
- MBEntityHandle h = *set_iter; ++set_iter;
- size_t remaining = offsets[r] + 1 - file_offset;
- if (remaining > data_len - file_offset) {
- readUtil->report_error( "Invalid set %s offset read from file.",
- parents ? "parent" : "child" );
- return MB_FAILURE;
- }
- while (remaining)
- {
- size_t count = remaining > chunk_size ? chunk_size : remaining;
- remaining -= count;
- mhdf_readSetParentsChildrenWithOpt( data_id, file_offset, count, handleType,
- buffer, ioProp, &status );
- if (mhdf_isError( &status )) {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
+ long sets_remaining = count;
+ long sets_offset = 0;
+ while (sets_remaining) {
+ // figure how many of the remaining sets are required to
+ // fill the set contents buffer.
+ long sets_count = std::lower_bound( offset_buffer + sets_offset,
+ offset_buffer + count, content_len + prev_idx )
+ - offset_buffer - sets_offset;
+ if (!sets_count) { // contents of single set don't fit in buffer
+ long content_remaining = offset_buffer[sets_offset] - prev_idx;
+ long content_offset = prev_idx+1;
+ while (content_remaining) {
+ long content_count = content_len < content_remaining ?
+ 2*(content_len/2) : content_remaining;
+ mhdf_readSetData( contents_handle, content_offset,
+ content_count, H5T_NATIVE_LONG,
+ content_buffer, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ if (set_map_intersect( flag_buffer[sets_offset],
+ content_buffer, content_count, idMap )) {
+ long id = fileInfo->sets.start_id + offset + sets_offset;
+ hint = file_ids.insert( hint, id, id );
+ break;
}
- file_offset += count;
-
- // convert from file_ids to set handles
- for (size_t j = 0; j < count; ++j) {
- buffer[j] -= setSet.first_id;
- if (buffer[j] >= total_sets) {
- readUtil->report_error("Invalid set %s ID", parents ? "parent" : "child" );
- return MB_FAILURE;
- }
- buffer[j] += setSet.range.front();
- }
-
- if (parents)
- rval = iFace->add_parent_meshsets( h, buffer, count );
- else
- rval = iFace->add_child_meshsets( h, buffer, count );
- if (MB_SUCCESS != rval)
- return rval;
- } // while(remaining)
- ++r;
- } // end special case (really big set)
-
- // normal case - read data for several sets
- else {
-
- // read data for sets in [r,i)
- size_t count = offsets[i-1] + 1 - file_offset;
- if (count > data_len - file_offset) {
- readUtil->report_error( "Invalid set %s offset read from file.",
- parents ? "parent" : "child" );
- return MB_FAILURE;
+ content_remaining -= content_count;
+ content_offset += content_count;
}
- mhdf_readSetParentsChildrenWithOpt( data_id, file_offset, count, handleType,
- buffer, ioProp, &status );
- if (mhdf_isError( &status )) {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
+ prev_idx = offset_buffer[sets_offset];
+ sets_count = 1;
+ }
+ else if (long read_num = offset_buffer[sets_offset + sets_count - 1] - prev_idx) {
+ assert(sets_count > 0);
+ mhdf_readSetData( contents_handle, prev_idx+1, read_num,
+ H5T_NATIVE_LONG, content_buffer, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
- // convert from file_ids to set handles
- for (size_t j = 0; j < count; ++j) {
- buffer[j] -= setSet.first_id;
- if (buffer[j] >= total_sets) {
- readUtil->report_error("Invalid set %s ID", parents ? "parent" : "child" );
- return MB_FAILURE;
+ long* buff_iter = content_buffer;
+ for (long i = 0; i < sets_count; ++i) {
+ long set_size = offset_buffer[i] - prev_idx;
+ prev_idx = offset_buffer[i];
+ if (set_map_intersect( flag_buffer[sets_offset+i],
+ buff_iter, set_size, idMap )) {
+ long id = fileInfo->sets.start_id + offset + sets_offset + i;
+ hint = file_ids.insert( hint, id, id );
}
- buffer[j] += setSet.range.front();
+ buff_iter += set_size;
}
-
- // add children to each set
- size_t mem_offset = 0;
- for (; r < i; ++r) {
- assert( set_iter != setSet.range.end() );
- MBEntityHandle h = *set_iter; ++set_iter;
- count = offsets[r] + 1 - file_offset;
- if (parents)
- rval = iFace->add_parent_meshsets( h, buffer+mem_offset, count );
- else
- rval = iFace->add_child_meshsets( h, buffer+mem_offset, count );
- if (MB_SUCCESS != rval)
- return rval;
-
- file_offset += count;
- mem_offset += count;
- }
}
- } // while(r < num_sets)
- set_offset += set_count;
- sets_remaining -= set_count;
- } // while (sets_remaining)
-
- assert( set_iter == setSet.range.end() );
+ sets_offset += sets_count;
+ sets_remaining -= sets_count;
+ }
+
+ offset += count;
+ remaining -= count;
+ }
+
return MB_SUCCESS;
}
+MBErrorCode ReadHDF5::read_child_ids_recursive( MBRange& file_ids,
+ hid_t meta_handle,
+ hid_t child_handle )
+{
+ MBErrorCode rval = MB_SUCCESS;
+ MBRange children, new_children(file_ids);
+ do {
+ children.clear();
+ rval = read_child_ids( new_children, meta_handle, child_handle, children );
+ if (MB_SUCCESS != rval)
+ break;
+
+ new_children = children.subtract( file_ids );
+ file_ids.merge( new_children );
+ } while (!new_children.empty());
+ return rval;
+}
-MBErrorCode ReadHDF5::read_sets()
+MBErrorCode ReadHDF5::read_child_ids( const MBRange& input_file_ids,
+ hid_t meta_handle,
+ hid_t child_handle,
+ MBRange& child_file_ids )
{
- MBErrorCode rval;
mhdf_Status status;
+ long* buffer = reinterpret_cast<long*>(dataBuffer);
+ long buffer_size = bufferSize / sizeof(long);
+ long first, range[2], count, remaining;
+ MBRange sets(input_file_ids);
+ MBRange::iterator hint;
+ while (!sets.empty()) {
+ count = (long)sets.const_pair_begin()->second - sets.front() + 1;
+ first = (long)sets.front() - fileInfo->sets.start_id;
+ sets.erase( sets.begin(), sets.begin() + count );
+
+ if (!first) {
+ range[0] = -1;
+ mhdf_readSetChildEndIndices( meta_handle, first+count-1, 1, H5T_NATIVE_LONG, range+1, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ }
+ else if (count == 1) {
+ mhdf_readSetChildEndIndices( meta_handle, first-1, 2, H5T_NATIVE_LONG, range, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ }
+ else {
+ mhdf_readSetChildEndIndices( meta_handle, first-1, 1, H5T_NATIVE_LONG, range+1, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ mhdf_readSetChildEndIndices( meta_handle, first+count-1, 1, H5T_NATIVE_LONG, range+1, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ }
+
+ remaining = range[1] - range[0];
+ long offset = range[0] + 1;
+ while (remaining) {
+ count = std::min( buffer_size, remaining );
+ remaining -= count;
+ mhdf_readSetParentsChildren( child_handle, offset, count, H5T_NATIVE_LONG, buffer, &status );
- // Check what data is in the file for sets
- int have_sets, have_data, have_children, have_parents;
- have_sets = mhdf_haveSets( filePtr, &have_data, &have_children, &have_parents, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
+ std::sort( buffer, buffer + count );
+ count = std::unique( buffer, buffer + count ) - buffer;
+ hint = child_file_ids.begin();
+ for (long i = 0; i < count; ++i) {
+ MBEntityHandle h = (MBEntityHandle)buffer[i];
+ hint = child_file_ids.insert( hint, h, h );
+ }
+ }
}
+
+ return MB_SUCCESS;
+}
- if (!have_sets)
+MBErrorCode ReadHDF5::read_sets( const MBRange& file_ids,
+ hid_t meta_handle,
+ MBRange& ranged_file_ids,
+ MBEntityHandle& start_handle,
+ bool create )
+{
+ MBErrorCode rval;
+ mhdf_Status status;
+
+ size_t count = file_ids.size();
+ if (!count)
return MB_SUCCESS;
-
- // Open the list of sets
- long num_sets, first_id;
- hid_t meta_id = mhdf_openSetMeta( filePtr, &num_sets, &first_id, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
- // Initialize internal bookkeeping
- setSet.first_id = first_id;
- setSet.type = MBENTITYSET;
- setSet.type2 = mhdf_set_type_handle();
- if (!num_sets) { // shouldn't happen if have_sets == true, but...
- mhdf_closeData( filePtr, meta_id, &status );
- return MB_SUCCESS;
+ std::vector<unsigned> tmp_buffer;
+ unsigned* buffer;
+ if (count > (bufferSize/sizeof(unsigned))) {
+ tmp_buffer.resize( count );
+ buffer = &tmp_buffer[0];
}
+ else {
+ buffer = reinterpret_cast<unsigned*>(dataBuffer);
+ }
- // Get last used MeshSet handle
- MBRange junk;
- iFace->get_entities_by_type( 0, MBENTITYSET, junk );
- MBEntityHandle start_handle = junk.empty() ? 1 : junk.back() + 1;
- junk.clear();
- bool first = true;
+ unsigned* buff_iter = buffer;
+ MBRange::const_pair_iterator p;
+ for (p = file_ids.const_pair_begin(); p != file_ids.const_pair_end(); ++p) {
+ long offset = p->first - fileInfo->sets.start_id;
+ long count = p->second - p->first + 1;
+ mhdf_readSetFlags( meta_handle, offset, count, H5T_NATIVE_UINT, buff_iter, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ offset += count;
+ buff_iter += count;
+ }
+ buff_iter = buffer;
+ MBRange::iterator hint = ranged_file_ids.begin();
+ for (MBRange::iterator i = file_ids.begin(); i != file_ids.end(); ++i, ++buff_iter) {
+ if ((*buff_iter) & mhdf_SET_RANGE_BIT) {
+ *buff_iter &= ~(unsigned)mhdf_SET_RANGE_BIT;
+ hint = ranged_file_ids.insert( hint, *i, *i );
+ }
+ }
- // Iterate over set metadata, creating all the sets.
- // Don't read any contents or parent/child links yet.
- // Create all the sets first, so all the contents
- // and parent/child links are valid.
- MBEntityHandle handle;
- size_t chunk_size = bufferSize / sizeof(unsigned);
- unsigned * buffer = reinterpret_cast<unsigned*>(dataBuffer);
- size_t remaining = num_sets, offset = 0;
- MBRange::iterator insert_iter = setSet.range.begin();
- while (remaining) {
- // Get a block of set flags
- size_t count = remaining > chunk_size ? chunk_size : remaining;
- mhdf_readSetFlagsWithOpt( meta_id, offset, count, H5T_NATIVE_UINT,
- buffer, ioProp, &status );
- if (mhdf_isError( &status )) {
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, meta_id, &status );
- return MB_FAILURE;
- }
- offset += count;
- remaining -= count;
-
- // clear ranged-storage bit. Its internal data for the file
- // format, not one of MOAB's set flags.
- for (size_t i = 0;i < count; ++i)
- buffer[i] &= ~(unsigned)mhdf_SET_RANGE_BIT;
+ if (create) {
+ rval = readUtil->create_entity_sets( count, buffer, 0, start_handle );
+ if (MB_SUCCESS != rval)
+ return error(rval);
- // create block of sets
- rval = readUtil->create_entity_sets( count,
- buffer,
- ID_FROM_HANDLE(start_handle),
- handle );
- if (MB_SUCCESS != rval) {
- mhdf_closeData( filePtr, meta_id, &status );
- return rval;
+ MBEntityHandle h = start_handle;
+ for (p = file_ids.const_pair_begin(); p != file_ids.const_pair_end(); ++p) {
+ long count = p->second - p->first + 1;
+ IDMap::iterator ins = idMap.insert( p->first, h, count );
+ if (ins == idMap.end())
+ return error(MB_FAILURE);
+ h += count;
}
-
- // We are careful to request start IDs such that the
- // resulting MBEntityHandles are always increasing.
- // We are relying on increasing handles, so make sure
- // that's what we get.
- if (!first && handle < start_handle) {
- readUtil->report_error( "Non-increasing handle space for mesh sets" );
- mhdf_closeData( filePtr, meta_id, &status );
- return MB_FAILURE;
- }
- first = false;
- start_handle = handle + count;
-
- insert_iter = setSet.range.insert( insert_iter, handle, handle + count - 1 );
}
- assert( setSet.range.size() == (size_t)num_sets );
- MBErrorCode result = MB_SUCCESS;
- if (have_data) {
- long data_len;
- hid_t data_id = mhdf_openSetData( filePtr, &data_len, &status );
- if (mhdf_isError(&status)) {
- readUtil->report_error( mhdf_message( &status ) );
- result = MB_FAILURE;
+ return MB_SUCCESS;
+}
+
+
+MBErrorCode ReadHDF5::read_contents( ContentReader& tool,
+ const MBRange& file_ids,
+ const long start_id,
+ const MBEntityHandle start_handle,
+ const long entity_count,
+ const long content_len,
+ const MBRange& ranged_ids_in )
+{
+ MBErrorCode rval;
+ mhdf_Status status;
+ if (file_ids.empty())
+ return MB_SUCCESS;
+
+ // things will get messed up if this isn't true
+ assert( ranged_ids_in.subtract( file_ids ).empty() );
+ assert( file_ids.front() >= (MBEntityHandle)start_id );
+ assert( file_ids.back() - start_id < (MBEntityHandle)entity_count );
+
+ const long avg_set_len = content_len / entity_count;
+ long sets_per_buffer = bufferSize / (sizeof(long) + (avg_set_len+1)*sizeof(MBEntityHandle));
+ // round to down multiple of 8 to avoid alignment issues
+ sets_per_buffer = 8 * (sets_per_buffer / 8);
+ if (sets_per_buffer < 10) // just in case there's one huge set
+ sets_per_buffer = 10;
+ long* offset_buffer = (long*)dataBuffer;
+ MBEntityHandle* content_buffer = (MBEntityHandle*)(offset_buffer + sets_per_buffer);
+ assert(bufferSize % sizeof(long) == 0);
+ long content_size = (MBEntityHandle*)(dataBuffer + bufferSize) - content_buffer;
+ assert(dataBuffer + bufferSize >= (char*)(content_buffer + content_size));
+
+ MBRange ranged_ids(ranged_ids_in);
+ MBEntityHandle h = start_handle;
+ MBRange sets(file_ids), range;
+ long prev_start = start_id;
+ long prev_count = 0;
+ while (!sets.empty()) {
+ long start = sets.front();
+ long count = sets.const_pair_begin()->second - start + 1;
+ long file_id = start;
+ if (count >= sets_per_buffer)
+ count = sets_per_buffer - 1; // less one because we need the previous offset
+ sets.erase( sets.begin(), sets.begin() + count );
+
+ if (start == start_id) {
+ offset_buffer[0] = -1;
+ tool.read_indices( 0, count, offset_buffer + 1, status );
}
+ else if (prev_start + prev_count == start) {
+ offset_buffer[0] = offset_buffer[prev_count];
+ tool.read_indices( start - start_id, count, offset_buffer + 1, status );
+ }
else {
- rval = read_set_contents( meta_id, data_id, data_len );
- mhdf_closeData( filePtr, data_id, &status );
- if (MB_SUCCESS != rval)
- result = rval;
+ tool.read_indices( start - start_id - 1, count+1, offset_buffer, status );
}
+ if (is_error(status))
+ return error(MB_FAILURE);
+ prev_start = start;
+ prev_count = count;
+
+ // read set contents
+ long remaining = count; //offset_buffer[count] - offset_buffer[0];
+ long offset = 0;
+ while (remaining) {
+ // Figure out how many set contents list we can fit in the
+ // buffer.
+ long read_count;
+ for (read_count = 1; read_count < remaining; ++read_count)
+ if (offset_buffer[read_count+offset+1] - offset_buffer[offset] >= content_size)
+ break;
+ // If no set contents list fit in the buffer, special case:
+ // iteratively read subsets of the content list.
+ if (read_count == 1) {
+ assert( 0 == content_size % 2 ); // otherwise problems with ranged data
+ long rem_contents = offset_buffer[offset+1] - offset_buffer[offset];
+ long set_offset = 0;
+ const bool ranged = !ranged_ids.empty() && ((long)ranged_ids.front() == start);
+ if (ranged)
+ ranged_ids.pop_front();
+ while (rem_contents) {
+ long content_count = std::min( content_size, rem_contents );
+ tool.read_contents( offset_buffer[offset]+1 + set_offset, content_count, content_buffer, status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+
+ rval = tool.store_data( h, file_id, content_buffer, content_count, ranged );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+
+ set_offset += content_count;
+ rem_contents -= content_count;
+ }
+ ++h;
+ ++file_id;
+ }
+ // Read contents for 'read_count' sets.
+ else if (long read_num = offset_buffer[read_count+offset] - offset_buffer[offset]){
+ tool.read_contents( offset_buffer[offset]+1, read_num,
+ content_buffer, status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ MBEntityHandle* content_iter = content_buffer;
+ for (long i = 0; i < read_count; ++i) {
+ long content_count = offset_buffer[i+1] - offset_buffer[i];
+ bool ranged = !ranged_ids.empty() && ((long)ranged_ids.front() == file_id);
+ rval = tool.store_data( h, file_id, content_iter, content_count, ranged );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+
+ content_iter += content_count;
+ ++file_id;
+ ++h;
+
+ if (ranged)
+ ranged_ids.pop_front();
+ }
+ }
+
+ remaining -= read_count;
+ offset += read_count;
+ }
}
+
+ return MB_SUCCESS;
+}
- if (have_children) {
- long data_len;
- hid_t data_id = mhdf_openSetChildren( filePtr, &data_len, &status );
- if (mhdf_isError(&status)) {
- readUtil->report_error( mhdf_message( &status ) );
- result = MB_FAILURE;
+
+
+MBErrorCode ReadHDF5::read_contents( const MBRange& set_file_ids,
+ MBEntityHandle start_handle,
+ hid_t set_meta_data_table,
+ hid_t set_contents_table,
+ long set_contents_length,
+ const MBRange& ranged_set_file_ids )
+{
+
+ class ReadSetContents : public ReadHDF5::ContentReader {
+ const hid_t metaHandle, contentHandle, handleType;
+ MBInterface *const mb;
+ const IDMap& idMap;
+ public:
+ ReadSetContents( hid_t meta, hid_t content, hid_t handle_type, MBInterface* iface,
+ const IDMap& id_map )
+ : metaHandle(meta), contentHandle(content),
+ handleType(handle_type), mb(iface), idMap(id_map)
+ {}
+ void read_indices( long offset, long count, long* buffer, mhdf_Status& status )
+ { mhdf_readSetContentEndIndices( metaHandle, offset, count, H5T_NATIVE_LONG, buffer, &status ); }
+ void read_contents( long offset, long count, MBEntityHandle* buffer, mhdf_Status& status )
+ { mhdf_readSetData( contentHandle, offset, count, handleType, buffer, &status ); }
+ MBErrorCode store_data( MBEntityHandle set, long, MBEntityHandle* array, long len, bool ranged )
+ {
+ if (ranged) {
+ assert(len % 2 == 0);
+ MBRange range;
+ convert_range_to_handle( array, len/2, idMap, range );
+ return mb->add_entities( set, range );
+ }
+ else {
+ assert(len >= 0);
+ size_t valid;
+ convert_id_to_handle( array, len, valid, idMap );
+ return mb->add_entities( set, array, valid );
+ }
}
- else {
- rval = read_parents_children( false, meta_id, data_id, data_len );
- mhdf_closeData( filePtr, data_id, &status );
- if (MB_SUCCESS != rval)
- result = rval;
+ };
+
+ ReadSetContents tool( set_meta_data_table, set_contents_table,
+ handleType, iFace, idMap );
+ return read_contents( tool, set_file_ids, fileInfo->sets.start_id, start_handle,
+ fileInfo->sets.count, set_contents_length, ranged_set_file_ids );
+}
+
+
+MBErrorCode ReadHDF5::read_children( const MBRange& set_file_ids,
+ MBEntityHandle start_handle,
+ hid_t set_meta_data_table,
+ hid_t set_contents_table,
+ long set_contents_length )
+{
+ class ReadSetChildren : public ReadHDF5::ContentReader {
+ const hid_t metaHandle, contentHandle, handleType;
+ MBInterface *const mb;
+ const IDMap& idMap;
+ public:
+ ReadSetChildren( hid_t meta, hid_t content, hid_t handle_type, MBInterface* iface,
+ const IDMap& id_map )
+ : metaHandle(meta), contentHandle(content),
+ handleType(handle_type), mb(iface), idMap(id_map)
+ {}
+ void read_indices( long offset, long count, long* buffer, mhdf_Status& status )
+ { mhdf_readSetChildEndIndices( metaHandle, offset, count, H5T_NATIVE_LONG, buffer, &status ); }
+ void read_contents( long offset, long count, MBEntityHandle* buffer, mhdf_Status& status )
+ { mhdf_readSetParentsChildren( contentHandle, offset, count, handleType, buffer, &status ); }
+ MBErrorCode store_data( MBEntityHandle set, long, MBEntityHandle* array, long len, bool ranged )
+ {
+ assert(!ranged);
+ size_t valid;
+ convert_id_to_handle( array, len, valid, idMap );
+ return mb->add_child_meshsets( set, array, valid );
}
+ };
+
+ MBRange empty;
+ ReadSetChildren tool( set_meta_data_table, set_contents_table,
+ handleType, iFace, idMap );
+ return read_contents( tool, set_file_ids, fileInfo->sets.start_id, start_handle,
+ fileInfo->sets.count, set_contents_length, empty );
+}
+
+MBErrorCode ReadHDF5::read_parents( const MBRange& set_file_ids,
+ MBEntityHandle start_handle,
+ hid_t set_meta_data_table,
+ hid_t set_contents_table,
+ long set_contents_length )
+{
+ class ReadSetParents : public ReadHDF5::ContentReader {
+ const hid_t metaHandle, contentHandle, handleType;
+ MBInterface *const mb;
+ const IDMap& idMap;
+ public:
+ ReadSetParents( hid_t meta, hid_t content, hid_t handle_type, MBInterface* iface,
+ const IDMap& id_map )
+ : metaHandle(meta), contentHandle(content),
+ handleType(handle_type), mb(iface), idMap(id_map)
+ {}
+ void read_indices( long offset, long count, long* buffer, mhdf_Status& status )
+ { mhdf_readSetParentEndIndices( metaHandle, offset, count, H5T_NATIVE_LONG, buffer, &status ); }
+ void read_contents( long offset, long count, MBEntityHandle* buffer, mhdf_Status& status )
+ { mhdf_readSetParentsChildren( contentHandle, offset, count, handleType, buffer, &status ); }
+ MBErrorCode store_data( MBEntityHandle set, long, MBEntityHandle* array, long len, bool ranged )
+ {
+ assert(!ranged);
+ size_t valid;
+ convert_id_to_handle( array, len, valid, idMap );
+ return mb->add_parent_meshsets( set, array, valid );
+ }
+ };
+
+ MBRange empty;
+ ReadSetParents tool( set_meta_data_table, set_contents_table,
+ handleType, iFace, idMap );
+ return read_contents( tool, set_file_ids, fileInfo->sets.start_id, start_handle,
+ fileInfo->sets.count, set_contents_length, empty );
+}
+
+static void copy_set_contents( int ranged,
+ const MBEntityHandle* contents,
+ long length,
+ MBRange& results )
+{
+ if (ranged) {
+ assert( length%2 == 0 );
+ MBRange::iterator hint = results.begin();
+ for (long i = 0; i < length; i += 2)
+ hint = results.insert( hint, contents[i], contents[i] + contents[i+1] - 1 );
}
+ else {
+ for (long i = 0; i < length; ++i)
+ results.insert( contents[i] );
+ }
+}
- if (have_parents) {
- long data_len;
- hid_t data_id = mhdf_openSetParents( filePtr, &data_len, &status );
- if (mhdf_isError(&status)) {
- readUtil->report_error( mhdf_message( &status ) );
- result = MB_FAILURE;
+
+MBErrorCode ReadHDF5::get_set_contents( const MBRange& sets, MBRange& file_ids )
+{
+ class GetContentList : public ReadHDF5::ContentReader {
+ const hid_t metaHandle, contentHandle, handleType;
+ MBRange *const resultList;
+ public:
+ GetContentList( hid_t meta, hid_t content, hid_t handle_type, MBRange* result_set )
+ : metaHandle(meta), contentHandle(content),
+ handleType(handle_type), resultList(result_set)
+ {}
+
+ void read_indices( long offset, long count, long* buffer, mhdf_Status& status )
+ { mhdf_readSetContentEndIndices( metaHandle, offset, count, H5T_NATIVE_LONG, buffer, &status ); }
+ void read_contents( long offset, long count, MBEntityHandle* buffer, mhdf_Status& status )
+ { mhdf_readSetData( contentHandle, offset, count, handleType, buffer, &status ); }
+ MBErrorCode store_data( MBEntityHandle set, long, MBEntityHandle* array, long len, bool ranged )
+ {
+ if (ranged) {
+ copy_set_contents( 1, array, len, *resultList );
+ }
+ else {
+ std::sort( array, array+len );
+ copy_sorted_file_ids( array, len, *resultList );
+ }
+ return MB_SUCCESS;
}
- else {
- rval = read_parents_children( true, meta_id, data_id, data_len );
- mhdf_closeData( filePtr, data_id, &status );
- if (MB_SUCCESS != rval)
- result = rval;
- }
+ };
+
+ MBErrorCode rval;
+ if (sets.empty())
+ return MB_SUCCESS;
+
+ mhdf_Status status;
+ long content_len;
+ hid_t meta, contents;
+ meta = mhdf_openSetMetaSimple( filePtr, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ contents = mhdf_openSetData( filePtr, &content_len, &status );
+ if (is_error(status)) {
+ mhdf_closeData( filePtr, meta, &status );
+ return error(MB_FAILURE);
}
+
+ MBEntityHandle junk;
+ MBRange ranged;
+ rval = read_sets( sets, meta, ranged, junk, false );
+ if (MB_SUCCESS != rval) {
+ mhdf_closeData( filePtr, meta, &status );
+ mhdf_closeData( filePtr, contents, &status );
+ return error(rval);
+ }
- mhdf_closeData( filePtr, meta_id, &status );
- return result;
+ GetContentList tool( meta, contents, handleType, &file_ids );
+ rval = read_contents( tool, sets, fileInfo->sets.start_id, junk,
+ fileInfo->sets.count, content_len, ranged );
+ mhdf_closeData( filePtr, meta, &status );
+ mhdf_closeData( filePtr, contents, &status );
+ return rval;
}
-MBErrorCode ReadHDF5::read_adjacencies( ElemSet& elems )
+
+MBErrorCode ReadHDF5::read_adjacencies( hid_t table, long table_len )
{
MBErrorCode rval;
mhdf_Status status;
- hid_t table;
- long data_len;
- int adj = mhdf_haveAdjacency( filePtr, elems.type2, &status );
- if (mhdf_isError(&status))
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
-
- if (!adj)
- return MB_SUCCESS;
-
- table = mhdf_openAdjacency( filePtr, elems.type2, &data_len, &status );
- if (mhdf_isError(&status))
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
-
MBEntityHandle* buffer = (MBEntityHandle*)dataBuffer;
size_t chunk_size = bufferSize / sizeof(MBEntityHandle);
- size_t remaining = data_len;
- size_t leading = 0;
+ size_t remaining = table_len;
+ size_t left_over = 0;
size_t offset = 0;
while (remaining)
{
- size_t count = remaining > chunk_size ? chunk_size : remaining;
- count -= leading;
+ size_t count = std::min( chunk_size, remaining );
+ count -= left_over;
remaining -= count;
- mhdf_readAdjacencyWithOpt( table, offset, count, handleType, buffer + leading,
+ mhdf_readAdjacencyWithOpt( table, offset, count, handleType, buffer + left_over,
ioProp, &status );
- if (mhdf_isError(&status))
- {
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, table, &status );
- return MB_FAILURE;
- }
+ if (is_error(status))
+ return error(MB_FAILURE);
MBEntityHandle* iter = buffer;
- MBEntityHandle* end = buffer + count + leading;
+ MBEntityHandle* end = buffer + count + left_over;
while (end - iter >= 3)
{
- rval = convert_id_to_handle( elems, iter, 1 );
- MBEntityHandle entity = *iter;
- MBEntityHandle count = *++iter;
- if (MB_SUCCESS != rval || count < 1)
- {
- assert(0);
- mhdf_closeData( filePtr, table, &status );
- return rval == MB_SUCCESS ? MB_FAILURE : rval;
+ MBEntityHandle h = idMap.find( *iter++ );
+ MBEntityHandle count2 = *iter++;
+ if (!h) {
+ iter += count2;
+ continue;
}
- ++iter;
-
- if (end < count + iter)
+
+ if (count2 < 1)
+ return error(MB_FAILURE);
+
+ if (end < count2 + iter)
{
iter -= 2;
break;
}
- rval = convert_id_to_handle( iter, count );
+ size_t valid;
+ convert_id_to_handle( iter, count2, valid, idMap );
+ rval = iFace->add_adjacencies( h, iter, valid, false );
if (MB_SUCCESS != rval)
- {
- assert(0);
- mhdf_closeData( filePtr, table, &status );
- return rval;
- }
-
- rval = iFace->add_adjacencies( entity, iter, count, false );
- if (MB_SUCCESS != rval)
- {
- assert(0);
- mhdf_closeData( filePtr, table, &status );
- return rval;
- }
-
- iter += count;
+ return error(rval);
+
+ iter += count2;
}
- leading = end - iter;
- memmove( buffer, iter, leading );
+ left_over = end - iter;
+ memmove( buffer, iter, left_over );
}
- assert(!leading); // unexpected truncation of data
+ assert(!left_over); // unexpected truncation of data
- mhdf_closeData( filePtr, table, &status );
- if (mhdf_isError(&status))
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
+ return MB_SUCCESS;
+}
+
+
+MBErrorCode ReadHDF5::read_tag( int tag_index )
+{
+ MBErrorCode rval;
+ mhdf_Status status;
+ MBTag tag = 0;
+ hid_t read_type;
+ rval = create_tag( fileInfo->tags[tag_index], tag, read_type );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+
+ if (fileInfo->tags[tag_index].have_sparse) {
+ hid_t handles[3];
+ long num_ent, num_val;
+ mhdf_openSparseTagData( filePtr,
+ fileInfo->tags[tag_index].name,
+ &num_ent, &num_val,
+ handles, &status );
+ if (is_error(status)) {
+ if (read_type) H5Tclose( read_type );
+ return error(MB_FAILURE);
+ }
+
+ if (fileInfo->tags[tag_index].size > 0)
+ rval = read_sparse_tag( tag, read_type, handles[0], handles[1], num_ent );
+ else
+ rval = read_var_len_tag( tag, read_type, handles[0], handles[1], handles[2], num_ent, num_val );
+
+ mhdf_closeData( filePtr, handles[0], &status );
+ if (MB_SUCCESS == rval && is_error(status))
+ rval = MB_FAILURE;
+ mhdf_closeData( filePtr, handles[1], &status );
+ if (MB_SUCCESS == rval && is_error(status))
+ rval = MB_FAILURE;
+ if (fileInfo->tags[tag_index].size <= 0) {
+ mhdf_closeData( filePtr, handles[2], &status );
+ if (MB_SUCCESS == rval && is_error(status))
+ rval = MB_FAILURE;
+ }
+ if (MB_SUCCESS != rval) {
+ if (read_type) H5Tclose( read_type );
+ return error(rval);
+ }
}
- return MB_SUCCESS;
+ for (int j = 0; j < fileInfo->tags[tag_index].num_dense_indices; ++j) {
+ long count;
+ const char* name = 0;
+ mhdf_EntDesc* desc;
+ int elem_idx = fileInfo->tags[tag_index].dense_elem_indices[j];
+ if (elem_idx == -2) {
+ desc = &fileInfo->sets;
+ name = mhdf_set_type_handle();
+ }
+ else if (elem_idx == -1) {
+ desc = &fileInfo->nodes;
+ name = mhdf_node_type_handle();
+ }
+ else if (elem_idx >= 0 && elem_idx < fileInfo->num_elem_desc) {
+ desc = &fileInfo->elems[elem_idx].desc;
+ name = fileInfo->elems[elem_idx].handle;
+ }
+
+ hid_t handle = mhdf_openDenseTagData( filePtr,
+ fileInfo->tags[tag_index].name,
+ name,
+ &count, &status );
+ if (is_error(status)) {
+ rval = error(MB_FAILURE);
+ break;
+ }
+
+ if (count > desc->count) {
+ readUtil->report_error( "Invalid data length for dense tag data: %s/%s\n",
+ name, fileInfo->tags[tag_index].name );
+ mhdf_closeData( filePtr, handle, &status );
+ rval = error(MB_FAILURE);
+ break;
+ }
+
+ rval = read_dense_tag( tag, read_type, handle, desc->start_id, count );
+ mhdf_closeData( filePtr, handle, &status );
+ if (MB_SUCCESS != rval)
+ break;
+ if (is_error(status)) {
+ rval = error(MB_FAILURE);
+ break;
+ }
+ }
+
+ if (read_type)
+ H5Tclose( read_type );
+ return rval;
}
+
+
+
-MBErrorCode ReadHDF5::read_tag( const char* name )
+
+MBErrorCode ReadHDF5::create_tag( const mhdf_TagDesc& info,
+ MBTag& handle,
+ hid_t& hdf_type )
{
MBErrorCode rval;
mhdf_Status status;
- std::string tag_type_name;
-
- mhdf_TagDataType mhdf_type; // Enum for tag data type
- int tag_size; // Size of tag
- int mhdf_storage; // TSTT storage type (dense vs. sparse)
- int have_default; // File contains default value for tag
- int have_global; // File contains global value for tag
- int have_sparse; // File contains sparse data table for tag
- hid_t hdf_type = 0; // Type to use when reading tag data.
- int elem_size; // Bytes required for one elem of array
- int array_size; // If tag is not opaque, the number of data per entity
- MBTag handle; // The handle for the tag
- MBDataType mb_type; // The MOAB data type for the data
MBTagType storage;
-
- // Get description of tag
- mhdf_getTagInfo( filePtr, name, &mhdf_type, &tag_size, &mhdf_storage,
- &have_default, &have_global, &have_sparse, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
- switch (mhdf_storage) {
+ MBDataType mb_type;
+ bool re_read_default = false;
+
+ switch (info.storage) {
case mhdf_DENSE_TYPE : storage = MB_TAG_DENSE ; break;
case mhdf_SPARSE_TYPE: storage = MB_TAG_SPARSE; break;
case mhdf_BIT_TYPE : storage = MB_TAG_BIT; break;
case mhdf_MESH_TYPE : storage = MB_TAG_MESH; break;
default:
- readUtil->report_error( "Invalid storage type for tag '%s': %d\n", name, mhdf_storage );
- return MB_FAILURE;
+ readUtil->report_error( "Invalid storage type for tag '%s': %d\n", info.name, info.storage );
+ return error(MB_FAILURE);
}
// Type-specific stuff
- switch (mhdf_type)
- {
- case mhdf_BITFIELD:
-
- if (!tag_size || tag_size > 8)
- {
- readUtil->report_error( "Invalid bit tag: class is MB_TAG_BIT, num bits = %d\n", tag_size );
- return MB_FAILURE;
- }
-
- elem_size = tag_size;
- tag_size = 1;
- array_size = 1;
- hdf_type = H5T_NATIVE_B8;
- mb_type = MB_TYPE_BIT;
- break;
-
- case mhdf_INTEGER:
-
- elem_size = sizeof(int);
- array_size = tag_size;
- hdf_type = H5T_NATIVE_INT;
- tag_size = elem_size * array_size;
- mb_type = MB_TYPE_INTEGER;
- break;
-
- case mhdf_FLOAT:
-
- elem_size = sizeof(double);
- array_size = tag_size;
- hdf_type = H5T_NATIVE_DOUBLE;
- tag_size = elem_size * array_size;
- mb_type = MB_TYPE_DOUBLE;
- break;
-
- case mhdf_BOOLEAN:
-
- elem_size = sizeof(int);
- array_size = tag_size;
- hdf_type = H5T_NATIVE_UINT;
- tag_size = elem_size * array_size;
- mb_type = MB_TYPE_INTEGER;
- break;
-
- case mhdf_ENTITY_ID:
-
- elem_size = sizeof(MBEntityHandle);
- array_size = tag_size;
- hdf_type = handleType;
- tag_size = elem_size * array_size;
- mb_type = MB_TYPE_HANDLE;
- break;
-
- case mhdf_OPAQUE:
- default:
+ if (info.type == mhdf_BITFIELD) {
+ if (info.size < 1 || info.size > 8)
+ {
+ readUtil->report_error( "Invalid bit tag: class is MB_TAG_BIT, num bits = %d\n", info.size );
+ return error(MB_FAILURE);
+ }
+ hdf_type = H5Tcopy(H5T_NATIVE_B8);
+ mb_type = MB_TYPE_BIT;
+ if (hdf_type < 0)
+ return error(MB_FAILURE);
+ }
+ else if (info.type == mhdf_OPAQUE) {
+ mb_type = MB_TYPE_OPAQUE;
- if (tag_size < 0) { // variable-length
- elem_size = 1;
- array_size = -1;
- }
- else {
- elem_size = tag_size;
- array_size = 1;
- }
- mb_type = MB_TYPE_OPAQUE;
- hdf_type = (hid_t)0;
+ // Check for user-provided type
+ MBTag type_handle;
+ std::string tag_type_name = "__hdf5_tag_type_";
+ tag_type_name += info.name;
+ rval = iFace->tag_get_handle( tag_type_name.c_str(), type_handle );
+ if (MB_SUCCESS == rval) {
+ rval = iFace->tag_get_data( type_handle, 0, 0, &hdf_type );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+ hdf_type = H5Tcopy( hdf_type );
+ re_read_default = true;
+ }
+ else if (MB_TAG_NOT_FOUND == rval) {
+ hdf_type = 0;
+ }
+ else
+ return error(rval);
- // Check for user-provided type
- MBTag type_handle;
- tag_type_name = "__hdf5_tag_type_";
- tag_type_name += name;
- rval = iFace->tag_get_handle( tag_type_name.c_str(), type_handle );
- if (MB_SUCCESS == rval)
- {
- rval = iFace->tag_get_data( type_handle, 0, 0, &hdf_type );
- if (MB_SUCCESS == rval)
- elem_size = H5Tget_size( hdf_type );
- else if (MB_TAG_NOT_FOUND != rval)
- return rval;
- }
- else if (MB_TAG_NOT_FOUND != rval)
- return rval;
-
- break;
+ if (hdf_type < 0)
+ return error(MB_FAILURE);
}
- if (tag_size < 0) // variable length
- tag_size = MB_VARIABLE_LENGTH;
+ else {
+ switch (info.type)
+ {
+ case mhdf_INTEGER:
+ hdf_type = H5T_NATIVE_INT;
+ mb_type = MB_TYPE_INTEGER;
+ break;
-
- // Create array type from base type if array
- if (array_size > 1)
- {
- hsize_t tmpsize = array_size;
+ case mhdf_FLOAT:
+ hdf_type = H5T_NATIVE_DOUBLE;
+ mb_type = MB_TYPE_DOUBLE;
+ break;
+
+ case mhdf_BOOLEAN:
+ hdf_type = H5T_NATIVE_UINT;
+ mb_type = MB_TYPE_INTEGER;
+ break;
+
+ case mhdf_ENTITY_ID:
+ hdf_type = handleType;
+ mb_type = MB_TYPE_HANDLE;
+ break;
+
+ default:
+ return error(MB_FAILURE);
+ }
+
+ if (info.size > 1) { // array
+ hsize_t tmpsize = info.size;
#if defined(H5Tarray_create_vers) && H5Tarray_create_vers > 1
- hdf_type = H5Tarray_create2( hdf_type, 1, &tmpsize );
+ hdf_type = H5Tarray_create2( hdf_type, 1, &tmpsize );
#else
- hdf_type = H5Tarray_create( hdf_type, 1, &tmpsize, NULL );
+ hdf_type = H5Tarray_create( hdf_type, 1, &tmpsize, NULL );
#endif
+ }
+ else {
+ hdf_type = H5Tcopy( hdf_type );
+ }
if (hdf_type < 0)
- return MB_FAILURE;
- }
+ return error(MB_FAILURE);
+ }
// If default or global/mesh value in file, read it.
- void *default_ptr = 0, *global_ptr = 0;
- int default_size = 0, global_size = 0;
- if (have_default || have_global)
+ if (info.default_value || info.global_value)
{
- if (array_size == -1) { // variable-length tag
- default_size = have_default;
- global_size = have_global;
+ if (re_read_default) {
+ mhdf_getTagValues( filePtr, info.name, hdf_type, info.default_value, info.global_value, &status );
+ if (mhdf_isError( &status ))
+ {
+ readUtil->report_error( mhdf_message( &status ) );
+ if (hdf_type) H5Tclose( hdf_type );
+ return error(MB_FAILURE);
+ }
}
- else {
- default_size = global_size = array_size;
- }
- assert( (default_size + global_size) * elem_size <= bufferSize );
- default_ptr = dataBuffer;
- global_ptr = dataBuffer + default_size*elem_size;
-
- mhdf_getTagValues( filePtr, name, hdf_type, default_ptr, global_ptr, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
-
if (MB_TYPE_HANDLE == mb_type) {
- if (have_default) {
- rval = convert_id_to_handle( (MBEntityHandle*)default_ptr, default_size );
- if (MB_SUCCESS != rval)
- have_default = 0;
+ if (info.default_value) {
+ rval = convert_id_to_handle( (MBEntityHandle*)info.default_value, info.default_value_size );
+ if (MB_SUCCESS != rval) {
+ if (hdf_type) H5Tclose( hdf_type );
+ return error(rval);
+ }
}
- if (have_global) {
- rval = convert_id_to_handle( (MBEntityHandle*)global_ptr, global_size );
- if (MB_SUCCESS != rval)
- have_global = 0;
+ if (info.global_value) {
+ rval = convert_id_to_handle( (MBEntityHandle*)info.global_value, info.global_value_size );
+ if (MB_SUCCESS != rval) {
+ if (hdf_type) H5Tclose( hdf_type );
+ return error(rval);
+ }
}
}
}
- global_size *= elem_size;
- default_size *= elem_size;
// Check if tag already exists
- rval = iFace->tag_get_handle( name, handle );
- if (MB_SUCCESS == rval)
- {
+ rval = iFace->tag_get_handle( info.name, handle );
+ if (MB_SUCCESS == rval) {
// If tag exists, make sure it is consistant with the type in the file
int curr_size;
MBDataType curr_type;
@@ -1372,250 +2179,169 @@
rval = iFace->tag_get_size( handle, curr_size );
if (MB_VARIABLE_DATA_LENGTH == rval)
curr_size = -1;
- else if (MB_SUCCESS != rval)
- return rval;
-
+ else if (MB_SUCCESS != rval) {
+ if (hdf_type) H5Tclose( hdf_type );
+ return error(rval);
+ }
+
rval = iFace->tag_get_data_type( handle, curr_type );
- if (MB_SUCCESS != rval)
- return rval;
+ if (MB_SUCCESS != rval) {
+ if (hdf_type) H5Tclose( hdf_type );
+ return error(rval);
+ }
rval = iFace->tag_get_type( handle, curr_store );
- if (MB_SUCCESS != rval)
- return rval;
+ if (MB_SUCCESS != rval) {
+ if (hdf_type) H5Tclose( hdf_type );
+ return error(rval);
+ }
- if ((curr_store != MB_TAG_BIT && curr_size != tag_size) || curr_type != mb_type ||
+ if ((curr_store != MB_TAG_BIT && curr_size != info.bytes) || curr_type != mb_type ||
((curr_store == MB_TAG_BIT || storage == MB_TAG_BIT) &&
curr_store != storage))
{
readUtil->report_error( "Tag type in file does not match type in "
- "database for \"%s\"\n", name );
- return MB_FAILURE;
+ "database for \"%s\"\n", info.name );
+ if (hdf_type) H5Tclose( hdf_type );
+ return error(MB_FAILURE);
}
}
// Create the tag if it doesn't exist
else if (MB_TAG_NOT_FOUND == rval)
{
- if (tag_size == MB_VARIABLE_LENGTH)
- rval = iFace->tag_create_variable_length( name, storage, mb_type,
- handle, default_ptr, default_size );
+ if (info.size < 0) {
+ size_t size = hdf_type ? H5Tget_size(hdf_type) : 1;
+ rval = iFace->tag_create_variable_length( info.name, storage, mb_type,
+ handle, info.default_value,
+ info.default_value_size * size );
+ }
else
- rval = iFace->tag_create( name, tag_size, storage, mb_type,
- handle, default_ptr );
- if (MB_SUCCESS != rval)
- return rval;
+ rval = iFace->tag_create( info.name, info.bytes, storage, mb_type,
+ handle, info.default_value );
+ if (MB_SUCCESS != rval) {
+ if (hdf_type) H5Tclose( hdf_type );
+ return error(rval);
+ }
}
// error
- else
- return rval;
+ else {
+ if (hdf_type) H5Tclose( hdf_type );
+ return error(rval);
+ }
- if (have_global) {
- rval = iFace->tag_set_data( handle, 0, 0, &global_ptr, &global_size );
- if (MB_SUCCESS != rval)
- return rval;
+ if (info.global_value) {
+ int type_size = hdf_type ? H5Tget_size(hdf_type) : 1;
+ int tag_size = info.global_value_size * type_size;
+ rval = iFace->tag_set_data( handle, 0, 0, &info.global_value, &tag_size );
+ if (MB_SUCCESS != rval) {
+ if (hdf_type) H5Tclose( hdf_type );
+ return error(rval);
+ }
}
- // Read tag data
- MBErrorCode tmp = MB_SUCCESS;
- if (have_sparse) {
- if (tag_size == MB_VARIABLE_LENGTH)
- tmp = read_var_len_tag( handle, hdf_type, mb_type == MB_TYPE_HANDLE );
- else
- tmp = read_sparse_tag( handle, hdf_type, tag_size, mb_type == MB_TYPE_HANDLE );
- }
- rval = read_dense_tag( handle, hdf_type, tag_size, mb_type == MB_TYPE_HANDLE );
-
-
- // If an array type, need to release the type object created above.
- if (array_size > 1)
- H5Tclose( hdf_type );
-
- return MB_SUCCESS == tmp ? rval : tmp;
+ return MB_SUCCESS;
}
-
MBErrorCode ReadHDF5::read_dense_tag( MBTag tag_handle,
hid_t hdf_read_type,
- size_t read_size,
- bool is_handle_type )
+ hid_t data,
+ long start_id,
+ long num_values )
{
- std::list<ElemSet>::iterator iter;
- const std::list<ElemSet>::iterator end = elemList.end();
mhdf_Status status;
- std::string name;
MBErrorCode rval;
- int have;
+ MBDataType mb_type;
- rval = iFace->tag_get_name( tag_handle, name );
- if (MB_SUCCESS != rval)
- return rval;
+ rval = iFace->tag_get_data_type( tag_handle, mb_type );
+ if (MB_SUCCESS != rval)
+ return error(rval);
- have = mhdf_haveDenseTag( filePtr, name.c_str(), nodeSet.type2, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
+ hsize_t read_size = 0;
+ if (mb_type == MB_TYPE_HANDLE) {
+ read_size = H5Tget_size( hdf_read_type );
+ if (!read_size)
+ return error(MB_FAILURE);
}
- if (have)
- {
- rval = read_dense_tag( nodeSet, tag_handle, hdf_read_type, read_size, is_handle_type );
- if (!rval)
- return rval;
- }
-
-
- have = mhdf_haveDenseTag( filePtr, name.c_str(), setSet.type2, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
-
- if (have)
- {
- rval = read_dense_tag( setSet, tag_handle, hdf_read_type, read_size, is_handle_type );
- if (!rval)
- return rval;
- }
-
-
- for (iter = elemList.begin(); iter != end; ++iter)
- {
- have = mhdf_haveDenseTag( filePtr, name.c_str(), iter->type2, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
+ // get actual entities read from file
+ MBRange file_ids;
+ IDMap::iterator l, u;
+ l = idMap.lower_bound( start_id );
+ u = idMap.lower_bound( start_id + num_values - 1 );
+ if (l != idMap.end() && start_id + num_values > l->begin) {
+ if (l == u) {
+ file_ids.insert( std::max(start_id, l->begin),
+ std::min(start_id + num_values, u->begin + u->count) - 1 );
}
-
- if (have)
- {
- rval = read_dense_tag( *iter, tag_handle, hdf_read_type, read_size, is_handle_type );
- if (!rval)
- return rval;
+ else {
+ file_ids.insert( std::max(start_id, l->begin), l->begin + l->count - 1 );
+ if (u != idMap.end() && u->begin < start_id + num_values)
+ file_ids.insert( u->begin, std::min( start_id + num_values, u->begin + u->count) - 1 );
+ for (++l; l != u; ++l)
+ file_ids.insert( l->begin, l->begin + l->count - 1 );
}
}
- return MB_SUCCESS;
-}
+ long buffer_size = bufferSize / read_size;
+ while (!file_ids.empty()) {
+ long first = file_ids.front();
+ long count = file_ids.const_pair_begin()->second - first + 1;
+ if (buffer_size < count)
+ count = buffer_size;
+ file_ids.erase( file_ids.begin(), file_ids.begin() + (count - 1) );
+
+ mhdf_readDenseTagWithOpt( data, first - start_id, count, hdf_read_type,
+ dataBuffer, ioProp, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
-
-MBErrorCode ReadHDF5::read_dense_tag( ElemSet& set,
- MBTag tag_handle,
- hid_t hdf_read_type,
- size_t read_size,
- bool is_handle_type )
-{
- mhdf_Status status;
- std::string name;
- MBErrorCode rval;
- long num_values;
-
- rval = iFace->tag_get_name( tag_handle, name );
- if (MB_SUCCESS != rval)
- return rval;
-
- hid_t data = mhdf_openDenseTagData( filePtr, name.c_str(),
- set.type2, &num_values, &status );
- if (mhdf_isError( &status ) )
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
-
- if ((unsigned long)num_values != set.range.size())
- {
- assert( 0 );
- return MB_FAILURE;
- }
-
- MBRange::const_iterator iter = set.range.begin();
- MBRange subrange;
-
- assert ((hdf_read_type == 0) || (H5Tget_size(hdf_read_type) == read_size));
- size_t chunk_size = bufferSize / read_size;
- size_t remaining = set.range.size();
- size_t offset = 0;
- while (remaining)
- {
- size_t count = remaining > chunk_size ? chunk_size : remaining;
- remaining -= count;
-
- MBRange::const_iterator stop = iter;
- stop += count;
- subrange.clear();
- subrange.merge( iter, stop );
- iter = stop;
-
- mhdf_readDenseTagWithOpt( data, offset, count, hdf_read_type, dataBuffer,
- ioProp, &status );
- offset += count;
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, data, &status );
- return MB_FAILURE;
- }
-
- if (is_handle_type)
- {
+ if (MB_TYPE_HANDLE == mb_type) {
rval = convert_id_to_handle( (MBEntityHandle*)dataBuffer, count * read_size / sizeof(MBEntityHandle) );
if (MB_SUCCESS != rval)
- {
- mhdf_closeData( filePtr, data, &status );
- return rval;
- }
+ return error(rval);
}
- rval = iFace->tag_set_data( tag_handle, subrange, dataBuffer );
+ MBRange ents;
+ ents.insert( idMap.find( first ), idMap.find( first + count - 1 ) );
+ rval = iFace->tag_set_data( tag_handle, ents, dataBuffer );
if (MB_SUCCESS != rval)
- {
- mhdf_closeData( filePtr, data, &status );
- return MB_FAILURE;
- }
+ return error(MB_FAILURE);
}
-
- mhdf_closeData( filePtr, data, &status );
- if (mhdf_isError( &status ) )
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
-
+
return MB_SUCCESS;
}
MBErrorCode ReadHDF5::read_sparse_tag( MBTag tag_handle,
hid_t hdf_read_type,
- size_t read_size,
- bool is_handle_type )
+ hid_t id_table,
+ hid_t value_table,
+ long num_values )
{
mhdf_Status status;
- std::string name;
MBErrorCode rval;
- long num_values, data_size;
- hid_t data[3];
- MBTagType mbtype;
- assert ((hdf_read_type == 0) || (H5Tget_size(hdf_read_type) == read_size));
+ MBDataType mbtype;
- rval = iFace->tag_get_name( tag_handle, name );
- if (MB_SUCCESS != rval)
- return rval;
+ rval = iFace->tag_get_data_type( tag_handle, mbtype );
+ if (MB_SUCCESS != rval)
+ return error(rval);
- rval = iFace->tag_get_type( tag_handle, mbtype );
- if (MB_SUCCESS != rval)
- return rval;
-
- mhdf_openSparseTagData( filePtr, name.c_str(), &num_values, &data_size, data, &status );
- if (mhdf_isError( &status ) )
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
+ int read_size;
+ rval = iFace->tag_get_size( tag_handle, read_size );
+ if (MB_SUCCESS != rval) // wrong function for variable-length tags
+ return error(rval);
+ if (MB_TYPE_BIT == mbtype)
+ read_size = (read_size + 7)/8; // convert bits to bytes, plus 7 for ceiling
+
+ if (hdf_read_type) { // if not opaque
+ hsize_t hdf_size = H5Tget_size( hdf_read_type );
+ if (hdf_size != (hsize_t)read_size)
+ return error(MB_FAILURE);
}
- // fixed-length tag
- assert( num_values == data_size );
+
+ const int handles_per_tag = read_size/sizeof(MBEntityHandle);
+
// Split buffer into two portions: one for handles and one for data.
// We want to read the same number of handles as data values for each
@@ -1623,7 +2349,7 @@
// pass as the size of the buffer over the sum of the size of a handle
// and value. Subtract off the size of one value so we reserve space
// for adjusting for data alignment.
- size_t chunk_size = (bufferSize - read_size) / (sizeof(MBEntityHandle) + read_size);
+ long chunk_size = (bufferSize - read_size) / (sizeof(MBEntityHandle) + read_size);
// Use the first half of the buffer for the handles.
MBEntityHandle* idbuf = (MBEntityHandle*)dataBuffer;
@@ -1635,80 +2361,99 @@
// Make sure the above calculations are correct
assert( databuf + chunk_size*read_size < dataBuffer + bufferSize );
- size_t remaining = (size_t)num_values;
- size_t offset = 0;
+ long remaining = num_values;
+ long offset = 0;
while (remaining)
{
- size_t count = remaining > chunk_size ? chunk_size : remaining;
+ long count = std::min( chunk_size, remaining );
+ long next_offset = offset + count;
remaining -= count;
- mhdf_readSparseTagEntitiesWithOpt( data[0], offset, count, handleType, idbuf,
+ mhdf_readSparseTagEntitiesWithOpt( id_table, offset, count, handleType, idbuf,
ioProp, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- return MB_FAILURE;
- }
+ if (is_error(status))
+ return error(MB_FAILURE);
- mhdf_readSparseTagValuesWithOpt( data[1], offset, count, hdf_read_type,
- databuf, ioProp, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- return MB_FAILURE;
- }
-
- offset += count;
-
rval = convert_id_to_handle( idbuf, count );
if (MB_SUCCESS != rval)
- {
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- return rval;
- }
-
- if (is_handle_type)
- {
- rval = convert_id_to_handle( (MBEntityHandle*)databuf, count * read_size / sizeof(MBEntityHandle) );
- if (MB_SUCCESS != rval)
+ return error(rval);
+
+ // Find contiguous blocks of values to read.
+ // (convert_id_to_handle will return zero-valued handles for entities
+ // not read from the file--i.e. values to skip).
+ long i = 0, j;
+ for (;;) {
+ // skip initial zeros
+ while (i < count && 0 == idbuf[i])
+ ++i;
+ // if no more, stop
+ if (i == count)
+ break;
+ // advance to end of range of non-zero handles
+ j = i +1;
+ while (j < count && 0 != idbuf[j])
+ ++j;
+
+ // if we've reached the end and the chunk is fairly small,
+ // shift to the front of the buffer and read more to avoid
+ // small data reads when blocks get split due to the buffer
+ // size
+ if (j == count && 2*i >= count && remaining > count) {
+ long keep = j - i;
+ memmove( idbuf, idbuf + i, sizeof(MBEntityHandle)*keep );
+ long count2 = std::min( remaining - keep, count - keep );
+ mhdf_readSparseTagEntitiesWithOpt( id_table, next_offset, count2, handleType,
+ idbuf+keep, ioProp, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ offset += i;
+ next_offset += count2;
+ remaining -= count2;
+ i = 0;
+
+ rval = convert_id_to_handle( idbuf + keep, count2 );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+
+ j = keep;
+ while (j < count && 0 != idbuf[j])
+ ++j;
+ }
+
+ // read tag values
+ mhdf_readSparseTagValuesWithOpt( value_table, offset + i, j - i,
+ hdf_read_type, databuf + i*read_size,
+ ioProp, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+
+ if (MB_TYPE_HANDLE == mbtype) {
+ rval = convert_id_to_handle( (MBEntityHandle*)databuf + i*handles_per_tag,
+ (j-i) * handles_per_tag );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+ }
+
+/*** FIX ME - need to do one at a time for BIT tags! This is stupid. ***/
+ if (mbtype == MB_TYPE_BIT)
{
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- return rval;
+ rval = MB_SUCCESS;
+ for ( ; MB_SUCCESS == rval && i < j; ++i)
+ rval = iFace->tag_set_data( tag_handle, idbuf + i, 1, databuf + i );
}
- }
-
-/*** FIX ME - need to do one at a time for BIT tags! This is stupid. ***/
- if (mbtype == MB_TAG_BIT)
- {
- rval = MB_SUCCESS;
- for (size_t i = 0; MB_SUCCESS == rval && i < count; ++i)
- rval = iFace->tag_set_data( tag_handle, idbuf + i, 1, databuf + i );
- }
- else
- {
- rval = iFace->tag_set_data( tag_handle, idbuf, count, databuf );
- }
- if (MB_SUCCESS != rval)
- {
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- return rval;
- }
- }
+ else
+ {
+ rval = iFace->tag_set_data( tag_handle, idbuf + i, j - i, databuf + i*read_size );
+ i = j;
+ }
+ if (MB_SUCCESS != rval)
+ return error(rval);
+ } // for(ever)
+
+
+ offset = next_offset;
+ } // while(remaining)
- mhdf_closeData( filePtr, data[0], &status );
- if (mhdf_isError( &status ) )
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, data[1], &status );
- if (mhdf_isError( &status ) )
- readUtil->report_error( mhdf_message( &status ) );
-
return MB_SUCCESS;
}
@@ -1717,50 +2462,58 @@
MBErrorCode ReadHDF5::read_var_len_tag( MBTag tag_handle,
hid_t hdf_read_type,
- bool is_handle_type )
+ hid_t ent_table,
+ hid_t val_table,
+ hid_t off_table,
+ long num_entities,
+ long num_values )
{
+ std::vector<char> tmp_buffer;
mhdf_Status status;
- std::string name;
MBErrorCode rval;
- long num_values, num_data;
- hid_t data[3];
- MBTagType mbtype;
- // hdf_read_type is NULL (zero) for opaque tag data.
- long elem_size = hdf_read_type ? H5Tget_size( hdf_read_type ) : 1;
- if (elem_size < 1) // invalid type handle?
- return MB_FAILURE;
+ MBDataType mbtype;
- rval = iFace->tag_get_name( tag_handle, name );
- if (MB_SUCCESS != rval)
- return rval;
+ rval = iFace->tag_get_data_type( tag_handle, mbtype );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+
+ // can't do variable-length bit tags
+ if (MB_TYPE_BIT == mbtype)
+ return error(MB_VARIABLE_DATA_LENGTH);
+
+ // if here, MOAB tag must be variable-length
+ int mbsize;
+ if (MB_VARIABLE_DATA_LENGTH != iFace->tag_get_size( tag_handle, mbsize )) {
+ assert(false);
+ return error(MB_VARIABLE_DATA_LENGTH);
+ }
- rval = iFace->tag_get_type( tag_handle, mbtype );
- if (MB_SUCCESS != rval)
- return rval;
+ int read_size;
+ if (hdf_read_type) {
+ hsize_t hdf_size = H5Tget_size( hdf_read_type );
+ if (hdf_size < 1)
+ return error(MB_FAILURE);
+ read_size = hdf_size;
+ }
+ else {
+ // opaque
+ read_size = 1;
+ }
- mhdf_openSparseTagData( filePtr, name.c_str(), &num_values, &num_data, data, &status );
- if (mhdf_isError( &status ) )
- {
- readUtil->report_error( mhdf_message( &status ) );
- return MB_FAILURE;
- }
-
- // Subdivide buffer into 5 chunks:
+ // Subdivide buffer into 4 chunks:
// Be careful of order so alignment is valid
- // 1) pointer array (input for MOAB)
- // 2) offset array (read from file)
- // 3) entity handles
- // 4) tag sizes (calculated from file data)
- // 5) tag data
- const size_t avg_data_size = (num_data * elem_size) / num_values;
- const size_t per_ent_size = sizeof(void*) + sizeof(long) + sizeof(MBEntityHandle) + sizeof(int);
- long num_ent = bufferSize / (per_ent_size + 2*avg_data_size);
+ // 1) pointer array (input for MOAB) / offset array (read from file)
+ // 2) entity handles (read as file IDs and converted to handles)
+ // 3) tag sizes (calculated from file data)
+ // 4) tag data
+ const long avg_data_size = (num_values * read_size) / num_entities;
+ const long per_ent_size = sizeof(long) + sizeof(MBEntityHandle) + sizeof(int);
+ long num_ent = bufferSize / (per_ent_size + avg_data_size + avg_data_size/2);
if (num_ent == 0)
num_ent = bufferSize / 4 / sizeof(void*);
- const size_t data_buffer_size = (bufferSize - num_ent * per_ent_size) / elem_size;
- const void** const pointer_buffer = reinterpret_cast<const void**>(dataBuffer);
- long* const end_idx_buffer = reinterpret_cast<long*>(pointer_buffer + num_ent);
- char* handle_buffer_start = reinterpret_cast<char*>(end_idx_buffer + num_ent);
+ const long data_buffer_size = (bufferSize - num_ent * per_ent_size) / read_size;
+ long* const end_idx_buffer = reinterpret_cast<long*>(dataBuffer);
+ char* handle_buffer_start = reinterpret_cast<char*>(end_idx_buffer + num_ent+1);
if (((size_t)handle_buffer_start) % sizeof(MBEntityHandle))
handle_buffer_start += sizeof(MBEntityHandle) - ((size_t)handle_buffer_start);
MBEntityHandle* const handle_buffer = reinterpret_cast<MBEntityHandle*>(handle_buffer_start);
@@ -1769,312 +2522,218 @@
// do num_ent blocks of entities
- long remaining = num_values;
+ long remaining = num_entities;
long offset = 0;
- long data_offset = 0;
+ long prev_end_idx = -1;
+ long prev_end = 0;
while (remaining) {
- const long count = remaining < num_ent ? remaining : num_ent;
+ const long count = std::min( remaining, num_ent );
+ long next_offset = offset + count;
remaining -= count;
-
+
// read entity IDs
assert_range( handle_buffer, count * sizeof(MBEntityHandle) );
- mhdf_readSparseTagEntitiesWithOpt( data[0], offset, count, handleType,
+ mhdf_readSparseTagEntitiesWithOpt( ent_table, offset, count, handleType,
handle_buffer, ioProp, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- mhdf_closeData( filePtr, data[2], &status );
- return MB_FAILURE;
- }
+ if (is_error(status))
+ return error(MB_FAILURE);
+
// convert entity ID to MBEntityHandle
rval = convert_id_to_handle( handle_buffer, count );
if (MB_SUCCESS != rval)
- {
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- mhdf_closeData( filePtr, data[2], &status );
- return rval;
- }
- // read end index of tag value
- assert_range( end_idx_buffer, count * sizeof(long) );
- mhdf_readSparseTagIndicesWithOpt( data[2], offset, count, H5T_NATIVE_LONG,
- end_idx_buffer, ioProp, &status );
- if (mhdf_isError( &status ))
- {
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- mhdf_closeData( filePtr, data[2], &status );
- return MB_FAILURE;
- }
- // update entity offset
- offset += count;
-
- char* pointer = data_buffer;
- long finished = 0;
- while (finished < count) {
+ return error(rval);
+
+ // Find contiguous blocks of values to read.
+ // (convert_id_to_handle will return zero-valued handles for entities
+ // not read from the file--i.e. tag values to skip).
+ long i = 0, j;
+ for (;;) {
+ // skip initial zeros
+ while (i < count && 0 == handle_buffer[i])
+ ++i;
+ // if no more, stop
+ if (i == count)
+ break;
+ // advance to end of range of non-zero handles
+ j = i +1;
+ while (j < count && 0 != handle_buffer[j])
+ ++j;
+
+ // if we've reached the end and the chunk is fairly small,
+ // shift to the front of the buffer and read more to avoid
+ // small data reads when blocks get split due to the buffer
+ // size
+ if (j == count && 2*i >= count && remaining > count) {
+ long keep = j - i;
+ memmove( handle_buffer, handle_buffer + i, sizeof(MBEntityHandle)*keep );
+ // read more entity IDs
+ long count2 = std::min( remaining - keep, count - keep );
+ mhdf_readSparseTagEntitiesWithOpt( ent_table, next_offset, count2, handleType,
+ handle_buffer+keep, ioProp, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+ offset += i;
+ next_offset += count2;
+ remaining -= count2;
+ i = 0;
+
+ rval = convert_id_to_handle( handle_buffer + keep, count2 );
+ if (MB_SUCCESS != rval)
+ return error(rval);
- // iterate over entities until we have enough to fill the data buffer
- long i = finished;
- long prev_end_idx = data_offset - 1;
- for (; i < count && end_idx_buffer[i] - data_offset < (long)data_buffer_size; ++i) {
- // calculate tag size for entity
- const int size = (end_idx_buffer[i] - prev_end_idx);
- if (size < 0 || (long)size != (end_idx_buffer[i] - prev_end_idx)) {
- readUtil->report_error( "Invalid end index in variable length tag data for tag: \"%s\"", name.c_str() );
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- mhdf_closeData( filePtr, data[2], &status );
- return MB_FAILURE;
- }
- assert_range( size_buffer + i - finished, sizeof(int) );
- size_buffer[i-finished] = size * elem_size;
- assert_range( pointer_buffer + i - finished, sizeof(void*) );
- pointer_buffer[i-finished] = pointer;
- assert_range( pointer_buffer[i-finished], size_buffer[i - finished] );
- pointer += size_buffer[i-finished];
- prev_end_idx = end_idx_buffer[i];
+ j = keep;
+ while (j < count && 0 != handle_buffer[j])
+ ++j;
}
-
- const size_t num_val = prev_end_idx - data_offset + 1;
- if (num_val) {
- // read data
- assert( num_val <= data_buffer_size );
- assert_range( data_buffer, num_val * elem_size );
- mhdf_readSparseTagValuesWithOpt( data[1], data_offset, num_val,
- hdf_read_type, data_buffer,
- ioProp, &status );
- if (mhdf_isError( &status )) {
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- mhdf_closeData( filePtr, data[2], &status );
- return MB_FAILURE;
+
+ // Read end-indices for each tagged entity. Also need the
+ // end of the previous entity. If no previous entity, then -1.
+ long remaining_ent = j - i;
+ if (offset + i == prev_end) {
+ end_idx_buffer[0] = prev_end_idx;
+ mhdf_readSparseTagIndicesWithOpt( off_table, offset + i,
+ remaining_ent, H5T_NATIVE_LONG,
+ end_idx_buffer + 1, ioProp, &status );
+ }
+ else {
+ mhdf_readSparseTagIndicesWithOpt( off_table, offset + i - 1,
+ remaining_ent + 1, H5T_NATIVE_LONG,
+ end_idx_buffer, ioProp, &status );
+ }
+ if (is_error(status))
+ return error(MB_FAILURE);
+ prev_end = offset + i + remaining_ent;
+
+
+ prev_end_idx = end_idx_buffer[0];
+ long* idx_buffer = end_idx_buffer + 1;
+ while (remaining_ent) {
+ // Count the subset of remaining_ent entities for which the
+ // concatentated tag data will fit in the data buffer.
+ long tag_count = 0;
+ while (tag_count < remaining_ent &&
+ idx_buffer[tag_count] - prev_end_idx < data_buffer_size)
+ ++tag_count;
+
+ // If the tag value for a single entity doesn't fit in the buffer,
+ // then we need to allocate a temporary buffer for it.
+ long val_count;
+ char* memptr = data_buffer;
+ if (tag_count == 0) {
+ tag_count = 1;
+ val_count = idx_buffer[0] - prev_end_idx;
+ tmp_buffer.resize(val_count * read_size);
+ memptr = &tmp_buffer[0];
}
- data_offset += num_val;
-
- if (is_handle_type) {
- rval = convert_id_to_handle( reinterpret_cast<MBEntityHandle*>(data_buffer), num_val );
- if (MB_SUCCESS != rval) {
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- mhdf_closeData( filePtr, data[2], &status );
- return rval;
- }
+ else {
+ val_count = idx_buffer[tag_count-1] - prev_end_idx;
}
- // put data in tags
- rval = iFace->tag_set_data( tag_handle, handle_buffer + finished, i - finished, pointer_buffer, size_buffer );
- if (MB_SUCCESS != rval) {
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- mhdf_closeData( filePtr, data[2], &status );
- return rval;
- }
- finished = i;
- }
- else if (finished < i) { // zero-length tag values???
- finished = i;
- }
- // if tag value to big for buffer
- else {
- const int size = (end_idx_buffer[i] - prev_end_idx);
- std::vector<char*> tmp_buffer( size * elem_size );
- mhdf_readSparseTagValuesWithOpt( data[1], data_offset, size,
- hdf_read_type, &tmp_buffer[0],
- ioProp, &status );
- if (mhdf_isError( &status )) {
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- mhdf_closeData( filePtr, data[2], &status );
- return MB_FAILURE;
+ // Read the tag data
+ mhdf_readSparseTagValues( val_table, prev_end_idx + 1,
+ val_count, hdf_read_type, memptr, &status );
+ if (is_error(status))
+ return error(MB_FAILURE);
+
+ if (MB_TYPE_HANDLE == mbtype) {
+ rval = convert_id_to_handle( (MBEntityHandle*)memptr, val_count );
+ if (MB_SUCCESS != rval)
+ return error(rval);
}
- data_offset += size;
- if (is_handle_type) {
- rval = convert_id_to_handle( reinterpret_cast<MBEntityHandle*>(&tmp_buffer[0]), size );
- if (MB_SUCCESS != rval) {
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- mhdf_closeData( filePtr, data[2], &status );
- return rval;
- }
+ // Calculate sizes from end indices
+ size_buffer[0] = read_size * (idx_buffer[0] - prev_end_idx);
+ for (long k = 1; k < tag_count; ++k)
+ size_buffer[k] = read_size * (idx_buffer[k] - idx_buffer[k-1]);
+ // save prev_end_index for next iteration because it will
+ // get overwritten in the buffer next.
+ prev_end_idx = idx_buffer[tag_count-1];
+ // store pointers to individual tag values in end_idx_buffer
+ assert(sizeof(long) == sizeof(void*));
+ const void** ptr_buffer = reinterpret_cast<const void**>(idx_buffer);
+ const char* ptr_iter = memptr;
+ ptr_buffer[0] = ptr_iter;
+ ptr_iter += size_buffer[0];
+ for (long k = 1; k < tag_count; ++k) {
+ ptr_buffer[k] = ptr_iter;
+ ptr_iter += size_buffer[k];
}
+
+ // Pass data to MOAB to store for each tag
+ rval = iFace->tag_set_data( tag_handle, handle_buffer+i, tag_count,
+ ptr_buffer, size_buffer );
+ if (MB_SUCCESS != rval)
+ return error(rval);
+ remaining_ent -= tag_count;
+ i += tag_count;
+ idx_buffer += tag_count;
+ }
- pointer_buffer[0] = &tmp_buffer[0];
- size_buffer[0] = size * elem_size;
- rval = iFace->tag_set_data( tag_handle, handle_buffer + i, 1, pointer_buffer, size_buffer );
- if (MB_SUCCESS != rval) {
- mhdf_closeData( filePtr, data[0], &status );
- mhdf_closeData( filePtr, data[1], &status );
- mhdf_closeData( filePtr, data[2], &status );
- return rval;
- }
-
- prev_end_idx = end_idx_buffer[i];
- ++finished;
- }
- }
- }
+ } // for(ever)
+
+
+ offset = next_offset;
+ } // while(remaining)
- mhdf_closeData( filePtr, data[0], &status );
- if (mhdf_isError( &status ) )
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, data[1], &status );
- if (mhdf_isError( &status ) )
- readUtil->report_error( mhdf_message( &status ) );
- mhdf_closeData( filePtr, data[2], &status );
- if (mhdf_isError( &status ) )
- readUtil->report_error( mhdf_message( &status ) );
-
return MB_SUCCESS;
}
-MBErrorCode ReadHDF5::convert_id_to_handle( const ElemSet& elems,
- MBEntityHandle* array,
+MBErrorCode ReadHDF5::convert_id_to_handle( MBEntityHandle* array,
size_t size )
{
- MBEntityHandle offset = elems.first_id;
- MBEntityHandle last = offset + elems.range.size();
- for (MBEntityHandle *const end = array + size; array != end; ++array)
- {
- if (*array >= last || *array < (MBEntityHandle)offset)
- return MB_FAILURE;
- MBRange:: const_iterator iter = elems.range.begin();
- iter += *array - offset;
- *array = *iter;
- }
-
+ convert_id_to_handle( array, size, idMap );
return MB_SUCCESS;
}
-MBErrorCode ReadHDF5::convert_id_to_handle( MBEntityHandle* array,
- size_t size )
+void ReadHDF5::convert_id_to_handle( MBEntityHandle* array,
+ size_t size,
+ const RangeMap<long,MBEntityHandle>& id_map )
{
- MBEntityHandle offset = 1;
- MBEntityHandle last = 0;
- ElemSet* set = 0;
- std::list<ElemSet>::iterator iter;
- const std::list<ElemSet>::iterator i_end = elemList.end();
+ for (MBEntityHandle* const end = array + size; array != end; ++array)
+ *array = id_map.find( *array );
+}
- for (MBEntityHandle *const end = array + size; array != end; ++array)
- {
- // special case for ZERO
- if (!*array)
- continue;
-
- if (nodeSet.first_id && (*array < offset || *array >= last))
- {
- offset = nodeSet.first_id;
- last = offset + nodeSet.range.size();
- set = &nodeSet;
+void ReadHDF5::convert_id_to_handle( MBEntityHandle* array,
+ size_t size, size_t& new_size,
+ const RangeMap<long,MBEntityHandle>& id_map )
+{
+ RangeMap<long,MBEntityHandle>::const_iterator it;
+ new_size = 0;
+ for (size_t i = 0; i < size; ++i) {
+ it = id_map.lower_bound( array[i] );
+ if (it != id_map.end() && it->begin <= (long)array[i])
+ array[new_size++] = it->value + (array[i] - it->begin);
+ }
+}
+
+void ReadHDF5::convert_range_to_handle( const MBEntityHandle* ranges,
+ size_t num_ranges,
+ const RangeMap<long,MBEntityHandle>& id_map,
+ MBRange& merge )
+{
+ RangeMap<long,MBEntityHandle>::iterator it = id_map.begin();
+ for (size_t i = 0; i < num_ranges; ++i) {
+ long id = ranges[2*i];
+ const long end = id + ranges[2*i+1];
+ it = id_map.lower_bound( it, id_map.end(), id );
+ if (id < it->begin)
+ id = it->begin;
+ const long off = id - it->begin;
+ while (id < end) {
+ long count = std::min( it->count - off, end - id );
+ merge.insert( it->value + off, it->value + off + count - 1 );
+ id += count;
+ if (id < end)
+ ++it;
}
- if (setSet.first_id && (*array < offset || *array >= last))
- {
- offset = setSet.first_id;
- last = offset + setSet.range.size();
- set = &setSet;
- }
- iter = elemList.begin();
- while (*array < offset || *array >= last)
- {
- if (iter == i_end)
- {
- return MB_FAILURE;
- }
-
- set = &*iter;
- offset = set->first_id;
- last = offset + set->range.size();
- ++iter;
- }
-
- MBRange:: const_iterator riter = set->range.begin();
- riter += *array - offset;
- *array = *riter;
}
-
- return MB_SUCCESS;
}
MBErrorCode ReadHDF5::convert_range_to_handle( const MBEntityHandle* array,
size_t num_ranges,
MBRange& range )
{
- const MBEntityHandle *const end = array + 2*num_ranges;
- MBEntityHandle offset = 1;
- MBEntityHandle last = 0;
- ElemSet* set = 0;
- std::list<ElemSet>::iterator iter;
- const std::list<ElemSet>::iterator i_end = elemList.end();
- MBEntityHandle start = *(array++);
- MBEntityHandle count = *(array++);
-
- while (true)
- {
- if (nodeSet.first_id && (start < offset || start >= last))
- {
- offset = nodeSet.first_id;
- last = offset + nodeSet.range.size();
- set = &nodeSet;
- }
- if (setSet.first_id && (start < offset || start >= last))
- {
- offset = setSet.first_id;
- last = offset + setSet.range.size();
- set = &setSet;
- }
- iter = elemList.begin();
- while (start < offset || start >= last)
- {
- if (iter == i_end)
- {
- return MB_FAILURE;
- }
-
- set = &*iter;
- offset = set->first_id;
- last = offset + set->range.size();
- ++iter;
- }
-
- MBEntityHandle s_rem = set->range.size() - (start - offset);
- MBEntityHandle num = count > s_rem ? s_rem : count;
- MBRange::const_iterator riter = set->range.begin();
- riter += (start - offset);
- MBRange::const_iterator rend = riter;
- rend += num;
- assert( riter != rend );
- MBEntityHandle h_start = *riter++;
- MBEntityHandle h_prev = h_start;
-
- while (riter != rend)
- {
- if (h_prev + 1 != *riter)
- {
- range.insert( h_start, h_prev );
- h_start = *riter;
- }
- h_prev = *riter;
- ++riter;
- }
- range.insert( h_start, h_prev );
-
- count -= num;
- start += num;
- if (count == 0)
- {
- if (array == end)
- break;
-
- start = *(array++);
- count = *(array++);
- }
- }
-
+ convert_range_to_handle( array, num_ranges, idMap, range );
return MB_SUCCESS;
}
@@ -2089,7 +2748,7 @@
if (mhdf_isError( &status ))
{
readUtil->report_error( "%s", mhdf_message( &status ) );
- return MB_FAILURE;
+ return error(MB_FAILURE);
}
qa_list.resize(qa_len);
for (int i = 0; i < qa_len; i++)
Modified: MOAB/trunk/ReadHDF5.hpp
===================================================================
--- MOAB/trunk/ReadHDF5.hpp 2009-04-30 21:01:58 UTC (rev 2861)
+++ MOAB/trunk/ReadHDF5.hpp 2009-04-30 21:02:48 UTC (rev 2862)
@@ -30,6 +30,7 @@
#include "MBReadUtilIface.hpp"
#include "MBRange.hpp"
#include "MBReaderIface.hpp"
+#include "RangeMap.hpp"
class MB_DLL_EXPORT ReadHDF5 : public MBReaderIface
{
@@ -54,27 +55,27 @@
int num_set_tag_values );
protected:
- MBErrorCode load_file_impl( MBEntityHandle file_set,
- bool use_mpio );
+ MBErrorCode load_file_impl( MBEntityHandle file_set,
+ const FileOptions& opts );
+ MBErrorCode load_file_partial( MBEntityHandle file_set,
+ const char* set_tag_name,
+ const int* set_tag_values,
+ int num_set_tag_values,
+ const FileOptions& opts );
+
private:
MBErrorCode init();
- //! Range of entities, grouped by type
- struct ElemSet
- {
- //! The range of entities.
- MBRange range;
- //! The type of the entities in the range
- MBEntityType type;
- //! The type handle for the mhdf library.
- const char* type2;
- //! The first Id allocated by the mhdf library. Entities in range have sequential IDs.
- MBEntityHandle first_id;
- };
+ inline int is_error( mhdf_Status& status ) {
+ int i;
+ if ((i = mhdf_isError(&status)))
+ readUtil->report_error( mhdf_message(&status) );
+ return i;
+ }
//! The size of the data buffer (<code>dataBuffer</code>).
- const int bufferSize;
+ int bufferSize;
//! A memory buffer to use for all I/O operations.
char* dataBuffer;
@@ -84,35 +85,55 @@
//! The file handle from the mhdf library
mhdf_FileHandle filePtr;
+ //! File summary
+ mhdf_FileDesc* fileInfo;
+
+ //! Map from File ID to MOAB handle
+ typedef RangeMap< long, MBEntityHandle > IDMap;
+ IDMap idMap;
+
//! Cache pointer to read util
MBReadUtilIface* readUtil;
- //! The list elements to export.
- std::list<ElemSet> elemList;
-
- //! The list of nodes to export
- ElemSet nodeSet;
-
- //! The list of sets to export
- ElemSet setSet;
-
//! The type of an MBEntityHandle
hid_t handleType;
//! read/write property handle
hid_t ioProp;
-
- //! Read node coordinates.
- MBErrorCode read_nodes( );
+ MBErrorCode read_nodes( const MBRange& node_file_ids );
+
+ // Read elements in fileInfo->elems[index]
+ MBErrorCode read_elems( int index );
+
+ // Read subset of elements in fileInfo->elems[index]
+ MBErrorCode read_elems( int index, const MBRange& file_ids );
+
//! Read element connectivity.
- MBErrorCode read_elems( const char* elem_group );
+ MBErrorCode read_elems( const mhdf_ElemDesc& elems, const MBRange& file_ids );
+
+ // Read connectivity data for a list of element file ids.
+ // passing back the file IDs for the element connectivity
+ // w/out actually creating any elements in MOAB.
+ MBErrorCode read_elems( int index, const MBRange& element_file_ids, MBRange& node_file_ids );
+
+ // Scan all elements in group. For each element for which all vertices
+ // are contained in idMap (class member), read the element. All new
+ // elements are added to idMap.
+ MBErrorCode read_node_adj_elems( const mhdf_ElemDesc& group );
+
+ // Scan all elements in specified file table. For each element for
+ // which all vertices are contained in idMap (class member), read the
+ // element. All new elements are added to idMap.
+ MBErrorCode read_node_adj_elems( const mhdf_ElemDesc& group,
+ hid_t connectivity_handle );
+
//! Read poly(gons|hedra)
- MBErrorCode read_poly( const char* elem_group );
+ MBErrorCode read_poly( const mhdf_ElemDesc& elems, const MBRange& file_ids );
//! Read sets
- MBErrorCode read_sets( );
+ MBErrorCode read_sets( const MBRange& set_file_ids );
//! Read set contents
MBErrorCode read_set_contents( hid_t set_description_handle,
@@ -125,48 +146,219 @@
hid_t set_contents_handle,
const unsigned long data_len );
- //! Read element adjacencies
- MBErrorCode read_adjacencies( ElemSet& for_this_set );
+ MBErrorCode read_adjacencies( hid_t adjacency_table,
+ long table_length );
+
//! Create tag and read all data.
- MBErrorCode read_tag( const char* name );
+ MBErrorCode read_tag( int index );
+ //! Create new tag or varify type matches existing tag
+ MBErrorCode create_tag( const mhdf_TagDesc& info, MBTag& handle, hid_t& type );
+
+
//! Read dense tag for all entities
MBErrorCode read_dense_tag( MBTag tag_handle,
hid_t hdf_read_type,
- size_t read_size,
- bool is_handle_type );
+ hid_t data_table,
+ long start_id,
+ long count );
- //! Read dense tag for specified entity set
- MBErrorCode read_dense_tag( ElemSet& set,
- MBTag tag_handle,
- hid_t hdf_read_type,
- size_t read_size,
- bool is_handle_type );
//! Read sparse tag for all entities.
MBErrorCode read_sparse_tag( MBTag tag_handle,
hid_t hdf_read_type,
- size_t read_size,
- bool is_handle_type );
+ hid_t ent_table,
+ hid_t val_table,
+ long num_entities );
//! Read variable-length tag for all entities.
MBErrorCode read_var_len_tag( MBTag tag_handle,
hid_t hdf_read_type,
- bool is_handle_type );
+ hid_t ent_table,
+ hid_t val_table,
+ hid_t off_table,
+ long num_entities,
+ long num_values );
MBErrorCode read_qa( MBEntityHandle file_set );
- MBErrorCode convert_id_to_handle( const ElemSet& elems_in_this_set,
- MBEntityHandle* in_out_array,
- size_t array_length );
-
MBErrorCode convert_id_to_handle( MBEntityHandle* in_out_array,
size_t array_length );
MBErrorCode convert_range_to_handle( const MBEntityHandle* ranges,
size_t num_ranges,
MBRange& merge );
+
+ static
+ void convert_id_to_handle( MBEntityHandle* in_out_array,
+ size_t array_length,
+ const RangeMap<long,MBEntityHandle>& id_map );
+
+ static
+ void convert_id_to_handle( MBEntityHandle* in_out_array,
+ size_t array_length,
+ size_t& array_length_out,
+ const RangeMap<long,MBEntityHandle>& id_map );
+
+ static
+ void convert_range_to_handle( const MBEntityHandle* ranges,
+ size_t num_ranges,
+ const RangeMap<long,MBEntityHandle>& id_map,
+ MBRange& merge );
+
+ /**\brief Search for entities with specified tag values
+ *
+ *\param tag_index Index into info->tags specifying which tag to search.
+ *\param sorted_values List of tag values to check for, in ascending sorted
+ * order.
+ *\param file_ids_out File IDs for entities with specified tag values.
+ */
+ MBErrorCode search_tag_values( int tag_index,
+ const std::vector<int>& sorted_values,
+ MBRange& file_ids_out );
+
+ /**\brief Search a table of tag data for a specified set of values.
+ *
+ * Search a table of tag values, returning the indices into the table
+ * at which matches were found.
+ *\param info Summary of data contained in file.
+ *\param tag_table HDF5/mhdf handle for tag values
+ *\param table_size Number of values in table
+ *\param sorted_values Sorted list of values to search for.
+ *\param value_indices Output: Offsets into the table of data at which
+ * matching values were found.
+ */
+ MBErrorCode search_tag_values( hid_t tag_table,
+ unsigned long table_size,
+ const std::vector<int>& sorted_values,
+ std::vector<long>& value_indices );
+
+ /**\brief Get the file IDs for nodes and elements contained in sets.
+ *
+ * Read the contents for the specified sets and return the file IDs
+ * of all nodes and elements contained within those sets.
+ *\param sets Container of file IDs designating entity sets.
+ *\param file_ids Output: File IDs of entities contained in sets.
+ */
+ MBErrorCode get_set_contents( const MBRange& sets, MBRange& file_ids );
+
+ /** Given a list of file IDs for entity sets, find all child sets
+ * (at any depth) and append them to the MBRange of file IDs.
+ */
+ MBErrorCode read_child_sets( MBRange& sets_in_out );
+
+ /** Find all sets containing one or more entities read from the file
+ * and added to idMap
+ */
+ MBErrorCode find_sets_containing( MBRange& sets_out );
+
+ /**\brief Read sets from file into MOAB for partial read of file.
+ *
+ * Given the file IDs for entity sets (sets_in) and elements and
+ * nodes (id_map), read in all sets containing any of the elements
+ * or nodes and all sets that are (recursively) children of any
+ * other set to be read (those in sets_in or those containging any
+ * already-read element or node.)
+ *\param sets_in File IDs for sets to read (unconditionally)
+ */
+ MBErrorCode read_sets_partial( const MBRange& sets_in );
+
+ /** Find file IDs of sets containing any entities in the passed id_map */
+ MBErrorCode find_sets_containing( hid_t meta_handle,
+ hid_t content_handle,
+ long content_len,
+ MBRange& file_ids );
+
+ /** Recursively find all child sets contained in file */
+ MBErrorCode read_child_ids_recursive( MBRange& file_ids,
+ hid_t meta_handle,
+ hid_t child_handle );
+
+ /** Given a list of file IDs for entity sets, read the list of
+ * file IDs for all child entity sets.
+ */
+ MBErrorCode read_child_ids( const MBRange& set_file_ids,
+ hid_t meta_handle,
+ hid_t child_handle,
+ MBRange& child_file_ids );
+
+ /**\brief Create sets
+ *
+ * For the list of entity sets designated by the file IDs contained
+ * in file_ids, instantiate the sets in MOAB with consecutive handles.
+ *
+ *\param info Summary of data contained in the file.
+ *\param file_ids List of file IDs designating which sets will be read.
+ *\param set_meta_handle HDF5/mhdf handle for set metadata table.
+ *\parma id_map Map from file IDs to MBEntityHandle for entities read
+ * from file. Sets created by this function will be appended.
+ *\param ranged_file_ids_out This function will add to this container
+ * the file IDs for any sets for which the contents are
+ * stored using ranged compression (any set for which
+ * mhdf_SET_RANGE_BIT is set in the flags.)
+ */
+ MBErrorCode read_sets( const MBRange& file_ids,
+ hid_t set_meta_handle,
+ MBRange& ranged_file_ids_out,
+ MBEntityHandle& start_handle,
+ bool create = true );
+
+ MBErrorCode read_contents( const MBRange& set_file_ids,
+ MBEntityHandle start_handle,
+ hid_t set_meta_data_table,
+ hid_t set_contents_table,
+ long set_contents_length,
+ const MBRange& ranged_set_file_ids );
+
+ MBErrorCode read_parents( const MBRange& set_file_ids,
+ MBEntityHandle start_handle,
+ hid_t set_meta_data_table,
+ hid_t set_parents_table,
+ long set_parents_length );
+
+ MBErrorCode read_children( const MBRange& set_file_ids,
+ MBEntityHandle start_handle,
+ hid_t set_meta_data_table,
+ hid_t set_children_table,
+ long set_children_length );
+
+
+ class ContentReader {
+ public:
+ virtual void
+ read_indices( long, long, long*, mhdf_Status& ) = 0;
+
+ virtual void
+ read_contents( long, long, MBEntityHandle*, mhdf_Status& ) = 0;
+
+ virtual MBErrorCode
+ store_data( MBEntityHandle, long file_id, MBEntityHandle*, long len, bool ranged = false ) = 0;
+ };
+
+ /**\brief Read end-indexed variable length handle lists such as
+ * set parents, set children, set contents, and old-format
+ * poly connectivity.
+ *
+ * Read the contents of each entity set from the file, and add to
+ * the corresponding entity set in MOAB any contained entities that
+ * have been read from the file.
+ *\param file_ids File IDs of entity sets to read.
+ *\param start_id ID of first entity in table.
+ *\param start_handle MBEntityHandle for first entity set in file_ids
+ * (assumes all sets in file_ids have sequential
+ * handles.)
+ *\param set_content_len Length of set contents table.
+ *\param ranged_file_ids Subset of file_ids for which set contents
+ * are stored in ranged format.
+ */
+ MBErrorCode read_contents( ContentReader& tool,
+ const MBRange& file_ids,
+ const long start_id,
+ const MBEntityHandle start_handle,
+ const long num_sets,
+ const long set_content_len,
+ const MBRange& ranged_file_ids );
};
#endif
More information about the moab-dev
mailing list