Seastar
High performance C++ framework for concurrent servers
tmp_file.hh
1 /*
2  * This file is open source software, licensed to you under the terms
3  * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4  * distributed with this work for additional information regarding copyright
5  * ownership. You may not use this file except in compliance with the License.
6  *
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an
13  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14  * KIND, either express or implied. See the License for the
15  * specific language governing permissions and limitations
16  * under the License.
17  */
18 
19 /*
20  * Copyright 2020 ScyllaDB
21  */
22 
23 #pragma once
24 
25 #include <seastar/core/future.hh>
26 #include <seastar/core/file.hh>
27 #include <seastar/core/thread.hh>
28 #include <seastar/util/std-compat.hh>
29 
30 namespace seastar {
31 
32 const std::filesystem::path& default_tmpdir();
33 void set_default_tmpdir(std::filesystem::path);
34 
35 class tmp_file {
36  std::filesystem::path _path;
37  file _file;
38  bool _is_open = false;
39 
40  static_assert(std::is_nothrow_constructible<std::filesystem::path>::value,
41  "filesystem::path's constructor must not throw");
42  static_assert(std::is_nothrow_move_constructible<std::filesystem::path>::value,
43  "filesystem::path's move constructor must not throw");
44 public:
45  tmp_file() noexcept = default;
46  tmp_file(const tmp_file&) = delete;
47  tmp_file(tmp_file&& x) noexcept;
48 
49  tmp_file& operator=(tmp_file&&) noexcept = default;
50 
51  ~tmp_file();
52 
53  future<> open(std::filesystem::path path_template = default_tmpdir(),
54  open_flags oflags = open_flags::rw,
55  file_open_options options = {}) noexcept;
56  future<> close() noexcept;
57  future<> remove() noexcept;
58 
59  template <typename Func>
60  static future<> do_with(std::filesystem::path path_template, Func&& func,
61  open_flags oflags = open_flags::rw,
62  file_open_options options = {}) noexcept {
63  static_assert(std::is_nothrow_move_constructible<Func>::value,
64  "Func's move constructor must not throw");
65  return seastar::do_with(tmp_file(), [func = std::move(func), path_template = std::move(path_template), oflags, options = std::move(options)] (tmp_file& t) mutable {
66  return t.open(std::move(path_template), oflags, std::move(options)).then([&t, func = std::move(func)] () mutable {
67  return func(t);
68  }).finally([&t] {
69  return t.close().finally([&t] {
70  return t.remove();
71  });
72  });
73  });
74  }
75 
76  template <typename Func>
77  static future<> do_with(Func&& func) noexcept {
78  return do_with(default_tmpdir(), std::move(func));
79  }
80 
81  bool has_path() const {
82  return !_path.empty();
83  }
84 
85  bool is_open() const {
86  return _is_open;
87  }
88 
89  const std::filesystem::path& get_path() const {
90  return _path;
91  }
92 
93  file& get_file() {
94  return _file;
95  }
96 };
97 
116 future<tmp_file> make_tmp_file(std::filesystem::path path_template = default_tmpdir(),
117  open_flags oflags = open_flags::rw, file_open_options options = {}) noexcept;
118 
119 class tmp_dir {
120  std::filesystem::path _path;
121 
122 public:
123  tmp_dir() = default;
124  tmp_dir(const tmp_dir&) = delete;
125  tmp_dir(tmp_dir&& x) = default;
126 
127  tmp_dir& operator=(tmp_dir&&) noexcept = default;
128 
129  ~tmp_dir();
130 
131  future<> create(std::filesystem::path path_template = default_tmpdir(),
132  file_permissions create_permissions = file_permissions::default_dir_permissions) noexcept;
133  future<> remove() noexcept;
134 
135  template <typename Func>
136  SEASTAR_CONCEPT( requires std::is_nothrow_move_constructible_v<Func> )
137  static future<> do_with(std::filesystem::path path_template, Func&& func,
138  file_permissions create_permissions = file_permissions::default_dir_permissions) noexcept {
139  static_assert(std::is_nothrow_move_constructible_v<Func>,
140  "Func's move constructor must not throw");
141  return seastar::do_with(tmp_dir(), [func = std::move(func), path_template = std::move(path_template), create_permissions] (tmp_dir& t) mutable {
142  return t.create(std::move(path_template), create_permissions).then([&t, func = std::move(func)] () mutable {
143  return func(t);
144  }).finally([&t] {
145  return t.remove();
146  });
147  });
148  }
149 
150  template <typename Func>
151  static future<> do_with(Func&& func) noexcept {
152  return do_with(default_tmpdir(), std::move(func));
153  }
154 
155  template <typename Func>
156 
157  SEASTAR_CONCEPT( requires std::is_nothrow_move_constructible_v<Func> )
158  static future<> do_with_thread(Func&& func) noexcept {
159  static_assert(std::is_nothrow_move_constructible_v<Func>,
160  "Func's move constructor must not throw");
161  return async([func = std::move(func)] () mutable {
162  auto t = tmp_dir();
163  t.create().get();
164  futurize_invoke(func, t).finally([&t] {
165  return t.remove();
166  }).get();
167  });
168  }
169 
170  bool has_path() const {
171  return !_path.empty();
172  }
173 
174  const std::filesystem::path& get_path() const {
175  return _path;
176  }
177 };
178 
196 future<tmp_dir> make_tmp_dir(std::filesystem::path path_template = default_tmpdir(),
197  file_permissions create_permissions = file_permissions::default_dir_permissions) noexcept;
198 
199 } // namespace seastar
Definition: file.hh:166
A representation of a possibly not-yet-computed value.
Definition: future.hh:1337
future< T > finally(Func &&func) noexcept
Definition: future.hh:1744
Definition: tmp_file.hh:119
Definition: tmp_file.hh:35
open_flags
Definition: file-types.hh:36
auto do_with(T1 &&rv1, T2 &&rv2, More &&... more) noexcept
Definition: do_with.hh:129
futurize_t< std::result_of_t< std::decay_t< Func >std::decay_t< Args >...)> > async(thread_attributes attr, Func &&func, Args &&... args) noexcept
Definition: thread.hh:243
Seastar API namespace.
Definition: abort_on_ebadf.hh:24
future< tmp_dir > make_tmp_dir(std::filesystem::path path_template=default_tmpdir(), file_permissions create_permissions=file_permissions::default_dir_permissions) noexcept
future< tmp_file > make_tmp_file(std::filesystem::path path_template=default_tmpdir(), open_flags oflags=open_flags::rw, file_open_options options={}) noexcept