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

Generated on Fri Feb 12 20:05:23 2016 for OpenDDS by  doxygen 1.4.7