]> git.proxmox.com Git - ceph.git/blob - ceph/src/crimson/os/cyan_store.cc
update download target update for octopus release
[ceph.git] / ceph / src / crimson / os / cyan_store.cc
1 #include "cyan_store.h"
2
3 #include <fmt/format.h>
4
5 #include "common/safe_io.h"
6
7 #include "crimson/os/cyan_collection.h"
8 #include "crimson/os/cyan_object.h"
9 #include "crimson/os/Transaction.h"
10
11 namespace {
12 seastar::logger& logger() {
13 return ceph::get_logger(ceph_subsys_filestore);
14 }
15 }
16
17 namespace ceph::os {
18
19 using ObjectRef = boost::intrusive_ptr<Object>;
20
21 CyanStore::CyanStore(const std::string& path)
22 : path{path}
23 {}
24
25 CyanStore::~CyanStore() = default;
26
27 seastar::future<> CyanStore::mount()
28 {
29 bufferlist bl;
30 string fn = path + "/collections";
31 string err;
32 if (int r = bl.read_file(fn.c_str(), &err); r < 0) {
33 throw std::runtime_error("read_file");
34 }
35
36 set<coll_t> collections;
37 auto p = bl.cbegin();
38 decode(collections, p);
39
40 for (auto& coll : collections) {
41 string fn = fmt::format("{}/{}", path, coll);
42 bufferlist cbl;
43 if (int r = cbl.read_file(fn.c_str(), &err); r < 0) {
44 throw std::runtime_error("read_file");
45 }
46 CollectionRef c{new Collection{coll}};
47 auto p = cbl.cbegin();
48 c->decode(p);
49 coll_map[coll] = c;
50 used_bytes += c->used_bytes();
51 }
52 return seastar::now();
53 }
54
55 seastar::future<> CyanStore::umount()
56 {
57 set<coll_t> collections;
58 for (auto& [col, ch] : coll_map) {
59 collections.insert(col);
60 bufferlist bl;
61 ceph_assert(ch);
62 ch->encode(bl);
63 string fn = fmt::format("{}/{}", path, col);
64 if (int r = bl.write_file(fn.c_str()); r < 0) {
65 throw std::runtime_error("write_file");
66 }
67 }
68
69 string fn = path + "/collections";
70 bufferlist bl;
71 encode(collections, bl);
72 if (int r = bl.write_file(fn.c_str()); r < 0) {
73 throw std::runtime_error("write_file");
74 }
75 return seastar::now();
76 }
77
78 seastar::future<> CyanStore::mkfs(uuid_d osd_fsid)
79 {
80 string fsid_str;
81 int r = read_meta("fsid", &fsid_str);
82 if (r == -ENOENT) {
83 write_meta("fsid", fmt::format("{}", osd_fsid));
84 } else if (r < 0) {
85 throw std::runtime_error("read_meta");
86 } else {
87 logger().error("{} already has fsid {}", __func__, fsid_str);
88 throw std::runtime_error("mkfs");
89 }
90
91 string fn = path + "/collections";
92 bufferlist bl;
93 set<coll_t> collections;
94 encode(collections, bl);
95 r = bl.write_file(fn.c_str());
96 if (r < 0)
97 throw std::runtime_error("write_file");
98
99 write_meta("type", "memstore");
100 return seastar::now();
101 }
102
103 CyanStore::CollectionRef CyanStore::create_new_collection(const coll_t& cid)
104 {
105 auto c = new Collection{cid};
106 return new_coll_map[cid] = c;
107 }
108
109 CyanStore::CollectionRef CyanStore::open_collection(const coll_t& cid)
110 {
111 auto cp = coll_map.find(cid);
112 if (cp == coll_map.end())
113 return {};
114 return cp->second;
115 }
116
117 std::vector<coll_t> CyanStore::list_collections()
118 {
119 std::vector<coll_t> collections;
120 for (auto& coll : coll_map) {
121 collections.push_back(coll.first);
122 }
123 return collections;
124 }
125
126 seastar::future<bufferlist> CyanStore::read(CollectionRef c,
127 const ghobject_t& oid,
128 uint64_t offset,
129 size_t len,
130 uint32_t op_flags)
131 {
132 logger().info("{} {} {} {}~{}",
133 __func__, c->cid, oid, offset, len);
134 if (!c->exists) {
135 throw std::runtime_error(fmt::format("collection does not exist: {}", c->cid));
136 }
137 ObjectRef o = c->get_object(oid);
138 if (!o) {
139 throw std::runtime_error(fmt::format("object does not exist: {}", oid));
140 }
141 if (offset >= o->get_size())
142 return seastar::make_ready_future<bufferlist>();
143 size_t l = len;
144 if (l == 0 && offset == 0) // note: len == 0 means read the entire object
145 l = o->get_size();
146 else if (offset + l > o->get_size())
147 l = o->get_size() - offset;
148 bufferlist bl;
149 if (int r = o->read(offset, l, bl); r < 0) {
150 throw std::runtime_error("read");
151 }
152 return seastar::make_ready_future<bufferlist>(std::move(bl));
153 }
154
155 seastar::future<CyanStore::omap_values_t>
156 CyanStore::omap_get_values(CollectionRef c,
157 const ghobject_t& oid,
158 std::vector<std::string>&& keys)
159 {
160 logger().info("{} {} {}",
161 __func__, c->cid, oid);
162 auto o = c->get_object(oid);
163 if (!o) {
164 throw std::runtime_error(fmt::format("object does not exist: {}", oid));
165 }
166 omap_values_t values;
167 for (auto& key : keys) {
168 if (auto found = o->omap.find(key); found != o->omap.end()) {
169 values.insert(*found);
170 }
171 }
172 return seastar::make_ready_future<omap_values_t>(std::move(values));
173 }
174
175 seastar::future<> CyanStore::do_transaction(CollectionRef ch,
176 Transaction&& t)
177 {
178 auto i = t.begin();
179 while (i.have_op()) {
180 Transaction::Op* op = i.decode_op();
181 int r = 0;
182 switch (op->op) {
183 case Transaction::OP_NOP:
184 break;
185 case Transaction::OP_WRITE:
186 {
187 coll_t cid = i.get_cid(op->cid);
188 ghobject_t oid = i.get_oid(op->oid);
189 uint64_t off = op->off;
190 uint64_t len = op->len;
191 uint32_t fadvise_flags = i.get_fadvise_flags();
192 bufferlist bl;
193 i.decode_bl(bl);
194 r = _write(cid, oid, off, len, bl, fadvise_flags);
195 }
196 break;
197 case Transaction::OP_MKCOLL:
198 {
199 coll_t cid = i.get_cid(op->cid);
200 r = _create_collection(cid, op->split_bits);
201 }
202 break;
203 default:
204 logger().error("bad op {}", static_cast<unsigned>(op->op));
205 abort();
206 }
207 if (r < 0) {
208 abort();
209 }
210 }
211 return seastar::now();
212 }
213
214 int CyanStore::_write(const coll_t& cid, const ghobject_t& oid,
215 uint64_t offset, size_t len, const bufferlist& bl,
216 uint32_t fadvise_flags)
217 {
218 logger().info("{} {} {} {} ~ {}",
219 __func__, cid, oid, offset, len);
220 assert(len == bl.length());
221
222 auto c = open_collection(cid);
223 if (!c)
224 return -ENOENT;
225
226 ObjectRef o = c->get_or_create_object(oid);
227 if (len > 0) {
228 const ssize_t old_size = o->get_size();
229 o->write(offset, bl);
230 used_bytes += (o->get_size() - old_size);
231 }
232
233 return 0;
234 }
235
236 int CyanStore::_create_collection(const coll_t& cid, int bits)
237 {
238 auto result = coll_map.insert(std::make_pair(cid, CollectionRef()));
239 if (!result.second)
240 return -EEXIST;
241 auto p = new_coll_map.find(cid);
242 assert(p != new_coll_map.end());
243 result.first->second = p->second;
244 result.first->second->bits = bits;
245 new_coll_map.erase(p);
246 return 0;
247 }
248
249 void CyanStore::write_meta(const std::string& key,
250 const std::string& value)
251 {
252 std::string v = value;
253 v += "\n";
254 if (int r = safe_write_file(path.c_str(), key.c_str(),
255 v.c_str(), v.length(), 0600);
256 r < 0) {
257 throw std::runtime_error{fmt::format("unable to write_meta({})", key)};
258 }
259 }
260
261 int CyanStore::read_meta(const std::string& key,
262 std::string* value)
263 {
264 char buf[4096];
265 int r = safe_read_file(path.c_str(), key.c_str(),
266 buf, sizeof(buf));
267 if (r <= 0) {
268 return r;
269 }
270 // drop trailing newlines
271 while (r && isspace(buf[r-1])) {
272 --r;
273 }
274 *value = string{buf, static_cast<size_t>(r)};
275 return 0;
276 }
277 }