OpenDDS  Snapshot(2023/04/28-20:55)
FileSystemStorage.h
Go to the documentation of this file.
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 
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 
95 
96 class File;
97 
98 class OpenDDS_Dcps_Export Directory : public virtual RcObject {
99 public:
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  typename Item::Ptr operator->() const {
125  return deref();
126  }
127 
129  ++delegate_;
130  item_.reset();
131  return *this;
132  }
133 
135  Iterator tmp(*this);
136  ++delegate_;
137  item_.reset();
138  return tmp;
139  }
140 
141  bool operator==(const Iterator& rhs) const {
142  return delegate_ == rhs.delegate_;
143  }
144 
145  bool operator!=(const Iterator& rhs) const {
146  return delegate_ != rhs.delegate_;
147  }
148 
149  private:
150  friend class Directory;
151  typedef Map::iterator IterDelegate;
152  Iterator(const IterDelegate& del, const Directory::Ptr& outer)
153  : delegate_(del)
154  , outer_(outer)
155  , item_() {}
156 
157  typename Item::Ptr deref() const {
158  if (item_.is_nil()) {
159  item_ = OpenDDS::DCPS::make_rch<Item>(outer_->full_path(delegate_->second),
160  delegate_->first, outer_);
161  }
162 
163  return item_;
164  }
165 
166  IterDelegate delegate_;
168  mutable typename Item::Ptr item_;
169  };
170 
171 public:
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;
196  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 
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:
227 
228  bool write(std::ofstream& stream);
229  bool read(std::ifstream& stream);
230  bool remove();
231  OPENDDS_STRING name() 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_;
246 };
247 
248 // Encode/decode using Base32Hex as described by RFC4648
249 
251 ACE_TString b32h_encode(const ACE_TCHAR* decoded);
252 
255 
256 } // namespace FileSystemStorage
257 } // namespace OpenDDS
258 
260 
261 #endif
262 #endif
ACE_TString b32h_encode(const ACE_TCHAR *decoded)
#define OpenDDS_Dcps_Export
Definition: dcps_export.h:24
RcHandle< T > make_rch()
Definition: RcHandle_T.h:256
#define ACE_DIRENT
int close(ACE_HANDLE handle)
#define OPENDDS_STRING
ACE_HANDLE open(const char *filename, int mode, mode_t perms=ACE_DEFAULT_OPEN_PERMS, LPSECURITY_ATTRIBUTES sa=0)
char ACE_TCHAR
Iterator(const IterDelegate &del, const Directory::Ptr &outer)
ssize_t read(ACE_HANDLE handle, void *buf, size_t len)
const char *const name
Definition: debug.cpp:60
#define OPENDDS_MAP(K, V)
#define OPENDDS_VECTOR(T)
#define DDS_Dirent
ACE_TString b32h_decode(const ACE_TCHAR *encoded)
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
::DDS::ReturnCode_t write(in<%SCOPED%> instance_data, in ::DDS::InstanceHandle_t handle)
sequence<<%SCOPED%><%TYPE%><%SEQ%> local interface<%TYPE%> out string encoded
Definition: IDLTemplate.txt:4
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
#define DDS_DIRENT