diff options
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/Notify/Persistent_File_Allocator.h')
-rw-r--r-- | TAO/orbsvcs/orbsvcs/Notify/Persistent_File_Allocator.h | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/TAO/orbsvcs/orbsvcs/Notify/Persistent_File_Allocator.h b/TAO/orbsvcs/orbsvcs/Notify/Persistent_File_Allocator.h new file mode 100644 index 00000000000..718be6e8f54 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Notify/Persistent_File_Allocator.h @@ -0,0 +1,208 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Persistent_File_Allocator.h + * + * $Id$ + * + * A Persistent_File_Allocator manages a free list and allocates and + * deallocates blocks from a Random_File. There should be only one + * Persistent_File_Allocator for each Random_File. + * + * @author Jonathan Pollack <pollack_j@ociweb.com> + */ +//============================================================================= + +#ifndef PERSISTENT_FILE_ALLOCATOR_H +#define PERSISTENT_FILE_ALLOCATOR_H +#include /**/ "ace/pre.h" +#include /**/ "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "orbsvcs/Notify/notify_serv_export.h" +#include "orbsvcs/Notify/Random_File.h" +#include "orbsvcs/Notify/Bit_Vector.h" +#include "ace/Containers_T.h" +#include "ace/Unbounded_Queue.h" +#include "ace/Thread_Manager.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace TAO_Notify +{ + +/// \brief An interface to allow callbacks on completion of persistent storage +/// requests. +class TAO_Notify_Serv_Export Persistent_Callback +{ +public: + virtual ~Persistent_Callback(); + /// \brief Called by a Persistent_File_Allocator when a write request has + /// completed. + virtual void persist_complete() = 0; +}; + +/** + * \brief A class to represent a block on disk. + * + * Contains the raw data to be written on disk as well as + * positioning information, synchronization information, and a pointer + * to a callback. + */ +class TAO_Notify_Serv_Export Persistent_Storage_Block +{ +public: + /// The constructor. Initializes the callback to NULL. + Persistent_Storage_Block( + const size_t block_number, + const size_t block_size); + /// The copy constructor. Makes a deep copy of the passed in PSB. + Persistent_Storage_Block(const Persistent_Storage_Block& psb); + /// The destructor. + ~Persistent_Storage_Block(); + + /// Set our block to not have any data at all - a no-op. This can be + /// used to implement a checkpoint in the write stream. + void set_no_write(); + /// Find out whether we have data to be written. + bool get_no_write(); + + /// Set our block to be written as a near-atomic operation. + void set_sync(); + /// Find out whether this block should be written near-atomically. + bool get_sync() const; + + /// Find out our physical block number. + size_t block_number() const; + + /// Return our data to the user. + unsigned char* data() const; + /// Set our data pointer, and optionally delete it. + void reassign_data(unsigned char* newptr, bool delete_old = false); + + /// Return block number and relinquish ownership. + size_t detach (); + + /// Set our callback. + void set_callback(Persistent_Callback* callback); + /// Get our callback. + Persistent_Callback* get_callback() const; + + /// Set ownership of this PSB. + void set_allocator_owns(bool allocator_owns = true); + /// Get ownership status of this PSB. + bool get_allocator_owns() const; + +private: + /// Our raw data. + unsigned char* data_; + /// The block number corresponding to our data. + size_t block_number_; + /// Are we a no-op with just a callback? + bool no_write_; + /// Write in near-atomic fashion. + bool sync_; + /// The size of our block. + size_t block_size_; + /// Our optional callback function, to be used in such things as state + /// transitions. + Persistent_Callback* callback_; + /// Does the allocator obtain ownership of our block? + bool allocator_owns_; +}; + +/** + * \brief 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. + */ +class TAO_Notify_Serv_Export Persistent_File_Allocator +{ +public: + /// The constructor. + Persistent_File_Allocator(); + /// The destructor. + ~Persistent_File_Allocator(); + + bool open (const ACE_TCHAR* filename, + const size_t block_size = 512); + + /// \brief Wait for pending I/O and terminate our work thread. + void shutdown(); + + /// Allocate a new Persistent_Storage_Block and initialize it to an unused + /// block of storage. + Persistent_Storage_Block* allocate(); + + /// \brief Allocate a new Persistent_Storage_Block at a given address + Persistent_Storage_Block* allocate_at(size_t block_number); + + /// \brief Allocate a PSB that is marked to not persist + Persistent_Storage_Block* allocate_nowrite(); + + /// \brief Mark a block as used, removing it from the free list. + void used(size_t block_number); + + /// \brief Mark a block number as able to be used again. + void free(size_t block_number); + + /// \brief Access block size. + size_t block_size() const; + + /// \brief 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. + bool read(Persistent_Storage_Block* psb); + + /// \brief 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. + bool write(Persistent_Storage_Block* psb); + + /// for information (unit test) only. + size_t file_size () const; + +private: + /// Free a previously assigned block. + void free_block(const size_t block_number); + /// Find and allocate a free block. + bool allocate_block(size_t& block_number); + + /// Used during thread startup to cast us back to ourselves and call the + /// run() method. + static ACE_THR_FUNC_RETURN thr_func(void * arg); + /// Wait for pending I/O to complete and shut our worker thread down safely. + void shutdown_thread(); + /// The worker's execution thread. + void run(); + +private: + 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_; +}; + +} /* namespace TAO_Notify */ + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* PERSISTENT_FILE_ALLOCATOR_H */ |