Sierra Toolkit Version of the Day
Transaction.cpp
00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010 Sandia Corporation.                     */
00003 /*  Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive   */
00004 /*  license for use of this work by or on behalf of the U.S. Government.  */
00005 /*  Export of this program may require a license from the                 */
00006 /*  United States Government.                                             */
00007 /*------------------------------------------------------------------------*/
00008 
00009 
00013 #if 0
00014 
00015 #include <unistd.h> // For sleep
00016 #include <stdexcept>
00017 
00018 
00019 
00020 #include <stk_mesh/base/Entity.hpp>
00021 #include <stk_mesh/base/Bucket.hpp>
00022 #include <stk_mesh/base/BulkData.hpp>
00023 #include <stk_mesh/base/Transaction.hpp>
00024 
00025 namespace stk {
00026 namespace mesh {
00027 
00028 
00029 void Transaction::print_bucket_list ( const BucketList &bl , std::ostream &os ) const
00030 {
00031   BucketList::const_iterator  cur_bucket = bl.begin();
00032   while ( cur_bucket != bl.end() )
00033   {
00034     os << "Bucket key: ";
00035     for ( unsigned i = 0 ; i <= (*cur_bucket)->m_key[0] ; i++ )
00036       os << (*cur_bucket)->m_key[i] << " ";
00037     os << "\n";
00038     os << "Entities: ";
00039     for ( unsigned i = 0 ; i != (*cur_bucket)->m_size ; i++ )
00040       os << (*cur_bucket)->m_entities[i]->identifier() << " ";
00041     os << "\n-------------------\n";
00042     cur_bucket++;
00043   }
00044 }
00045 
00046 
00047 void Transaction::print_transaction ( unsigned type , std::ostream &os ) const
00048 {
00049   os << "Transaction details for type = " << type << "\n";
00050   os << "-=-=- Proc " << m_bulk_data.parallel_rank() << " -=-=-\n";
00051   print_proc_transaction ( type , os );
00052   os << std::endl;
00053 }
00054 
00055 void Transaction::print_proc_transaction ( unsigned type , std::ostream &os ) const
00056 {
00057   os << "  Modified has " << m_modified[type].size() << " buckets\n"
00058      << "  Nowhere has " << m_deleted[type].size() << " buckets\n"
00059      << "  Inserted has " << m_inserted[type].size() << " buckets\n";
00060   os << " Modified buckets:\n";
00061   print_bucket_list ( m_modified[type] , os );
00062   os << " Nowhere buckets:\n";
00063   print_bucket_list ( m_deleted[type] , os );
00064   os << " Inserted buckets:\n";
00065   print_bucket_list ( m_inserted[type] , os );
00066 }
00067 
00068 std::ostream & Transaction::print_stream ( std::ostream &os ) const
00069 {
00070   for ( unsigned i = 0 ; i != m_modified.size() ; i++ )
00071     print_transaction ( i , os );
00072   return os;
00073 }
00074 
00075 Transaction::Transaction ( BulkData &bd , TransactionType type ) : m_transaction_type(type) ,
00076                                                                    m_bulk_data ( bd ) ,
00077                                                                    m_modified ( ) ,
00078                                                                    m_deleted ( ) ,
00079                                                                    m_inserted ( )
00080 {
00081   allocate_bucket_lists ();
00082 }
00083 
00084 Transaction::~Transaction ()
00085 {
00086   reset ();
00087 }
00088 
00089 
00090 
00091 // This allocation works on the assumption that the entity types are
00092 // packed and enumerated from zero.  This assumption is currently safe
00093 // since bulk data makes the same assumption.  Should this ever
00094 // change in bulk data, the same change must occur here.
00095 void Transaction::allocate_bucket_lists ()
00096 {
00097   m_modified.resize ( m_bulk_data.mesh_meta_data().entity_rank_count() );
00098   m_deleted.resize ( m_bulk_data.mesh_meta_data().entity_rank_count() );
00099   m_inserted.resize ( m_bulk_data.mesh_meta_data().entity_rank_count() );
00100 }
00101 
00102 
00103 // This method will place entity e in the modified buckets.  Unlike
00104 // modify_entity, this will not add the from-entity relations to the
00105 // modified bucket.  This method is invoked on the to-entity of a new
00106 // or changed relation.  If the entity is already in a transaction
00107 // bucket, this method returns with no change
00108 void Transaction::modify_sole_entity ( Entity &e )
00109 {
00110   // If no bucket is specified yet, then the entity is inserted and
00111   // should be ignored
00112   if ( e.m_bucket == 0 ) return;
00113 
00114   // Ignore spurious calls to internal_change_entity_parts
00115   if ( e.m_trans_bucket != 0 ) return;
00116 
00117   add_parts_to_partset ( e , m_modified_parts );
00118 
00119   // If this is not an incremental transaction, ignore
00120   if ( m_transaction_type != INCREMENTAL ) return;
00121 
00122   Bucket *transaction_bucket = get_unfilled_transaction_bucket ( e , m_modified[e.entity_rank()] , MODIFIED );
00123 
00124   add_entity_to_transaction_bucket ( e , transaction_bucket );
00125 }
00126 
00127 // This method will add e to the modified bucket and every entity for
00128 // which e is directly related to.  This method is invoked an all
00129 // modification other than the to-entity of a new or modified
00130 // relation.  If the entity is already in a transaction bucket, this
00131 // method returns with no change.
00132 void Transaction::modify_entity ( Entity &e )
00133 {
00134 
00135   // If no bucket is specified yet, then the entity is inserted and
00136   // should be ignored
00137   if ( e.m_bucket == 0 ) return;
00138 
00139   // Ignore spurious calls to internal_change_entity_parts
00140   if ( e.m_trans_bucket != 0 ) return;
00141 
00142   add_parts_to_partset ( e , m_modified_parts );
00143 
00144   // If this is not an incremental transaction, ignore
00145   if ( m_transaction_type != INCREMENTAL ) return;
00146 
00147   Bucket *transaction_bucket = get_unfilled_transaction_bucket ( e , m_modified[e.entity_rank()] , MODIFIED );
00148 
00149   add_entity_to_transaction_bucket ( e , transaction_bucket );
00150 
00151   PairIterRelation current_relation = e.relations();
00152   while ( current_relation.first != current_relation.second )
00153   {
00154     if ( current_relation->entity_rank() > e.entity_rank() )
00155       modify_sole_entity ( *(current_relation->entity()) );
00156     current_relation++;
00157   }
00158 }
00159 
00160 // If an entity is removed from this process, it is placed in the
00161 // deleted bucket.  If the entity is in another transaction bucket, it
00162 // is moved to the deleted bucket and the corresponding parts the
00163 // entity is a member of is moved along with it
00164 void Transaction::delete_entity ( Entity &e )
00165 {
00166   add_parts_to_partset ( e , m_deleted_parts );
00167 
00168   // Determine if entity has already been deleted after insert
00169   // If so, return
00170   if ( m_to_delete.find ( &e ) != m_to_delete.end () )
00171     return;
00172 
00173   // Mark for deletion if the transaction type is BULK
00174   if ( m_transaction_type == BULK )
00175     m_to_delete.insert ( &e );
00176 
00177   // If this is not an incremental transaction, ignore
00178   if ( m_transaction_type != INCREMENTAL ) return;
00179 
00180   if ( e.m_trans_bucket )
00181   {
00182     if ( e.transaction_bucket()->transaction_state() == DELETED ) return;
00183     if ( e.transaction_bucket()->transaction_state() == MODIFIED )
00184     {
00185       swap_entity_between_transaction_buckets ( e , m_modified[e.entity_rank()] , m_deleted[e.entity_rank()] , DELETED );
00186       return;
00187     }
00188     if ( e.transaction_bucket()->transaction_state() == INSERTED )
00189     {
00190       remove_entity_from_bucket ( e , m_inserted[e.entity_rank()]  );
00191       // Need to mark this for deletion at reset since it will not be
00192       // stored anywhere
00193       m_to_delete.insert ( &e );
00194       return;
00195     }
00196   }
00197 
00198   Bucket *transaction_bucket = get_unfilled_transaction_bucket ( e , m_deleted[e.entity_rank()] , DELETED );
00199   add_entity_to_transaction_bucket ( e , transaction_bucket );
00200 }
00201 
00202 // If an entity is inserted into the mesh, it is placed in the insert
00203 // bucket.  If it is a member of another bucket, this function does
00204 // nothing.  It should be an error to be in another bucket and this
00205 // should be caught elsewhere.
00206 void Transaction::insert_entity ( Entity &e )
00207 {
00208 
00209   if ( e.m_trans_bucket != 0 ) return;
00210 
00211   add_parts_to_partset ( e , m_inserted_parts );
00212 
00213   // If this is not an incremental transaction, ignore
00214   if ( m_transaction_type != INCREMENTAL ) return;
00215 
00216   Bucket *transaction_bucket = get_unfilled_transaction_bucket ( e , m_inserted[e.entity_rank()] , INSERTED );
00217   add_entity_to_transaction_bucket ( e , transaction_bucket );
00218 }
00219 
00220 // Upon modification_begin() in bulk data, the transaction purges the
00221 // transaction buckets.  This function simply deallocates the bucket
00222 // and removes entities from the transaction bucket.
00223 void Transaction::purge_map ( BucketListByType &buckets )
00224 {
00225   BucketListByType::iterator cur_type = buckets.begin();
00226   while ( cur_type != buckets.end() )
00227   {
00228     BucketList::iterator cur_bucket = cur_type->begin();
00229     while ( cur_bucket != cur_type->end() )
00230     {
00231       BucketIterator  cur_entity = (*cur_bucket)->begin();
00232       while ( cur_entity != (*cur_bucket)->end() )
00233       {
00234         cur_entity->m_trans_bucket = NULL;
00235         cur_entity++;
00236       }
00237       Bucket::destroy_bucket ( *cur_bucket );
00238       cur_bucket++;
00239     }
00240     cur_type->clear();
00241     cur_type++;
00242   }
00243 
00244 }
00245 
00246 // This method will purge buckets and delete entities from memory.
00247 // This method uses the internal_destroy_entire_bucket method in
00248 // BulkData which does not, in turn, call the delete_entity
00249 // transaction function.
00250 /*
00251 void Transaction::purge_and_erase_map ( BucketListByType &buckets )
00252 {
00253   BucketListByType::iterator cur_type = buckets.begin();
00254   while ( cur_type != buckets.end() )
00255   {
00256     BucketList::iterator cur_bucket = cur_type->begin();
00257     while ( cur_bucket != cur_type->end() )
00258     {
00259       m_bulk_data.internal_destroy_entire_bucket ( *cur_bucket );
00260       cur_bucket++;
00261     }
00262     cur_type->clear();
00263     cur_type++;
00264   }
00265 }
00266 
00267 void Transaction::flush_deletes ()
00268 {
00269   for ( std::set<Entity *>::iterator  cur_del_entity = m_to_delete.begin() ; cur_del_entity != m_to_delete.end() ; cur_del_entity++ )
00270     m_bulk_data.internal_expunge_entity ( *cur_del_entity );
00271   m_to_delete.clear ();
00272 }
00273 */
00274 
00275 
00276 void Transaction::flush()
00277 {
00278   purge_map ( m_modified );
00279   purge_map ( m_inserted );
00280   purge_map ( m_deleted );
00281 
00282   m_modified_parts.clear();
00283   m_deleted_parts.clear();
00284   m_inserted_parts.clear();
00285 }
00286 
00287 // Explicity purge and erase memory as needed.
00288 void Transaction::reset ( TransactionType type )
00289 {
00290   m_transaction_type = type;
00291   flush();
00292 }
00293 
00294 void Transaction::add_parts_to_partset ( Entity &e , PartSet &pl )
00295 {
00296   PartVector  parts;
00297   e.bucket().supersets ( parts );
00298 
00299   for ( PartVector::iterator part_iter = parts.begin(); part_iter != parts.end() ; ++part_iter )
00300     pl.insert ( *part_iter );
00301 
00302 
00303 }
00304 
00305 void Transaction::translate_partset_to_partvector ( const PartSet &in , PartVector &out ) const
00306 {
00307   out.resize ( in.size() );
00308   unsigned i = 0;
00309   for ( PartSet::const_iterator cur_in = in.begin() ; cur_in != in.end() ; cur_in++ )
00310   {
00311     out[i] = *cur_in;
00312     ++i;
00313   }
00314 }
00315 
00316 // The bucket b is assumed to have enough space to add entity e.  This
00317 // is placed on the end of the array and the size is incremented.
00318 void Transaction::add_entity_to_transaction_bucket ( Entity &e , Bucket *b )
00319 {
00320   b->m_entities[b->m_size] = &e;
00321   e.m_trans_bucket = b;
00322   e.m_trans_bucket_ord = b->m_size;
00323   b->m_size++;
00324 }
00325 
00326 // Entity e is removed from ''from'' and placed in ''to''.
00327 void Transaction::swap_entity_between_transaction_buckets ( Entity &e , BucketList &from , BucketList &to , State s )
00328 {
00329   Bucket *to_bucket = get_unfilled_transaction_bucket ( e , to , s );
00330   remove_entity_from_bucket ( e , from );
00331   add_entity_to_transaction_bucket ( e , to_bucket );
00332 }
00333 
00334 
00335 // This is a wrapper around the Bucket::declare_bucket.  Each bucket
00336 // has no field data and has a copy of the key from the current bucket
00337 // the entity is in.
00338 Bucket *Transaction::get_unfilled_transaction_bucket ( const unsigned * const key , EntityRank type , BucketList &buckets , State s )
00339 {
00340   Bucket *new_bucket = Bucket::declare_bucket ( m_bulk_data ,
00341                                                 type ,
00342                                                 key[0] - 1 ,
00343                                                 key+1 ,
00344                                                 m_bulk_data.bucket_capacity() ,
00345                                                 std::vector<FieldBase *> () ,
00346                                                 buckets );
00347 
00348   new_bucket->m_transaction_state = s;
00349 
00350   return new_bucket;
00351 }
00352 
00353 
00354 // This code was copied from bulk data and used to remove entities
00355 // from buckets.  In order to remove an entity, an appropriate entity
00356 // must be found to copy into the hole.  This logic will find the
00357 // appropriate bucket which has an entity to copy into the bucket.
00358 void Transaction::remove_entity_from_bucket ( Entity &e , BucketList &buckets )
00359 {
00360   Bucket *k = e.m_trans_bucket;
00361   unsigned i = e.m_trans_bucket_ord;
00362 
00363   Bucket * const first = k->m_key[ *k->m_key ] ? k->m_bucket : k ;
00364   Bucket * const last  = first->m_bucket ;
00365 
00366   // Only move if not the last entity being removed
00367 
00368   if ( last != k || k->m_size != i + 1 ) {
00369 
00370     // Not the same bucket or not the last entity
00371 
00372     // Copy last entity in last to ik slot i
00373 
00374     Entity * const entity = last->m_entities[ last->m_size - 1 ];
00375 
00376     k->m_entities[i]     = entity ;
00377     entity->m_trans_bucket     = k ;
00378     entity->m_trans_bucket_ord = i ;
00379 
00380   }
00381 
00382   --( last->m_size );
00383 
00384   if ( last->m_size != 0 ) {
00385     last->m_entities[ last->m_size ] = NULL ;
00386   }
00387   else {
00388 
00389     // The current 'last' bucket is to be deleted.
00390     // The previous 'last' bucket becomes the
00391     // new 'last' bucket in the family:
00392 
00393     std::vector<Bucket*>::iterator ik = lower_bound(buckets, last->m_key);
00394 
00395     if ( ik == buckets.end() || last != *ik ) {
00396       throw std::runtime_error(
00397         std::string("stk::mesh::Transaction::remove_entity_from_bucket INTERNAL FAILURE") );
00398     }
00399 
00400     ik = buckets.erase( ik );
00401 
00402     if ( first != last ) { first->m_bucket = *--ik ; }
00403 
00404     Bucket::destroy_bucket( last );
00405   }
00406 
00407   e.m_trans_bucket = NULL;
00408 }
00409 
00410 
00411 }
00412 }
00413 
00414 #endif
00415 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends