MOAB: Mesh Oriented datABase  (version 5.2.1)
SparseTag.cpp
Go to the documentation of this file.
00001 /**
00002  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003  * storing and accessing finite element mesh data.
00004  *
00005  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
00006  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007  * retains certain rights in this software.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  */
00015 
00016 #include <memory.h>
00017 #include <algorithm>
00018 
00019 #include "SparseTag.hpp"
00020 #include "moab/Range.hpp"
00021 #include "TagCompare.hpp"
00022 #include "SysUtil.hpp"
00023 #include "SequenceManager.hpp"
00024 #include "moab/Error.hpp"
00025 #include "moab/ErrorHandler.hpp"
00026 #include "moab/CN.hpp"
00027 
00028 namespace moab
00029 {
00030 
00031 SparseTag::SparseTag( const char* name, int size, DataType type, const void* default_value )
00032     : TagInfo( name, size, type, default_value, size )
00033 {
00034 }
00035 
00036 SparseTag::~SparseTag()
00037 {
00038     release_all_data( 0, 0, true );
00039 }
00040 
00041 TagType SparseTag::get_storage_type() const
00042 {
00043     return MB_TAG_SPARSE;
00044 }
00045 
00046 ErrorCode SparseTag::release_all_data( SequenceManager*, Error*, bool )
00047 {
00048     for( MapType::iterator i = mData.begin(); i != mData.end(); ++i )
00049         mAllocator.destroy( i->second );
00050     mData.clear();
00051     return MB_SUCCESS;
00052 }
00053 
00054 ErrorCode SparseTag::set_data( Error*, EntityHandle entity_handle, const void* data )
00055 {
00056 #ifdef MOAB_HAVE_UNORDERED_MAP
00057     MapType::iterator iter = mData.find( entity_handle );
00058 #else
00059     MapType::iterator iter = mData.lower_bound( entity_handle );
00060 #endif
00061 
00062     // Data space already exists
00063     if( iter != mData.end() && iter->first == entity_handle ) memcpy( iter->second, data, get_size() );
00064     // We need to make some data space
00065     else
00066     {
00067         void* new_data = allocate_data( entity_handle, iter, false );
00068         memcpy( new_data, data, get_size() );
00069     }
00070 
00071     return MB_SUCCESS;
00072 }
00073 
00074 ErrorCode SparseTag::get_data_ptr( EntityHandle entity_handle, const void*& ptr, bool allocate ) const
00075 {
00076     MapType::const_iterator iter = mData.find( entity_handle );
00077 
00078     if( iter != mData.end() )
00079         ptr = iter->second;
00080     else if( get_default_value() && allocate )
00081         ptr = const_cast< SparseTag* >( this )->allocate_data( entity_handle, iter, allocate );
00082     else
00083         return MB_FAILURE;
00084 
00085     return MB_SUCCESS;
00086 }
00087 
00088 ErrorCode SparseTag::get_data( Error* /* error */, EntityHandle entity_handle, void* data ) const
00089 {
00090     const void* ptr = 0;
00091     ErrorCode rval  = get_data_ptr( entity_handle, ptr, false );
00092     if( MB_SUCCESS == rval )
00093     {
00094         memcpy( data, ptr, get_size() );
00095         return rval;
00096     }
00097     else if( get_default_value() )
00098     {
00099         memcpy( data, get_default_value(), get_size() );
00100         return MB_SUCCESS;
00101     }
00102     else
00103         return MB_TAG_NOT_FOUND;
00104 }
00105 
00106 ErrorCode SparseTag::remove_data( Error* /* error */, EntityHandle entity_handle )
00107 {
00108     MapType::iterator i = mData.find( entity_handle );
00109     if( i == mData.end() ) return MB_TAG_NOT_FOUND;
00110 
00111     mAllocator.destroy( i->second );
00112     mData.erase( i );
00113 
00114     return MB_SUCCESS;
00115 }
00116 
00117 ErrorCode SparseTag::get_data( const SequenceManager*, Error* /* error */, const EntityHandle* entities,
00118                                size_t num_entities, void* data ) const
00119 {
00120     ErrorCode rval;
00121     unsigned char* ptr = reinterpret_cast< unsigned char* >( data );
00122     for( size_t i = 0; i < num_entities; ++i, ptr += get_size() )
00123     {
00124         rval = get_data( NULL, entities[i], ptr );
00125         if( MB_SUCCESS != rval ) return rval;
00126     }
00127 
00128     return MB_SUCCESS;
00129 }
00130 
00131 ErrorCode SparseTag::get_data( const SequenceManager*, Error* /* error */, const Range& entities, void* data ) const
00132 {
00133     ErrorCode rval;
00134     unsigned char* ptr = reinterpret_cast< unsigned char* >( data );
00135     Range::const_iterator i;
00136     for( i = entities.begin(); i != entities.end(); ++i, ptr += get_size() )
00137     {
00138         rval = get_data( NULL, *i, ptr );
00139         if( MB_SUCCESS != rval ) return rval;
00140     }
00141 
00142     return MB_SUCCESS;
00143 }
00144 
00145 ErrorCode SparseTag::get_data( const SequenceManager*, Error* /* error */, const EntityHandle* entities,
00146                                size_t num_entities, const void** pointers, int* data_lengths ) const
00147 {
00148     if( data_lengths )
00149     {
00150         int len = get_size();
00151         SysUtil::setmem( data_lengths, &len, sizeof( int ), num_entities );
00152     }
00153 
00154     ErrorCode rval = MB_SUCCESS, rval_tmp;
00155     for( size_t i = 0; i < num_entities; ++i, ++pointers )
00156     {
00157         rval_tmp = get_data_ptr( entities[i], *pointers );
00158         if( MB_SUCCESS != rval_tmp && get_default_value() ) { *pointers = get_default_value(); }
00159         else if( MB_SUCCESS != rval_tmp )
00160         {
00161             return MB_TAG_NOT_FOUND;
00162         }
00163     }
00164 
00165     return rval;
00166 }
00167 
00168 ErrorCode SparseTag::get_data( const SequenceManager*, Error* /* error */, const Range& entities, const void** pointers,
00169                                int* data_lengths ) const
00170 {
00171     if( data_lengths )
00172     {
00173         int len = get_size();
00174         SysUtil::setmem( data_lengths, &len, sizeof( int ), entities.size() );
00175     }
00176 
00177     ErrorCode rval = MB_SUCCESS, rval_tmp;
00178     Range::const_iterator i;
00179     for( i = entities.begin(); i != entities.end(); ++i, ++pointers )
00180     {
00181         rval_tmp = get_data_ptr( *i, *pointers );
00182         if( MB_SUCCESS != rval_tmp && get_default_value() ) { *pointers = get_default_value(); }
00183         else if( MB_SUCCESS != rval_tmp )
00184         {
00185             return MB_TAG_NOT_FOUND;
00186         }
00187     }
00188 
00189     return rval;
00190 }
00191 
00192 ErrorCode SparseTag::set_data( SequenceManager* seqman, Error* /* error */, const EntityHandle* entities,
00193                                size_t num_entities, const void* data )
00194 {
00195     ErrorCode rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval );
00196 
00197     const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data );
00198     for( size_t i = 0; i < num_entities; ++i, ptr += get_size() )
00199     {
00200         rval = set_data( NULL, entities[i], ptr );MB_CHK_ERR( rval );
00201     }
00202 
00203     return MB_SUCCESS;
00204 }
00205 
00206 ErrorCode SparseTag::set_data( SequenceManager* seqman, Error* /* error */, const Range& entities, const void* data )
00207 {
00208     ErrorCode rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval );
00209 
00210     const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data );
00211     Range::const_iterator i;
00212     for( i = entities.begin(); i != entities.end(); ++i, ptr += get_size() )
00213         if( MB_SUCCESS != ( rval = set_data( NULL, *i, ptr ) ) ) return rval;
00214 
00215     return MB_SUCCESS;
00216 }
00217 
00218 ErrorCode SparseTag::set_data( SequenceManager* seqman, Error* /* error */, const EntityHandle* entities,
00219                                size_t num_entities, void const* const* pointers, const int* lengths )
00220 {
00221     ErrorCode rval = validate_lengths( NULL, lengths, num_entities );MB_CHK_ERR( rval );
00222 
00223     rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval );
00224 
00225     for( size_t i = 0; i < num_entities; ++i, ++pointers )
00226     {
00227         rval = set_data( NULL, entities[i], *pointers );MB_CHK_ERR( rval );
00228     }
00229 
00230     return MB_SUCCESS;
00231 }
00232 
00233 ErrorCode SparseTag::set_data( SequenceManager* seqman, Error* /* error */, const Range& entities,
00234                                void const* const* pointers, const int* lengths )
00235 {
00236     ErrorCode rval = validate_lengths( NULL, lengths, entities.size() );MB_CHK_ERR( rval );
00237 
00238     rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval );
00239 
00240     Range::const_iterator i;
00241     for( i = entities.begin(); i != entities.end(); ++i, ++pointers )
00242     {
00243         rval = set_data( NULL, *i, *pointers );MB_CHK_ERR( rval );
00244     }
00245 
00246     return MB_SUCCESS;
00247 }
00248 
00249 ErrorCode SparseTag::clear_data( SequenceManager* seqman, Error* /* error */, const EntityHandle* entities,
00250                                  size_t num_entities, const void* value_ptr, int value_len )
00251 {
00252     if( value_len && value_len != get_size() )
00253     {
00254         MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name()
00255                                                           << " of size " << value_len );
00256     }
00257 
00258     ErrorCode rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval );
00259 
00260     for( size_t i = 0; i < num_entities; ++i )
00261     {
00262         rval = set_data( NULL, entities[i], value_ptr );MB_CHK_ERR( rval );
00263     }
00264 
00265     return MB_SUCCESS;
00266 }
00267 
00268 ErrorCode SparseTag::clear_data( SequenceManager* seqman, Error* /* error */, const Range& entities,
00269                                  const void* value_ptr, int value_len )
00270 {
00271     if( value_len && value_len != get_size() )
00272     {
00273         MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name()
00274                                                           << " of size " << value_len );
00275     }
00276 
00277     ErrorCode rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval );
00278 
00279     Range::const_iterator i;
00280     for( i = entities.begin(); i != entities.end(); ++i )
00281     {
00282         rval = set_data( NULL, *i, value_ptr );MB_CHK_ERR( rval );
00283     }
00284 
00285     return MB_SUCCESS;
00286 }
00287 
00288 ErrorCode SparseTag::remove_data( SequenceManager*, Error* /* error */, const EntityHandle* entities,
00289                                   size_t num_entities )
00290 {
00291     ErrorCode rval;
00292     for( size_t i = 0; i < num_entities; ++i )
00293     {
00294         rval = remove_data( NULL, entities[i] );
00295         if( MB_SUCCESS != rval ) return rval;
00296     }
00297 
00298     return MB_SUCCESS;
00299 }
00300 
00301 ErrorCode SparseTag::remove_data( SequenceManager*, Error* /* error */, const Range& entities )
00302 {
00303     for( Range::const_iterator i = entities.begin(); i != entities.end(); ++i )
00304         if( MB_SUCCESS != remove_data( NULL, *i ) ) return MB_TAG_NOT_FOUND;
00305 
00306     return MB_SUCCESS;
00307 }
00308 
00309 ErrorCode SparseTag::tag_iterate( SequenceManager* seqman, Error* /* error */, Range::iterator& iter,
00310                                   const Range::iterator& end, void*& data_ptr, bool allocate )
00311 {
00312     // Note: We are asked to returning a block of contiguous storage
00313     //       for some block of contiguous handles for which the tag
00314     //       storage is also contiguous. As sparse tag storage is
00315     //       never contiguous, all we can do is return a pointer to the
00316     //       data for the first entity.
00317 
00318     // If asked for nothing, successfully return nothing.
00319     if( iter == end ) return MB_SUCCESS;
00320 
00321     // Note: get_data_ptr will return the default value if the
00322     //       handle is not found, so test to make sure that the
00323     //       handle is valid.
00324     ErrorCode rval = seqman->check_valid_entities( NULL, &*iter, 1 );MB_CHK_ERR( rval );
00325 
00326     // Get pointer to tag storage for entity pointed to by iter
00327     const void* ptr = NULL;
00328     rval            = get_data_ptr( *iter, ptr );
00329     if( MB_SUCCESS == rval )
00330         data_ptr = const_cast< void* >( ptr );
00331     else if( get_default_value() && allocate )
00332     {
00333         ptr      = allocate_data( *iter, mData.end() );
00334         data_ptr = const_cast< void* >( ptr );
00335     }
00336     else
00337     {
00338         // If allocation was not requested, need to increment the iterator so that
00339         // the count can be computed properly
00340         if( get_default_value() && !allocate ) ++iter;
00341         // return not_found(get_name(), *iter);
00342     }
00343 
00344     // Increment iterator and return
00345     ++iter;
00346     return MB_SUCCESS;
00347 }
00348 
00349 template < class Container >
00350 static inline void get_tagged( const SparseTag::MapType& mData, EntityType type, Container& output_range )
00351 {
00352     SparseTag::MapType::const_iterator iter;
00353     typename Container::iterator hint = output_range.begin();
00354     if( MBMAXTYPE == type )
00355     {
00356         for( iter = mData.begin(); iter != mData.end(); ++iter )
00357             hint = output_range.insert( hint, iter->first );
00358     }
00359     else
00360     {
00361 #ifdef MOAB_HAVE_UNORDERED_MAP
00362         for( iter = mData.begin(); iter != mData.end(); ++iter )
00363             if( TYPE_FROM_HANDLE( iter->first ) == type ) hint = output_range.insert( hint, iter->first );
00364 #else
00365         iter                                   = mData.lower_bound( FIRST_HANDLE( type ) );
00366         SparseTag::MapType::const_iterator end = mData.lower_bound( LAST_HANDLE( type ) + 1 );
00367         for( ; iter != end; ++iter )
00368             hint = output_range.insert( hint, iter->first );
00369 #endif
00370     }
00371 }
00372 
00373 template < class Container >
00374 static inline void get_tagged( const SparseTag::MapType& mData, Range::const_iterator begin, Range::const_iterator end,
00375                                Container& output_range )
00376 {
00377     typename Container::iterator hint = output_range.begin();
00378     for( Range::const_iterator i = begin; i != end; ++i )
00379         if( mData.find( *i ) != mData.end() ) hint = output_range.insert( hint, *i );
00380 }
00381 
00382 template < class Container >
00383 static inline void get_tagged( const SparseTag::MapType& mData, Container& entities, EntityType type,
00384                                const Range* intersect )
00385 {
00386     if( !intersect )
00387         get_tagged< Container >( mData, type, entities );
00388     else if( MBMAXTYPE == type )
00389         get_tagged< Container >( mData, intersect->begin(), intersect->end(), entities );
00390     else
00391     {
00392         std::pair< Range::iterator, Range::iterator > r = intersect->equal_range( type );
00393         get_tagged< Container >( mData, r.first, r.second, entities );
00394     }
00395 }
00396 
00397 //! Gets all entity handles that match a type and tag
00398 ErrorCode SparseTag::get_tagged_entities( const SequenceManager*, Range& output_range, EntityType type,
00399                                           const Range* intersect ) const
00400 {
00401     get_tagged( mData, output_range, type, intersect );
00402     return MB_SUCCESS;
00403 }
00404 
00405 //! Gets all entity handles that match a type and tag
00406 ErrorCode SparseTag::num_tagged_entities( const SequenceManager*, size_t& output_count, EntityType type,
00407                                           const Range* intersect ) const
00408 {
00409     InsertCount counter( output_count );
00410     get_tagged( mData, counter, type, intersect );
00411     output_count = counter.end();
00412     return MB_SUCCESS;
00413 }
00414 
00415 ErrorCode SparseTag::find_entities_with_value(
00416 #ifdef MOAB_HAVE_UNORDERED_MAP
00417     const SequenceManager* seqman,
00418 #else
00419     const SequenceManager*,
00420 #endif
00421     Error* /* error */, Range& output_entities, const void* value, int value_bytes, EntityType type,
00422     const Range* intersect_entities ) const
00423 {
00424     if( value_bytes && value_bytes != get_size() )
00425     {
00426         MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name()
00427                                                           << " of size " << value_bytes );
00428     }
00429 
00430     MapType::const_iterator iter, end;
00431 #ifdef MOAB_HAVE_UNORDERED_MAP
00432     if( intersect_entities )
00433     {
00434         std::pair< Range::iterator, Range::iterator > r;
00435         if( type == MBMAXTYPE )
00436         {
00437             r.first  = intersect_entities->begin();
00438             r.second = intersect_entities->end();
00439         }
00440         else
00441         {
00442             r = intersect_entities->equal_range( type );
00443         }
00444 
00445         find_map_values_equal( *this, value, get_size(), r.first, r.second, mData, output_entities );
00446     }
00447     else if( type == MBMAXTYPE )
00448     {
00449         find_tag_values_equal( *this, value, get_size(), mData.begin(), mData.end(), output_entities );
00450     }
00451     else
00452     {
00453         Range tmp;
00454         seqman->get_entities( type, tmp );
00455         find_map_values_equal( *this, value, get_size(), tmp.begin(), tmp.end(), mData, output_entities );
00456     }
00457 #else
00458     if( intersect_entities )
00459     {
00460         for( Range::const_pair_iterator p = intersect_entities->begin(); p != intersect_entities->end(); ++p )
00461         {
00462             iter = mData.lower_bound( p->first );
00463             end = mData.upper_bound( p->second );
00464             find_tag_values_equal( *this, value, get_size(), iter, end, output_entities );
00465         }
00466     }
00467     else
00468     {
00469         if( type == MBMAXTYPE )
00470         {
00471             iter = mData.begin();
00472             end = mData.end();
00473         }
00474         else
00475         {
00476             iter = mData.lower_bound( CREATE_HANDLE( type, MB_START_ID ) );
00477             end = mData.upper_bound( CREATE_HANDLE( type, MB_END_ID ) );
00478         }
00479         find_tag_values_equal( *this, value, get_size(), iter, end, output_entities );
00480     }
00481 #endif
00482 
00483     return MB_SUCCESS;
00484 }
00485 
00486 bool SparseTag::is_tagged( const SequenceManager*, EntityHandle h ) const
00487 {
00488     return mData.find( h ) != mData.end();
00489 }
00490 
00491 ErrorCode SparseTag::get_memory_use( const SequenceManager*, unsigned long& total, unsigned long& per_entity ) const
00492 
00493 {
00494     per_entity = get_size() + 4 * sizeof( void* );
00495     total      = ( mData.size() * per_entity ) + sizeof( *this ) + TagInfo::get_memory_use();
00496 
00497     return MB_SUCCESS;
00498 }
00499 
00500 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines