Persistent_File_Allocator.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 //=============================================================================
00004 /**
00005  *  @file    Persistent_File_Allocator.h
00006  *
00007  *  Persistent_File_Allocator.h,v 1.6 2006/03/14 06:14:34 jtc Exp
00008  *
00009  *  A Persistent_File_Allocator manages a free list and allocates and
00010  *  deallocates blocks from a Random_File.  There should be only one
00011  *  Persistent_File_Allocator for each Random_File.
00012  *
00013  *  @author Jonathan Pollack <pollack_j@ociweb.com>
00014  */
00015 //=============================================================================
00016 
00017 #ifndef PERSISTENT_FILE_ALLOCATOR_H
00018 #define PERSISTENT_FILE_ALLOCATOR_H
00019 #include /**/ "ace/pre.h"
00020 #include /**/ "ace/config-all.h"
00021 
00022 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00023 #pragma once
00024 #endif /* ACE_LACKS_PRAGMA_ONCE */
00025 
00026 #include "orbsvcs/Notify/notify_serv_export.h"
00027 #include "orbsvcs/Notify/Random_File.h"
00028 #include "orbsvcs/Notify/Bit_Vector.h"
00029 #include "ace/Containers_T.h"
00030 #include "ace/Unbounded_Queue.h"
00031 #include "ace/Thread_Manager.h"
00032 
00033 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00034 
00035 namespace TAO_Notify
00036 {
00037 
00038 /// \brief An interface to allow callbacks on completion of persistent storage
00039 /// requests.
00040 class TAO_Notify_Serv_Export Persistent_Callback
00041 {
00042 public:
00043   virtual ~Persistent_Callback();
00044   /// \brief Called by a Persistent_File_Allocator when a write request has
00045   /// completed.
00046   virtual void persist_complete() = 0;
00047 };
00048 
00049 /**
00050  * \brief A class to represent a block on disk.
00051  *
00052  * Contains the raw data to be written on disk as well as
00053  * positioning information, synchronization information, and a pointer
00054  * to a callback.
00055  */
00056 class TAO_Notify_Serv_Export Persistent_Storage_Block
00057 {
00058 public:
00059   /// The constructor.  Initializes the callback to NULL.
00060   Persistent_Storage_Block(
00061     const size_t block_number,
00062     const size_t block_size);
00063   /// The copy constructor.  Makes a deep copy of the passed in PSB.
00064   Persistent_Storage_Block(const Persistent_Storage_Block& psb);
00065   /// The destructor.
00066   ~Persistent_Storage_Block();
00067 
00068   /// Set our block to not have any data at all - a no-op.  This can be
00069   /// used to implement a checkpoint in the write stream.
00070   void set_no_write();
00071   /// Find out whether we have data to be written.
00072   bool get_no_write();
00073 
00074   /// Set our block to be written as a near-atomic operation.
00075   void set_sync();
00076   /// Find out whether this block should be written near-atomically.
00077   bool get_sync() const;
00078 
00079   /// Find out our physical block number.
00080   size_t block_number() const;
00081 
00082   /// Return our data to the user.
00083   unsigned char* data() const;
00084   /// Set our data pointer, and optionally delete it.
00085   void reassign_data(unsigned char* newptr, bool delete_old = false);
00086 
00087   /// Return block number and relinquish ownership.
00088   size_t detach ();
00089 
00090   /// Set our callback.
00091   void set_callback(Persistent_Callback* callback);
00092   /// Get our callback.
00093   Persistent_Callback* get_callback() const;
00094 
00095   /// Set ownership of this PSB.
00096   void set_allocator_owns(bool allocator_owns = true);
00097   /// Get ownership status of this PSB.
00098   bool get_allocator_owns() const;
00099 
00100 private:
00101   /// Our raw data.
00102   unsigned char* data_;
00103   /// The block number corresponding to our data.
00104   size_t block_number_;
00105   /// Are we a no-op with just a callback?
00106   bool no_write_;
00107   /// Write in near-atomic fashion.
00108   bool sync_;
00109   /// The size of our block.
00110   size_t block_size_;
00111   /// Our optional callback function, to be used in such things as state
00112   /// transitions.
00113   Persistent_Callback* callback_;
00114   /// Does the allocator obtain ownership of our block?
00115   bool allocator_owns_;
00116 };
00117 
00118 /**
00119  * \brief A class that manages the details of persistent storage.
00120  *
00121  * Maintains a free list, write queue, allocations of new
00122  * blocks, reads, and writes.  This class also manages a thread that performs
00123  * background updating of a Random_File.
00124  * @@todo this is too much for one class to do.  It should be refactored.
00125  * @@todo: we shouldn't arbitrarily use a thread.
00126  */
00127 class TAO_Notify_Serv_Export Persistent_File_Allocator
00128 {
00129 public:
00130   /// The constructor.
00131   Persistent_File_Allocator();
00132   /// The destructor.
00133   ~Persistent_File_Allocator();
00134 
00135   bool open (const ACE_TCHAR* filename,
00136     const size_t block_size = 512);
00137 
00138   /// \brief Wait for pending I/O and terminate our work thread.
00139   void shutdown();
00140 
00141   /// Allocate a new Persistent_Storage_Block and initialize it to an unused
00142   /// block of storage.
00143   Persistent_Storage_Block* allocate();
00144 
00145   /// \brief Allocate a new Persistent_Storage_Block at a given address
00146   Persistent_Storage_Block* allocate_at(size_t block_number);
00147 
00148   /// \brief Allocate a PSB that is marked to not persist
00149   Persistent_Storage_Block* allocate_nowrite();
00150 
00151   /// \brief Mark a block as used, removing it from the free list.
00152   void used(size_t block_number);
00153 
00154   /// \brief Mark a block number as able to be used again.
00155   void free(size_t block_number);
00156 
00157   /// \brief Access block size.
00158   size_t block_size() const;
00159 
00160   /// \brief Read data into a PSB.
00161   ///
00162   /// Data will come either from the queue of blocks to be written, or
00163   /// it will be read from the file if there are no queued write requests for
00164   /// this block.
00165   bool read(Persistent_Storage_Block* psb);
00166 
00167   /// \brief Write this block to the file,
00168   ///
00169   /// Add the Persistent_Storage_Block to our write queue and let the
00170   /// worker thread handle writing this to the Random_File.
00171   bool write(Persistent_Storage_Block* psb);
00172 
00173   /// for information (unit test) only.
00174   size_t file_size () const;
00175 
00176 private:
00177   /// Free a previously assigned block.
00178   void free_block(const size_t block_number);
00179   /// Find and allocate a free block.
00180   bool allocate_block(size_t& block_number);
00181 
00182   /// Used during thread startup to cast us back to ourselves and call the
00183   /// run() method.
00184   static ACE_THR_FUNC_RETURN thr_func(void * arg);
00185   /// Wait for pending I/O to complete and shut our worker thread down safely.
00186   void shutdown_thread();
00187   /// The worker's execution thread.
00188   void run();
00189 
00190 private:
00191   ACE_Thread_Manager thread_manager_;
00192   Random_File pstore_;
00193   Bit_Vector free_blocks_;
00194   ACE_Unbounded_Queue<Persistent_Storage_Block*> block_queue_;
00195   ACE_SYNCH_MUTEX lock_;
00196   ACE_SYNCH_MUTEX free_blocks_lock_;
00197   ACE_SYNCH_MUTEX queue_lock_;
00198   bool terminate_thread_;
00199   bool thread_active_;
00200   ACE_SYNCH_CONDITION wake_up_thread_;
00201 };
00202 
00203 } /* namespace TAO_Notify */
00204 
00205 TAO_END_VERSIONED_NAMESPACE_DECL
00206 
00207 #include /**/ "ace/post.h"
00208 #endif /* PERSISTENT_FILE_ALLOCATOR_H */

Generated on Thu Nov 9 13:24:13 2006 for TAO_CosNotification by doxygen 1.3.6