TAO_Notify::Persistent_File_Allocator Class Reference

A class that manages the details of persistent storage. More...

#include <Persistent_File_Allocator.h>

Collaboration diagram for TAO_Notify::Persistent_File_Allocator:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 Persistent_File_Allocator ()
 The constructor.

 ~Persistent_File_Allocator ()
 The destructor.

bool open (const ACE_TCHAR *filename, const size_t block_size=512)
void shutdown ()
 Wait for pending I/O and terminate our work thread.

Persistent_Storage_Blockallocate ()
Persistent_Storage_Blockallocate_at (size_t block_number)
 Allocate a new Persistent_Storage_Block at a given address.

Persistent_Storage_Blockallocate_nowrite ()
 Allocate a PSB that is marked to not persist.

void used (size_t block_number)
 Mark a block as used, removing it from the free list.

void free (size_t block_number)
 Mark a block number as able to be used again.

size_t block_size () const
 Access block size.

bool read (Persistent_Storage_Block *psb)
 Read data into a PSB.

bool write (Persistent_Storage_Block *psb)
 Write this block to the file,.

size_t file_size () const
 for information (unit test) only.


Private Member Functions

void free_block (const size_t block_number)
 Free a previously assigned block.

bool allocate_block (size_t &block_number)
 Find and allocate a free block.

void shutdown_thread ()
 Wait for pending I/O to complete and shut our worker thread down safely.

void run ()
 The worker's execution thread.


Static Private Member Functions

ACE_THR_FUNC_RETURN thr_func (void *arg)

Private Attributes

ACE_Thread_Manager thread_manager_
Random_File pstore_
Bit_Vector free_blocks_
ACE_Unbounded_Queue< Persistent_Storage_Block * > block_queue_
ACE_SYNCH_MUTEX lock_
ACE_SYNCH_MUTEX free_blocks_lock_
ACE_SYNCH_MUTEX queue_lock_
bool terminate_thread_
bool thread_active_
ACE_SYNCH_CONDITION wake_up_thread_

Detailed Description

A class that manages the details of persistent storage.

Maintains a free list, write queue, allocations of new blocks, reads, and writes. This class also manages a thread that performs background updating of a Random_File. @todo this is too much for one class to do. It should be refactored. @todo: we shouldn't arbitrarily use a thread.

Definition at line 127 of file Persistent_File_Allocator.h.


Constructor & Destructor Documentation

TAO_Notify::Persistent_File_Allocator::Persistent_File_Allocator  ) 
 

The constructor.

Definition at line 127 of file Persistent_File_Allocator.cpp.

00128   : pstore_()
00129   , terminate_thread_(false)
00130   , thread_active_(false)
00131   , wake_up_thread_(queue_lock_)
00132 {
00133 }

TAO_Notify::Persistent_File_Allocator::~Persistent_File_Allocator  ) 
 

The destructor.

Definition at line 135 of file Persistent_File_Allocator.cpp.

References shutdown_thread().

00136 {
00137   this->shutdown_thread();
00138 }


Member Function Documentation

Persistent_Storage_Block * TAO_Notify::Persistent_File_Allocator::allocate  ) 
 

Allocate a new Persistent_Storage_Block and initialize it to an unused block of storage.

Definition at line 160 of file Persistent_File_Allocator.cpp.

References ACE_DEBUG, ACE_GUARD_RETURN, ACE_SYNCH_MUTEX, ACE_TEXT(), allocate_at(), allocate_block(), DEBUG_LEVEL, and LM_DEBUG.

Referenced by TAO_Notify::Routing_Slip_Persistence_Manager::build_chain(), TAO_Notify::Standard_Event_Persistence_Factory::get_preallocated_pointer(), and TAO_Notify::Routing_Slip_Persistence_Manager::store_event().

00161 {
00162   Persistent_Storage_Block* result = 0;
00163   size_t block_number = 0;
00164   ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0);
00165   if (!this->allocate_block(block_number))
00166   {
00167     //@@todo: this should never happen
00168     // why not.  What if the disk is full?  Oh, I see we
00169     // allocate non-existent blocks.  FIX this
00170   }
00171   if (DEBUG_LEVEL > 0) ACE_DEBUG ((LM_DEBUG,
00172     ACE_TEXT ("(%P|%t) Persistent_File_Allocator::allocate: %d\n"),
00173     static_cast<int> (block_number)
00174     ));
00175   result = this->allocate_at(block_number);
00176   return result;
00177 }

Persistent_Storage_Block * TAO_Notify::Persistent_File_Allocator::allocate_at size_t  block_number  ) 
 

Allocate a new Persistent_Storage_Block at a given address.

Definition at line 180 of file Persistent_File_Allocator.cpp.

References ACE_DEBUG, ACE_NEW_RETURN, ACE_TEXT(), DEBUG_LEVEL, LM_DEBUG, and used().

Referenced by allocate(), TAO_Notify::Routing_Slip_Persistence_Manager::load(), and TAO_Notify::Routing_Slip_Persistence_Manager::reload_chain().

00181 {
00182   Persistent_Storage_Block* result = 0;
00183   this->used(block_number);
00184   if (DEBUG_LEVEL > 0) ACE_DEBUG ((LM_DEBUG,
00185     ACE_TEXT ("(%P|%t) Persistent_File_Allocator::allocate at : %d\n"),
00186     static_cast<int> (block_number)
00187     ));
00188   ACE_NEW_RETURN(result, Persistent_Storage_Block(
00189     block_number,
00190     this->block_size()),
00191     0);
00192   return result;
00193 }

bool TAO_Notify::Persistent_File_Allocator::allocate_block size_t &  block_number  )  [private]
 

Find and allocate a free block.

Definition at line 306 of file Persistent_File_Allocator.cpp.

References ACE_GUARD_RETURN, ACE_SYNCH_MUTEX, TAO_Notify::Bit_Vector::find_first_bit(), and free_blocks_.

Referenced by allocate().

00307 {
00308   ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->free_blocks_lock_, 0);
00309   block_number = this->free_blocks_.find_first_bit(false);
00310   return true;
00311 }

Persistent_Storage_Block * TAO_Notify::Persistent_File_Allocator::allocate_nowrite  ) 
 

Allocate a PSB that is marked to not persist.

Definition at line 196 of file Persistent_File_Allocator.cpp.

References ACE_NEW_RETURN, and TAO_Notify::Persistent_Storage_Block::set_no_write().

Referenced by TAO_Notify::Routing_Slip_Persistence_Manager::remove(), TAO_Notify::Routing_Slip_Persistence_Manager::store_i(), and TAO_Notify::Routing_Slip_Persistence_Manager::update_i().

00197 {
00198   Persistent_Storage_Block* result = 0;
00199   ACE_NEW_RETURN (result,
00200                   Persistent_Storage_Block (static_cast<size_t> (~0), 0),
00201                   0);
00202   result->set_no_write();
00203 
00204   return result;
00205 }

size_t TAO_Notify::Persistent_File_Allocator::block_size  )  const
 

Access block size.

Definition at line 231 of file Persistent_File_Allocator.cpp.

References TAO_Notify::Random_File::block_size(), and pstore_.

Referenced by TAO_Notify::Routing_Slip_Persistence_Manager::fill_block(), TAO_Notify::Routing_Slip_Persistence_Manager::load(), read(), and TAO_Notify::Routing_Slip_Persistence_Manager::reload_chain().

00232 {
00233   return pstore_.block_size();
00234 }

size_t TAO_Notify::Persistent_File_Allocator::file_size  )  const
 

for information (unit test) only.

Definition at line 322 of file Persistent_File_Allocator.cpp.

References pstore_, and TAO_Notify::Random_File::size().

00323 {
00324   return this->pstore_.size ();
00325 }

void TAO_Notify::Persistent_File_Allocator::free size_t  block_number  ) 
 

Mark a block number as able to be used again.

Definition at line 220 of file Persistent_File_Allocator.cpp.

References ACE_ASSERT, ACE_DEBUG, ACE_TEXT(), DEBUG_LEVEL, free_block(), and LM_DEBUG.

Referenced by TAO_Notify::Routing_Slip_Persistence_Manager::build_chain(), and TAO_Notify::Routing_Slip_Persistence_Manager::remove().

00221 {
00222   if (DEBUG_LEVEL > 0) ACE_DEBUG ((LM_DEBUG,
00223     ACE_TEXT ("(%P|%t) Persistent_File_Allocator::free: %d\n"),
00224     static_cast<int> (block_number)
00225     ));
00226   ACE_ASSERT (this->free_blocks_.is_set (block_number));
00227   this->free_block(block_number);
00228 }

void TAO_Notify::Persistent_File_Allocator::free_block const size_t  block_number  )  [private]
 

Free a previously assigned block.

Definition at line 298 of file Persistent_File_Allocator.cpp.

References ACE_ASSERT, ACE_GUARD, ACE_SYNCH_MUTEX, free_blocks_, and TAO_Notify::Bit_Vector::set_bit().

Referenced by free().

00299 {
00300   ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->free_blocks_lock_);
00301   ACE_ASSERT (this->free_blocks_.is_set (block_number));
00302   this->free_blocks_.set_bit(block_number, false);
00303 }

bool TAO_Notify::Persistent_File_Allocator::open const ACE_TCHAR filename,
const size_t  block_size = 512
 

Definition at line 141 of file Persistent_File_Allocator.cpp.

References TAO_Notify::Random_File::open(), pstore_, ACE_Thread_Manager::spawn(), and thread_active_.

Referenced by TAO_Notify::Standard_Event_Persistence_Factory::open().

00143 {
00144   bool file_opened = this->pstore_.open(filename, block_size);
00145   if (file_opened)
00146   {
00147     this->thread_active_ = true;
00148     this->thread_manager_.spawn(this->thr_func, this);
00149   }
00150   return file_opened;
00151 }

bool TAO_Notify::Persistent_File_Allocator::read Persistent_Storage_Block psb  ) 
 

Read data into a PSB.

Data will come either from the queue of blocks to be written, or it will be read from the file if there are no queued write requests for this block.

Definition at line 237 of file Persistent_File_Allocator.cpp.

References ACE_GUARD_RETURN, ACE_SYNCH_MUTEX, TAO_Notify::Persistent_Storage_Block::block_number(), block_queue_, block_size(), TAO_Notify::Persistent_Storage_Block::data(), ACE_Unbounded_Queue< Persistent_Storage_Block * >::get(), ACE_OS::memcpy(), pstore_, TAO_Notify::Random_File::read(), ACE_Unbounded_Queue< Persistent_Storage_Block * >::size(), and thread_active_.

Referenced by TAO_Notify::Routing_Slip_Persistence_Manager::reload_chain().

00238 {
00239   bool result = this->thread_active_;
00240   bool cached = false;
00241   if (result)
00242   {
00243     Persistent_Storage_Block** psbtemp = 0;
00244     {
00245       ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->queue_lock_, false);
00246       size_t queue_size = this->block_queue_.size();
00247       for (size_t idx = 0; !cached && (idx < queue_size); ++idx)
00248       {
00249         // We want to start at the end of the queue and work backwards...
00250         size_t actual_block = (queue_size - idx) - 1;
00251         if (0 == this->block_queue_.get(psbtemp, actual_block))
00252         {
00253           cached = ((*psbtemp)->block_number() == psb->block_number());
00254         }
00255       }
00256       // this needs to be done in the guarded section
00257       if (cached && (0 != psbtemp))
00258       {
00259         ACE_OS::memcpy(psb->data(), (*psbtemp)->data(), this->block_size());
00260       }
00261     }
00262     if (!cached)
00263     {
00264       result = pstore_.read(psb->block_number(), psb->data());
00265     }
00266   }
00267   return result;
00268 }

void TAO_Notify::Persistent_File_Allocator::run  )  [private]
 

The worker's execution thread.

Definition at line 344 of file Persistent_File_Allocator.cpp.

References ACE_ASSERT, ACE_GUARD, ACE_SYNCH_MUTEX, TAO_Notify::Persistent_Storage_Block::block_number(), block_queue_, TAO_Notify::Persistent_Storage_Block::data(), ACE_Unbounded_Queue< Persistent_Storage_Block * >::dequeue_head(), ACE_Unbounded_Queue< Persistent_Storage_Block * >::get(), TAO_Notify::Persistent_Storage_Block::get_allocator_owns(), TAO_Notify::Persistent_Storage_Block::get_callback(), TAO_Notify::Persistent_Storage_Block::get_no_write(), TAO_Notify::Persistent_Storage_Block::get_sync(), ACE_Unbounded_Queue< Persistent_Storage_Block * >::is_empty(), TAO_Notify::Persistent_Callback::persist_complete(), pstore_, terminate_thread_, thread_active_, wake_up_thread_, and TAO_Notify::Random_File::write().

Referenced by thr_func().

00345 {
00346   // We need this because we could be working on writing data
00347   // when a call to terminate comes in!
00348   bool do_more_work = true;
00349   while (do_more_work)
00350   {
00351     do_more_work = false;
00352     Persistent_Storage_Block * blk = 0;
00353     {
00354       ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->queue_lock_);
00355       while (this->block_queue_.is_empty() && !terminate_thread_)
00356       {
00357         this->wake_up_thread_.wait();
00358       }
00359       // Awkward interface to peek at head of unbounded queue
00360       Persistent_Storage_Block ** pblk = 0;
00361       if (0 == this->block_queue_.get(pblk))
00362       {
00363         do_more_work = true;
00364         blk = *pblk;
00365       }
00366     }
00367     if (0 != blk)
00368     {
00369       Persistent_Callback *callback = blk->get_callback();
00370       if (!blk->get_no_write())
00371       {
00372         pstore_.write(blk->block_number(), blk->data(), blk->get_sync());
00373       }
00374       {
00375         Persistent_Storage_Block * blk2 = 0;
00376         ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->queue_lock_);
00377         this->block_queue_.dequeue_head (blk2);
00378         // if this triggers, someone pushed onto the head of the queue
00379         // or removed the head from the queue without telling ME.
00380         ACE_ASSERT (blk2 == blk);
00381       }
00382       // If we own the block, then delete it.
00383       if (blk->get_allocator_owns())
00384       {
00385         delete blk;
00386         blk = 0;
00387       }
00388       if (0 != callback)
00389       {
00390         callback->persist_complete();
00391       }
00392     }
00393   }
00394   this->terminate_thread_ = false;
00395   this->thread_active_ = false;
00396 }

void TAO_Notify::Persistent_File_Allocator::shutdown  ) 
 

Wait for pending I/O and terminate our work thread.

Definition at line 154 of file Persistent_File_Allocator.cpp.

References shutdown_thread().

Referenced by TAO_Notify::Standard_Event_Persistence_Factory::~Standard_Event_Persistence_Factory().

00155 {
00156   this->shutdown_thread();
00157 }

void TAO_Notify::Persistent_File_Allocator::shutdown_thread  )  [private]
 

Wait for pending I/O to complete and shut our worker thread down safely.

Definition at line 328 of file Persistent_File_Allocator.cpp.

References ACE_ASSERT, ACE_GUARD, ACE_SYNCH_MUTEX, ACE_Thread_Manager::close(), terminate_thread_, thread_active_, and wake_up_thread_.

Referenced by shutdown(), and ~Persistent_File_Allocator().

00329 {
00330   if (this->thread_active_)
00331   {
00332     {
00333       ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->queue_lock_);
00334       this->terminate_thread_ = true;
00335       this->wake_up_thread_.signal();
00336     }
00337     this->thread_manager_.close();
00338     ACE_ASSERT (!this->terminate_thread_);
00339     ACE_ASSERT (!this->thread_active_);
00340   }
00341 }

ACE_THR_FUNC_RETURN TAO_Notify::Persistent_File_Allocator::thr_func void *  arg  )  [static, private]
 

Used during thread startup to cast us back to ourselves and call the run() method.

Definition at line 314 of file Persistent_File_Allocator.cpp.

References run().

00315 {
00316   Persistent_File_Allocator* pfa = static_cast<Persistent_File_Allocator*> (arg);
00317   pfa->run();
00318   return 0;
00319 }

void TAO_Notify::Persistent_File_Allocator::used size_t  block_number  ) 
 

Mark a block as used, removing it from the free list.

Definition at line 208 of file Persistent_File_Allocator.cpp.

References ACE_ASSERT, ACE_DEBUG, ACE_GUARD, ACE_SYNCH_MUTEX, ACE_TEXT(), DEBUG_LEVEL, free_blocks_, LM_DEBUG, and TAO_Notify::Bit_Vector::set_bit().

Referenced by allocate_at().

00209 {
00210   ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->free_blocks_lock_);
00211   if (DEBUG_LEVEL > 0) ACE_DEBUG ((LM_DEBUG,
00212     ACE_TEXT ("(%P|%t) Persistent_File_Allocator::used: %d\n"),
00213     static_cast<int> (block_number)
00214     ));
00215   ACE_ASSERT (!this->free_blocks_.is_set (block_number));
00216   this->free_blocks_.set_bit(block_number, true);
00217 }

bool TAO_Notify::Persistent_File_Allocator::write Persistent_Storage_Block psb  ) 
 

Write this block to the file,.

Add the Persistent_Storage_Block to our write queue and let the worker thread handle writing this to the Random_File.

Definition at line 271 of file Persistent_File_Allocator.cpp.

References ACE_DEBUG, ACE_GUARD_RETURN, ACE_NEW_RETURN, ACE_SYNCH_MUTEX, ACE_TEXT(), TAO_Notify::Persistent_Storage_Block::block_number(), block_queue_, DEBUG_LEVEL, ACE_Unbounded_Queue< Persistent_Storage_Block * >::enqueue_tail(), TAO_Notify::Persistent_Storage_Block::get_allocator_owns(), LM_DEBUG, TAO_Notify::Persistent_Storage_Block::set_allocator_owns(), thread_active_, and wake_up_thread_.

Referenced by TAO_Notify::Routing_Slip_Persistence_Manager::build_chain(), TAO_Notify::Routing_Slip_Persistence_Manager::remove(), TAO_Notify::Routing_Slip_Persistence_Manager::store_event(), TAO_Notify::Routing_Slip_Persistence_Manager::store_i(), TAO_Notify::Routing_Slip_Persistence_Manager::store_root(), TAO_Notify::Routing_Slip_Persistence_Manager::update_i(), and TAO_Notify::Routing_Slip_Persistence_Manager::write_first_routing_slip_block().

00272 {
00273   bool result = this->thread_active_;
00274   if (result)
00275   {
00276     Persistent_Storage_Block* ourpsb = psb;
00277     if (!psb->get_allocator_owns())
00278     {
00279       if (DEBUG_LEVEL) ACE_DEBUG ((LM_DEBUG,
00280         ACE_TEXT ("(%P|%t) Copy PSB %d\n")
00281         , static_cast<int> (psb->block_number ())
00282         ));
00283       ACE_NEW_RETURN(ourpsb, Persistent_Storage_Block(*psb), false);
00284       ourpsb->set_allocator_owns(true);
00285     }
00286     ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->queue_lock_, false);
00287     if (DEBUG_LEVEL) ACE_DEBUG ((LM_DEBUG,
00288       ACE_TEXT ("(%P|%t) Queueing PSB to write block %d\n")
00289       , static_cast<int> (psb->block_number ())
00290       ));
00291     result = (0 == this->block_queue_.enqueue_tail(ourpsb));
00292     this->wake_up_thread_.signal();
00293   }
00294   return result;
00295 }


Member Data Documentation

ACE_Unbounded_Queue<Persistent_Storage_Block*> TAO_Notify::Persistent_File_Allocator::block_queue_ [private]
 

Definition at line 194 of file Persistent_File_Allocator.h.

Referenced by read(), run(), and write().

Bit_Vector TAO_Notify::Persistent_File_Allocator::free_blocks_ [private]
 

Definition at line 193 of file Persistent_File_Allocator.h.

Referenced by allocate_block(), free_block(), and used().

ACE_SYNCH_MUTEX TAO_Notify::Persistent_File_Allocator::free_blocks_lock_ [private]
 

Definition at line 196 of file Persistent_File_Allocator.h.

ACE_SYNCH_MUTEX TAO_Notify::Persistent_File_Allocator::lock_ [private]
 

Definition at line 195 of file Persistent_File_Allocator.h.

Random_File TAO_Notify::Persistent_File_Allocator::pstore_ [private]
 

Definition at line 192 of file Persistent_File_Allocator.h.

Referenced by block_size(), file_size(), open(), read(), and run().

ACE_SYNCH_MUTEX TAO_Notify::Persistent_File_Allocator::queue_lock_ [private]
 

Definition at line 197 of file Persistent_File_Allocator.h.

bool TAO_Notify::Persistent_File_Allocator::terminate_thread_ [private]
 

Definition at line 198 of file Persistent_File_Allocator.h.

Referenced by run(), and shutdown_thread().

bool TAO_Notify::Persistent_File_Allocator::thread_active_ [private]
 

Definition at line 199 of file Persistent_File_Allocator.h.

Referenced by open(), read(), run(), shutdown_thread(), and write().

ACE_Thread_Manager TAO_Notify::Persistent_File_Allocator::thread_manager_ [private]
 

Definition at line 191 of file Persistent_File_Allocator.h.

ACE_SYNCH_CONDITION TAO_Notify::Persistent_File_Allocator::wake_up_thread_ [private]
 

Definition at line 200 of file Persistent_File_Allocator.h.

Referenced by run(), shutdown_thread(), and write().


The documentation for this class was generated from the following files:
Generated on Thu Nov 9 13:34:15 2006 for TAO_CosNotification by doxygen 1.3.6