#include <Persistent_File_Allocator.h>
Collaboration diagram for TAO_Notify::Persistent_File_Allocator:
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_Block * | allocate () |
Persistent_Storage_Block * | allocate_at (size_t block_number) |
Allocate a new Persistent_Storage_Block at a given address. | |
Persistent_Storage_Block * | allocate_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_ |
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.
we shouldn't arbitrarily use a thread.
Definition at line 127 of file Persistent_File_Allocator.h.
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 }
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 }
ACE_Unbounded_Queue<Persistent_Storage_Block*> TAO_Notify::Persistent_File_Allocator::block_queue_ [private] |
Definition at line 194 of file Persistent_File_Allocator.h.
Definition at line 193 of file Persistent_File_Allocator.h.
Referenced by allocate_block(), free_block(), and used().
Definition at line 196 of file Persistent_File_Allocator.h.
Definition at line 195 of file Persistent_File_Allocator.h.
Definition at line 192 of file Persistent_File_Allocator.h.
Referenced by block_size(), file_size(), open(), read(), and run().
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 191 of file Persistent_File_Allocator.h.
Referenced by open(), and shutdown_thread().
Definition at line 200 of file Persistent_File_Allocator.h.
Referenced by shutdown_thread(), and write().