Line data Source code
1 : /* 2 : * 3 : * 4 : * Distributed under the OpenDDS License. 5 : * See: http://www.opendds.org/license.html 6 : */ 7 : 8 : #ifndef OPENDDS_DCPS_FILESYSTEMSTORAGE_H 9 : #define OPENDDS_DCPS_FILESYSTEMSTORAGE_H 10 : 11 : #ifndef OPENDDS_SAFETY_PROFILE 12 : 13 : #include "dcps_export.h" 14 : 15 : #include "DirentWrapper.h" 16 : #include "RcHandle_T.h" 17 : #include "RcObject.h" 18 : 19 : #include "ace/Synch_Traits.h" 20 : #include "ace/SString.h" 21 : 22 : #include <iosfwd> 23 : #include "PoolAllocator.h" 24 : 25 : #include <iterator> 26 : 27 : #if !defined (ACE_LACKS_PRAGMA_ONCE) 28 : #pragma once 29 : #endif /* ACE_LACKS_PRAGMA_ONCE */ 30 : 31 : // This can be overridden by the user, but make sure that it's less than 32 : // the actual operating system and filesystem limit so that the "overflow" 33 : // directories can be created as needed. 34 : #ifndef OPENDDS_FILESYSTEMSTORAGE_MAX_FILES_PER_DIR 35 : #define OPENDDS_FILESYSTEMSTORAGE_MAX_FILES_PER_DIR 512 36 : #endif 37 : 38 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL 39 : 40 : namespace OpenDDS { 41 : namespace FileSystemStorage { 42 : 43 : /// See $DDS_ROOT/docs/design/persistence.txt 44 : /// General usage notes for FileSystemStorage: 45 : /// - Start by calling Directory::create() to get a handle on a new or 46 : /// existing directory. All of its files and subdirectories must be 47 : /// managed by this library. The file and directory names will be encoded 48 : /// so the application doesn't need to be aware of filesystem limitations 49 : /// regarding special characters or length limits (for directory names). 50 : /// - File names are limited to 150 characters, but directory names are 51 : /// unlimited. 52 : /// - The get_*() functions always create the file/dir if it doesn't exist. 53 : /// - The application must take care not to create two objects representing 54 : /// the same node in the filesystem (for example via get_file() and via 55 : /// iteration) because their state will not be kept consistent if one is 56 : /// modified. 57 : /// - Locking is the responsibility of the application. 58 : /// - These classes will throw std::runtime_error if there is a problem 59 : /// with the underlying file system (out of space, bad permissions, etc.) 60 : /// or other unexpected/irregular condition. 61 : 62 : // For Win32 long path name support, used internally and not exported 63 : #if defined ACE_WIN32 || defined ACE_USES_WCHAR 64 : 65 : # ifdef ACE_WIN32 66 : typedef ACE_DIRENT DDS_DIRENT; 67 : # else // !ACE_WIN32 68 : struct DDS_DIRENT { 69 : ACE_DIRENT* real_dirent_; 70 : ACE_TCHAR* d_name; 71 : DDS_DIRENT() : real_dirent_(), d_name() {} 72 : }; 73 : # endif // ACE_WIN32 74 : 75 : struct DDS_DIR; 76 : class DDS_Dirent { 77 : public: 78 : explicit DDS_Dirent(const ACE_TCHAR* path = 0); 79 : ~DDS_Dirent(); 80 : int open(const ACE_TCHAR* path); 81 : void close(); 82 : DDS_DIRENT* read(); 83 : 84 : private: 85 : DDS_DIR* dirp_; 86 : }; 87 : 88 : #else // non-Win32 non-uses-wchar 89 : # define DDS_DIRENT ACE_DIRENT 90 : # define DDS_Dirent ACE_Dirent 91 : #endif // ACE_WIN32 92 : 93 : using OpenDDS::DCPS::RcObject; 94 : using OpenDDS::DCPS::RcHandle; 95 : 96 : class File; 97 : 98 : class OpenDDS_Dcps_Export Directory : public virtual RcObject { 99 : public: 100 : typedef RcHandle<Directory> Ptr; 101 : 102 : /// If root_path is relative it is up to the application to make sure the 103 : /// current directory is not changed while this object or any of its 104 : /// "child" objects are still alive. 105 : static Ptr create(const char* root_path); 106 : 107 : private: 108 : ACE_TString full_path(const ACE_TString& relative) const; 109 : typedef OPENDDS_MAP(ACE_TString, ACE_TString) Map; 110 : 111 : template <typename Item> 112 : class Iterator { 113 : public: 114 : typedef std::input_iterator_tag iterator_category; 115 : typedef typename Item::Ptr value_type; 116 : typedef std::ptrdiff_t difference_type; 117 : typedef value_type* pointer; 118 : typedef value_type& reference; 119 : 120 : typename Item::Ptr operator*() const { 121 : return deref(); 122 : } 123 : 124 0 : typename Item::Ptr operator->() const { 125 0 : return deref(); 126 : } 127 : 128 0 : Iterator& operator++() { 129 0 : ++delegate_; 130 0 : item_.reset(); 131 0 : return *this; 132 : } 133 : 134 : Iterator operator++(int) { 135 : Iterator tmp(*this); 136 : ++delegate_; 137 : item_.reset(); 138 : return tmp; 139 : } 140 : 141 0 : bool operator==(const Iterator& rhs) const { 142 0 : return delegate_ == rhs.delegate_; 143 : } 144 : 145 0 : bool operator!=(const Iterator& rhs) const { 146 0 : return delegate_ != rhs.delegate_; 147 : } 148 : 149 : private: 150 : friend class Directory; 151 : typedef Map::iterator IterDelegate; 152 0 : Iterator(const IterDelegate& del, const Directory::Ptr& outer) 153 0 : : delegate_(del) 154 0 : , outer_(outer) 155 0 : , item_() {} 156 : 157 0 : typename Item::Ptr deref() const { 158 0 : if (item_.is_nil()) { 159 0 : item_ = OpenDDS::DCPS::make_rch<Item>(outer_->full_path(delegate_->second), 160 0 : delegate_->first, outer_); 161 : } 162 : 163 0 : return item_; 164 : } 165 : 166 : IterDelegate delegate_; 167 : Directory::Ptr outer_; 168 : mutable typename Item::Ptr item_; 169 : }; 170 : 171 : public: 172 : typedef Iterator<File> FileIterator; 173 : typedef Iterator<Directory> DirectoryIterator; 174 : 175 : FileIterator begin_files(); // files will be sorted 176 : FileIterator end_files(); 177 : 178 : RcHandle<File> get_file(const char* name); // slash is not a separator 179 : 180 : /// assumes all files in this dir are created with this API 181 : RcHandle<File> create_next_file(); 182 : 183 : DirectoryIterator begin_dirs(); // dirs will be sorted 184 : DirectoryIterator end_dirs(); 185 : 186 : Directory::Ptr get_dir(const OPENDDS_VECTOR(OPENDDS_STRING)& path); 187 : Directory::Ptr get_subdir(const char* name); // slash is not a separator 188 : 189 : /// assumes all subdirectories in this dir are created with this API 190 : Directory::Ptr create_next_dir(); 191 : 192 : void remove(); // recursive 193 : 194 : OPENDDS_STRING name() const; 195 0 : Directory::Ptr parent() const { 196 0 : return parent_; 197 : } 198 : 199 : private: 200 : friend class File; 201 : template <typename T, typename U0, typename U1, typename U2> 202 : friend RcHandle<T> OpenDDS::DCPS::make_rch(const U0&, const U1&, const U2&); 203 : 204 : Directory(const ACE_TString& root_path, const ACE_TString& logical, 205 : const Directory::Ptr& parent); 206 : void scan_dir(const ACE_TString& relative, DDS_Dirent& dir, 207 : unsigned int overflow_index); 208 : RcHandle<File> make_new_file(const ACE_TString& t_name); 209 : void removing(const ACE_TString& logical_child, bool file); 210 : Directory::Ptr make_new_subdir(const ACE_TString& logical); 211 : ACE_TString add_entry(); // returns overflow directory prefix 212 : 213 : Directory::Ptr parent_; 214 : ACE_TString physical_dirname_, logical_dirname_; 215 : 216 : // overflow bucket (0==immediate) -> #entries 217 : OPENDDS_MAP(unsigned int, unsigned int) overflow_; 218 : 219 : Map files_, dirs_; // logical -> physical 220 : OPENDDS_MAP(ACE_TString, unsigned int) long_names_; 221 : // phys. prefix (before '.') -> next available counter # 222 : }; 223 : 224 : class OpenDDS_Dcps_Export File : public virtual RcObject { 225 : public: 226 : typedef RcHandle<File> Ptr; 227 : 228 : bool write(std::ofstream& stream); 229 : bool read(std::ifstream& stream); 230 : bool remove(); 231 : OPENDDS_STRING name() const; 232 : Directory::Ptr parent() const { 233 : return parent_; 234 : } 235 : 236 : private: 237 : friend class Directory; 238 : template <typename T, typename U0, typename U1, typename U2> 239 : friend OpenDDS::DCPS::RcHandle<T> OpenDDS::DCPS::make_rch(const U0&, const U1&, const U2&); 240 : template <typename Item> friend class Directory::Iterator; 241 : File(const ACE_TString& fname_phys, const ACE_TString& logical, 242 : const Directory::Ptr& parent); 243 : 244 : ACE_TString physical_file_, physical_dir_, logical_relative_; 245 : Directory::Ptr parent_; 246 : }; 247 : 248 : // Encode/decode using Base32Hex as described by RFC4648 249 : 250 : OpenDDS_Dcps_Export 251 : ACE_TString b32h_encode(const ACE_TCHAR* decoded); 252 : 253 : OpenDDS_Dcps_Export 254 : ACE_TString b32h_decode(const ACE_TCHAR* encoded); 255 : 256 : } // namespace FileSystemStorage 257 : } // namespace OpenDDS 258 : 259 : OPENDDS_END_VERSIONED_NAMESPACE_DECL 260 : 261 : #endif 262 : #endif