// -*- C++ -*- //============================================================================= /** * @file Filecache.h * * $Id$ * * @author James Hu */ //============================================================================= #ifndef ACE_FILECACHE_H #define ACE_FILECACHE_H #include /**/ "ace/pre.h" #include "ace/Mem_Map.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Hash_Map_Manager_T.h" #include "ace/Null_Mutex.h" #include "ace/Synch_Traits.h" #include "ace/RW_Thread_Mutex.h" #include "ace/OS_NS_sys_stat.h" ACE_BEGIN_VERSIONED_NAMESPACE_DECL enum ACE_Filecache_Flag { ACE_NOMAP = 0, ACE_MAPIT = 1 }; class ACE_Filecache_Object; /** * @class ACE_Filecache_Handle * * @brief Abstraction over a real file. This is meant to be the entry * point into the Cached Virtual Filesystem. * * This is a cached filesystem implementation based loosely on the * implementation of JAWS_File. The interfaces will be nearly the * same. The under-the-hood implementation should hopefully be a * much faster thing. * These will be given their own implementations later. For now, we * borrow the implementation provided by JAWS. * On creation, the cache is checked, and reference count is * incremented. On destruction, reference count is decremented. If * the reference count is 0, the file is removed from the cache. * E.g. 1, * { * ACE_Filecache_Handle foo("foo.html"); * this->peer ().send (foo.address (), foo.size ()); * } * E.g. 2, * { * ACE_Filecache_Handle foo("foo.html"); * io->transmitfile (foo.handle (), this->peer ().handle ()); * } * E.g. 3, * { * ACE_Filecache_Handle foo("foo.html", content_length); * this->peer ().recv (foo.address (), content_length); * } * TODO: */ class ACE_Export ACE_Filecache_Handle { // (1) Get rid of the useless copying of files when reading. // Although it does make sure the file you send isn't being changed, // it doesn't make sure the file is in a sensible state before // sending it. // // Alternative: if the file get's trashed while it is being shipped, // let the client request the file again. The cache should have an // updated copy by that point. // // (2) Use hashing for locating files. This means I need a hastable // implementation with buckets. // // (3) Only lock when absolutely necessary. JAWS_Virtual_Filesystem was // rather conservative, but for some reason it still ran into problems. // Since this design should be simpler, problems should be easier to spot. // public: /// Query cache for file, and acquire it. Assumes the file is being /// opened for reading. ACE_Filecache_Handle (const ACE_TCHAR *filename, ACE_Filecache_Flag mapit = ACE_MAPIT); /** * Create new entry, and acquire it. Presence of SIZE assumes the * file is being opened for writing. If SIZE is zero, assumes the * file is to be removed from the cache. */ ACE_Filecache_Handle (const ACE_TCHAR *filename, int size, ACE_Filecache_Flag mapit = ACE_MAPIT); /// Closes any open handles, release acquired file. ~ACE_Filecache_Handle (void); /// Base address of memory mapped file. void *address (void) const; /// A handle (e.g., UNIX file descriptor, or NT file handle). ACE_HANDLE handle (void) const; /// Any associated error in handle creation and acquisition. int error (void) const; /// The size of the file. off_t size (void) const; protected: /// Default do nothing constructor. Prevent it from being called. ACE_Filecache_Handle (void); /// Common initializations for constructors. void init (void); public: /// These come from ACE_Filecache_Object, which is an internal class. enum { ACE_SUCCESS = 0, ACE_ACCESS_FAILED, ACE_OPEN_FAILED, ACE_COPY_FAILED, ACE_STAT_FAILED, ACE_MEMMAP_FAILED, ACE_WRITE_FAILED }; private: /// A reference to the low level instance. ACE_Filecache_Object *file_; /// A 'd version of the one from . ACE_HANDLE handle_; int mapit_; }; typedef ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_Null_Mutex> ACE_Filecache_Hash; typedef ACE_Hash_Map_Entry ACE_Filecache_Hash_Entry; /** * @class ACE_Filecache * * @brief A hash table holding the information about entry point into * the Cached Virtual Filesystem. On insertion, the reference * count is incremented. On destruction, reference count is * decremented. */ class ACE_Export ACE_Filecache { public: /// Singleton pattern. static ACE_Filecache *instance (void); ~ACE_Filecache (void); /// Returns 0 if the file associated with ``filename'' is in the cache, /// or -1 if not. int find (const ACE_TCHAR *filename); /// Return the file associated with ``filename'' if it is in the cache, /// or create if not. ACE_Filecache_Object *fetch (const ACE_TCHAR *filename, int mapit = 1); /// Remove the file associated with ``filename'' from the cache. ACE_Filecache_Object *remove (const ACE_TCHAR *filename); /// Create a new Filecache_Object, returns it. ACE_Filecache_Object *create (const ACE_TCHAR *filename, int size); /// Release an acquired Filecache_Object, returns it again or NULL if it /// was deleted. ACE_Filecache_Object *finish (ACE_Filecache_Object *&new_file); protected: ACE_Filecache_Object *insert_i (const ACE_TCHAR *filename, ACE_SYNCH_RW_MUTEX &filelock, int mapit); ACE_Filecache_Object *remove_i (const ACE_TCHAR *filename); ACE_Filecache_Object *update_i (const ACE_TCHAR *filename, ACE_SYNCH_RW_MUTEX &filelock, int mapit); public: enum { /// For this stupid implementation, use an array. Someday, use a /// balanced search tree, or real hash table. ACE_DEFAULT_VIRTUAL_FILESYSTEM_TABLE_SIZE = 512, /// This determines the highwater mark in megabytes for the cache. /// This will be ignored for now. ACE_DEFAULT_VIRTUAL_FILESYSTEM_CACHE_SIZE = 20 }; protected: /// Prevent it from being called. ACE_Filecache (void); private: int size_; /// The hash table ACE_Filecache_Hash hash_; /// The reference to the instance static ACE_Filecache *cvf_; // = Synchronization variables. ACE_SYNCH_RW_MUTEX hash_lock_[ACE_DEFAULT_VIRTUAL_FILESYSTEM_TABLE_SIZE]; ACE_SYNCH_RW_MUTEX file_lock_[ACE_DEFAULT_VIRTUAL_FILESYSTEM_TABLE_SIZE]; }; /** * @class ACE_Filecache_Object * * @brief Abstraction over a real file. This is what the Virtual * Filesystem contains. This class is not intended for general * consumption. Please consult a physician before attempting to * use this class. */ class ACE_Export ACE_Filecache_Object { public: friend class ACE_Filecache; /// Creates a file for reading. ACE_Filecache_Object (const ACE_TCHAR *filename, ACE_SYNCH_RW_MUTEX &lock, LPSECURITY_ATTRIBUTES sa = 0, int mapit = 1); /// Creates a file for writing. ACE_Filecache_Object (const ACE_TCHAR *filename, off_t size, ACE_SYNCH_RW_MUTEX &lock, LPSECURITY_ATTRIBUTES sa = 0); /// Only if reference count is zero should this be called. ~ACE_Filecache_Object (void); /// Increment the reference_count_. int acquire (void); /// Decrement the reference_count_. int release (void); // = error_ accessors int error (void) const; int error (int error_value, const ACE_TCHAR *s = ACE_LIB_TEXT ("ACE_Filecache_Object")); /// filename_ accessor const ACE_TCHAR *filename (void) const; /// handle_ accessor. ACE_HANDLE handle (void) const; /// Base memory address for memory mapped file. void *address (void) const; /// size_ accessor. off_t size (void) const; /// True if file on disk is newer than cached file. int update (void) const; protected: /// Prevent from being called. ACE_Filecache_Object (void); /// Common initialization code, void init (void); private: /// Internal error logging method, no locking. int error_i (int error_value, const ACE_TCHAR *s = ACE_LIB_TEXT ("ACE_Filecache_Object")); public: enum Creation_States { ACE_READING = 1, ACE_WRITING = 2 }; enum Error_Conditions { ACE_SUCCESS = 0, ACE_ACCESS_FAILED, ACE_OPEN_FAILED, ACE_COPY_FAILED, ACE_STAT_FAILED, ACE_MEMMAP_FAILED, ACE_WRITE_FAILED }; private: /// The temporary file name and the real file name. The real file is /// copied into the temporary file for safety reasons. ACE_TCHAR *tempname_; ACE_TCHAR filename_[MAXPATHLEN + 1]; /// Holds the memory mapped version of the temporary file. ACE_Mem_Map mmap_; /// The descriptor to the temporary file. ACE_HANDLE handle_; /// Used to compare against the real file to test if an update is needed. ACE_stat stat_; off_t size_; /// Status indicators. int action_; int error_; /// If set to 1, means the object is flagged for removal. int stale_; /// Security attribute object. LPSECURITY_ATTRIBUTES sa_; /// The default initializer ACE_SYNCH_RW_MUTEX junklock_; /// Provides a bookkeeping mechanism for users of this object. ACE_SYNCH_RW_MUTEX &lock_; }; ACE_END_VERSIONED_NAMESPACE_DECL #include /**/ "ace/post.h" #endif /* ACE_FILECACHE_H */