]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/include/seastar/util/tmp_file.hh
import quincy beta 17.1.0
[ceph.git] / ceph / src / seastar / include / seastar / util / 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
98 /// Returns a future for an opened tmp_file exclusively created by the function.
99 ///
100 /// \param path_template - path where the file is to be created,
101 /// optionally including a template for the file name.
102 /// \param oflags - optional \ref open_flags (open_flags::create | open_flags::exclusive are added to those by default)
103 /// \param options - additional \ref file_open_options, e.g. for setting the created file permission.
104 ///
105 /// \note
106 /// path_template may optionally include a filename template in the last component of the path.
107 /// The template is indicated by two or more consecutive XX's.
108 /// Those will be replaced in the result path by a unique string.
109 ///
110 /// If no filename template is found, then path_template is assumed to refer to the directory where
111 /// the temporary file is to be created at (a.k.a. the parent directory) and `default_tmp_name_template`
112 /// is appended to the path as the filename template.
113 ///
114 /// The parent directory must exist and be writable to the current process.
115 ///
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
179 /// Returns a future for a tmp_dir exclusively created by the function.
180 ///
181 /// \param path_template - path where the file is to be created,
182 /// optionally including a template for the file name.
183 /// \param create_permissions - optional permissions for the newly created directory.
184 ///
185 /// \note
186 /// path_template may optionally include a name template in the last component of the path.
187 /// The template is indicated by two or more consecutive XX's.
188 /// Those will be replaced in the result path by a unique string.
189 ///
190 /// If no name template is found, then path_template is assumed to refer to the directory where
191 /// the temporary dir is to be created at (a.k.a. the parent directory) and `default_tmp_name_template`
192 /// is appended to the path as the name template for the to-be-created directory.
193 ///
194 /// The parent directory must exist and be writable to the current process.
195 ///
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