1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #ifndef CEPH_RGW_BUCKET_H
5 #define CEPH_RGW_BUCKET_H
10 #include "include/types.h"
11 #include "rgw_common.h"
12 #include "rgw_tools.h"
14 #include "rgw_rados.h"
16 #include "rgw_string.h"
18 #include "common/Formatter.h"
19 #include "common/lru_map.h"
20 #include "common/ceph_time.h"
21 #include "rgw_formats.h"
23 // define as static when RGWBucket implementation completes
24 extern void rgw_get_buckets_obj(const rgw_user
& user_id
, string
& buckets_obj_id
);
26 extern int rgw_bucket_store_info(RGWRados
*store
, const string
& bucket_name
, bufferlist
& bl
, bool exclusive
,
27 map
<string
, bufferlist
> *pattrs
, RGWObjVersionTracker
*objv_tracker
,
29 extern int rgw_bucket_instance_store_info(RGWRados
*store
, string
& oid
, bufferlist
& bl
, bool exclusive
,
30 map
<string
, bufferlist
> *pattrs
, RGWObjVersionTracker
*objv_tracker
,
33 extern int rgw_bucket_parse_bucket_instance(const string
& bucket_instance
, string
*target_bucket_instance
, int *shard_id
);
34 extern int rgw_bucket_parse_bucket_key(CephContext
*cct
, const string
& key
,
35 rgw_bucket
* bucket
, int *shard_id
);
37 extern int rgw_bucket_instance_remove_entry(RGWRados
*store
, const string
& entry
,
38 RGWObjVersionTracker
*objv_tracker
);
39 extern void rgw_bucket_instance_key_to_oid(string
& key
);
40 extern void rgw_bucket_instance_oid_to_key(string
& oid
);
42 extern int rgw_bucket_delete_bucket_obj(RGWRados
*store
,
43 const string
& tenant_name
,
44 const string
& bucket_name
,
45 RGWObjVersionTracker
& objv_tracker
);
47 extern int rgw_bucket_sync_user_stats(RGWRados
*store
, const rgw_user
& user_id
, const RGWBucketInfo
& bucket_info
);
48 extern int rgw_bucket_sync_user_stats(RGWRados
*store
, const string
& tenant_name
, const string
& bucket_name
);
50 extern std::string
rgw_make_bucket_entry_name(const std::string
& tenant_name
,
51 const std::string
& bucket_name
);
52 static inline void rgw_make_bucket_entry_name(const string
& tenant_name
,
53 const string
& bucket_name
,
54 std::string
& bucket_entry
) {
55 bucket_entry
= rgw_make_bucket_entry_name(tenant_name
, bucket_name
);
58 extern void rgw_parse_url_bucket(const string
& bucket
,
59 const string
& auth_tenant
,
60 string
&tenant_name
, string
&bucket_name
);
62 struct RGWBucketCompleteInfo
{
64 map
<string
, bufferlist
> attrs
;
66 void dump(Formatter
*f
) const;
67 void decode_json(JSONObj
*obj
);
70 class RGWBucketEntryMetadataObject
: public RGWMetadataObject
{
71 RGWBucketEntryPoint ep
;
73 RGWBucketEntryMetadataObject(RGWBucketEntryPoint
& _ep
, obj_version
& v
, real_time m
) : ep(_ep
) {
78 void dump(Formatter
*f
) const override
{
83 class RGWBucketInstanceMetadataObject
: public RGWMetadataObject
{
84 RGWBucketCompleteInfo info
;
86 RGWBucketInstanceMetadataObject() {}
87 RGWBucketInstanceMetadataObject(RGWBucketCompleteInfo
& i
, obj_version
& v
, real_time m
) : info(i
) {
92 void dump(Formatter
*f
) const override
{
96 void decode_json(JSONObj
*obj
) {
97 info
.decode_json(obj
);
100 RGWBucketInfo
& get_bucket_info() { return info
.info
; }
104 * Store a list of the user's buckets, with associated functinos.
108 std::map
<std::string
, RGWBucketEnt
> buckets
;
111 RGWUserBuckets() = default;
112 RGWUserBuckets(RGWUserBuckets
&&) = default;
114 RGWUserBuckets
& operator=(const RGWUserBuckets
&) = default;
116 void encode(bufferlist
& bl
) const {
120 void decode(bufferlist::const_iterator
& bl
) {
125 * Check if the user owns a bucket by the given name.
127 bool owns(string
& name
) {
128 map
<string
, RGWBucketEnt
>::iterator iter
;
129 iter
= buckets
.find(name
);
130 return (iter
!= buckets
.end());
134 * Add a (created) bucket to the user's bucket list.
136 void add(const RGWBucketEnt
& bucket
) {
137 buckets
[bucket
.bucket
.name
] = bucket
;
141 * Remove a bucket from the user's list by name.
143 void remove(const string
& name
) {
144 map
<string
, RGWBucketEnt
>::iterator iter
;
145 iter
= buckets
.find(name
);
146 if (iter
!= buckets
.end()) {
152 * Get the user's buckets as a map.
154 map
<string
, RGWBucketEnt
>& get_buckets() { return buckets
; }
157 * Cleanup data structure
159 void clear() { buckets
.clear(); }
161 size_t count() { return buckets
.size(); }
163 WRITE_CLASS_ENCODER(RGWUserBuckets
)
165 class RGWMetadataManager
;
166 class RGWMetadataHandler
;
168 class RGWBucketMetaHandlerAllocator
{
170 static RGWMetadataHandler
*alloc();
173 class RGWBucketInstanceMetaHandlerAllocator
{
175 static RGWMetadataHandler
*alloc();
178 class RGWArchiveBucketMetaHandlerAllocator
{
180 static RGWMetadataHandler
*alloc();
183 class RGWArchiveBucketInstanceMetaHandlerAllocator
{
185 static RGWMetadataHandler
*alloc();
188 extern void rgw_bucket_init(RGWMetadataManager
*mm
);
190 * Get all the buckets owned by a user and fill up an RGWUserBuckets with them.
191 * Returns: 0 on success, -ERR# on failure.
193 extern int rgw_read_user_buckets(RGWRados
*store
,
194 const rgw_user
& user_id
,
195 RGWUserBuckets
& buckets
,
196 const string
& marker
,
197 const string
& end_marker
,
201 uint64_t default_amount
= 1000);
203 extern int rgw_link_bucket(RGWRados
* store
,
204 const rgw_user
& user_id
,
206 ceph::real_time creation_time
,
207 bool update_entrypoint
= true);
208 extern int rgw_unlink_bucket(RGWRados
*store
, const rgw_user
& user_id
,
209 const string
& tenant_name
, const string
& bucket_name
, bool update_entrypoint
= true);
211 extern int rgw_remove_object(RGWRados
*store
, const RGWBucketInfo
& bucket_info
, const rgw_bucket
& bucket
, rgw_obj_key
& key
);
212 extern int rgw_remove_bucket(RGWRados
*store
, rgw_bucket
& bucket
, bool delete_children
);
213 extern int rgw_remove_bucket_bypass_gc(RGWRados
*store
, rgw_bucket
& bucket
, int concurrent_max
);
215 extern int rgw_bucket_set_attrs(RGWRados
*store
, RGWBucketInfo
& bucket_info
,
216 map
<string
, bufferlist
>& attrs
,
217 RGWObjVersionTracker
*objv_tracker
);
218 extern int rgw_object_get_attr(RGWRados
* store
, const RGWBucketInfo
& bucket_info
,
219 const rgw_obj
& obj
, const char* attr_name
,
222 extern void check_bad_user_bucket_mapping(RGWRados
*store
, const rgw_user
& user_id
, bool fix
);
224 struct RGWBucketAdminOpState
{
226 std::string display_name
;
227 std::string bucket_name
;
228 std::string bucket_id
;
229 std::string object_name
;
235 bool delete_child_objects
;
243 void set_fetch_stats(bool value
) { stat_buckets
= value
; }
244 void set_check_objects(bool value
) { check_objects
= value
; }
245 void set_fix_index(bool value
) { fix_index
= value
; }
246 void set_delete_children(bool value
) { delete_child_objects
= value
; }
248 void set_max_aio(int value
) { max_aio
= value
; }
250 void set_user_id(const rgw_user
& user_id
) {
251 if (!user_id
.empty())
254 void set_bucket_name(const std::string
& bucket_str
) {
255 bucket_name
= bucket_str
;
257 void set_object(std::string
& object_str
) {
258 object_name
= object_str
;
260 void set_quota(RGWQuotaInfo
& value
) {
265 rgw_user
& get_user_id() { return uid
; }
266 std::string
& get_user_display_name() { return display_name
; }
267 std::string
& get_bucket_name() { return bucket_name
; }
268 std::string
& get_object_name() { return object_name
; }
270 rgw_bucket
& get_bucket() { return bucket
; }
271 void set_bucket(rgw_bucket
& _bucket
) {
273 bucket_stored
= true;
276 void set_bucket_id(const string
& bi
) {
279 const string
& get_bucket_id() { return bucket_id
; }
281 bool will_fetch_stats() { return stat_buckets
; }
282 bool will_fix_index() { return fix_index
; }
283 bool will_delete_children() { return delete_child_objects
; }
284 bool will_check_objects() { return check_objects
; }
285 bool is_user_op() { return !uid
.empty(); }
286 bool is_system_op() { return uid
.empty(); }
287 bool has_bucket_stored() { return bucket_stored
; }
288 int get_max_aio() { return max_aio
; }
290 RGWBucketAdminOpState() : list_buckets(false), stat_buckets(false), check_objects(false),
291 fix_index(false), delete_child_objects(false),
292 bucket_stored(false) {}
296 * A simple wrapper class for administrative bucket operations
301 RGWUserBuckets buckets
;
303 RGWAccessHandle handle
;
305 RGWUserInfo user_info
;
307 std::string bucket_name
;
311 RGWBucketInfo bucket_info
;
314 RGWBucket() : store(NULL
), handle(NULL
), failure(false) {}
315 int init(RGWRados
*storage
, RGWBucketAdminOpState
& op_state
);
317 int check_bad_index_multipart(RGWBucketAdminOpState
& op_state
,
318 RGWFormatterFlusher
& flusher
, std::string
*err_msg
= NULL
);
320 int check_object_index(RGWBucketAdminOpState
& op_state
,
321 RGWFormatterFlusher
& flusher
,
322 std::string
*err_msg
= NULL
);
324 int check_index(RGWBucketAdminOpState
& op_state
,
325 map
<RGWObjCategory
, RGWStorageStats
>& existing_stats
,
326 map
<RGWObjCategory
, RGWStorageStats
>& calculated_stats
,
327 std::string
*err_msg
= NULL
);
329 int remove(RGWBucketAdminOpState
& op_state
, bool bypass_gc
= false, bool keep_index_consistent
= true, std::string
*err_msg
= NULL
);
330 int link(RGWBucketAdminOpState
& op_state
, std::string
*err_msg
= NULL
);
331 int unlink(RGWBucketAdminOpState
& op_state
, std::string
*err_msg
= NULL
);
332 int set_quota(RGWBucketAdminOpState
& op_state
, std::string
*err_msg
= NULL
);
334 int remove_object(RGWBucketAdminOpState
& op_state
, std::string
*err_msg
= NULL
);
335 int policy_bl_to_stream(bufferlist
& bl
, ostream
& o
);
336 int get_policy(RGWBucketAdminOpState
& op_state
, RGWAccessControlPolicy
& policy
);
338 void clear_failure() { failure
= false; }
340 const RGWBucketInfo
& get_bucket_info() const { return bucket_info
; }
343 class RGWBucketAdminOp
346 static int get_policy(RGWRados
*store
, RGWBucketAdminOpState
& op_state
,
347 RGWFormatterFlusher
& flusher
);
348 static int get_policy(RGWRados
*store
, RGWBucketAdminOpState
& op_state
,
349 RGWAccessControlPolicy
& policy
);
350 static int dump_s3_policy(RGWRados
*store
, RGWBucketAdminOpState
& op_state
,
353 static int unlink(RGWRados
*store
, RGWBucketAdminOpState
& op_state
);
354 static int link(RGWRados
*store
, RGWBucketAdminOpState
& op_state
, string
*err_msg
= NULL
);
356 static int check_index(RGWRados
*store
, RGWBucketAdminOpState
& op_state
,
357 RGWFormatterFlusher
& flusher
);
359 static int remove_bucket(RGWRados
*store
, RGWBucketAdminOpState
& op_state
, bool bypass_gc
= false, bool keep_index_consistent
= true);
360 static int remove_object(RGWRados
*store
, RGWBucketAdminOpState
& op_state
);
361 static int info(RGWRados
*store
, RGWBucketAdminOpState
& op_state
, RGWFormatterFlusher
& flusher
);
362 static int limit_check(RGWRados
*store
, RGWBucketAdminOpState
& op_state
,
363 const std::list
<std::string
>& user_ids
,
364 RGWFormatterFlusher
& flusher
,
365 bool warnings_only
= false);
366 static int set_quota(RGWRados
*store
, RGWBucketAdminOpState
& op_state
);
368 static int list_stale_instances(RGWRados
*store
, RGWBucketAdminOpState
& op_state
,
369 RGWFormatterFlusher
& flusher
);
371 static int clear_stale_instances(RGWRados
*store
, RGWBucketAdminOpState
& op_state
,
372 RGWFormatterFlusher
& flusher
);
373 static int fix_lc_shards(RGWRados
*store
, RGWBucketAdminOpState
& op_state
,
374 RGWFormatterFlusher
& flusher
);
375 static int fix_obj_expiry(RGWRados
*store
, RGWBucketAdminOpState
& op_state
,
376 RGWFormatterFlusher
& flusher
, bool dry_run
= false);
380 enum DataLogEntityType
{
381 ENTITY_TYPE_UNKNOWN
= 0,
382 ENTITY_TYPE_BUCKET
= 1,
385 struct rgw_data_change
{
386 DataLogEntityType entity_type
;
390 void encode(bufferlist
& bl
) const {
391 ENCODE_START(1, 1, bl
);
392 uint8_t t
= (uint8_t)entity_type
;
395 encode(timestamp
, bl
);
399 void decode(bufferlist::const_iterator
& bl
) {
403 entity_type
= (DataLogEntityType
)t
;
405 decode(timestamp
, bl
);
409 void dump(Formatter
*f
) const;
410 void decode_json(JSONObj
*obj
);
412 WRITE_CLASS_ENCODER(rgw_data_change
)
414 struct rgw_data_change_log_entry
{
416 real_time log_timestamp
;
417 rgw_data_change entry
;
419 void encode(bufferlist
& bl
) const {
420 ENCODE_START(1, 1, bl
);
422 encode(log_timestamp
, bl
);
427 void decode(bufferlist::const_iterator
& bl
) {
430 decode(log_timestamp
, bl
);
435 void dump(Formatter
*f
) const;
436 void decode_json(JSONObj
*obj
);
438 WRITE_CLASS_ENCODER(rgw_data_change_log_entry
)
440 struct RGWDataChangesLogInfo
{
442 real_time last_update
;
444 void dump(Formatter
*f
) const;
445 void decode_json(JSONObj
*obj
);
449 struct BucketChangeObserver
;
452 class RGWDataChangesLog
{
455 rgw::BucketChangeObserver
*observer
= nullptr;
461 RWLock modified_lock
;
462 map
<int, set
<string
> > modified_shards
;
464 std::atomic
<bool> down_flag
= { false };
466 struct ChangeStatus
{
467 real_time cur_expiration
;
470 RefCountedCond
*cond
;
473 ChangeStatus() : pending(false), cond(NULL
) {
474 lock
= new Mutex("RGWDataChangesLog::ChangeStatus");
482 typedef std::shared_ptr
<ChangeStatus
> ChangeStatusPtr
;
484 lru_map
<rgw_bucket_shard
, ChangeStatusPtr
> changes
;
486 map
<rgw_bucket_shard
, bool> cur_cycle
;
488 void _get_change(const rgw_bucket_shard
& bs
, ChangeStatusPtr
& status
);
489 void register_renew(rgw_bucket_shard
& bs
);
490 void update_renewed(rgw_bucket_shard
& bs
, real_time
& expiration
);
492 class ChangesRenewThread
: public Thread
{
494 RGWDataChangesLog
*log
;
499 ChangesRenewThread(CephContext
*_cct
, RGWDataChangesLog
*_log
) : cct(_cct
), log(_log
), lock("ChangesRenewThread::lock") {}
500 void *entry() override
;
504 ChangesRenewThread
*renew_thread
;
508 RGWDataChangesLog(CephContext
*_cct
, RGWRados
*_store
) : cct(_cct
), store(_store
),
509 lock("RGWDataChangesLog::lock"), modified_lock("RGWDataChangesLog::modified_lock"),
510 changes(cct
->_conf
->rgw_data_log_changes_size
) {
511 num_shards
= cct
->_conf
->rgw_data_log_num_shards
;
513 oids
= new string
[num_shards
];
515 string prefix
= cct
->_conf
->rgw_data_log_obj_prefix
;
517 if (prefix
.empty()) {
521 for (int i
= 0; i
< num_shards
; i
++) {
523 snprintf(buf
, sizeof(buf
), "%s.%d", prefix
.c_str(), i
);
527 renew_thread
= new ChangesRenewThread(cct
, this);
528 renew_thread
->create("rgw_dt_lg_renew");
531 ~RGWDataChangesLog();
533 int choose_oid(const rgw_bucket_shard
& bs
);
534 const std::string
& get_oid(int shard_id
) const { return oids
[shard_id
]; }
535 int add_entry(rgw_bucket
& bucket
, int shard_id
);
536 int get_log_shard_id(rgw_bucket
& bucket
, int shard_id
);
538 int list_entries(int shard
, const real_time
& start_time
, const real_time
& end_time
, int max_entries
,
539 list
<rgw_data_change_log_entry
>& entries
,
540 const string
& marker
,
543 int trim_entries(int shard_id
, const real_time
& start_time
, const real_time
& end_time
,
544 const string
& start_marker
, const string
& end_marker
);
545 int get_info(int shard_id
, RGWDataChangesLogInfo
*info
);
546 int lock_exclusive(int shard_id
, timespan duration
, string
& zone_id
, string
& owner_id
);
547 int unlock(int shard_id
, string
& zone_id
, string
& owner_id
);
552 LogMarker() : shard(0) {}
554 int list_entries(const real_time
& start_time
, const real_time
& end_time
, int max_entries
,
555 list
<rgw_data_change_log_entry
>& entries
, LogMarker
& marker
, bool *ptruncated
);
557 void mark_modified(int shard_id
, const rgw_bucket_shard
& bs
);
558 void read_clear_modified(map
<int, set
<string
> > &modified
);
560 void set_observer(rgw::BucketChangeObserver
*observer
) {
561 this->observer
= observer
;