1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
11 #include "common/debug.h"
13 #include "include/types.h"
14 #include "include/rados/librados.hpp"
15 #include "common/ceph_mutex.h"
16 #include "common/Cond.h"
17 #include "common/iso_8601.h"
18 #include "common/Thread.h"
19 #include "rgw_common.h"
20 #include "rgw_rados.h"
21 #include "cls/rgw/cls_rgw_types.h"
28 #define HASH_PRIME 7877
29 #define MAX_ID_LEN 255
30 static string lc_oid_prefix
= "lc";
31 static string lc_index_lock_name
= "lc_process";
33 extern const char* LC_STATUS
[];
46 //At present only current object has expiration date
50 LCExpiration(const string
& _days
, const string
& _date
) : days(_days
), date(_date
) {}
52 void encode(bufferlist
& bl
) const {
53 ENCODE_START(3, 2, bl
);
58 void decode(bufferlist::const_iterator
& bl
) {
59 DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, bl
);
66 void dump(Formatter
*f
) const;
67 // static void generate_test_instances(list<ACLOwner*>& o);
68 void set_days(const string
& _days
) { days
= _days
; }
69 string
get_days_str() const {
72 int get_days() const {return atoi(days
.c_str()); }
73 bool has_days() const {
76 void set_date(const string
& _date
) { date
= _date
; }
77 string
get_date() const {
80 bool has_date() const {
84 return days
.empty() && date
.empty();
87 if (!days
.empty() && !date
.empty()) {
89 } else if (!days
.empty() && get_days() <= 0) {
92 //We've checked date in xml parsing
96 WRITE_CLASS_ENCODER(LCExpiration
)
103 string storage_class
;
106 int get_days() const {
107 return atoi(days
.c_str());
110 string
get_date() const {
114 string
get_storage_class() const {
115 return storage_class
;
118 bool has_days() const {
119 return !days
.empty();
122 bool has_date() const {
123 return !date
.empty();
127 return days
.empty() && date
.empty();
131 if (!days
.empty() && !date
.empty()) {
133 } else if (!days
.empty() && get_days() < 0) {
136 //We've checked date in xml parsing
140 void encode(bufferlist
& bl
) const {
141 ENCODE_START(1, 1, bl
);
144 encode(storage_class
, bl
);
148 void decode(bufferlist::const_iterator
& bl
) {
152 decode(storage_class
, bl
);
155 void dump(Formatter
*f
) const {
156 f
->dump_string("days", days
);
157 f
->dump_string("date", date
);
158 f
->dump_string("storage_class", storage_class
);
161 WRITE_CLASS_ENCODER(LCTransition
)
171 const std::string
& get_prefix() const {
175 const RGWObjTags
& get_tags() const {
180 return !(has_prefix() || has_tags());
183 // Determine if we need AND tag when creating xml
184 bool has_multi_condition() const {
185 if (obj_tags
.count() > 1)
187 else if (has_prefix() && has_tags())
193 bool has_prefix() const {
194 return !prefix
.empty();
197 bool has_tags() const {
198 return !obj_tags
.empty();
201 void encode(bufferlist
& bl
) const {
202 ENCODE_START(2, 1, bl
);
204 encode(obj_tags
, bl
);
207 void decode(bufferlist::const_iterator
& bl
) {
211 decode(obj_tags
, bl
);
215 void dump(Formatter
*f
) const;
217 WRITE_CLASS_ENCODER(LCFilter
)
225 LCExpiration expiration
;
226 LCExpiration noncur_expiration
;
227 LCExpiration mp_expiration
;
229 map
<string
, LCTransition
> transitions
;
230 map
<string
, LCTransition
> noncur_transitions
;
231 bool dm_expiration
= false;
238 const string
& get_id() const {
242 const string
& get_status() const {
246 bool is_enabled() const {
247 return status
== "Enabled";
250 void set_enabled(bool flag
) {
251 status
= (flag
? "Enabled" : "Disabled");
254 const string
& get_prefix() const {
258 const LCFilter
& get_filter() const {
262 const LCExpiration
& get_expiration() const {
266 const LCExpiration
& get_noncur_expiration() const {
267 return noncur_expiration
;
270 const LCExpiration
& get_mp_expiration() const {
271 return mp_expiration
;
274 bool get_dm_expiration() const {
275 return dm_expiration
;
278 const map
<string
, LCTransition
>& get_transitions() const {
282 const map
<string
, LCTransition
>& get_noncur_transitions() const {
283 return noncur_transitions
;
286 void set_id(const string
& _id
) {
290 void set_prefix(const string
& _prefix
) {
294 void set_status(const string
& _status
) {
298 void set_expiration(const LCExpiration
& _expiration
) {
299 expiration
= _expiration
;
302 void set_noncur_expiration(const LCExpiration
& _noncur_expiration
) {
303 noncur_expiration
= _noncur_expiration
;
306 void set_mp_expiration(const LCExpiration
& _mp_expiration
) {
307 mp_expiration
= _mp_expiration
;
310 void set_dm_expiration(bool _dm_expiration
) {
311 dm_expiration
= _dm_expiration
;
314 bool add_transition(const LCTransition
& _transition
) {
315 auto ret
= transitions
.emplace(_transition
.get_storage_class(), _transition
);
319 bool add_noncur_transition(const LCTransition
& _noncur_transition
) {
320 auto ret
= noncur_transitions
.emplace(_noncur_transition
.get_storage_class(), _noncur_transition
);
326 void encode(bufferlist
& bl
) const {
327 ENCODE_START(6, 1, bl
);
331 encode(expiration
, bl
);
332 encode(noncur_expiration
, bl
);
333 encode(mp_expiration
, bl
);
334 encode(dm_expiration
, bl
);
336 encode(transitions
, bl
);
337 encode(noncur_transitions
, bl
);
340 void decode(bufferlist::const_iterator
& bl
) {
341 DECODE_START_LEGACY_COMPAT_LEN(6, 1, 1, bl
);
345 decode(expiration
, bl
);
347 decode(noncur_expiration
, bl
);
350 decode(mp_expiration
, bl
);
353 decode(dm_expiration
, bl
);
359 decode(transitions
, bl
);
360 decode(noncur_transitions
, bl
);
364 void dump(Formatter
*f
) const;
366 void init_simple_days_rule(std::string_view _id
, std::string_view _prefix
, int num_days
);
368 WRITE_CLASS_ENCODER(LCRule
)
370 struct transition_action
373 boost::optional
<ceph::real_time
> date
;
374 string storage_class
;
375 transition_action() : days(0) {}
376 void dump(Formatter
*f
) const {
378 f
->dump_int("days", days
);
381 f
->dump_stream("date") << ut
;
386 /* XXX why not LCRule? */
391 bool dm_expiration
{false};
393 int noncur_expiration
{0};
394 int mp_expiration
{0};
395 boost::optional
<ceph::real_time
> expiration_date
;
396 boost::optional
<RGWObjTags
> obj_tags
;
397 map
<string
, transition_action
> transitions
;
398 map
<string
, transition_action
> noncur_transitions
;
403 lc_op(const std::string id
) : id(id
)
406 void dump(Formatter
*f
) const;
409 class RGWLifecycleConfiguration
413 multimap
<string
, lc_op
> prefix_map
;
414 multimap
<string
, LCRule
> rule_map
;
415 bool _add_rule(const LCRule
& rule
);
416 bool has_same_action(const lc_op
& first
, const lc_op
& second
);
418 explicit RGWLifecycleConfiguration(CephContext
*_cct
) : cct(_cct
) {}
419 RGWLifecycleConfiguration() : cct(NULL
) {}
421 void set_ctx(CephContext
*ctx
) {
425 virtual ~RGWLifecycleConfiguration() {}
427 // int get_perm(string& id, int perm_mask);
428 // int get_group_perm(ACLGroupTypeEnum group, int perm_mask);
429 void encode(bufferlist
& bl
) const {
430 ENCODE_START(1, 1, bl
);
431 encode(rule_map
, bl
);
434 void decode(bufferlist::const_iterator
& bl
) {
435 DECODE_START_LEGACY_COMPAT_LEN(1, 1, 1, bl
);
436 decode(rule_map
, bl
);
437 multimap
<string
, LCRule
>::iterator iter
;
438 for (iter
= rule_map
.begin(); iter
!= rule_map
.end(); ++iter
) {
439 LCRule
& rule
= iter
->second
;
444 void dump(Formatter
*f
) const;
445 static void generate_test_instances(list
<RGWLifecycleConfiguration
*>& o
);
447 void add_rule(const LCRule
& rule
);
449 int check_and_add_rule(const LCRule
& rule
);
453 multimap
<string
, LCRule
>& get_rule_map() { return rule_map
; }
454 multimap
<string
, lc_op
>& get_prefix_map() { return prefix_map
; }
456 void create_default(string id, string name) {
458 grant.set_canon(id, name, RGW_PERM_FULL_CONTROL);
463 WRITE_CLASS_ENCODER(RGWLifecycleConfiguration
)
465 class RGWLC
: public DoutPrefixProvider
{
467 rgw::sal::RGWRadosStore
*store
;
469 string
*obj_names
{nullptr};
470 std::atomic
<bool> down_flag
= { false };
477 class LCWorker
: public Thread
479 const DoutPrefixProvider
*dpp
;
484 std::condition_variable cond
;
485 WorkPool
* workpool
{nullptr};
489 using lock_guard
= std::lock_guard
<std::mutex
>;
490 using unique_lock
= std::unique_lock
<std::mutex
>;
492 LCWorker(const DoutPrefixProvider
* dpp
, CephContext
*_cct
, RGWLC
*_lc
,
494 RGWLC
* get_lc() { return lc
; }
495 void *entry() override
;
497 bool should_work(utime_t
& now
);
498 int schedule_next_start_time(utime_t
& start
, utime_t
& now
);
501 friend class RGWRados
;
506 friend class RGWRados
;
508 std::vector
<std::unique_ptr
<RGWLC::LCWorker
>> workers
;
510 RGWLC() : cct(nullptr), store(nullptr) {}
513 void initialize(CephContext
*_cct
, rgw::sal::RGWRadosStore
*_store
);
516 int process(LCWorker
* worker
, bool once
);
517 int process(int index
, int max_secs
, LCWorker
* worker
, bool once
);
518 bool if_already_run_today(time_t start_date
);
519 bool expired_session(time_t started
);
520 time_t thread_stop_at();
521 int list_lc_progress(string
& marker
, uint32_t max_entries
,
522 vector
<cls_rgw_lc_entry
>&, int& index
);
523 int bucket_lc_prepare(int index
, LCWorker
* worker
);
524 int bucket_lc_process(string
& shard_id
, LCWorker
* worker
, time_t stop_at
,
526 int bucket_lc_post(int index
, int max_lock_sec
,
527 cls_rgw_lc_entry
& entry
, int& result
, LCWorker
* worker
);
529 void start_processor();
530 void stop_processor();
531 int set_bucket_config(RGWBucketInfo
& bucket_info
,
532 const map
<string
, bufferlist
>& bucket_attrs
,
533 RGWLifecycleConfiguration
*config
);
534 int remove_bucket_config(RGWBucketInfo
& bucket_info
,
535 const map
<string
, bufferlist
>& bucket_attrs
);
537 CephContext
*get_cct() const override
{ return store
->ctx(); }
538 unsigned get_subsys() const;
539 std::ostream
& gen_prefix(std::ostream
& out
) const;
543 int handle_multipart_expiration(RGWRados::Bucket
*target
,
544 const multimap
<string
, lc_op
>& prefix_map
,
545 LCWorker
* worker
, time_t stop_at
, bool once
);
550 int fix_lc_shard_entry(rgw::sal::RGWRadosStore
*store
, const RGWBucketInfo
& bucket_info
,
551 const map
<std::string
,bufferlist
>& battrs
);
553 std::string
s3_expiration_header(
554 DoutPrefixProvider
* dpp
,
555 const rgw_obj_key
& obj_key
,
556 const RGWObjTags
& obj_tagset
,
557 const ceph::real_time
& mtime
,
558 const std::map
<std::string
, buffer::list
>& bucket_attrs
);
560 bool s3_multipart_abort_header(
561 DoutPrefixProvider
* dpp
,
562 const rgw_obj_key
& obj_key
,
563 const ceph::real_time
& mtime
,
564 const std::map
<std::string
, buffer::list
>& bucket_attrs
,
565 ceph::real_time
& abort_date
,
566 std::string
& rule_id
);
568 } // namespace rgw::lc