Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
VarLenDenseTag.cpp
Go to the documentation of this file.
1 /** \file VarLenDenseTag.cpp
2  * \author Jason Kraftcheck
3  * \date 2010-12-14
4  */
5 
6 #include "VarLenDenseTag.hpp"
7 #include "moab/Range.hpp"
8 #include "TagCompare.hpp"
9 #include "SysUtil.hpp"
10 #include "SequenceManager.hpp"
11 #include "SequenceData.hpp"
13 #include "moab/Error.hpp"
14 #include "moab/ErrorHandler.hpp"
15 #include "moab/CN.hpp"
16 #include <utility>
17 
18 namespace moab
19 {
20 
21 inline static ErrorCode not_found( std::string /*name*/, EntityHandle /*h*/ )
22 {
23 #if 0
24  // MB_TAG_NOT_FOUND could be a non-error condition, do not call MB_SET_ERR on it
25  // Print warning messages for debugging only
26  if (h)
27  fprintf(stderr, "[Warning]: No variable-length dense tag %s value for %s %lu\n",
28  name.c_str(),
30  (unsigned long)ID_FROM_HANDLE(h));
31  else
32  fprintf(stderr, "[Warning]: No variable-length dense tag %s value for root set\n", name.c_str());
33 #endif
34 
35  return MB_TAG_NOT_FOUND;
36 }
37 
39  const char* name,
40  DataType type,
41  const void* default_value,
42  int default_value_size )
43  : TagInfo( name, MB_VARIABLE_LENGTH, type, default_value, default_value_size ), mySequenceArray( index )
44 {
45 }
46 
48  Error* error,
49  const char* name,
50  DataType type,
51  const void* default_value,
52  int default_value_size )
53 {
54  int index;
55  if( MB_SUCCESS != seqman->reserve_tag_array( error, MB_VARIABLE_LENGTH, index ) ) return NULL;
56 
57  return new VarLenDenseTag( index, name, type, default_value, default_value_size );
58 }
59 
61 {
62  assert( mySequenceArray < 0 );
63 }
64 
66 {
67  return MB_TAG_DENSE;
68 }
69 
71 {
72  Range all_ents;
73  seqman->get_entities( all_ents );
74  MB_CHK_ERR( remove_data( seqman, error, all_ents ) );
75  MB_CHK_ERR( seqman->release_tag_array( error, mySequenceArray, delete_pending ) );
76  if( delete_pending ) mySequenceArray = -1;
77  return MB_SUCCESS;
78 }
79 
81  Error* /* error */,
82  EntityHandle h,
83  const VarLenTag*& ptr,
84  size_t& count ) const
85 {
86  const EntitySequence* seq = nullptr;
87  if( MB_SUCCESS != seqman->find( h, seq ) )
88  {
89  if( !h )
90  { // Root set
91  ptr = &meshValue;
92  count = 1;
93  return MB_SUCCESS;
94  }
95  else
96  {
97  ptr = NULL;
98  count = 0;
99  return not_found( get_name(), h );
100  }
101  }
102 
103  const void* mem = seq->data()->get_tag_data( mySequenceArray );
104  ptr = reinterpret_cast< const VarLenTag* >( mem );
105  count = seq->data()->end_handle() - h + 1;
106  if( ptr ) ptr += h - seq->data()->start_handle();
107 
108  return MB_SUCCESS;
109 }
110 
112  Error* /* error */,
113  EntityHandle h,
114  VarLenTag*& ptr,
115  size_t& count,
116  bool allocate )
117 {
118  EntitySequence* seq = nullptr;
119  if( MB_SUCCESS != seqman->find( h, seq ) )
120  {
121  if( !h )
122  { // Root set
123  ptr = &meshValue;
124  count = 1;
125  return MB_SUCCESS;
126  }
127  else
128  {
129  ptr = NULL;
130  count = 0;
131  return not_found( get_name(), h );
132  }
133  }
134 
135  void* mem = seq->data()->get_tag_data( mySequenceArray );
136  if( !mem && allocate )
137  {
138  mem = seq->data()->allocate_tag_array( mySequenceArray, sizeof( VarLenTag ) );
139  if( !mem )
140  {
141  MB_SET_ERR( MB_MEMORY_ALLOCATION_FAILED, "Memory allocation for variable-length dense tag data failed" );
142  }
143 
144  memset( mem, 0, sizeof( VarLenTag ) * seq->data()->size() );
145  }
146 
147  ptr = reinterpret_cast< VarLenTag* >( mem );
148  count = seq->data()->end_handle() - h + 1;
149  if( ptr ) ptr += h - seq->data()->start_handle();
150 
151  return MB_SUCCESS;
152 }
153 
155  Error* /* error */,
156  const EntityHandle*,
157  size_t,
158  void* ) const
159 {
160  MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag " << get_name() << " data" );
161 }
162 
163 ErrorCode VarLenDenseTag::get_data( const SequenceManager*, Error* /* error */, const Range&, void* ) const
164 {
165  MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag " << get_name() << " data" );
166 }
167 
169  Error* /* error */,
170  const EntityHandle* entities,
171  size_t num_entities,
172  const void** pointers,
173  int* lengths ) const
174 {
175  if( !lengths )
176  {
177  MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag " << get_name() << " data" );
178  }
179 
180  ErrorCode result = MB_SUCCESS;
181  const EntityHandle* const end = entities + num_entities;
182  size_t junk = 0;
183  const VarLenTag* ptr = NULL;
184 
185  for( const EntityHandle* i = entities; i != end; ++i, ++pointers, ++lengths )
186  {
187  MB_CHK_ERR( get_array( seqman, NULL, *i, ptr, junk ) );
188 
189  if( ptr && ptr->size() )
190  {
191  *pointers = ptr->data();
192  *lengths = ptr->size();
193  }
194  else if( get_default_value() )
195  {
196  *pointers = get_default_value();
197  *lengths = get_default_value_size();
198  }
199  else
200  {
201  *pointers = 0;
202  *lengths = 0;
203  result = not_found( get_name(), *i );
204  }
205  }
206 
207  return result;
208 }
209 
211  Error* /* error */,
212  const Range& entities,
213  const void** pointers,
214  int* lengths ) const
215 {
216  if( !lengths )
217  {
218  MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag " << get_name() << " data" );
219  }
220 
221  size_t avail = 0;
222  const VarLenTag* array = NULL;
223 
224  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
225  {
226  EntityHandle start = p->first;
227  while( start <= p->second )
228  {
229  MB_CHK_ERR( get_array( seqman, NULL, start, array, avail ) );
230 
231  const size_t count = std::min< size_t >( p->second - start + 1, avail );
232 
233  if( !array )
234  {
235  const void* defval = get_default_value();
236  const int len = get_default_value_size();
237  SysUtil::setmem( pointers, &defval, sizeof( void* ), count );
238  SysUtil::setmem( lengths, &len, sizeof( int ), count );
239  pointers += count;
240  lengths += count;
241  if( !defval ) return not_found( get_name(), start );
242  }
243 
244  const VarLenTag* end_data = array + count;
245  while( array != end_data )
246  {
247  if( array->size() )
248  {
249  *pointers = array->data();
250  *lengths = array->size();
251  }
252  else if( get_default_value() )
253  {
254  *pointers = get_default_value();
255  *lengths = get_default_value_size();
256  }
257  else
258  {
259  *pointers = NULL;
260  *lengths = 0;
261  return not_found( get_name(), start );
262  }
263  ++pointers;
264  ++lengths;
265  ++array;
266  ++start;
267  }
268  }
269  }
270 
271  return MB_SUCCESS;
272 }
273 
274 ErrorCode VarLenDenseTag::set_data( SequenceManager*, Error* /* error */, const EntityHandle*, size_t, const void* )
275 {
276  MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag " << get_name() << " data" );
277 }
278 
279 ErrorCode VarLenDenseTag::set_data( SequenceManager*, Error* /* error */, const Range&, const void* )
280 {
281  MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag " << get_name() << " data" );
282 }
283 
285  Error* /* error */,
286  const EntityHandle* entities,
287  size_t num_entities,
288  bool one_value,
289  void const* const* pointers,
290  const int* lengths )
291 {
292  MB_CHK_ERR( validate_lengths( NULL, lengths, one_value ? 1 : num_entities ) );
293 
294  const EntityHandle* const end = entities + num_entities;
295  VarLenTag* array = NULL;
296  size_t junk = 0;
297  const size_t step = one_value ? 0 : 1;
298 
299  for( const EntityHandle* i = entities; i != end; ++i )
300  {
301  MB_CHK_ERR( get_array( seqman, NULL, *i, array, junk, true ) );
302 
303  array->set( *pointers, *lengths );
304  pointers += step;
305  lengths += step;
306  }
307 
308  return MB_SUCCESS;
309 }
310 
312  Error* /* error */,
313  const Range& entities,
314  bool one_value,
315  void const* const* pointers,
316  const int* lengths )
317 {
318  MB_CHK_ERR( validate_lengths( NULL, lengths, one_value ? 1 : entities.size() ) );
319 
320  VarLenTag* array = NULL;
321  size_t avail = 0;
322  const size_t step = one_value ? 0 : 1;
323 
324  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
325  {
326  EntityHandle start = p->first;
327  while( start <= p->second )
328  {
329  MB_CHK_ERR( get_array( seqman, NULL, start, array, avail, true ) );
330 
331  const EntityHandle end = std::min< EntityHandle >( p->second + 1, start + avail );
332  while( start != end )
333  {
334  array->set( *pointers, *lengths );
335  ++start;
336  ++array;
337  pointers += step;
338  lengths += step;
339  }
340  }
341  }
342 
343  return MB_SUCCESS;
344 }
345 
347  Error* /* error */,
348  const EntityHandle* entities,
349  size_t num_entities,
350  void const* const* pointers,
351  const int* lengths )
352 {
353  return set_data( seqman, NULL, entities, num_entities, false, pointers, lengths );
354 }
355 
357  Error* /* error */,
358  const Range& entities,
359  void const* const* pointers,
360  const int* lengths )
361 {
362  return set_data( seqman, NULL, entities, false, pointers, lengths );
363 }
364 
366  Error* /* error */,
367  const EntityHandle* entities,
368  size_t num_entities,
369  const void* value_ptr,
370  int value_len )
371 {
372  if( !value_ptr || !value_len )
373  return remove_data( seqman, NULL, entities, num_entities );
374  else
375  return set_data( seqman, NULL, entities, num_entities, true, &value_ptr, &value_len );
376 }
377 
379  Error* /* error */,
380  const Range& entities,
381  const void* value_ptr,
382  int value_len )
383 {
384  if( !value_ptr || !value_len )
385  return remove_data( seqman, NULL, entities );
386  else
387  return set_data( seqman, NULL, entities, true, &value_ptr, &value_len );
388 }
389 
391  Error* /* error */,
392  const EntityHandle* entities,
393  size_t num_entities )
394 {
395  const EntityHandle* const end = entities + num_entities;
396  VarLenTag* array = NULL;
397  size_t junk = 0;
398 
399  for( const EntityHandle* i = entities; i != end; ++i )
400  {
401  MB_CHK_ERR( get_array( seqman, NULL, *i, array, junk, false ) );
402 
403  if( array ) array->clear();
404  }
405 
406  return MB_SUCCESS;
407 }
408 
409 ErrorCode VarLenDenseTag::remove_data( SequenceManager* seqman, Error* /* error */, const Range& entities )
410 {
411  VarLenTag* array = NULL;
412  size_t avail = 0;
413 
414  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
415  {
416  EntityHandle start = p->first;
417  while( start <= p->second )
418  {
419  MB_CHK_ERR( get_array( seqman, NULL, start, array, avail, false ) );
420 
421  const EntityHandle end = std::min< EntityHandle >( p->second + 1, start + avail );
422  if( array )
423  {
424  while( start != end )
425  {
426  array->clear();
427  ++start;
428  ++array;
429  }
430  }
431  else
432  {
433  start = end;
434  }
435  }
436  }
437 
438  return MB_SUCCESS;
439 }
440 
442  Error* /* error */,
444  const Range::iterator&,
445  void*&,
446  bool )
447 {
448  MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "Cannot iterate over variable-length tag data" );
449 }
450 
451 template < class Container >
452 static inline ErrorCode get_tagged( const SequenceManager* seqman,
453  int mySequenceArray,
454  EntityType type,
455  Container& entities )
456 {
457  typename Container::iterator hint = entities.begin();
458  std::pair< EntityType, EntityType > range = type_range( type );
460  const VarLenTag *data, *iter, *end;
461  for( EntityType t = range.first; t != range.second; ++t )
462  {
463  const TypeSequenceManager& map = seqman->entity_map( t );
464  for( i = map.begin(); i != map.end(); ++i )
465  {
466  data = reinterpret_cast< const VarLenTag* >( ( *i )->data()->get_tag_data( mySequenceArray ) );
467  if( !data ) continue;
468  end = data + ( *i )->end_handle() - ( *i )->data()->start_handle() + 1;
469  iter = data + ( *i )->start_handle() - ( *i )->data()->start_handle();
470  EntityHandle handle = ( *i )->start_handle();
471  for( ; iter != end; ++iter, ++handle )
472  if( iter->size() ) hint = entities.insert( hint, handle );
473  }
474  }
475 
476  return MB_SUCCESS;
477 }
478 
479 template < class Container >
480 static inline ErrorCode get_tagged( const SequenceManager* seqman,
481  int mySequenceArray,
482  Range::const_iterator begin,
484  Container& entities )
485 {
486  typename Container::iterator hint = entities.begin();
487  RangeSeqIntersectIter iter( const_cast< SequenceManager* >( seqman ) );
488  ErrorCode rval = iter.init( begin, end );
489  const VarLenTag* data;
490  for( ; MB_SUCCESS == rval; rval = iter.step() )
491  {
492  data = reinterpret_cast< const VarLenTag* >( iter.get_sequence()->data()->get_tag_data( mySequenceArray ) );
493  if( !data ) continue;
494 
495  data += iter.get_start_handle() - iter.get_sequence()->data()->start_handle();
496  size_t count = iter.get_end_handle() - iter.get_start_handle() + 1;
497  for( size_t i = 0; i < count; ++i )
498  if( data[i].size() ) hint = entities.insert( hint, iter.get_start_handle() + i );
499  rval = iter.step();
500  }
501 
502  if( MB_FAILURE != rval ) // We get MB_FAILURE at iterator end
503  return rval;
504 
505  return MB_SUCCESS;
506 }
507 
508 template < class Container >
509 static inline ErrorCode get_tagged( const SequenceManager* seqman,
510  int mySequenceArray,
511  Container& entities,
512  EntityType type,
513  const Range* intersect )
514 {
515  if( !intersect )
516  return get_tagged< Container >( seqman, mySequenceArray, type, entities );
517  else if( MBMAXTYPE == type )
518  return get_tagged< Container >( seqman, mySequenceArray, intersect->begin(), intersect->end(), entities );
519  else
520  {
521  std::pair< Range::iterator, Range::iterator > r = intersect->equal_range( type );
522  return get_tagged< Container >( seqman, mySequenceArray, r.first, r.second, entities );
523  }
524 }
525 
527  Range& entities,
528  EntityType type,
529  const Range* intersect ) const
530 {
531  return get_tagged( seqman, mySequenceArray, entities, type, intersect );
532 }
533 
535  size_t& output_count,
536  EntityType type,
537  const Range* intersect ) const
538 {
539  InsertCount counter( output_count );
540  MB_CHK_ERR( get_tagged( seqman, mySequenceArray, counter, type, intersect ) );
541  output_count = counter.end();
542  return MB_SUCCESS;
543 }
544 
546  Error* error,
547  Range& output_entities,
548  const void* value,
549  int value_bytes,
550  EntityType type,
551  const Range* intersect_entities ) const
552 {
553  if( !intersect_entities )
554  {
555  std::pair< EntityType, EntityType > range = type_range( type );
557  for( EntityType t = range.first; t != range.second; ++t )
558  {
559  const TypeSequenceManager& map = seqman->entity_map( t );
560  for( i = map.begin(); i != map.end(); ++i )
561  {
562  const void* data = ( *i )->data()->get_tag_data( mySequenceArray );
563  if( data )
564  {
565  ByteArrayIterator start( ( *i )->data()->start_handle(), data, *this );
566  ByteArrayIterator end( ( *i )->end_handle() + 1, 0, 0 );
567  start += ( *i )->start_handle() - ( *i )->data()->start_handle();
568  find_tag_varlen_values_equal( *this, value, value_bytes, start, end, output_entities );
569  }
570  }
571  }
572  }
573  else
574  {
575  const VarLenTag* array;
576  size_t count;
577 
578  Range::const_pair_iterator p = intersect_entities->begin();
579  if( type != MBMAXTYPE )
580  {
581  p = intersect_entities->lower_bound( type );
582  assert( TYPE_FROM_HANDLE( p->first ) == type );
583  }
584  for( ;
585  p != intersect_entities->const_pair_end() && ( MBMAXTYPE == type || TYPE_FROM_HANDLE( p->first ) == type );
586  ++p )
587  {
588  EntityHandle start = p->first;
589  while( start <= p->second )
590  {
591  MB_CHK_ERR( get_array( seqman, error, start, array, count ) );
592 
593  if( p->second - start < count - 1 ) count = p->second - start + 1;
594 
595  if( array )
596  {
597  ByteArrayIterator istart( start, array, *this );
598  ByteArrayIterator iend( start + count, 0, 0 );
599  find_tag_varlen_values_equal( *this, value, value_bytes, istart, iend, output_entities );
600  }
601  start += count;
602  }
603  }
604  }
605 
606  return MB_SUCCESS;
607 }
608 
610 {
611  const VarLenTag* ptr = NULL; // Initialize to get rid of warning
612  size_t count;
613  return ( MB_SUCCESS == get_array( seqman, 0, h, ptr, count ) ) && ( NULL != ptr ) && ( NULL != ptr->data() );
614 }
615 
617  unsigned long& total,
618  unsigned long& per_entity ) const
619 
620 {
621  total = 0;
622  per_entity = 0;
623  size_t count = 0;
624  for( EntityType t = MBVERTEX; t <= MBENTITYSET; ++t )
625  {
626  const TypeSequenceManager& map = seqman->entity_map( t );
627  const SequenceData* prev_data = 0;
628  for( TypeSequenceManager::const_iterator i = map.begin(); i != map.end(); ++i )
629  {
630  const void* mem = ( *i )->data()->get_tag_data( mySequenceArray );
631  if( !mem ) continue;
632 
633  if( ( *i )->data() != prev_data )
634  {
635  total += ( *i )->data()->size();
636  prev_data = ( *i )->data();
637  }
638 
639  count += ( *i )->size();
640  const VarLenTag* array = reinterpret_cast< const VarLenTag* >( mem );
641  for( int j = 0; j < ( *i )->size(); ++j )
642  per_entity += array[j].mem();
643  }
644  }
645  total *= sizeof( VarLenTag );
646  total += per_entity + sizeof( *this ) + TagInfo::get_memory_use();
647  total += meshValue.mem() + sizeof( meshValue );
648  if( count ) per_entity /= count;
649  per_entity += sizeof( VarLenTag );
650 
651  return MB_SUCCESS;
652 }
653 
654 } // namespace moab