]> git.proxmox.com Git - ceph.git/blob - ceph/src/crimson/os/alienstore/alien_store.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / crimson / os / alienstore / alien_store.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "alien_collection.h"
5 #include "alien_store.h"
6
7 #include <map>
8 #include <string_view>
9 #include <boost/algorithm/string/trim.hpp>
10 #include <fmt/format.h>
11 #include <fmt/ostream.h>
12
13 #include <seastar/core/alien.hh>
14 #include <seastar/core/future-util.hh>
15 #include <seastar/core/reactor.hh>
16
17 #include "common/ceph_context.h"
18 #include "global/global_context.h"
19 #include "include/Context.h"
20 #include "os/bluestore/BlueStore.h"
21 #include "os/ObjectStore.h"
22 #include "os/Transaction.h"
23
24 #include "crimson/common/log.h"
25 #include "crimson/os/futurized_store.h"
26
27 namespace {
28 seastar::logger& logger()
29 {
30 return crimson::get_logger(ceph_subsys_filestore);
31 }
32
33 class OnCommit final: public Context
34 {
35 int cpuid;
36 Context *oncommit;
37 seastar::promise<> &alien_done;
38 public:
39 OnCommit(
40 int id,
41 seastar::promise<> &done,
42 Context *oncommit,
43 ceph::os::Transaction& txn)
44 : cpuid(id), oncommit(oncommit),
45 alien_done(done) {}
46
47 void finish(int) final {
48 return seastar::alien::submit_to(cpuid, [this] {
49 if (oncommit) oncommit->complete(0);
50 alien_done.set_value();
51 return seastar::make_ready_future<>();
52 }).wait();
53 }
54 };
55 }
56
57 namespace crimson::os {
58
59 AlienStore::AlienStore(const std::string& path, const ConfigValues& values)
60 : path{path}
61 {
62 cct = std::make_unique<CephContext>(CEPH_ENTITY_TYPE_OSD);
63 g_ceph_context = cct.get();
64 cct->_conf.set_config_values(values);
65 store = std::make_unique<BlueStore>(cct.get(), path);
66 tp = std::make_unique<crimson::thread::ThreadPool>(1, 128, seastar::engine().cpu_id() + 10);
67 }
68
69 seastar::future<> AlienStore::start()
70 {
71 return tp->start();
72 }
73
74 seastar::future<> AlienStore::stop()
75 {
76 return tp->submit([this] {
77 for (auto [cid, ch]: coll_map)
78 static_cast<AlienCollection*>(ch.get())->collection.reset();
79 store.reset();
80 }).then([this] {
81 return tp->stop();
82 });
83 }
84
85 AlienStore::~AlienStore() = default;
86
87 seastar::future<> AlienStore::mount()
88 {
89 logger().debug("{}", __func__);
90 return tp->submit([this] {
91 return store->mount();
92 }).then([] (int) {
93 return seastar::now();
94 });
95 }
96
97 seastar::future<> AlienStore::umount()
98 {
99 logger().debug("{}", __func__);
100 return transaction_gate.close().then([this] {
101 return tp->submit([this] {
102 return store->umount();
103 });
104 }).then([] (int) {
105 return seastar::now();
106 });
107 }
108
109 seastar::future<> AlienStore::mkfs(uuid_d new_osd_fsid)
110 {
111 logger().debug("{}", __func__);
112 osd_fsid = new_osd_fsid;
113 return tp->submit([this] {
114 return store->mkfs();
115 }).then([] (int) {
116 return seastar::now();
117 });
118 }
119
120 seastar::future<std::vector<ghobject_t>, ghobject_t>
121 AlienStore::list_objects(CollectionRef ch,
122 const ghobject_t& start,
123 const ghobject_t& end,
124 uint64_t limit) const
125 {
126 logger().debug("{}", __func__);
127 return seastar::do_with(std::vector<ghobject_t>(), ghobject_t(),
128 [=] (auto &objects, auto &next) {
129 objects.reserve(limit);
130 return tp->submit([=, &objects, &next] {
131 auto c = static_cast<AlienCollection*>(ch.get());
132 return store->collection_list(c->collection, start, end,
133 store->get_ideal_list_max(),
134 &objects, &next);
135 }).then([&objects, &next] (int) {
136 return seastar::make_ready_future<std::vector<ghobject_t>, ghobject_t>(
137 std::move(objects), std::move(next));
138 });
139 });
140 }
141
142 seastar::future<CollectionRef> AlienStore::create_new_collection(const coll_t& cid)
143 {
144 logger().debug("{}", __func__);
145 return tp->submit([this, cid] {
146 return store->create_new_collection(cid);
147 }).then([this, cid] (ObjectStore::CollectionHandle c) {
148 CollectionRef ch;
149 auto cp = coll_map.find(c->cid);
150 if (cp == coll_map.end()) {
151 ch = new AlienCollection(c);
152 coll_map[c->cid] = ch;
153 } else {
154 ch = cp->second;
155 auto ach = static_cast<AlienCollection*>(ch.get());
156 if (ach->collection != c) {
157 ach->collection = c;
158 }
159 }
160 return seastar::make_ready_future<CollectionRef>(ch);
161 });
162
163 }
164
165 seastar::future<CollectionRef> AlienStore::open_collection(const coll_t& cid)
166 {
167 logger().debug("{}", __func__);
168 return tp->submit([this, cid] {
169 return store->open_collection(cid);
170 }).then([this] (ObjectStore::CollectionHandle c) {
171 CollectionRef ch;
172 auto cp = coll_map.find(c->cid);
173 if (cp == coll_map.end()){
174 ch = new AlienCollection(c);
175 coll_map[c->cid] = ch;
176 } else {
177 ch = cp->second;
178 auto ach = static_cast<AlienCollection*>(ch.get());
179 if (ach->collection != c){
180 ach->collection = c;
181 }
182 }
183 return seastar::make_ready_future<CollectionRef>(ch);
184 });
185 }
186
187 seastar::future<std::vector<coll_t>> AlienStore::list_collections()
188 {
189 logger().debug("{}", __func__);
190
191 return seastar::do_with(std::vector<coll_t>{}, [=] (auto &ls) {
192 return tp->submit([this, &ls] {
193 return store->list_collections(ls);
194 }).then([&ls] (int) {
195 return seastar::make_ready_future<std::vector<coll_t>>(std::move(ls));
196 });
197 });
198 }
199
200 AlienStore::read_errorator::future<ceph::bufferlist>
201 AlienStore::read(CollectionRef ch,
202 const ghobject_t& oid,
203 uint64_t offset,
204 size_t len,
205 uint32_t op_flags)
206 {
207 logger().debug("{}", __func__);
208 return seastar::do_with(ceph::bufferlist{}, [=] (auto &bl) {
209 return tp->submit([=, &bl] {
210 auto c = static_cast<AlienCollection*>(ch.get());
211 return store->read(c->collection, oid, offset, len, bl, op_flags);
212 }).then([&bl] (int r) -> read_errorator::future<ceph::bufferlist> {
213 if (r == -ENOENT) {
214 return crimson::ct_error::enoent::make();
215 } else if (r == -EIO) {
216 return crimson::ct_error::input_output_error::make();
217 } else {
218 return read_errorator::make_ready_future<ceph::bufferlist>(std::move(bl));
219 }
220 });
221 });
222 }
223
224 AlienStore::get_attr_errorator::future<ceph::bufferptr>
225 AlienStore::get_attr(CollectionRef ch,
226 const ghobject_t& oid,
227 std::string_view name) const
228 {
229 logger().debug("{}", __func__);
230 return seastar::do_with(ceph::bufferptr{}, [=] (auto &value) {
231 return tp->submit([=, &value] {
232 auto c =static_cast<AlienCollection*>(ch.get());
233 return store->getattr(c->collection, oid,
234 static_cast<std::string>(name).c_str(), value);
235 }).then([oid, name, &value] (int r) -> get_attr_errorator::future<ceph::bufferptr> {
236 if (r == -ENOENT) {
237 return crimson::ct_error::enoent::make();
238 } else if (r == -ENODATA) {
239 return crimson::ct_error::enodata::make();
240 } else {
241 return get_attr_errorator::make_ready_future<ceph::bufferptr>(
242 std::move(value));
243 }
244 });
245 });
246 }
247
248 AlienStore::get_attrs_ertr::future<AlienStore::attrs_t>
249 AlienStore::get_attrs(CollectionRef ch,
250 const ghobject_t& oid)
251 {
252 logger().debug("{}", __func__);
253 return seastar::do_with(attrs_t{}, [=] (auto &aset) {
254 return tp->submit([=, &aset] {
255 auto c = static_cast<AlienCollection*>(ch.get());
256 return store->getattrs(c->collection, oid,
257 reinterpret_cast<map<string,bufferptr>&>(aset));
258 }).then([&aset] (int r) -> get_attrs_ertr::future<attrs_t> {
259 if (r == -ENOENT) {
260 return crimson::ct_error::enoent::make();;
261 } else {
262 return get_attrs_ertr::make_ready_future<attrs_t>(std::move(aset));
263 }
264 });
265 });
266 }
267
268 seastar::future<AlienStore::omap_values_t>
269 AlienStore::omap_get_values(CollectionRef ch,
270 const ghobject_t& oid,
271 const set<string>& keys)
272 {
273 logger().debug("{}", __func__);
274 return seastar::do_with(omap_values_t{}, [=] (auto &values) {
275 return tp->submit([=, &values] {
276 auto c = static_cast<AlienCollection*>(ch.get());
277 return store->omap_get_values(c->collection, oid, keys,
278 reinterpret_cast<map<string, bufferlist>*>(&values));
279 }).then([&values] (int) {
280 return seastar::make_ready_future<omap_values_t>(std::move(values));
281 });
282 });
283 }
284
285 seastar::future<bool, AlienStore::omap_values_t>
286 AlienStore::omap_get_values(CollectionRef ch,
287 const ghobject_t &oid,
288 const std::optional<string> &start)
289 {
290 logger().debug("{} with_start", __func__);
291 return seastar::do_with(omap_values_t{}, [=] (auto &values) {
292 return tp->submit([=, &values] {
293 auto c = static_cast<AlienCollection*>(ch.get());
294 return store->omap_get_values(c->collection, oid, start,
295 reinterpret_cast<map<string, bufferlist>*>(&values));
296 }).then([&values] (int r) {
297 return seastar::make_ready_future<bool, omap_values_t>(true, std::move(values));
298 });
299 });
300 }
301
302 seastar::future<> AlienStore::do_transaction(CollectionRef ch,
303 ceph::os::Transaction&& txn)
304 {
305 logger().debug("{}", __func__);
306 auto id = seastar::engine().cpu_id();
307 auto done = seastar::promise<>();
308 return seastar::do_with(
309 std::move(txn),
310 std::move(done),
311 [this, ch, id] (auto &txn, auto &done) {
312 return seastar::with_gate(transaction_gate, [this, ch, id, &txn, &done] {
313 return tp_mutex.lock().then ([this, ch, id, &txn, &done] {
314 Context *crimson_wrapper =
315 ceph::os::Transaction::collect_all_contexts(txn);
316 return tp->submit([this, ch, id, crimson_wrapper, &txn, &done] {
317 txn.register_on_commit(new OnCommit(id, done, crimson_wrapper, txn));
318 auto c = static_cast<AlienCollection*>(ch.get());
319 return store->queue_transaction(c->collection, std::move(txn));
320 });
321 }).then([this, &done] (int) {
322 tp_mutex.unlock();
323 return done.get_future();
324 });
325 });
326 });
327 }
328
329 seastar::future<> AlienStore::write_meta(const std::string& key,
330 const std::string& value)
331 {
332 logger().debug("{}", __func__);
333 return tp->submit([=] {
334 return store->write_meta(key, value);
335 }).then([] (int) {
336 return seastar::make_ready_future<>();
337 });
338 }
339
340 seastar::future<int, std::string> AlienStore::read_meta(const std::string& key)
341 {
342 logger().debug("{}", __func__);
343 return tp->submit([this, key] {
344 std::string value;
345 int r = store->read_meta(key, &value);
346 if (r > 0) {
347 value.resize(r);
348 boost::algorithm::trim_right_if(value,
349 [] (unsigned char c) {return isspace(c);});
350 } else {
351 value.clear();
352 }
353 return std::make_pair(r, value);
354 }).then([] (auto entry) {
355 return seastar::make_ready_future<int, std::string>(entry.first, entry.second);
356 });
357 }
358
359 uuid_d AlienStore::get_fsid() const
360 {
361 logger().debug("{}", __func__);
362 return osd_fsid;
363 }
364
365 seastar::future<store_statfs_t> AlienStore::stat() const
366 {
367 logger().info("{}", __func__);
368 return seastar::do_with(store_statfs_t{}, [this] (store_statfs_t &st) {
369 return tp->submit([this, &st] {
370 return store->statfs(&st, nullptr);
371 }).then([&st] (int) {
372 return seastar::make_ready_future<store_statfs_t>(std::move(st));
373 });
374 });
375 }
376
377 unsigned AlienStore::get_max_attr_name_length() const
378 {
379 logger().info("{}", __func__);
380 return 256;
381 }
382
383 }