FileSystemStorage.h

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
00006  */
00007 
00008 #ifndef OPENDDS_FILESYSTEMSTORAGE_H
00009 #define OPENDDS_FILESYSTEMSTORAGE_H
00010 
00011 #ifndef OPENDDS_SAFETY_PROFILE
00012 
00013 #include "dds/DCPS/dcps_export.h"
00014 #include "dds/DCPS/RcHandle_T.h"
00015 #include "dds/DCPS/RcObject.h"
00016 
00017 #include "ace/Synch_Traits.h"
00018 #include "ace/SString.h"
00019 #include "ace/os_include/os_dirent.h"
00020 
00021 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00022 class ACE_Dirent;
00023 ACE_END_VERSIONED_NAMESPACE_DECL
00024 
00025 #include <iosfwd>
00026 #include "dds/DCPS/PoolAllocator.h"
00027 
00028 #include <iterator>
00029 
00030 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00031 #pragma once
00032 #endif /* ACE_LACKS_PRAGMA_ONCE */
00033 
00034 // This can be overriden by the user, but make sure that it's less than
00035 // the actual operating system and filesystem limit so that the "overflow"
00036 // directories can be created as needed.
00037 #ifndef OPENDDS_FILESYSTEMSTORAGE_MAX_FILES_PER_DIR
00038 #define OPENDDS_FILESYSTEMSTORAGE_MAX_FILES_PER_DIR 512
00039 #endif
00040 
00041 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
00042 
00043 namespace OpenDDS {
00044 namespace FileSystemStorage {
00045 
00046 /// See $DDS_ROOT/docs/design/persistence.txt
00047 /// General usage notes for FileSystemStorage:
00048 ///  - Start by calling Directory::create() to get a handle on a new or
00049 ///    existing directory.  All of its files and subdirectories must be
00050 ///    managed by this library.  The file and directory names will be encoded
00051 ///    so the application doesn't need to be aware of filesystem limitations
00052 ///    regarding special characters or length limits (for directory names).
00053 ///  - File names are limited to 150 characters, but directory names are
00054 ///    unlimited.
00055 ///  - The get_*() functions always create the file/dir if it doesn't exist.
00056 ///  - The application must take care not to create two objects representing
00057 ///    the same node in the filesystem (for example via get_file() and via
00058 ///    iteration) because their state will not be kept consistent if one is
00059 ///    modified.
00060 ///  - Locking is the responsibility of the application.
00061 ///  - These classes will throw std::runtime_error if there is a problem
00062 ///    with the underlying file system (out of space, bad permissions, etc.)
00063 ///    or other unexpected/irregular condition.
00064 
00065 // For Win32 long path name support, used internally and not exported
00066 #if defined ACE_WIN32 || defined ACE_USES_WCHAR
00067 
00068 # ifdef ACE_WIN32
00069 typedef ACE_DIRENT DDS_DIRENT;
00070 # else // !ACE_WIN32
00071 struct DDS_DIRENT {
00072   ACE_DIRENT* real_dirent_;
00073   ACE_TCHAR* d_name;
00074   DDS_DIRENT() : real_dirent_(), d_name() {}
00075 };
00076 # endif // ACE_WIN32
00077 
00078 struct DDS_DIR;
00079 class DDS_Dirent {
00080 public:
00081   explicit DDS_Dirent(const ACE_TCHAR* path = 0);
00082   ~DDS_Dirent();
00083   int open(const ACE_TCHAR* path);
00084   void close();
00085   DDS_DIRENT* read();
00086 
00087 private:
00088   DDS_DIR* dirp_;
00089 };
00090 
00091 #else // non-Win32 non-uses-wchar
00092 #  define DDS_DIRENT ACE_DIRENT
00093 #  define DDS_Dirent ACE_Dirent
00094 #endif // ACE_WIN32
00095 
00096 using OpenDDS::DCPS::RcObject;
00097 using OpenDDS::DCPS::RcHandle;
00098 
00099 class File;
00100 
00101 class OpenDDS_Dcps_Export Directory : public RcObject {
00102 public:
00103   typedef RcHandle<Directory> Ptr;
00104 
00105   /// If root_path is relative it is up to the application to make sure the
00106   /// current directory is not changed while this object or any of its
00107   /// "child" objects are still alive.
00108   static Ptr create(const char* root_path);
00109 
00110 private:
00111   ACE_TString full_path(const ACE_TString& relative) const;
00112   typedef OPENDDS_MAP(ACE_TString, ACE_TString) Map;
00113 
00114   template <typename Item>
00115   class Iterator
00116         : public std::iterator<std::input_iterator_tag, typename Item::Ptr> {
00117   public:
00118     typename Item::Ptr operator*() const {
00119       return deref();
00120     }
00121 
00122     typename Item::Ptr operator->() const {
00123       return deref();
00124     }
00125 
00126     Iterator& operator++() {
00127       ++delegate_;
00128       item_.reset();
00129       return *this;
00130     }
00131 
00132     Iterator operator++(int) {
00133       Iterator tmp(*this);
00134       ++delegate_;
00135       item_.reset();
00136       return tmp;
00137     }
00138 
00139     bool operator==(const Iterator& rhs) const {
00140       return delegate_ == rhs.delegate_;
00141     }
00142 
00143     bool operator!=(const Iterator& rhs) const {
00144       return delegate_ != rhs.delegate_;
00145     }
00146 
00147   private:
00148     friend class Directory;
00149     typedef Map::iterator IterDelegate;
00150     Iterator(const IterDelegate& del, const Directory::Ptr& outer)
00151         : delegate_(del)
00152         , outer_(outer)
00153         , item_() {}
00154 
00155     typename Item::Ptr deref() const {
00156       if (item_.is_nil()) {
00157         item_ = OpenDDS::DCPS::make_rch<Item>(outer_->full_path(delegate_->second),
00158                               delegate_->first, outer_);
00159       }
00160 
00161       return item_;
00162     }
00163 
00164     IterDelegate delegate_;
00165     Directory::Ptr outer_;
00166     mutable typename Item::Ptr item_;
00167   };
00168 
00169 public:
00170   typedef Iterator<File> FileIterator;
00171   typedef Iterator<Directory> DirectoryIterator;
00172 
00173   FileIterator begin_files(); // files will be sorted
00174   FileIterator end_files();
00175 
00176   RcHandle<File> get_file(const char* name);  // slash is not a separator
00177 
00178   /// assumes all files in this dir are created with this API
00179   RcHandle<File> create_next_file();
00180 
00181   DirectoryIterator begin_dirs(); // dirs will be sorted
00182   DirectoryIterator end_dirs();
00183 
00184   Directory::Ptr get_dir(const OPENDDS_VECTOR(OPENDDS_STRING)& path);
00185   Directory::Ptr get_subdir(const char* name);  // slash is not a separator
00186 
00187   /// assumes all subdirectories in this dir are created with this API
00188   Directory::Ptr create_next_dir();
00189 
00190   void remove(); // recursive
00191 
00192   OPENDDS_STRING name() const;
00193   Directory::Ptr parent() const {
00194     return parent_;
00195   }
00196 
00197 private:
00198   friend class File;
00199   template <typename T, typename U0, typename U1, typename U2>
00200   friend RcHandle<T> OpenDDS::DCPS::make_rch(const U0&, const U1&, const U2&);
00201 
00202   Directory(const ACE_TString& root_path, const ACE_TString& logical,
00203             const Directory::Ptr& parent);
00204   void scan_dir(const ACE_TString& relative, DDS_Dirent& dir,
00205                 unsigned int overflow_index);
00206   RcHandle<File> make_new_file(const ACE_TString& t_name);
00207   void removing(const ACE_TString& logical_child, bool file);
00208   Directory::Ptr make_new_subdir(const ACE_TString& logical);
00209   ACE_TString add_entry(); // returns overflow directory prefix
00210 
00211   Directory::Ptr parent_;
00212   ACE_TString physical_dirname_, logical_dirname_;
00213 
00214   // overflow bucket (0==immediate) -> #entries
00215   OPENDDS_MAP(unsigned int, unsigned int) overflow_;
00216 
00217   Map files_, dirs_; // logical -> physical
00218   OPENDDS_MAP(ACE_TString, unsigned int) long_names_;
00219   // phys. prefix (before '.') -> next available counter #
00220 };
00221 
00222 class OpenDDS_Dcps_Export File : public RcObject {
00223 public:
00224   typedef RcHandle<File> Ptr;
00225 
00226   bool write(std::ofstream& stream);
00227   bool read(std::ifstream& stream);
00228   bool remove();
00229   OPENDDS_STRING name() const;
00230   Directory::Ptr parent() const {
00231     return parent_;
00232   }
00233 
00234 private:
00235   friend class Directory;
00236   template <typename T, typename U0, typename U1, typename U2>
00237   friend OpenDDS::DCPS::RcHandle<T> OpenDDS::DCPS::make_rch(const U0&, const U1&, const U2&);
00238   template <typename Item> friend class Directory::Iterator;
00239   File(const ACE_TString& fname_phys, const ACE_TString& logical,
00240        const Directory::Ptr& parent);
00241 
00242   ACE_TString physical_file_, physical_dir_, logical_relative_;
00243   Directory::Ptr parent_;
00244 };
00245 
00246 // Encode/decode using Base32Hex as described by RFC4648
00247 
00248 OpenDDS_Dcps_Export
00249 ACE_TString b32h_encode(const ACE_TCHAR* decoded);
00250 
00251 OpenDDS_Dcps_Export
00252 ACE_TString b32h_decode(const ACE_TCHAR* encoded);
00253 
00254 } // namespace FileSystemStorage
00255 } // namespace OpenDDS
00256 
00257 OPENDDS_END_VERSIONED_NAMESPACE_DECL
00258 
00259 #endif
00260 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1