]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_lc.h
Import ceph 15.2.8
[ceph.git] / ceph / src / rgw / rgw_lc.h
CommitLineData
11fdf7f2 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
11fdf7f2 3
7c673cae
FG
4#ifndef CEPH_RGW_LC_H
5#define CEPH_RGW_LC_H
6
7#include <map>
8#include <string>
9#include <iostream>
7c673cae
FG
10
11#include "common/debug.h"
12
13#include "include/types.h"
14#include "include/rados/librados.hpp"
9f95a23c 15#include "common/ceph_mutex.h"
7c673cae 16#include "common/Cond.h"
224ce89b 17#include "common/iso_8601.h"
7c673cae
FG
18#include "common/Thread.h"
19#include "rgw_common.h"
20#include "rgw_rados.h"
7c673cae 21#include "cls/rgw/cls_rgw_types.h"
11fdf7f2 22#include "rgw_tag.h"
9f95a23c 23#include "rgw_sal.h"
7c673cae
FG
24
25#include <atomic>
9f95a23c 26#include <tuple>
7c673cae 27
7c673cae
FG
28#define HASH_PRIME 7877
29#define MAX_ID_LEN 255
30static string lc_oid_prefix = "lc";
31static string lc_index_lock_name = "lc_process";
32
33extern const char* LC_STATUS[];
34
35typedef enum {
36 lc_uninitial = 0,
37 lc_processing,
38 lc_failed,
39 lc_complete,
11fdf7f2 40} LC_BUCKET_STATUS;
7c673cae
FG
41
42class LCExpiration
43{
44protected:
45 string days;
224ce89b
WB
46 //At present only current object has expiration date
47 string date;
7c673cae
FG
48public:
49 LCExpiration() {}
11fdf7f2 50 LCExpiration(const string& _days, const string& _date) : days(_days), date(_date) {}
7c673cae
FG
51
52 void encode(bufferlist& bl) const {
224ce89b 53 ENCODE_START(3, 2, bl);
11fdf7f2
TL
54 encode(days, bl);
55 encode(date, bl);
7c673cae
FG
56 ENCODE_FINISH(bl);
57 }
11fdf7f2 58 void decode(bufferlist::const_iterator& bl) {
224ce89b 59 DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, bl);
11fdf7f2 60 decode(days, bl);
224ce89b 61 if (struct_v >= 3) {
11fdf7f2 62 decode(date, bl);
224ce89b 63 }
7c673cae
FG
64 DECODE_FINISH(bl);
65 }
66 void dump(Formatter *f) const;
67// static void generate_test_instances(list<ACLOwner*>& o);
68 void set_days(const string& _days) { days = _days; }
224ce89b 69 string get_days_str() const {
31f18b77
FG
70 return days;
71 }
224ce89b
WB
72 int get_days() const {return atoi(days.c_str()); }
73 bool has_days() const {
74 return !days.empty();
75 }
76 void set_date(const string& _date) { date = _date; }
77 string get_date() const {
78 return date;
79 }
80 bool has_date() const {
81 return !date.empty();
82 }
83 bool empty() const {
84 return days.empty() && date.empty();
85 }
86 bool valid() const {
87 if (!days.empty() && !date.empty()) {
88 return false;
9f95a23c 89 } else if (!days.empty() && get_days() <= 0) {
224ce89b
WB
90 return false;
91 }
92 //We've checked date in xml parsing
93 return true;
7c673cae
FG
94 }
95};
96WRITE_CLASS_ENCODER(LCExpiration)
97
11fdf7f2
TL
98class LCTransition
99{
100protected:
101 string days;
102 string date;
103 string storage_class;
104
105public:
106 int get_days() const {
107 return atoi(days.c_str());
108 }
109
110 string get_date() const {
111 return date;
112 }
113
114 string get_storage_class() const {
115 return storage_class;
116 }
117
118 bool has_days() const {
119 return !days.empty();
120 }
121
122 bool has_date() const {
123 return !date.empty();
124 }
125
126 bool empty() const {
127 return days.empty() && date.empty();
128 }
129
130 bool valid() const {
131 if (!days.empty() && !date.empty()) {
132 return false;
9f95a23c 133 } else if (!days.empty() && get_days() < 0) {
11fdf7f2
TL
134 return false;
135 }
136 //We've checked date in xml parsing
137 return true;
138 }
139
140 void encode(bufferlist& bl) const {
141 ENCODE_START(1, 1, bl);
142 encode(days, bl);
143 encode(date, bl);
144 encode(storage_class, bl);
145 ENCODE_FINISH(bl);
146 }
147
148 void decode(bufferlist::const_iterator& bl) {
149 DECODE_START(1, bl);
150 decode(days, bl);
151 decode(date, bl);
152 decode(storage_class, bl);
153 DECODE_FINISH(bl);
154 }
f91f0fd5
TL
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);
159 }
11fdf7f2
TL
160};
161WRITE_CLASS_ENCODER(LCTransition)
162
181888fb
FG
163class LCFilter
164{
165 protected:
166 std::string prefix;
11fdf7f2
TL
167 RGWObjTags obj_tags;
168
181888fb 169 public:
11fdf7f2
TL
170
171 const std::string& get_prefix() const {
181888fb
FG
172 return prefix;
173 }
174
11fdf7f2
TL
175 const RGWObjTags& get_tags() const {
176 return obj_tags;
181888fb
FG
177 }
178
11fdf7f2
TL
179 bool empty() const {
180 return !(has_prefix() || has_tags());
181888fb
FG
181 }
182
11fdf7f2
TL
183 // Determine if we need AND tag when creating xml
184 bool has_multi_condition() const {
185 if (obj_tags.count() > 1)
186 return true;
187 else if (has_prefix() && has_tags())
188 return true;
189
190 return false;
181888fb
FG
191 }
192
193 bool has_prefix() const {
194 return !prefix.empty();
195 }
196
11fdf7f2
TL
197 bool has_tags() const {
198 return !obj_tags.empty();
199 }
200
181888fb 201 void encode(bufferlist& bl) const {
11fdf7f2
TL
202 ENCODE_START(2, 1, bl);
203 encode(prefix, bl);
204 encode(obj_tags, bl);
181888fb
FG
205 ENCODE_FINISH(bl);
206 }
11fdf7f2
TL
207 void decode(bufferlist::const_iterator& bl) {
208 DECODE_START(2, bl);
209 decode(prefix, bl);
210 if (struct_v >= 2) {
211 decode(obj_tags, bl);
212 }
181888fb
FG
213 DECODE_FINISH(bl);
214 }
11fdf7f2 215 void dump(Formatter *f) const;
181888fb 216};
11fdf7f2 217WRITE_CLASS_ENCODER(LCFilter)
181888fb 218
7c673cae
FG
219class LCRule
220{
221protected:
222 string id;
223 string prefix;
224 string status;
225 LCExpiration expiration;
226 LCExpiration noncur_expiration;
227 LCExpiration mp_expiration;
181888fb 228 LCFilter filter;
11fdf7f2
TL
229 map<string, LCTransition> transitions;
230 map<string, LCTransition> noncur_transitions;
224ce89b 231 bool dm_expiration = false;
7c673cae
FG
232
233public:
234
235 LCRule(){};
236 ~LCRule(){};
237
11fdf7f2
TL
238 const string& get_id() const {
239 return id;
7c673cae
FG
240 }
241
11fdf7f2 242 const string& get_status() const {
7c673cae
FG
243 return status;
244 }
181888fb 245
11fdf7f2
TL
246 bool is_enabled() const {
247 return status == "Enabled";
248 }
249
250 void set_enabled(bool flag) {
251 status = (flag ? "Enabled" : "Disabled");
252 }
253
254 const string& get_prefix() const {
7c673cae
FG
255 return prefix;
256 }
257
11fdf7f2 258 const LCFilter& get_filter() const {
181888fb
FG
259 return filter;
260 }
261
11fdf7f2 262 const LCExpiration& get_expiration() const {
7c673cae
FG
263 return expiration;
264 }
265
11fdf7f2 266 const LCExpiration& get_noncur_expiration() const {
7c673cae
FG
267 return noncur_expiration;
268 }
269
11fdf7f2 270 const LCExpiration& get_mp_expiration() const {
7c673cae
FG
271 return mp_expiration;
272 }
273
11fdf7f2 274 bool get_dm_expiration() const {
31f18b77
FG
275 return dm_expiration;
276 }
277
11fdf7f2
TL
278 const map<string, LCTransition>& get_transitions() const {
279 return transitions;
280 }
281
282 const map<string, LCTransition>& get_noncur_transitions() const {
283 return noncur_transitions;
7c673cae
FG
284 }
285
11fdf7f2
TL
286 void set_id(const string& _id) {
287 id = _id;
288 }
289
290 void set_prefix(const string& _prefix) {
291 prefix = _prefix;
7c673cae
FG
292 }
293
11fdf7f2
TL
294 void set_status(const string& _status) {
295 status = _status;
7c673cae
FG
296 }
297
11fdf7f2
TL
298 void set_expiration(const LCExpiration& _expiration) {
299 expiration = _expiration;
7c673cae
FG
300 }
301
11fdf7f2
TL
302 void set_noncur_expiration(const LCExpiration& _noncur_expiration) {
303 noncur_expiration = _noncur_expiration;
7c673cae
FG
304 }
305
11fdf7f2
TL
306 void set_mp_expiration(const LCExpiration& _mp_expiration) {
307 mp_expiration = _mp_expiration;
7c673cae
FG
308 }
309
31f18b77
FG
310 void set_dm_expiration(bool _dm_expiration) {
311 dm_expiration = _dm_expiration;
312 }
313
11fdf7f2
TL
314 bool add_transition(const LCTransition& _transition) {
315 auto ret = transitions.emplace(_transition.get_storage_class(), _transition);
316 return ret.second;
317 }
318
319 bool add_noncur_transition(const LCTransition& _noncur_transition) {
320 auto ret = noncur_transitions.emplace(_noncur_transition.get_storage_class(), _noncur_transition);
321 return ret.second;
322 }
323
324 bool valid() const;
7c673cae
FG
325
326 void encode(bufferlist& bl) const {
11fdf7f2
TL
327 ENCODE_START(6, 1, bl);
328 encode(id, bl);
329 encode(prefix, bl);
330 encode(status, bl);
331 encode(expiration, bl);
332 encode(noncur_expiration, bl);
333 encode(mp_expiration, bl);
334 encode(dm_expiration, bl);
335 encode(filter, bl);
336 encode(transitions, bl);
337 encode(noncur_transitions, bl);
7c673cae
FG
338 ENCODE_FINISH(bl);
339 }
11fdf7f2
TL
340 void decode(bufferlist::const_iterator& bl) {
341 DECODE_START_LEGACY_COMPAT_LEN(6, 1, 1, bl);
342 decode(id, bl);
343 decode(prefix, bl);
344 decode(status, bl);
345 decode(expiration, bl);
7c673cae 346 if (struct_v >=2) {
11fdf7f2 347 decode(noncur_expiration, bl);
7c673cae
FG
348 }
349 if (struct_v >= 3) {
11fdf7f2 350 decode(mp_expiration, bl);
7c673cae 351 }
31f18b77 352 if (struct_v >= 4) {
11fdf7f2 353 decode(dm_expiration, bl);
31f18b77 354 }
181888fb 355 if (struct_v >= 5) {
11fdf7f2
TL
356 decode(filter, bl);
357 }
358 if (struct_v >= 6) {
359 decode(transitions, bl);
360 decode(noncur_transitions, bl);
181888fb 361 }
7c673cae
FG
362 DECODE_FINISH(bl);
363 }
11fdf7f2 364 void dump(Formatter *f) const;
7c673cae 365
11fdf7f2 366 void init_simple_days_rule(std::string_view _id, std::string_view _prefix, int num_days);
7c673cae
FG
367};
368WRITE_CLASS_ENCODER(LCRule)
369
11fdf7f2
TL
370struct transition_action
371{
372 int days;
373 boost::optional<ceph::real_time> date;
374 string storage_class;
375 transition_action() : days(0) {}
f91f0fd5
TL
376 void dump(Formatter *f) const {
377 if (!date) {
378 f->dump_int("days", days);
379 } else {
380 utime_t ut(*date);
381 f->dump_stream("date") << ut;
382 }
383 }
11fdf7f2
TL
384};
385
494da23a 386/* XXX why not LCRule? */
7c673cae
FG
387struct lc_op
388{
494da23a 389 string id;
11fdf7f2
TL
390 bool status{false};
391 bool dm_expiration{false};
392 int expiration{0};
393 int noncur_expiration{0};
394 int mp_expiration{0};
224ce89b 395 boost::optional<ceph::real_time> expiration_date;
11fdf7f2
TL
396 boost::optional<RGWObjTags> obj_tags;
397 map<string, transition_action> transitions;
398 map<string, transition_action> noncur_transitions;
494da23a
TL
399
400 /* ctors are nice */
401 lc_op() = delete;
402
403 lc_op(const std::string id) : id(id)
404 {}
405
11fdf7f2 406 void dump(Formatter *f) const;
7c673cae
FG
407};
408
409class RGWLifecycleConfiguration
410{
411protected:
412 CephContext *cct;
494da23a 413 multimap<string, lc_op> prefix_map;
7c673cae 414 multimap<string, LCRule> rule_map;
11fdf7f2 415 bool _add_rule(const LCRule& rule);
224ce89b 416 bool has_same_action(const lc_op& first, const lc_op& second);
7c673cae 417public:
11fdf7f2 418 explicit RGWLifecycleConfiguration(CephContext *_cct) : cct(_cct) {}
7c673cae
FG
419 RGWLifecycleConfiguration() : cct(NULL) {}
420
421 void set_ctx(CephContext *ctx) {
422 cct = ctx;
423 }
424
425 virtual ~RGWLifecycleConfiguration() {}
426
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);
11fdf7f2 431 encode(rule_map, bl);
7c673cae
FG
432 ENCODE_FINISH(bl);
433 }
11fdf7f2 434 void decode(bufferlist::const_iterator& bl) {
7c673cae 435 DECODE_START_LEGACY_COMPAT_LEN(1, 1, 1, bl);
11fdf7f2 436 decode(rule_map, bl);
7c673cae
FG
437 multimap<string, LCRule>::iterator iter;
438 for (iter = rule_map.begin(); iter != rule_map.end(); ++iter) {
439 LCRule& rule = iter->second;
11fdf7f2 440 _add_rule(rule);
7c673cae
FG
441 }
442 DECODE_FINISH(bl);
443 }
444 void dump(Formatter *f) const;
11fdf7f2 445 static void generate_test_instances(list<RGWLifecycleConfiguration*>& o);
7c673cae 446
11fdf7f2 447 void add_rule(const LCRule& rule);
7c673cae 448
11fdf7f2 449 int check_and_add_rule(const LCRule& rule);
7c673cae 450
224ce89b 451 bool valid();
7c673cae
FG
452
453 multimap<string, LCRule>& get_rule_map() { return rule_map; }
494da23a 454 multimap<string, lc_op>& get_prefix_map() { return prefix_map; }
7c673cae
FG
455/*
456 void create_default(string id, string name) {
457 ACLGrant grant;
458 grant.set_canon(id, name, RGW_PERM_FULL_CONTROL);
459 add_grant(&grant);
460 }
461*/
462};
463WRITE_CLASS_ENCODER(RGWLifecycleConfiguration)
464
11fdf7f2 465class RGWLC : public DoutPrefixProvider {
7c673cae 466 CephContext *cct;
9f95a23c 467 rgw::sal::RGWRadosStore *store;
224ce89b
WB
468 int max_objs{0};
469 string *obj_names{nullptr};
7c673cae
FG
470 std::atomic<bool> down_flag = { false };
471 string cookie;
472
e306af50
TL
473public:
474
475 class WorkPool;
476
477 class LCWorker : public Thread
478 {
11fdf7f2 479 const DoutPrefixProvider *dpp;
7c673cae
FG
480 CephContext *cct;
481 RGWLC *lc;
f6b5b4d7
TL
482 int ix;
483 std::mutex lock;
484 std::condition_variable cond;
e306af50 485 WorkPool* workpool{nullptr};
7c673cae
FG
486
487 public:
f6b5b4d7
TL
488
489 using lock_guard = std::lock_guard<std::mutex>;
490 using unique_lock = std::unique_lock<std::mutex>;
491
492 LCWorker(const DoutPrefixProvider* dpp, CephContext *_cct, RGWLC *_lc,
493 int ix);
e306af50 494 RGWLC* get_lc() { return lc; }
7c673cae
FG
495 void *entry() override;
496 void stop();
497 bool should_work(utime_t& now);
498 int schedule_next_start_time(utime_t& start, utime_t& now);
e306af50
TL
499 ~LCWorker();
500
501 friend class RGWRados;
502 friend class RGWLC;
f6b5b4d7 503 friend class WorkQ;
e306af50
TL
504 }; /* LCWorker */
505
506 friend class RGWRados;
507
508 std::vector<std::unique_ptr<RGWLC::LCWorker>> workers;
509
510 RGWLC() : cct(nullptr), store(nullptr) {}
511 ~RGWLC();
7c673cae 512
9f95a23c 513 void initialize(CephContext *_cct, rgw::sal::RGWRadosStore *_store);
7c673cae
FG
514 void finalize();
515
f6b5b4d7
TL
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);
e306af50 523 int bucket_lc_prepare(int index, LCWorker* worker);
f6b5b4d7
TL
524 int bucket_lc_process(string& shard_id, LCWorker* worker, time_t stop_at,
525 bool once);
526 int bucket_lc_post(int index, int max_lock_sec,
527 cls_rgw_lc_entry& entry, int& result, LCWorker* worker);
7c673cae
FG
528 bool going_down();
529 void start_processor();
530 void stop_processor();
11fdf7f2
TL
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);
536
537 CephContext *get_cct() const override { return store->ctx(); }
538 unsigned get_subsys() const;
539 std::ostream& gen_prefix(std::ostream& out) const;
7c673cae
FG
540
541 private:
11fdf7f2 542
494da23a 543 int handle_multipart_expiration(RGWRados::Bucket *target,
e306af50 544 const multimap<string, lc_op>& prefix_map,
f6b5b4d7 545 LCWorker* worker, time_t stop_at, bool once);
7c673cae
FG
546};
547
11fdf7f2
TL
548namespace rgw::lc {
549
9f95a23c 550int fix_lc_shard_entry(rgw::sal::RGWRadosStore *store, const RGWBucketInfo& bucket_info,
11fdf7f2 551 const map<std::string,bufferlist>& battrs);
7c673cae 552
9f95a23c
TL
553std::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);
559
f6b5b4d7
TL
560bool 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);
567
11fdf7f2 568} // namespace rgw::lc
7c673cae
FG
569
570#endif