]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_sal.cc
Import ceph 15.2.8
[ceph.git] / ceph / src / rgw / rgw_sal.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 /*
5 * Ceph - scalable distributed file system
6 *
7 * Copyright (C) 2019 Red Hat, Inc.
8 *
9 * This is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License version 2.1, as published by the Free Software
12 * Foundation. See file COPYING.
13 *
14 */
15
16 #include <errno.h>
17 #include <stdlib.h>
18 #include <system_error>
19 #include <unistd.h>
20 #include <sstream>
21
22 #include "common/errno.h"
23
24 #include "rgw_sal.h"
25 #include "rgw_bucket.h"
26 #include "rgw_multi.h"
27
28 #define dout_subsys ceph_subsys_rgw
29
30 namespace rgw::sal {
31
32 int RGWRadosUser::list_buckets(const string& marker, const string& end_marker,
33 uint64_t max, bool need_stats, RGWBucketList &buckets)
34 {
35 RGWUserBuckets ulist;
36 bool is_truncated = false;
37 int ret;
38
39 ret = store->ctl()->user->list_buckets(info.user_id, marker, end_marker, max,
40 need_stats, &ulist, &is_truncated);
41 if (ret < 0)
42 return ret;
43
44 buckets.set_truncated(is_truncated);
45 for (const auto& ent : ulist.get_buckets()) {
46 RGWRadosBucket *rb = new RGWRadosBucket(this->store, *this, ent.second);
47 buckets.add(rb);
48 }
49
50 return 0;
51 }
52
53 RGWBucketList::~RGWBucketList()
54 {
55 for (auto itr = buckets.begin(); itr != buckets.end(); itr++) {
56 delete itr->second;
57 }
58 buckets.clear();
59 }
60
61 RGWBucket* RGWRadosUser::add_bucket(rgw_bucket& bucket,
62 ceph::real_time creation_time)
63 {
64 return NULL;
65 }
66
67 int RGWRadosUser::get_by_id(rgw_user id, optional_yield y)
68
69 {
70 return store->ctl()->user->get_info_by_uid(id, &info, y);
71 }
72
73 RGWObject *RGWRadosBucket::create_object(const rgw_obj_key &key)
74 {
75 if (!object) {
76 object = new RGWRadosObject(store, key);
77 }
78
79 return object;
80 }
81
82 int RGWRadosBucket::remove_bucket(bool delete_children, optional_yield y)
83 {
84 int ret;
85 map<RGWObjCategory, RGWStorageStats> stats;
86 std::vector<rgw_bucket_dir_entry> objs;
87 map<string, bool> common_prefixes;
88 string bucket_ver, master_ver;
89
90 ret = get_bucket_info(y);
91 if (ret < 0)
92 return ret;
93
94 ret = get_bucket_stats(info, RGW_NO_SHARD, &bucket_ver, &master_ver, stats);
95 if (ret < 0)
96 return ret;
97
98 RGWRados::Bucket target(store->getRados(), info);
99 RGWRados::Bucket::List list_op(&target);
100 int max = 1000;
101
102 list_op.params.list_versions = true;
103 list_op.params.allow_unordered = true;
104
105 bool is_truncated = false;
106 do {
107 objs.clear();
108
109 ret = list_op.list_objects(max, &objs, &common_prefixes, &is_truncated, null_yield);
110 if (ret < 0)
111 return ret;
112
113 if (!objs.empty() && !delete_children) {
114 lderr(store->ctx()) << "ERROR: could not remove non-empty bucket " << ent.bucket.name << dendl;
115 return -ENOTEMPTY;
116 }
117
118 for (const auto& obj : objs) {
119 rgw_obj_key key(obj.key);
120 /* xxx dang */
121 ret = rgw_remove_object(store, info, ent.bucket, key);
122 if (ret < 0 && ret != -ENOENT) {
123 return ret;
124 }
125 }
126 } while(is_truncated);
127
128 string prefix, delimiter;
129
130 ret = abort_bucket_multiparts(store, store->ctx(), info, prefix, delimiter);
131 if (ret < 0) {
132 return ret;
133 }
134
135 ret = store->ctl()->bucket->sync_user_stats(info.owner, info);
136 if ( ret < 0) {
137 ldout(store->ctx(), 1) << "WARNING: failed sync user stats before bucket delete. ret=" << ret << dendl;
138 }
139
140 RGWObjVersionTracker objv_tracker;
141
142 // if we deleted children above we will force delete, as any that
143 // remain is detrius from a prior bug
144 ret = store->getRados()->delete_bucket(info, objv_tracker, null_yield, !delete_children);
145 if (ret < 0) {
146 lderr(store->ctx()) << "ERROR: could not remove bucket " <<
147 ent.bucket.name << dendl;
148 return ret;
149 }
150
151 ret = store->ctl()->bucket->unlink_bucket(info.owner, ent.bucket, null_yield, false);
152 if (ret < 0) {
153 lderr(store->ctx()) << "ERROR: unable to remove user bucket information" << dendl;
154 }
155
156 return ret;
157 }
158
159 int RGWRadosBucket::get_bucket_info(optional_yield y)
160 {
161 return store->getRados()->get_bucket_info(store->svc(), ent.bucket.tenant, ent.bucket.name, info,
162 NULL, y, &attrs);
163 }
164
165 int RGWRadosBucket::get_bucket_stats(RGWBucketInfo& bucket_info, int shard_id,
166 std::string *bucket_ver, std::string *master_ver,
167 std::map<RGWObjCategory, RGWStorageStats>& stats,
168 std::string *max_marker, bool *syncstopped)
169 {
170 return store->getRados()->get_bucket_stats(bucket_info, shard_id, bucket_ver, master_ver, stats, max_marker, syncstopped);
171 }
172
173 int RGWRadosBucket::read_bucket_stats(optional_yield y)
174 {
175 return store->ctl()->bucket->read_bucket_stats(ent.bucket, &ent, y);
176 }
177
178 int RGWRadosBucket::sync_user_stats()
179 {
180 return store->ctl()->bucket->sync_user_stats(user.info.user_id, info);
181 }
182
183 int RGWRadosBucket::update_container_stats(void)
184 {
185 int ret;
186 map<std::string, RGWBucketEnt> m;
187
188 m[ent.bucket.name] = ent;
189 ret = store->getRados()->update_containers_stats(m);
190 if (!ret)
191 return -EEXIST;
192 if (ret < 0)
193 return ret;
194
195 map<string, RGWBucketEnt>::iterator iter = m.find(ent.bucket.name);
196 if (iter == m.end())
197 return -EINVAL;
198
199 ent.count = iter->second.count;
200 ent.size = iter->second.size;
201 ent.size_rounded = iter->second.size_rounded;
202 ent.placement_rule = std::move(iter->second.placement_rule);
203
204 return 0;
205 }
206
207 int RGWRadosBucket::check_bucket_shards(void)
208 {
209 return store->getRados()->check_bucket_shards(info, ent.bucket, get_count());
210 }
211
212 int RGWRadosBucket::link(RGWUser* new_user, optional_yield y)
213 {
214 RGWBucketEntryPoint ep;
215 ep.bucket = ent.bucket;
216 ep.owner = new_user->get_user();
217 ep.creation_time = get_creation_time();
218 ep.linked = true;
219 map<string, bufferlist> ep_attrs;
220 rgw_ep_info ep_data{ep, ep_attrs};
221
222 return store->ctl()->bucket->link_bucket(new_user->get_user(), info.bucket,
223 ceph::real_time(), y, true, &ep_data);
224 }
225
226 int RGWRadosBucket::unlink(RGWUser* new_user, optional_yield y)
227 {
228 return -1;
229 }
230
231 int RGWRadosBucket::chown(RGWUser* new_user, RGWUser* old_user, optional_yield y)
232 {
233 string obj_marker;
234
235 return store->ctl()->bucket->chown(store, info, new_user->get_user(),
236 old_user->get_display_name(), obj_marker, y);
237 }
238
239 bool RGWRadosBucket::is_owner(RGWUser* user)
240 {
241 get_bucket_info(null_yield);
242
243 return (info.owner.compare(user->get_user()) == 0);
244 }
245
246 int RGWRadosBucket::set_acl(RGWAccessControlPolicy &acl, optional_yield y)
247 {
248 bufferlist aclbl;
249
250 acls = acl;
251 acl.encode(aclbl);
252
253 return store->ctl()->bucket->set_acl(acl.get_owner(), ent.bucket, info, aclbl, null_yield);
254 }
255
256 RGWUser *RGWRadosStore::get_user(const rgw_user &u)
257 {
258 return new RGWRadosUser(this, u);
259 }
260
261 //RGWBucket *RGWRadosStore::create_bucket(RGWUser &u, const rgw_bucket &b)
262 //{
263 //if (!bucket) {
264 //bucket = new RGWRadosBucket(this, u, b);
265 //}
266 //
267 //return bucket;
268 //}
269 //
270 void RGWRadosStore::finalize(void) {
271 if (rados)
272 rados->finalize();
273 }
274
275 int RGWRadosStore::get_bucket(RGWUser& u, const rgw_bucket& b, RGWBucket** bucket)
276 {
277 int ret;
278 RGWBucket* bp;
279
280 *bucket = nullptr;
281
282 bp = new RGWRadosBucket(this, u, b);
283 if (!bp) {
284 return -ENOMEM;
285 }
286 ret = bp->get_bucket_info(null_yield);
287 if (ret < 0) {
288 delete bp;
289 return ret;
290 }
291
292 *bucket = bp;
293 return 0;
294 }
295
296 } // namespace rgw::sal
297
298 rgw::sal::RGWRadosStore *RGWStoreManager::init_storage_provider(CephContext *cct, bool use_gc_thread, bool use_lc_thread, bool quota_threads, bool run_sync_thread, bool run_reshard_thread, bool use_cache)
299 {
300 RGWRados *rados = new RGWRados;
301 rgw::sal::RGWRadosStore *store = new rgw::sal::RGWRadosStore();
302
303 store->setRados(rados);
304 rados->set_store(store);
305
306 if ((*rados).set_use_cache(use_cache)
307 .set_run_gc_thread(use_gc_thread)
308 .set_run_lc_thread(use_lc_thread)
309 .set_run_quota_threads(quota_threads)
310 .set_run_sync_thread(run_sync_thread)
311 .set_run_reshard_thread(run_reshard_thread)
312 .initialize(cct) < 0) {
313 delete store;
314 return NULL;
315 }
316
317 return store;
318 }
319
320 rgw::sal::RGWRadosStore *RGWStoreManager::init_raw_storage_provider(CephContext *cct)
321 {
322 RGWRados *rados = new RGWRados;
323 rgw::sal::RGWRadosStore *store = new rgw::sal::RGWRadosStore();
324
325 store->setRados(rados);
326 rados->set_store(store);
327
328 rados->set_context(cct);
329
330 int ret = rados->init_svc(true);
331 if (ret < 0) {
332 ldout(cct, 0) << "ERROR: failed to init services (ret=" << cpp_strerror(-ret) << ")" << dendl;
333 delete store;
334 return nullptr;
335 }
336
337 if (rados->init_rados() < 0) {
338 delete store;
339 return nullptr;
340 }
341
342 return store;
343 }
344
345 void RGWStoreManager::close_storage(rgw::sal::RGWRadosStore *store)
346 {
347 if (!store)
348 return;
349
350 store->finalize();
351
352 delete store;
353 }