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,.
ACE_OFF_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

static 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_
TAO_SYNCH_MUTEX lock_
TAO_SYNCH_MUTEX free_blocks_lock_
TAO_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.

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_TEXT(), allocate_at(), DEBUG_LEVEL, LM_DEBUG, and TAO_SYNCH_MUTEX.

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 (TAO_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 307 of file Persistent_File_Allocator.cpp.

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

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

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 }

ACE_OFF_T TAO_Notify::Persistent_File_Allocator::file_size (  )  const

for information (unit test) only.

Definition at line 323 of file Persistent_File_Allocator.cpp.

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

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

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::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 299 of file Persistent_File_Allocator.cpp.

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

Referenced by free().

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

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(), thread_active_, and thread_manager_.

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, TAO_Notify::Persistent_Storage_Block::block_number(), block_queue_, block_size(), TAO_Notify::Persistent_Storage_Block::data(), ACE_OS::memcpy(), pstore_, TAO_Notify::Random_File::read(), TAO_SYNCH_MUTEX, 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 (TAO_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             && (psbtemp != 0))
00253         {
00254           cached = ((*psbtemp)->block_number() == psb->block_number());
00255         }
00256       }
00257       // this needs to be done in the guarded section
00258       if (cached && (0 != psbtemp))
00259       {
00260         ACE_OS::memcpy(psb->data(), (*psbtemp)->data(), this->block_size());
00261       }
00262     }
00263     if (!cached)
00264     {
00265       result = pstore_.read(psb->block_number(), psb->data());
00266     }
00267   }
00268   return result;
00269 }

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

The worker's execution thread.

Definition at line 345 of file Persistent_File_Allocator.cpp.

References ACE_ASSERT, ACE_GUARD, TAO_Notify::Persistent_Storage_Block::block_number(), block_queue_, TAO_Notify::Persistent_Storage_Block::data(), 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(), TAO_Notify::Persistent_Callback::persist_complete(), pstore_, TAO_SYNCH_MUTEX, terminate_thread_, thread_active_, and TAO_Notify::Random_File::write().

Referenced by thr_func().

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

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 329 of file Persistent_File_Allocator.cpp.

References ACE_ASSERT, ACE_GUARD, ACE_Thread_Manager::close(), TAO_SYNCH_MUTEX, terminate_thread_, thread_manager_, and wake_up_thread_.

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

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

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 315 of file Persistent_File_Allocator.cpp.

References run().

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

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_TEXT(), DEBUG_LEVEL, free_blocks_, LM_DEBUG, TAO_Notify::Bit_Vector::set_bit(), and TAO_SYNCH_MUTEX.

Referenced by allocate_at().

00209 {
00210   ACE_GUARD (TAO_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 272 of file Persistent_File_Allocator.cpp.

References ACE_DEBUG, ACE_GUARD_RETURN, ACE_NEW_RETURN, ACE_TEXT(), TAO_Notify::Persistent_Storage_Block::block_number(), block_queue_, DEBUG_LEVEL, TAO_Notify::Persistent_Storage_Block::get_allocator_owns(), LM_DEBUG, TAO_Notify::Persistent_Storage_Block::set_allocator_owns(), TAO_SYNCH_MUTEX, 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().

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


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().

TAO_SYNCH_MUTEX TAO_Notify::Persistent_File_Allocator::free_blocks_lock_ [private]

Definition at line 196 of file Persistent_File_Allocator.h.

TAO_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().

TAO_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(), and write().

ACE_Thread_Manager TAO_Notify::Persistent_File_Allocator::thread_manager_ [private]

Definition at line 191 of file Persistent_File_Allocator.h.

Referenced by open(), and shutdown_thread().

ACE_SYNCH_CONDITION TAO_Notify::Persistent_File_Allocator::wake_up_thread_ [private]

Definition at line 200 of file Persistent_File_Allocator.h.

Referenced by shutdown_thread(), and write().


The documentation for this class was generated from the following files:
Generated on Tue Feb 2 17:46:42 2010 for TAO_CosNotification by  doxygen 1.4.7