1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
5 * Ceph - scalable distributed file system
7 * Copyright (C) 2015 Red Hat
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.
16 #ifndef CEPH_RGW_ORPHAN_H
17 #define CEPH_RGW_ORPHAN_H
19 #include "common/config.h"
20 #include "common/Formatter.h"
21 #include "common/errno.h"
25 #define dout_subsys ceph_subsys_rgw
27 #define RGW_ORPHAN_INDEX_OID "orphan.index"
28 #define RGW_ORPHAN_INDEX_PREFIX "orphan.scan"
31 enum RGWOrphanSearchStageId
{
32 ORPHAN_SEARCH_STAGE_UNKNOWN
= 0,
33 ORPHAN_SEARCH_STAGE_INIT
= 1,
34 ORPHAN_SEARCH_STAGE_LSPOOL
= 2,
35 ORPHAN_SEARCH_STAGE_LSBUCKETS
= 3,
36 ORPHAN_SEARCH_STAGE_ITERATE_BI
= 4,
37 ORPHAN_SEARCH_STAGE_COMPARE
= 5,
41 struct RGWOrphanSearchStage
{
42 RGWOrphanSearchStageId stage
;
46 RGWOrphanSearchStage() : stage(ORPHAN_SEARCH_STAGE_UNKNOWN
), shard(0) {}
47 explicit RGWOrphanSearchStage(RGWOrphanSearchStageId _stage
) : stage(_stage
), shard(0) {}
48 RGWOrphanSearchStage(RGWOrphanSearchStageId _stage
, int _shard
, const string
& _marker
) : stage(_stage
), shard(_shard
), marker(_marker
) {}
50 void encode(bufferlist
& bl
) const {
51 ENCODE_START(1, 1, bl
);
52 encode((int)stage
, bl
);
58 void decode(bufferlist::const_iterator
& bl
) {
62 stage
= (RGWOrphanSearchStageId
)s
;
68 void dump(Formatter
*f
) const;
70 WRITE_CLASS_ENCODER(RGWOrphanSearchStage
)
72 struct RGWOrphanSearchInfo
{
78 void encode(bufferlist
& bl
) const {
79 ENCODE_START(2, 1, bl
);
81 encode(pool
.to_str(), bl
);
82 encode(num_shards
, bl
);
83 encode(start_time
, bl
);
87 void decode(bufferlist::const_iterator
& bl
) {
93 decode(num_shards
, bl
);
94 decode(start_time
, bl
);
98 void dump(Formatter
*f
) const;
100 WRITE_CLASS_ENCODER(RGWOrphanSearchInfo
)
102 struct RGWOrphanSearchState
{
103 RGWOrphanSearchInfo info
;
104 RGWOrphanSearchStage stage
;
106 RGWOrphanSearchState() : stage(ORPHAN_SEARCH_STAGE_UNKNOWN
) {}
108 void encode(bufferlist
& bl
) const {
109 ENCODE_START(1, 1, bl
);
115 void decode(bufferlist::const_iterator
& bl
) {
122 void dump(Formatter
*f
) const;
124 WRITE_CLASS_ENCODER(RGWOrphanSearchState
)
126 class RGWOrphanStore
{
127 rgw::sal::RGWRadosStore
*store
;
128 librados::IoCtx ioctx
;
133 explicit RGWOrphanStore(rgw::sal::RGWRadosStore
*_store
) : store(_store
), oid(RGW_ORPHAN_INDEX_OID
) {}
135 librados::IoCtx
& get_ioctx() { return ioctx
; }
139 int read_job(const string
& job_name
, RGWOrphanSearchState
& state
);
140 int write_job(const string
& job_name
, const RGWOrphanSearchState
& state
);
141 int remove_job(const string
& job_name
);
142 int list_jobs(map
<string
,RGWOrphanSearchState
> &job_list
);
145 int store_entries(const string
& oid
, const map
<string
, bufferlist
>& entries
);
146 int read_entries(const string
& oid
, const string
& marker
, map
<string
, bufferlist
> *entries
, bool *truncated
);
150 class RGWOrphanSearch
{
151 rgw::sal::RGWRadosStore
*store
;
153 RGWOrphanStore orphan_store
;
155 RGWOrphanSearchInfo search_info
;
156 RGWOrphanSearchStage search_stage
;
158 map
<int, string
> all_objs_index
;
159 map
<int, string
> buckets_instance_index
;
160 map
<int, string
> linked_objs_index
;
162 string index_objs_prefix
;
164 uint16_t max_concurrent_ios
;
166 int64_t max_list_bucket_entries
;
170 struct log_iter_info
{
172 list
<string
>::iterator cur
;
173 list
<string
>::iterator end
;
176 int log_oids(map
<int, string
>& log_shards
, map
<int, list
<string
> >& oids
);
178 #define RGW_ORPHANSEARCH_HASH_PRIME 7877
179 int orphan_shard(const string
& str
) {
180 return ceph_str_hash_linux(str
.c_str(), str
.size()) % RGW_ORPHANSEARCH_HASH_PRIME
% search_info
.num_shards
;
183 int handle_stat_result(map
<int, list
<string
> >& oids
, RGWRados::Object::Stat::Result
& result
);
184 int pop_and_handle_stat_op(map
<int, list
<string
> >& oids
, std::deque
<RGWRados::Object::Stat
>& ops
);
187 int remove_index(map
<int, string
>& index
);
189 RGWOrphanSearch(rgw::sal::RGWRadosStore
*_store
, int _max_ios
, uint64_t _stale_secs
) : store(_store
), orphan_store(store
), max_concurrent_ios(_max_ios
), stale_secs(_stale_secs
) {}
192 RGWOrphanSearchState state
;
193 state
.info
= search_info
;
194 state
.stage
= search_stage
;
195 return orphan_store
.write_job(search_info
.job_name
, state
);
198 int init(const string
& job_name
, RGWOrphanSearchInfo
*info
, bool _detailed_mode
=false);
200 int create(const string
& job_name
, int num_shards
);
202 int build_all_oids_index();
203 int build_buckets_instance_index();
204 int build_linked_oids_for_bucket(const string
& bucket_instance_id
, map
<int, list
<string
> >& oids
);
205 int build_linked_oids_index();
206 int compare_oid_indexes();
216 * process_t describes how to process a irectory, we will either
217 * process the whole thing (entire_container == true) or a portion
218 * of it (entire_container == false). When we only process a
219 * portion, we will list the specific keys and/or specific lexical
223 bool entire_container
;
224 std::set
<rgw_obj_key
> filter_keys
;
225 std::set
<std::string
> prefixes
;
228 entire_container(false)
232 std::map
<std::string
,process_t
> bucket_process_map
;
233 std::set
<std::string
> visited_oids
;
235 void add_bucket_entire(const std::string
& bucket_name
) {
236 auto p
= bucket_process_map
.emplace(std::make_pair(bucket_name
,
238 p
.first
->second
.entire_container
= true;
241 void add_bucket_prefix(const std::string
& bucket_name
,
242 const std::string
& prefix
) {
243 auto p
= bucket_process_map
.emplace(std::make_pair(bucket_name
,
245 p
.first
->second
.prefixes
.insert(prefix
);
248 void add_bucket_filter(const std::string
& bucket_name
,
249 const rgw_obj_key
& obj_key
) {
250 auto p
= bucket_process_map
.emplace(std::make_pair(bucket_name
,
252 p
.first
->second
.filter_keys
.insert(obj_key
);
255 rgw::sal::RGWRadosStore
* store
;
257 uint16_t max_concurrent_ios
;
259 std::string tenant_name
;
261 int handle_stat_result(RGWRados::Object::Stat::Result
& result
,
262 std::set
<string
>& obj_oids
);
263 int pop_and_handle_stat_op(RGWObjectCtx
& obj_ctx
,
264 std::deque
<RGWRados::Object::Stat
>& ops
);
268 RGWRadosList(rgw::sal::RGWRadosStore
* _store
,
270 uint64_t _stale_secs
,
271 const std::string
& _tenant_name
) :
273 max_concurrent_ios(_max_ios
),
274 stale_secs(_stale_secs
),
275 tenant_name(_tenant_name
)
278 int process_bucket(const std::string
& bucket_instance_id
,
279 const std::string
& prefix
,
280 const std::set
<rgw_obj_key
>& entries_filter
);
282 int do_incomplete_multipart(rgw::sal::RGWRadosStore
* store
,
283 RGWBucketInfo
& bucket_info
);
285 int build_linked_oids_index();
287 int run(const std::string
& bucket_id
);
289 }; // class RGWRadosList