Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
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*,
00118                                Error* /* error */,
00119                                const EntityHandle* entities,
00120                                size_t num_entities,
00121                                void* data ) const
00122 {
00123     ErrorCode rval;
00124     unsigned char* ptr = reinterpret_cast< unsigned char* >( data );
00125     for( size_t i = 0; i < num_entities; ++i, ptr += get_size() )
00126     {
00127         rval = get_data( NULL, entities[i], ptr );
00128         if( MB_SUCCESS != rval ) return rval;
00129     }
00130 
00131     return MB_SUCCESS;
00132 }
00133 
00134 ErrorCode SparseTag::get_data( const SequenceManager*, Error* /* error */, const Range& entities, void* data ) const
00135 {
00136     ErrorCode rval;
00137     unsigned char* ptr = reinterpret_cast< unsigned char* >( data );
00138     Range::const_iterator i;
00139     for( i = entities.begin(); i != entities.end(); ++i, ptr += get_size() )
00140     {
00141         rval = get_data( NULL, *i, ptr );
00142         if( MB_SUCCESS != rval ) return rval;
00143     }
00144 
00145     return MB_SUCCESS;
00146 }
00147 
00148 ErrorCode SparseTag::get_data( const SequenceManager*,
00149                                Error* /* error */,
00150                                const EntityHandle* entities,
00151                                size_t num_entities,
00152                                const void** pointers,
00153                                int* data_lengths ) const
00154 {
00155     if( data_lengths )
00156     {
00157         int len = get_size();
00158         SysUtil::setmem( data_lengths, &len, sizeof( int ), num_entities );
00159     }
00160 
00161     ErrorCode rval = MB_SUCCESS, rval_tmp;
00162     for( size_t i = 0; i < num_entities; ++i, ++pointers )
00163     {
00164         rval_tmp = get_data_ptr( entities[i], *pointers );
00165         if( MB_SUCCESS != rval_tmp && get_default_value() )
00166         {
00167             *pointers = get_default_value();
00168         }
00169         else if( MB_SUCCESS != rval_tmp )
00170         {
00171             return MB_TAG_NOT_FOUND;
00172         }
00173     }
00174 
00175     return rval;
00176 }
00177 
00178 ErrorCode SparseTag::get_data( const SequenceManager*,
00179                                Error* /* error */,
00180                                const Range& entities,
00181                                const void** pointers,
00182                                int* data_lengths ) const
00183 {
00184     if( data_lengths )
00185     {
00186         int len = get_size();
00187         SysUtil::setmem( data_lengths, &len, sizeof( int ), entities.size() );
00188     }
00189 
00190     ErrorCode rval = MB_SUCCESS, rval_tmp;
00191     Range::const_iterator i;
00192     for( i = entities.begin(); i != entities.end(); ++i, ++pointers )
00193     {
00194         rval_tmp = get_data_ptr( *i, *pointers );
00195         if( MB_SUCCESS != rval_tmp && get_default_value() )
00196         {
00197             *pointers = get_default_value();
00198         }
00199         else if( MB_SUCCESS != rval_tmp )
00200         {
00201             return MB_TAG_NOT_FOUND;
00202         }
00203     }
00204 
00205     return rval;
00206 }
00207 
00208 ErrorCode SparseTag::set_data( SequenceManager* seqman,
00209                                Error* /* error */,
00210                                const EntityHandle* entities,
00211                                size_t num_entities,
00212                                const void* data )
00213 {
00214     ErrorCode rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval );
00215 
00216     const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data );
00217     for( size_t i = 0; i < num_entities; ++i, ptr += get_size() )
00218     {
00219         rval = set_data( NULL, entities[i], ptr );MB_CHK_ERR( rval );
00220     }
00221 
00222     return MB_SUCCESS;
00223 }
00224 
00225 ErrorCode SparseTag::set_data( SequenceManager* seqman, Error* /* error */, const Range& entities, const void* data )
00226 {
00227     ErrorCode rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval );
00228 
00229     const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data );
00230     Range::const_iterator i;
00231     for( i = entities.begin(); i != entities.end(); ++i, ptr += get_size() )
00232         if( MB_SUCCESS != ( rval = set_data( NULL, *i, ptr ) ) ) return rval;
00233 
00234     return MB_SUCCESS;
00235 }
00236 
00237 ErrorCode SparseTag::set_data( SequenceManager* seqman,
00238                                Error* /* error */,
00239                                const EntityHandle* entities,
00240                                size_t num_entities,
00241                                void const* const* pointers,
00242                                const int* lengths )
00243 {
00244     ErrorCode rval = validate_lengths( NULL, lengths, num_entities );MB_CHK_ERR( rval );
00245 
00246     rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval );
00247 
00248     for( size_t i = 0; i < num_entities; ++i, ++pointers )
00249     {
00250         rval = set_data( NULL, entities[i], *pointers );MB_CHK_ERR( rval );
00251     }
00252 
00253     return MB_SUCCESS;
00254 }
00255 
00256 ErrorCode SparseTag::set_data( SequenceManager* seqman,
00257                                Error* /* error */,
00258                                const Range& entities,
00259                                void const* const* pointers,
00260                                const int* lengths )
00261 {
00262     ErrorCode rval = validate_lengths( NULL, lengths, entities.size() );MB_CHK_ERR( rval );
00263 
00264     rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval );
00265 
00266     Range::const_iterator i;
00267     for( i = entities.begin(); i != entities.end(); ++i, ++pointers )
00268     {
00269         rval = set_data( NULL, *i, *pointers );MB_CHK_ERR( rval );
00270     }
00271 
00272     return MB_SUCCESS;
00273 }
00274 
00275 ErrorCode SparseTag::clear_data( SequenceManager* seqman,
00276                                  Error* /* error */,
00277                                  const EntityHandle* entities,
00278                                  size_t num_entities,
00279                                  const void* value_ptr,
00280                                  int value_len )
00281 {
00282     if( value_len && value_len != get_size() )
00283     {
00284         MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name()
00285                                                           << " of size " << value_len );
00286     }
00287 
00288     ErrorCode rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval );
00289 
00290     for( size_t i = 0; i < num_entities; ++i )
00291     {
00292         rval = set_data( NULL, entities[i], value_ptr );MB_CHK_ERR( rval );
00293     }
00294 
00295     return MB_SUCCESS;
00296 }
00297 
00298 ErrorCode SparseTag::clear_data( SequenceManager* seqman,
00299                                  Error* /* error */,
00300                                  const Range& entities,
00301                                  const void* value_ptr,
00302                                  int value_len )
00303 {
00304     if( value_len && value_len != get_size() )
00305     {
00306         MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name()
00307                                                           << " of size " << value_len );
00308     }
00309 
00310     ErrorCode rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval );
00311 
00312     Range::const_iterator i;
00313     for( i = entities.begin(); i != entities.end(); ++i )
00314     {
00315         rval = set_data( NULL, *i, value_ptr );MB_CHK_ERR( rval );
00316     }
00317 
00318     return MB_SUCCESS;
00319 }
00320 
00321 ErrorCode SparseTag::remove_data( SequenceManager*,
00322                                   Error* /* error */,
00323                                   const EntityHandle* entities,
00324                                   size_t num_entities )
00325 {
00326     ErrorCode rval;
00327     for( size_t i = 0; i < num_entities; ++i )
00328     {
00329         rval = remove_data( NULL, entities[i] );
00330         if( MB_SUCCESS != rval ) return rval;
00331     }
00332 
00333     return MB_SUCCESS;
00334 }
00335 
00336 ErrorCode SparseTag::remove_data( SequenceManager*, Error* /* error */, const Range& entities )
00337 {
00338     for( Range::const_iterator i = entities.begin(); i != entities.end(); ++i )
00339         if( MB_SUCCESS != remove_data( NULL, *i ) ) return MB_TAG_NOT_FOUND;
00340 
00341     return MB_SUCCESS;
00342 }
00343 
00344 ErrorCode SparseTag::tag_iterate( SequenceManager* seqman,
00345                                   Error* /* error */,
00346                                   Range::iterator& iter,
00347                                   const Range::iterator& end,
00348                                   void*& data_ptr,
00349                                   bool allocate )
00350 {
00351     // Note: We are asked to returning a block of contiguous storage
00352     //       for some block of contiguous handles for which the tag
00353     //       storage is also contiguous. As sparse tag storage is
00354     //       never contiguous, all we can do is return a pointer to the
00355     //       data for the first entity.
00356 
00357     // If asked for nothing, successfully return nothing.
00358     if( iter == end ) return MB_SUCCESS;
00359 
00360     // Note: get_data_ptr will return the default value if the
00361     //       handle is not found, so test to make sure that the
00362     //       handle is valid.
00363     ErrorCode rval = seqman->check_valid_entities( NULL, &*iter, 1 );MB_CHK_ERR( rval );
00364 
00365     // Get pointer to tag storage for entity pointed to by iter
00366     const void* ptr = NULL;
00367     rval            = get_data_ptr( *iter, ptr );
00368     if( MB_SUCCESS == rval )
00369         data_ptr = const_cast< void* >( ptr );
00370     else if( get_default_value() && allocate )
00371     {
00372         ptr      = allocate_data( *iter, mData.end() );
00373         data_ptr = const_cast< void* >( ptr );
00374     }
00375     else
00376     {
00377         // If allocation was not requested, need to increment the iterator so that
00378         // the count can be computed properly
00379         if( get_default_value() && !allocate ) ++iter;
00380         // return not_found(get_name(), *iter);
00381     }
00382 
00383     // Increment iterator and return
00384     ++iter;
00385     return MB_SUCCESS;
00386 }
00387 
00388 template < class Container >
00389 static inline void get_tagged( const SparseTag::MapType& mData, EntityType type, Container& output_range )
00390 {
00391     SparseTag::MapType::const_iterator iter;
00392     typename Container::iterator hint = output_range.begin();
00393     if( MBMAXTYPE == type )
00394     {
00395         for( iter = mData.begin(); iter != mData.end(); ++iter )
00396             hint = output_range.insert( hint, iter->first );
00397     }
00398     else
00399     {
00400 #ifdef MOAB_HAVE_UNORDERED_MAP
00401         for( iter = mData.begin(); iter != mData.end(); ++iter )
00402             if( TYPE_FROM_HANDLE( iter->first ) == type ) hint = output_range.insert( hint, iter->first );
00403 #else
00404         iter                                   = mData.lower_bound( FIRST_HANDLE( type ) );
00405         SparseTag::MapType::const_iterator end = mData.lower_bound( LAST_HANDLE( type ) + 1 );
00406         for( ; iter != end; ++iter )
00407             hint = output_range.insert( hint, iter->first );
00408 #endif
00409     }
00410 }
00411 
00412 template < class Container >
00413 static inline void get_tagged( const SparseTag::MapType& mData,
00414                                Range::const_iterator begin,
00415                                Range::const_iterator end,
00416                                Container& output_range )
00417 {
00418     typename Container::iterator hint = output_range.begin();
00419     for( Range::const_iterator i = begin; i != end; ++i )
00420         if( mData.find( *i ) != mData.end() ) hint = output_range.insert( hint, *i );
00421 }
00422 
00423 template < class Container >
00424 static inline void get_tagged( const SparseTag::MapType& mData,
00425                                Container& entities,
00426                                EntityType type,
00427                                const Range* intersect )
00428 {
00429     if( !intersect )
00430         get_tagged< Container >( mData, type, entities );
00431     else if( MBMAXTYPE == type )
00432         get_tagged< Container >( mData, intersect->begin(), intersect->end(), entities );
00433     else
00434     {
00435         std::pair< Range::iterator, Range::iterator > r = intersect->equal_range( type );
00436         get_tagged< Container >( mData, r.first, r.second, entities );
00437     }
00438 }
00439 
00440 //! Gets all entity handles that match a type and tag
00441 ErrorCode SparseTag::get_tagged_entities( const SequenceManager*,
00442                                           Range& output_range,
00443                                           EntityType type,
00444                                           const Range* intersect ) const
00445 {
00446     get_tagged( mData, output_range, type, intersect );
00447     return MB_SUCCESS;
00448 }
00449 
00450 //! Gets all entity handles that match a type and tag
00451 ErrorCode SparseTag::num_tagged_entities( const SequenceManager*,
00452                                           size_t& output_count,
00453                                           EntityType type,
00454                                           const Range* intersect ) const
00455 {
00456     InsertCount counter( output_count );
00457     get_tagged( mData, counter, type, intersect );
00458     output_count = counter.end();
00459     return MB_SUCCESS;
00460 }
00461 
00462 ErrorCode SparseTag::find_entities_with_value(
00463 #ifdef MOAB_HAVE_UNORDERED_MAP
00464     const SequenceManager* seqman,
00465 #else
00466     const SequenceManager*,
00467 #endif
00468     Error* /* error */,
00469     Range& output_entities,
00470     const void* value,
00471     int value_bytes,
00472     EntityType type,
00473     const Range* intersect_entities ) const
00474 {
00475     if( value_bytes && value_bytes != get_size() )
00476     {
00477         MB_SET_ERR( MB_INVALID_SIZE, "Invalid data size " << get_size() << " specified for sparse tag " << get_name()
00478                                                           << " of size " << value_bytes );
00479     }
00480 
00481     MapType::const_iterator iter, end;
00482 #ifdef MOAB_HAVE_UNORDERED_MAP
00483     if( intersect_entities )
00484     {
00485         std::pair< Range::iterator, Range::iterator > r;
00486         if( type == MBMAXTYPE )
00487         {
00488             r.first  = intersect_entities->begin();
00489             r.second = intersect_entities->end();
00490         }
00491         else
00492         {
00493             r = intersect_entities->equal_range( type );
00494         }
00495 
00496         find_map_values_equal( *this, value, get_size(), r.first, r.second, mData, output_entities );
00497     }
00498     else if( type == MBMAXTYPE )
00499     {
00500         find_tag_values_equal( *this, value, get_size(), mData.begin(), mData.end(), output_entities );
00501     }
00502     else
00503     {
00504         Range tmp;
00505         seqman->get_entities( type, tmp );
00506         find_map_values_equal( *this, value, get_size(), tmp.begin(), tmp.end(), mData, output_entities );
00507     }
00508 #else
00509     if( intersect_entities )
00510     {
00511         for( Range::const_pair_iterator p = intersect_entities->begin(); p != intersect_entities->end(); ++p )
00512         {
00513             iter = mData.lower_bound( p->first );
00514             end = mData.upper_bound( p->second );
00515             find_tag_values_equal( *this, value, get_size(), iter, end, output_entities );
00516         }
00517     }
00518     else
00519     {
00520         if( type == MBMAXTYPE )
00521         {
00522             iter = mData.begin();
00523             end = mData.end();
00524         }
00525         else
00526         {
00527             iter = mData.lower_bound( CREATE_HANDLE( type, MB_START_ID ) );
00528             end = mData.upper_bound( CREATE_HANDLE( type, MB_END_ID ) );
00529         }
00530         find_tag_values_equal( *this, value, get_size(), iter, end, output_entities );
00531     }
00532 #endif
00533 
00534     return MB_SUCCESS;
00535 }
00536 
00537 bool SparseTag::is_tagged( const SequenceManager*, EntityHandle h ) const
00538 {
00539     return mData.find( h ) != mData.end();
00540 }
00541 
00542 ErrorCode SparseTag::get_memory_use( const SequenceManager*, unsigned long& total, unsigned long& per_entity ) const
00543 
00544 {
00545     per_entity = get_size() + 4 * sizeof( void* );
00546     total      = ( mData.size() * per_entity ) + sizeof( *this ) + TagInfo::get_memory_use();
00547 
00548     return MB_SUCCESS;
00549 }
00550 
00551 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines