]>
Commit | Line | Data |
---|---|---|
1e59de90 TL |
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 | /* N.B., this header defines fundamental serialized types. Do not | |
17 | * introduce changes or include files which can only be compiled in | |
18 | * radosgw or OSD contexts (e.g., rgw_sal.h, rgw_common.h) | |
19 | */ | |
20 | ||
21 | #pragma once | |
22 | ||
23 | #include <string> | |
24 | #include <set> | |
25 | #include <map> | |
26 | #include <list> | |
27 | #include <boost/optional.hpp> | |
28 | ||
29 | #include <fmt/format.h> | |
30 | ||
31 | #include "include/types.h" | |
32 | #include "rgw_bucket_layout.h" | |
33 | #include "rgw_zone_features.h" | |
34 | #include "rgw_pool_types.h" | |
35 | #include "rgw_acl_types.h" | |
36 | #include "rgw_placement_types.h" | |
37 | ||
38 | #include "common/Formatter.h" | |
39 | ||
40 | class JSONObj; | |
41 | ||
42 | namespace rgw_zone_defaults { | |
43 | ||
44 | extern std::string zone_names_oid_prefix; | |
45 | extern std::string region_info_oid_prefix; | |
46 | extern std::string realm_names_oid_prefix; | |
47 | extern std::string zone_group_info_oid_prefix; | |
48 | extern std::string realm_info_oid_prefix; | |
49 | extern std::string default_region_info_oid; | |
50 | extern std::string default_zone_group_info_oid; | |
51 | extern std::string region_map_oid; | |
52 | extern std::string default_realm_info_oid; | |
53 | extern std::string default_zonegroup_name; | |
54 | extern std::string default_zone_name; | |
55 | extern std::string zonegroup_names_oid_prefix; | |
56 | extern std::string RGW_DEFAULT_ZONE_ROOT_POOL; | |
57 | extern std::string RGW_DEFAULT_ZONEGROUP_ROOT_POOL; | |
58 | extern std::string RGW_DEFAULT_REALM_ROOT_POOL; | |
59 | extern std::string RGW_DEFAULT_PERIOD_ROOT_POOL; | |
60 | extern std::string avail_pools; | |
61 | extern std::string default_storage_pool_suffix; | |
62 | ||
63 | } /* namespace rgw_zone_defaults */ | |
64 | ||
65 | struct RGWNameToId { | |
66 | std::string obj_id; | |
67 | ||
68 | void encode(bufferlist& bl) const { | |
69 | ENCODE_START(1, 1, bl); | |
70 | encode(obj_id, bl); | |
71 | ENCODE_FINISH(bl); | |
72 | } | |
73 | ||
74 | void decode(bufferlist::const_iterator& bl) { | |
75 | DECODE_START(1, bl); | |
76 | decode(obj_id, bl); | |
77 | DECODE_FINISH(bl); | |
78 | } | |
79 | ||
80 | void dump(Formatter *f) const; | |
81 | void decode_json(JSONObj *obj); | |
82 | }; | |
83 | WRITE_CLASS_ENCODER(RGWNameToId) | |
84 | ||
85 | struct RGWDefaultSystemMetaObjInfo { | |
86 | std::string default_id; | |
87 | ||
88 | void encode(bufferlist& bl) const { | |
89 | ENCODE_START(1, 1, bl); | |
90 | encode(default_id, bl); | |
91 | ENCODE_FINISH(bl); | |
92 | } | |
93 | ||
94 | void decode(bufferlist::const_iterator& bl) { | |
95 | DECODE_START(1, bl); | |
96 | decode(default_id, bl); | |
97 | DECODE_FINISH(bl); | |
98 | } | |
99 | ||
100 | void dump(Formatter *f) const; | |
101 | void decode_json(JSONObj *obj); | |
102 | }; | |
103 | WRITE_CLASS_ENCODER(RGWDefaultSystemMetaObjInfo) | |
104 | ||
105 | struct RGWZoneStorageClass { | |
106 | boost::optional<rgw_pool> data_pool; | |
107 | boost::optional<std::string> compression_type; | |
108 | ||
109 | void encode(bufferlist& bl) const { | |
110 | ENCODE_START(1, 1, bl); | |
111 | encode(data_pool, bl); | |
112 | encode(compression_type, bl); | |
113 | ENCODE_FINISH(bl); | |
114 | } | |
115 | ||
116 | void decode(bufferlist::const_iterator& bl) { | |
117 | DECODE_START(1, bl); | |
118 | decode(data_pool, bl); | |
119 | decode(compression_type, bl); | |
120 | DECODE_FINISH(bl); | |
121 | } | |
122 | ||
123 | void dump(Formatter *f) const; | |
124 | void decode_json(JSONObj *obj); | |
125 | }; | |
126 | WRITE_CLASS_ENCODER(RGWZoneStorageClass) | |
127 | ||
128 | class RGWZoneStorageClasses { | |
129 | std::map<std::string, RGWZoneStorageClass> m; | |
130 | ||
131 | /* in memory only */ | |
132 | RGWZoneStorageClass *standard_class; | |
133 | ||
134 | public: | |
135 | RGWZoneStorageClasses() { | |
136 | standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; | |
137 | } | |
138 | RGWZoneStorageClasses(const RGWZoneStorageClasses& rhs) { | |
139 | m = rhs.m; | |
140 | standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; | |
141 | } | |
142 | RGWZoneStorageClasses& operator=(const RGWZoneStorageClasses& rhs) { | |
143 | m = rhs.m; | |
144 | standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; | |
145 | return *this; | |
146 | } | |
147 | ||
148 | const RGWZoneStorageClass& get_standard() const { | |
149 | return *standard_class; | |
150 | } | |
151 | ||
152 | bool find(const std::string& sc, const RGWZoneStorageClass** pstorage_class) const { | |
153 | auto iter = m.find(sc); | |
154 | if (iter == m.end()) { | |
155 | return false; | |
156 | } | |
157 | *pstorage_class = &iter->second; | |
158 | return true; | |
159 | } | |
160 | ||
161 | bool exists(const std::string& sc) const { | |
162 | if (sc.empty()) { | |
163 | return true; | |
164 | } | |
165 | auto iter = m.find(sc); | |
166 | return (iter != m.end()); | |
167 | } | |
168 | ||
169 | const std::map<std::string, RGWZoneStorageClass>& get_all() const { | |
170 | return m; | |
171 | } | |
172 | ||
173 | std::map<std::string, RGWZoneStorageClass>& get_all() { | |
174 | return m; | |
175 | } | |
176 | ||
177 | void set_storage_class(const std::string& sc, const rgw_pool* data_pool, const std::string* compression_type) { | |
178 | const std::string *psc = ≻ | |
179 | if (sc.empty()) { | |
180 | psc = &RGW_STORAGE_CLASS_STANDARD; | |
181 | } | |
182 | RGWZoneStorageClass& storage_class = m[*psc]; | |
183 | if (data_pool) { | |
184 | storage_class.data_pool = *data_pool; | |
185 | } | |
186 | if (compression_type) { | |
187 | storage_class.compression_type = *compression_type; | |
188 | } | |
189 | } | |
190 | ||
191 | void remove_storage_class(const std::string& sc) { | |
192 | if (!sc.empty()) { | |
193 | m.erase(sc); | |
194 | } | |
195 | } | |
196 | ||
197 | void encode(bufferlist& bl) const { | |
198 | ENCODE_START(1, 1, bl); | |
199 | encode(m, bl); | |
200 | ENCODE_FINISH(bl); | |
201 | } | |
202 | ||
203 | void decode(bufferlist::const_iterator& bl) { | |
204 | DECODE_START(1, bl); | |
205 | decode(m, bl); | |
206 | standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; | |
207 | DECODE_FINISH(bl); | |
208 | } | |
209 | ||
210 | void dump(Formatter *f) const; | |
211 | void decode_json(JSONObj *obj); | |
212 | }; | |
213 | WRITE_CLASS_ENCODER(RGWZoneStorageClasses) | |
214 | ||
215 | struct RGWZonePlacementInfo { | |
216 | rgw_pool index_pool; | |
217 | rgw_pool data_extra_pool; /* if not set we should use data_pool */ | |
218 | RGWZoneStorageClasses storage_classes; | |
219 | rgw::BucketIndexType index_type; | |
220 | bool inline_data; | |
221 | ||
222 | RGWZonePlacementInfo() : index_type(rgw::BucketIndexType::Normal), inline_data(true) {} | |
223 | ||
224 | void encode(bufferlist& bl) const { | |
225 | ENCODE_START(8, 1, bl); | |
226 | encode(index_pool.to_str(), bl); | |
227 | rgw_pool standard_data_pool = get_data_pool(RGW_STORAGE_CLASS_STANDARD); | |
228 | encode(standard_data_pool.to_str(), bl); | |
229 | encode(data_extra_pool.to_str(), bl); | |
230 | encode((uint32_t)index_type, bl); | |
231 | std::string standard_compression_type = get_compression_type(RGW_STORAGE_CLASS_STANDARD); | |
232 | encode(standard_compression_type, bl); | |
233 | encode(storage_classes, bl); | |
234 | encode(inline_data, bl); | |
235 | ENCODE_FINISH(bl); | |
236 | } | |
237 | ||
238 | void decode(bufferlist::const_iterator& bl) { | |
239 | DECODE_START(8, bl); | |
240 | std::string index_pool_str; | |
241 | std::string data_pool_str; | |
242 | decode(index_pool_str, bl); | |
243 | index_pool = rgw_pool(index_pool_str); | |
244 | decode(data_pool_str, bl); | |
245 | rgw_pool standard_data_pool(data_pool_str); | |
246 | if (struct_v >= 4) { | |
247 | std::string data_extra_pool_str; | |
248 | decode(data_extra_pool_str, bl); | |
249 | data_extra_pool = rgw_pool(data_extra_pool_str); | |
250 | } | |
251 | if (struct_v >= 5) { | |
252 | uint32_t it; | |
253 | decode(it, bl); | |
254 | index_type = (rgw::BucketIndexType)it; | |
255 | } | |
256 | std::string standard_compression_type; | |
257 | if (struct_v >= 6) { | |
258 | decode(standard_compression_type, bl); | |
259 | } | |
260 | if (struct_v >= 7) { | |
261 | decode(storage_classes, bl); | |
262 | } else { | |
263 | storage_classes.set_storage_class(RGW_STORAGE_CLASS_STANDARD, &standard_data_pool, | |
264 | (!standard_compression_type.empty() ? &standard_compression_type : nullptr)); | |
265 | } | |
266 | if (struct_v >= 8) { | |
267 | decode(inline_data, bl); | |
268 | } | |
269 | DECODE_FINISH(bl); | |
270 | } | |
271 | const rgw_pool& get_data_extra_pool() const { | |
272 | static rgw_pool no_pool; | |
273 | if (data_extra_pool.empty()) { | |
274 | return storage_classes.get_standard().data_pool.get_value_or(no_pool); | |
275 | } | |
276 | return data_extra_pool; | |
277 | } | |
278 | const rgw_pool& get_data_pool(const std::string& sc) const { | |
279 | const RGWZoneStorageClass *storage_class; | |
280 | static rgw_pool no_pool; | |
281 | ||
282 | if (!storage_classes.find(sc, &storage_class)) { | |
283 | return storage_classes.get_standard().data_pool.get_value_or(no_pool); | |
284 | } | |
285 | ||
286 | return storage_class->data_pool.get_value_or(no_pool); | |
287 | } | |
288 | const rgw_pool& get_standard_data_pool() const { | |
289 | return get_data_pool(RGW_STORAGE_CLASS_STANDARD); | |
290 | } | |
291 | ||
292 | const std::string& get_compression_type(const std::string& sc) const { | |
293 | const RGWZoneStorageClass *storage_class; | |
294 | static std::string no_compression; | |
295 | ||
296 | if (!storage_classes.find(sc, &storage_class)) { | |
297 | return no_compression; | |
298 | } | |
299 | return storage_class->compression_type.get_value_or(no_compression); | |
300 | } | |
301 | ||
302 | bool storage_class_exists(const std::string& sc) const { | |
303 | return storage_classes.exists(sc); | |
304 | } | |
305 | ||
306 | void dump(Formatter *f) const; | |
307 | void decode_json(JSONObj *obj); | |
308 | ||
309 | }; | |
310 | WRITE_CLASS_ENCODER(RGWZonePlacementInfo) | |
311 | ||
312 | struct RGWZone { | |
313 | std::string id; | |
314 | std::string name; | |
315 | std::list<std::string> endpoints; // std::vector? | |
316 | bool log_meta; | |
317 | bool log_data; | |
318 | bool read_only; | |
319 | std::string tier_type; | |
320 | std::string redirect_zone; | |
321 | ||
322 | /** | |
323 | * Represents the number of shards for the bucket index object, a value of zero | |
324 | * indicates there is no sharding. By default (no sharding, the name of the object | |
325 | * is '.dir.{marker}', with sharding, the name is '.dir.{marker}.{sharding_id}', | |
326 | * sharding_id is zero-based value. It is not recommended to set a too large value | |
327 | * (e.g. thousand) as it increases the cost for bucket listing. | |
328 | */ | |
329 | uint32_t bucket_index_max_shards; | |
330 | ||
331 | // pre-shard buckets on creation to enable some write-parallism by default, | |
332 | // delay the need to reshard as the bucket grows, and (in multisite) get some | |
333 | // bucket index sharding where dynamic resharding is not supported | |
334 | static constexpr uint32_t default_bucket_index_max_shards = 11; | |
335 | ||
336 | bool sync_from_all; | |
337 | std::set<std::string> sync_from; /* list of zones to sync from */ | |
338 | ||
339 | rgw::zone_features::set supported_features; | |
340 | ||
341 | RGWZone() | |
342 | : log_meta(false), log_data(false), read_only(false), | |
343 | bucket_index_max_shards(default_bucket_index_max_shards), | |
344 | sync_from_all(true) {} | |
345 | ||
346 | void encode(bufferlist& bl) const { | |
347 | ENCODE_START(8, 1, bl); | |
348 | encode(name, bl); | |
349 | encode(endpoints, bl); | |
350 | encode(log_meta, bl); | |
351 | encode(log_data, bl); | |
352 | encode(bucket_index_max_shards, bl); | |
353 | encode(id, bl); | |
354 | encode(read_only, bl); | |
355 | encode(tier_type, bl); | |
356 | encode(sync_from_all, bl); | |
357 | encode(sync_from, bl); | |
358 | encode(redirect_zone, bl); | |
359 | encode(supported_features, bl); | |
360 | ENCODE_FINISH(bl); | |
361 | } | |
362 | ||
363 | void decode(bufferlist::const_iterator& bl) { | |
364 | DECODE_START(8, bl); | |
365 | decode(name, bl); | |
366 | if (struct_v < 4) { | |
367 | id = name; | |
368 | } | |
369 | decode(endpoints, bl); | |
370 | if (struct_v >= 2) { | |
371 | decode(log_meta, bl); | |
372 | decode(log_data, bl); | |
373 | } | |
374 | if (struct_v >= 3) { | |
375 | decode(bucket_index_max_shards, bl); | |
376 | } | |
377 | if (struct_v >= 4) { | |
378 | decode(id, bl); | |
379 | decode(read_only, bl); | |
380 | } | |
381 | if (struct_v >= 5) { | |
382 | decode(tier_type, bl); | |
383 | } | |
384 | if (struct_v >= 6) { | |
385 | decode(sync_from_all, bl); | |
386 | decode(sync_from, bl); | |
387 | } | |
388 | if (struct_v >= 7) { | |
389 | decode(redirect_zone, bl); | |
390 | } | |
391 | if (struct_v >= 8) { | |
392 | decode(supported_features, bl); | |
393 | } | |
394 | DECODE_FINISH(bl); | |
395 | } | |
396 | void dump(Formatter *f) const; | |
397 | void decode_json(JSONObj *obj); | |
398 | static void generate_test_instances(std::list<RGWZone*>& o); | |
399 | ||
400 | bool is_read_only() const { return read_only; } | |
401 | ||
402 | bool syncs_from(const std::string& zone_name) const { | |
403 | return (sync_from_all || sync_from.find(zone_name) != sync_from.end()); | |
404 | } | |
405 | ||
406 | bool supports(std::string_view feature) const { | |
407 | return supported_features.contains(feature); | |
408 | } | |
409 | }; | |
410 | WRITE_CLASS_ENCODER(RGWZone) | |
411 | ||
412 | struct RGWDefaultZoneGroupInfo { | |
413 | std::string default_zonegroup; | |
414 | ||
415 | void encode(bufferlist& bl) const { | |
416 | ENCODE_START(1, 1, bl); | |
417 | encode(default_zonegroup, bl); | |
418 | ENCODE_FINISH(bl); | |
419 | } | |
420 | ||
421 | void decode(bufferlist::const_iterator& bl) { | |
422 | DECODE_START(1, bl); | |
423 | decode(default_zonegroup, bl); | |
424 | DECODE_FINISH(bl); | |
425 | } | |
426 | void dump(Formatter *f) const; | |
427 | void decode_json(JSONObj *obj); | |
428 | //todo: implement ceph-dencoder | |
429 | }; | |
430 | WRITE_CLASS_ENCODER(RGWDefaultZoneGroupInfo) | |
431 | ||
432 | struct RGWTierACLMapping { | |
433 | ACLGranteeTypeEnum type{ACL_TYPE_CANON_USER}; | |
434 | std::string source_id; | |
435 | std::string dest_id; | |
436 | ||
437 | RGWTierACLMapping() = default; | |
438 | ||
439 | RGWTierACLMapping(ACLGranteeTypeEnum t, | |
440 | const std::string& s, | |
441 | const std::string& d) : type(t), | |
442 | source_id(s), | |
443 | dest_id(d) {} | |
444 | ||
445 | void init(const JSONFormattable& config) { | |
446 | const std::string& t = config["type"]; | |
447 | ||
448 | if (t == "email") { | |
449 | type = ACL_TYPE_EMAIL_USER; | |
450 | } else if (t == "uri") { | |
451 | type = ACL_TYPE_GROUP; | |
452 | } else { | |
453 | type = ACL_TYPE_CANON_USER; | |
454 | } | |
455 | ||
456 | source_id = config["source_id"]; | |
457 | dest_id = config["dest_id"]; | |
458 | } | |
459 | ||
460 | void encode(bufferlist& bl) const { | |
461 | ENCODE_START(1, 1, bl); | |
462 | encode((uint32_t)type, bl); | |
463 | encode(source_id, bl); | |
464 | encode(dest_id, bl); | |
465 | ENCODE_FINISH(bl); | |
466 | } | |
467 | ||
468 | void decode(bufferlist::const_iterator& bl) { | |
469 | DECODE_START(1, bl); | |
470 | uint32_t it; | |
471 | decode(it, bl); | |
472 | type = (ACLGranteeTypeEnum)it; | |
473 | decode(source_id, bl); | |
474 | decode(dest_id, bl); | |
475 | DECODE_FINISH(bl); | |
476 | } | |
477 | void dump(Formatter *f) const; | |
478 | void decode_json(JSONObj *obj); | |
479 | }; | |
480 | WRITE_CLASS_ENCODER(RGWTierACLMapping) | |
481 | ||
482 | enum HostStyle { | |
483 | PathStyle = 0, | |
484 | VirtualStyle = 1, | |
485 | }; | |
486 | ||
487 | struct RGWZoneGroupPlacementTierS3 { | |
488 | #define DEFAULT_MULTIPART_SYNC_PART_SIZE (32 * 1024 * 1024) | |
489 | std::string endpoint; | |
490 | RGWAccessKey key; | |
491 | std::string region; | |
492 | HostStyle host_style{PathStyle}; | |
493 | std::string target_storage_class; | |
494 | ||
495 | /* Should below be bucket/zone specific?? */ | |
496 | std::string target_path; | |
497 | std::map<std::string, RGWTierACLMapping> acl_mappings; | |
498 | ||
499 | uint64_t multipart_sync_threshold{DEFAULT_MULTIPART_SYNC_PART_SIZE}; | |
500 | uint64_t multipart_min_part_size{DEFAULT_MULTIPART_SYNC_PART_SIZE}; | |
501 | ||
502 | int update_params(const JSONFormattable& config); | |
503 | int clear_params(const JSONFormattable& config); | |
504 | ||
505 | void encode(bufferlist& bl) const { | |
506 | ENCODE_START(1, 1, bl); | |
507 | encode(endpoint, bl); | |
508 | encode(key, bl); | |
509 | encode(region, bl); | |
510 | encode((uint32_t)host_style, bl); // XXX kill C-style casts | |
511 | encode(target_storage_class, bl); | |
512 | encode(target_path, bl); | |
513 | encode(acl_mappings, bl); | |
514 | encode(multipart_sync_threshold, bl); | |
515 | encode(multipart_min_part_size, bl); | |
516 | ENCODE_FINISH(bl); | |
517 | } | |
518 | ||
519 | void decode(bufferlist::const_iterator& bl) { | |
520 | DECODE_START(1, bl); | |
521 | decode(endpoint, bl); | |
522 | decode(key, bl); | |
523 | decode(region, bl); | |
524 | ||
525 | uint32_t it; | |
526 | decode(it, bl); | |
527 | host_style = (HostStyle)it; // XXX can't this be HostStyle(it)? | |
528 | ||
529 | decode(target_storage_class, bl); | |
530 | decode(target_path, bl); | |
531 | decode(acl_mappings, bl); | |
532 | decode(multipart_sync_threshold, bl); | |
533 | decode(multipart_min_part_size, bl); | |
534 | DECODE_FINISH(bl); | |
535 | } | |
536 | void dump(Formatter *f) const; | |
537 | void decode_json(JSONObj *obj); | |
538 | }; | |
539 | WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTierS3) | |
540 | ||
541 | struct RGWZoneGroupPlacementTier { | |
542 | std::string tier_type; | |
543 | std::string storage_class; | |
544 | bool retain_head_object = false; | |
545 | ||
546 | struct _tier { | |
547 | RGWZoneGroupPlacementTierS3 s3; | |
548 | } t; | |
549 | ||
550 | int update_params(const JSONFormattable& config); | |
551 | int clear_params(const JSONFormattable& config); | |
552 | ||
553 | void encode(bufferlist& bl) const { | |
554 | ENCODE_START(1, 1, bl); | |
555 | encode(tier_type, bl); | |
556 | encode(storage_class, bl); | |
557 | encode(retain_head_object, bl); | |
558 | if (tier_type == "cloud-s3") { | |
559 | encode(t.s3, bl); | |
560 | } | |
561 | ENCODE_FINISH(bl); | |
562 | } | |
563 | ||
564 | void decode(bufferlist::const_iterator& bl) { | |
565 | DECODE_START(1, bl); | |
566 | decode(tier_type, bl); | |
567 | decode(storage_class, bl); | |
568 | decode(retain_head_object, bl); | |
569 | if (tier_type == "cloud-s3") { | |
570 | decode(t.s3, bl); | |
571 | } | |
572 | DECODE_FINISH(bl); | |
573 | } | |
574 | ||
575 | void dump(Formatter *f) const; | |
576 | void decode_json(JSONObj *obj); | |
577 | }; | |
578 | WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTier) | |
579 | ||
580 | struct RGWZoneGroupPlacementTarget { | |
581 | std::string name; | |
582 | std::set<std::string> tags; | |
583 | std::set<std::string> storage_classes; | |
584 | std::map<std::string, RGWZoneGroupPlacementTier> tier_targets; | |
585 | ||
586 | bool user_permitted(const std::list<std::string>& user_tags) const { | |
587 | if (tags.empty()) { | |
588 | return true; | |
589 | } | |
590 | for (auto& rule : user_tags) { | |
591 | if (tags.find(rule) != tags.end()) { | |
592 | return true; | |
593 | } | |
594 | } | |
595 | return false; | |
596 | } | |
597 | ||
598 | void encode(bufferlist& bl) const { | |
599 | ENCODE_START(3, 1, bl); | |
600 | encode(name, bl); | |
601 | encode(tags, bl); | |
602 | encode(storage_classes, bl); | |
603 | encode(tier_targets, bl); | |
604 | ENCODE_FINISH(bl); | |
605 | } | |
606 | ||
607 | void decode(bufferlist::const_iterator& bl) { | |
608 | DECODE_START(3, bl); | |
609 | decode(name, bl); | |
610 | decode(tags, bl); | |
611 | if (struct_v >= 2) { | |
612 | decode(storage_classes, bl); | |
613 | } | |
614 | if (storage_classes.empty()) { | |
615 | storage_classes.insert(RGW_STORAGE_CLASS_STANDARD); | |
616 | } | |
617 | if (struct_v >= 3) { | |
618 | decode(tier_targets, bl); | |
619 | } | |
620 | DECODE_FINISH(bl); | |
621 | } | |
622 | void dump(Formatter *f) const; | |
623 | void decode_json(JSONObj *obj); | |
624 | }; | |
625 | WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTarget) |