libfilezilla
writer.hpp
Go to the documentation of this file.
1 #ifndef LIBFILEZILLA_AIO_WRITER_HEADER
2 #define LIBFILEZILLA_AIO_WRITER_HEADER
3 
10 #include "aio.hpp"
11 #include "../buffer.hpp"
12 #include "../file.hpp"
13 #include "../thread_pool.hpp"
14 
15 #include <list>
16 
17 namespace fz {
18 
27 class FZ_PUBLIC_SYMBOL writer_base : public aio_base, public aio_waitable
28 {
29 public:
30  writer_base(writer_base const&) = delete;
31  writer_base& operator=(writer_base const&) = delete;
32 
34  virtual aio_result preallocate(uint64_t /*size*/) { return aio_result::ok; }
35 
47  aio_result add_buffer(buffer_lease && b, event_handler & h);
48 
60  aio_result finalize(event_handler & h);
61 
63  virtual bool set_mtime(datetime const&) { return false; }
64 
65  void close();
66 
77  using progress_cb_t = std::function<void(writer_base const*, uint64_t written)>;
78 
79 protected:
80  virtual aio_result do_add_buffer(scoped_lock & l, buffer_lease && b) = 0;
81  virtual aio_result do_finalize(scoped_lock & l) = 0;
82 
83  writer_base(std::wstring && name, aio_buffer_pool & pool, progress_cb_t && progress_cb, size_t max_buffers) noexcept
84  : buffer_pool_(pool)
85  , name_(name)
86  , progress_cb_(std::move(progress_cb))
87  , max_buffers_(max_buffers ? max_buffers : 1)
88  {}
89 
90  writer_base(std::wstring_view name, aio_buffer_pool & pool, progress_cb_t && progress_cb, size_t max_buffers) noexcept
91  : buffer_pool_(pool)
92  , name_(name)
93  , progress_cb_(std::move(progress_cb))
94  , max_buffers_(max_buffers ? max_buffers : 1)
95  {}
96 
97  virtual void do_close(scoped_lock &) {}
98 
99  mutex mtx_;
100  aio_buffer_pool & buffer_pool_;
101 
102  std::wstring const name_;
103 
104  progress_cb_t progress_cb_;
105 
106  size_t const max_buffers_{};
107  std::list<buffer_lease> buffers_;
108 
109  bool error_{};
110  uint8_t finalizing_{};
111 };
112 
114 class FZ_PUBLIC_SYMBOL writer_factory
115 {
116 public:
117  explicit writer_factory(std::wstring const& name)
118  : name_(name)
119  {}
120  explicit writer_factory(std::wstring && name)
121  : name_(std::move(name))
122  {}
123 
124  virtual ~writer_factory() noexcept = default;
125 
127  virtual std::unique_ptr<writer_factory> clone() const = 0;
128 
136  virtual std::unique_ptr<writer_base> open(aio_buffer_pool & pool, uint64_t offset = 0, writer_base::progress_cb_t progress_cb = nullptr, size_t max_buffers = 0) = 0;
137 
138  std::wstring const& name() const { return name_; }
139 
141  virtual bool offsetable() const { return false; }
142 
144  virtual uint64_t size() const { return writer_base::nosize; }
145  virtual datetime mtime() const { return datetime(); }
146 
148  virtual size_t min_buffer_usage() const { return 1; }
149 
151  virtual bool multiple_buffer_usage() const { return false; }
152 
153  virtual size_t preferred_buffer_count() const { return 1; }
154 
160  virtual bool set_mtime(datetime const&) { return false; }
161 protected:
162  writer_factory() = default;
163  writer_factory(writer_factory const&) = default;
164 
165 private:
166  std::wstring const name_;
167 };
168 
169 class FZ_PUBLIC_SYMBOL writer_factory_holder final
170 {
171 public:
172  writer_factory_holder() = default;
173  writer_factory_holder(std::unique_ptr<writer_factory> && factory);
174  writer_factory_holder(std::unique_ptr<writer_factory> const& factory);
175  writer_factory_holder(writer_factory const& factory);
176 
178  writer_factory_holder& operator=(writer_factory_holder const& op);
179 
181  writer_factory_holder& operator=(writer_factory_holder && op) noexcept;
182  writer_factory_holder& operator=(std::unique_ptr<writer_factory> && factory);
183 
184  writer_factory const* operator->() const { return impl_.get(); }
185  writer_factory* operator->() { return impl_.get(); }
186  writer_factory const& operator*() const { return *impl_; }
187  writer_factory & operator*() { return *impl_; }
188 
189  explicit operator bool() const { return impl_.operator bool(); }
190 
191  std::wstring name() const { return impl_ ? impl_->name() : std::wstring(); }
192  datetime mtime() const { return impl_ ? impl_->mtime() : datetime(); }
193  uint64_t size() const { return impl_ ? impl_->size() : aio_base::nosize; }
194 
195 private:
196  std::unique_ptr<writer_factory> impl_;
197 };
198 
199 
200 
201 class thread_pool;
202 
204 class FZ_PUBLIC_SYMBOL threaded_writer : public writer_base
205 {
206 public:
207  using writer_base::writer_base;
208 
209 protected:
210  virtual aio_result do_add_buffer(scoped_lock & l, buffer_lease && b) override;
211  virtual aio_result do_finalize(scoped_lock & l) override;
212  void wakeup(scoped_lock & l) {
213  cond_.signal(l);
214  }
215 
216  virtual void do_close(scoped_lock & l) override;
217 
218  virtual aio_result continue_finalize(scoped_lock &) {
219  return aio_result::ok;
220  }
221 
222  condition cond_;
223  async_task task_;
224 
225  bool quit_{};
226 };
227 
229 class FZ_PUBLIC_SYMBOL file_writer final : public threaded_writer
230 {
231 public:
232  file_writer(std::wstring && name, aio_buffer_pool & pool, file && f, thread_pool & tpool, bool fsync = false, progress_cb_t && progress_cb = nullptr, size_t max_buffers = 4) noexcept;
233  file_writer(std::wstring_view name, aio_buffer_pool & pool, file && f, thread_pool & tpool, bool fsync = false, progress_cb_t && progress_cb = nullptr, size_t max_buffers = 4) noexcept;
234 
235  virtual ~file_writer() override;
236 
237  virtual aio_result preallocate(uint64_t size) override;
238 
239  virtual bool set_mtime(datetime const&) override;
240 
241 private:
242  virtual void FZ_PRIVATE_SYMBOL do_close(scoped_lock & l) override;
243  virtual aio_result FZ_PRIVATE_SYMBOL continue_finalize(scoped_lock & l) override;
244 
245  void FZ_PRIVATE_SYMBOL entry();
246 
247  file file_;
248 
249  bool fsync_{};
250  bool preallocated_{};
251 };
252 
253 enum class file_writer_flags : unsigned {
254  fsync = 0x01,
255  permissions_current_user_only = 0x02,
256  permissions_current_user_and_admins_only = 0x04
257 };
258 inline bool operator&(file_writer_flags lhs, file_writer_flags rhs) {
259  return (static_cast<std::underlying_type_t<file_writer_flags>>(lhs) & static_cast<std::underlying_type_t<file_writer_flags>>(rhs)) != 0;
260 }
261 inline file_writer_flags operator|(file_writer_flags lhs, file_writer_flags rhs) {
262  return static_cast<file_writer_flags>(static_cast<std::underlying_type_t<file_writer_flags>>(lhs) | static_cast<std::underlying_type_t<file_writer_flags>>(rhs));
263 }
264 
266 class FZ_PUBLIC_SYMBOL file_writer_factory final : public writer_factory
267 {
268 public:
269  file_writer_factory(std::wstring const& file, thread_pool & tpool, file_writer_flags = {});
270 
271  virtual std::unique_ptr<writer_base> open(aio_buffer_pool & pool, uint64_t offset, writer_base::progress_cb_t progress_cb = nullptr, size_t max_buffers = 0) override;
272  virtual std::unique_ptr<writer_factory> clone() const override;
273 
274  virtual bool offsetable() const override { return true; }
275 
276  virtual uint64_t size() const override;
277  virtual datetime mtime() const override;
278 
279  virtual bool set_mtime(datetime const& t) override;
280 
281  virtual bool multiple_buffer_usage() const override { return true; }
282 
283  virtual size_t preferred_buffer_count() const override { return 4; }
284 
285 private:
286  thread_pool & thread_pool_;
287  file_writer_flags flags_{};
288 };
289 
296 class FZ_PUBLIC_SYMBOL buffer_writer final : public writer_base
297 {
298 public:
299  buffer_writer(buffer & buffer, std::wstring const& name, aio_buffer_pool & pool, size_t size_limit, progress_cb_t && progress_cb = nullptr);
300 
301  virtual aio_result preallocate(uint64_t size) override;
302 
303 private:
304  virtual aio_result FZ_PRIVATE_SYMBOL do_add_buffer(scoped_lock & l, buffer_lease && b) override;
305  virtual aio_result FZ_PRIVATE_SYMBOL do_finalize(scoped_lock &) override { return error_ ? aio_result::error : aio_result::ok; }
306 
307  buffer & buffer_;
308  size_t size_limit_{};
309 };
310 
317 class FZ_PUBLIC_SYMBOL buffer_writer_factory final : public writer_factory
318 {
319 public:
320  buffer_writer_factory(buffer & b, std::wstring const& name, size_t size_limit);
321 
322  virtual std::unique_ptr<writer_base> open(aio_buffer_pool & pool, uint64_t offset, writer_base::progress_cb_t progress_cb = nullptr, size_t max_buffers = 0) override;
323  virtual std::unique_ptr<writer_factory> clone() const override;
324 
325 private:
326  buffer & buffer_;
327  size_t size_limit_{};
328 };
329 
330 }
331 
332 #endif
Buffer management and wait machinery for asynchronous I/O.
Definition: aio.hpp:226
A buffer pool for use with async readers/writers.
Definition: aio.hpp:132
Definition: aio.hpp:89
Definition: aio.hpp:69
Handle for asynchronous tasks.
Definition: thread_pool.hpp:24
Definition: aio.hpp:25
Definition: writer.hpp:318
virtual std::unique_ptr< writer_base > open(aio_buffer_pool &pool, uint64_t offset, writer_base::progress_cb_t progress_cb=nullptr, size_t max_buffers=0) override
Creates a writer.
virtual std::unique_ptr< writer_factory > clone() const override
Clones the factory.
Definition: writer.hpp:297
virtual aio_result preallocate(uint64_t size) override
Instructs writer to preallocate storage. May be a noop.
The buffer class is a simple buffer where data can be appended at the end and consumed at the front....
Definition: buffer.hpp:27
Waitable condition variable.
Definition: mutex.hpp:196
Represents a point of time in wallclock, tracking the timestamps accuracy/precision.
Definition: time.hpp:41
Simple handler for asynchronous event processing.
Definition: event_handler.hpp:55
Factory for.
Definition: writer.hpp:267
virtual bool multiple_buffer_usage() const override
Whether the writer can benefit from multiple buffers.
Definition: writer.hpp:281
virtual bool set_mtime(datetime const &t) override
Sets the mtime of the target.
virtual std::unique_ptr< writer_base > open(aio_buffer_pool &pool, uint64_t offset, writer_base::progress_cb_t progress_cb=nullptr, size_t max_buffers=0) override
Creates a writer.
virtual bool offsetable() const override
If true, writer can be opened from any position, not just the beginning, such as file_writer.
Definition: writer.hpp:274
virtual std::unique_ptr< writer_factory > clone() const override
Clones the factory.
virtual uint64_t size() const override
Some writers, e.g. for files, may have a pre-existing size.
File writer.
Definition: writer.hpp:230
virtual aio_result preallocate(uint64_t size) override
Instructs writer to preallocate storage. May be a noop.
virtual bool set_mtime(datetime const &) override
Must be finalized already.
Lean class for file access.
Definition: file.hpp:29
A simple scoped lock.
Definition: mutex.hpp:93
A dumb thread-pool for asynchronous tasks.
Definition: thread_pool.hpp:64
Base class for threaded writer.
Definition: writer.hpp:205
Base class for all writers.
Definition: writer.hpp:28
virtual aio_result preallocate(uint64_t)
Instructs writer to preallocate storage. May be a noop.
Definition: writer.hpp:34
aio_result add_buffer(buffer_lease &&b, aio_waiter &h)
Pass a buffer to be written out.
std::function< void(writer_base const *, uint64_t written)> progress_cb_t
Definition: writer.hpp:77
virtual bool set_mtime(datetime const &)
Must be finalized already.
Definition: writer.hpp:63
aio_result finalize(aio_waiter &h)
Finalizes the writer.
Definition: writer.hpp:170
A writer factory.
Definition: writer.hpp:115
virtual size_t min_buffer_usage() const
The writer requires at least this many buffers.
Definition: writer.hpp:148
virtual uint64_t size() const
Some writers, e.g. for files, may have a pre-existing size.
Definition: writer.hpp:144
virtual std::unique_ptr< writer_factory > clone() const =0
Clones the factory.
virtual std::unique_ptr< writer_base > open(aio_buffer_pool &pool, uint64_t offset=0, writer_base::progress_cb_t progress_cb=nullptr, size_t max_buffers=0)=0
Creates a writer.
virtual bool multiple_buffer_usage() const
Whether the writer can benefit from multiple buffers.
Definition: writer.hpp:151
virtual bool offsetable() const
If true, writer can be opened from any position, not just the beginning, such as file_writer.
Definition: writer.hpp:141
virtual bool set_mtime(datetime const &)
Sets the mtime of the target.
Definition: writer.hpp:160
The namespace used by libfilezilla.
Definition: apply.hpp:17
aio_result
Result of aio operations.
Definition: aio.hpp:213
@ ok
Success, proceed.
@ error
Operationf failed.