]>
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 | |
3 | ||
4 | #include "test/osd/scrubber_generators.h" | |
5 | ||
6 | #include <fmt/ranges.h> | |
7 | ||
8 | using namespace ScrubGenerator; | |
9 | ||
10 | // ref: PGLogTestRebuildMissing() | |
11 | bufferptr create_object_info(const ScrubGenerator::RealObj& objver) | |
12 | { | |
13 | object_info_t oi{}; | |
14 | oi.soid = objver.ghobj.hobj; | |
15 | oi.version = eversion_t(objver.ghobj.generation, 0); | |
16 | oi.size = objver.data.size; | |
17 | ||
18 | bufferlist bl; | |
19 | oi.encode(bl, | |
20 | 0 /*get_osdmap()->get_features(CEPH_ENTITY_TYPE_OSD, nullptr)*/); | |
21 | bufferptr bp(bl.c_str(), bl.length()); | |
22 | return bp; | |
23 | } | |
24 | ||
25 | std::pair<bufferptr, std::vector<snapid_t>> create_object_snapset( | |
26 | const ScrubGenerator::RealObj& robj, | |
27 | const SnapsetMockData* snapset_mock_data) | |
28 | { | |
29 | if (!snapset_mock_data) { | |
30 | return {bufferptr(), {}}; | |
31 | } | |
32 | /// \todo fill in missing version/osd details from the robj | |
33 | auto sns = snapset_mock_data->make_snapset(); | |
34 | bufferlist bl; | |
35 | encode(sns, bl); | |
36 | bufferptr bp = bufferptr(bl.c_str(), bl.length()); | |
37 | ||
38 | // extract the set of object snaps | |
39 | return {bp, sns.snaps}; | |
40 | } | |
41 | ||
42 | RealObjsConfList ScrubGenerator::make_real_objs_conf( | |
43 | int64_t pool_id, | |
44 | const RealObjsConf& blueprint, | |
45 | std::vector<int32_t> active_osds) | |
46 | { | |
47 | RealObjsConfList all_osds; | |
48 | ||
49 | for (auto osd : active_osds) { | |
50 | RealObjsConfRef this_osd_fakes = std::make_unique<RealObjsConf>(blueprint); | |
51 | // now - fix & corrupt every "object" in the blueprint | |
52 | for (RealObj& robj : this_osd_fakes->objs) { | |
53 | ||
54 | robj.ghobj.hobj.pool = pool_id; | |
55 | } | |
56 | ||
57 | all_osds[osd] = std::move(this_osd_fakes); | |
58 | } | |
59 | return all_osds; // reconsider (maybe add a move ctor?) | |
60 | } | |
61 | ||
62 | ///\todo dispose of the created buffer pointers | |
63 | ||
64 | ScrubGenerator::SmapEntry ScrubGenerator::make_smobject( | |
65 | const ScrubGenerator::RealObj& blueprint, | |
66 | int osd_num) | |
67 | { | |
68 | ScrubGenerator::SmapEntry ret; | |
69 | ||
70 | ret.ghobj = blueprint.ghobj; | |
71 | ret.smobj.attrs[OI_ATTR] = create_object_info(blueprint); | |
72 | if (blueprint.snapset_mock_data) { | |
73 | auto [bp, snaps] = | |
74 | create_object_snapset(blueprint, blueprint.snapset_mock_data); | |
75 | ret.smobj.attrs[SS_ATTR] = bp; | |
76 | std::cout << fmt::format("{}: ({}) osd:{} snaps:{}", | |
77 | __func__, | |
78 | ret.ghobj.hobj, | |
79 | osd_num, | |
80 | snaps) | |
81 | << std::endl; | |
82 | } | |
83 | ||
84 | for (const auto& [at_k, at_v] : blueprint.data.attrs) { | |
85 | ret.smobj.attrs[at_k] = ceph::buffer::copy(at_v.c_str(), at_v.size()); | |
86 | { | |
87 | // verifying (to be removed after dev phase) | |
88 | auto bk = ret.smobj.attrs[at_k].begin_deep().get_ptr( | |
89 | ret.smobj.attrs[at_k].length()); | |
90 | std::string bkstr{bk.raw_c_str(), bk.raw_length()}; | |
91 | std::cout << fmt::format("{}: verification: {}", __func__, bkstr) | |
92 | << std::endl; | |
93 | } | |
94 | } | |
95 | ret.smobj.size = blueprint.data.size; | |
96 | ret.smobj.digest = blueprint.data.hash; | |
97 | /// \todo handle the 'present' etc' | |
98 | ||
99 | ret.smobj.object_omap_keys = blueprint.data.omap.size(); | |
100 | ret.smobj.object_omap_bytes = blueprint.data.omap_bytes; | |
101 | return ret; | |
102 | } | |
103 | ||
104 | all_clones_snaps_t ScrubGenerator::all_clones( | |
105 | const ScrubGenerator::RealObj& head_obj) | |
106 | { | |
107 | std::cout << fmt::format("{}: head_obj.ghobj.hobj:{}", | |
108 | __func__, | |
109 | head_obj.ghobj.hobj) | |
110 | << std::endl; | |
111 | ||
112 | std::map<hobject_t, std::vector<snapid_t>> ret; | |
113 | ||
114 | for (const auto& clone : head_obj.snapset_mock_data->clones) { | |
115 | auto clone_set_it = head_obj.snapset_mock_data->clone_snaps.find(clone); | |
116 | if (clone_set_it == head_obj.snapset_mock_data->clone_snaps.end()) { | |
117 | std::cout << "note: no clone_snaps for " << clone << std::endl; | |
118 | continue; | |
119 | } | |
120 | auto clone_set = clone_set_it->second; | |
121 | hobject_t clone_hobj{head_obj.ghobj.hobj}; | |
122 | clone_hobj.snap = clone; | |
123 | ||
124 | ret[clone_hobj] = clone_set_it->second; | |
125 | std::cout << fmt::format("{}: clone:{} clone_set:{}", | |
126 | __func__, | |
127 | clone_hobj, | |
128 | clone_set) | |
129 | << std::endl; | |
130 | } | |
131 | ||
132 | return ret; | |
133 | } | |
134 | ||
135 | void ScrubGenerator::add_object(ScrubMap& map, | |
136 | const ScrubGenerator::RealObj& real_obj, | |
137 | int osd_num) | |
138 | { | |
139 | // do we have data corruption recipe for this OSD? | |
140 | /// \todo c++20: use contains() | |
141 | CorruptFunc relevant_fix = crpt_do_nothing; | |
142 | ||
143 | auto p = real_obj.corrupt_funcs->find(osd_num); | |
144 | if (p != real_obj.corrupt_funcs->end()) { | |
145 | // yes, we have a corruption recepie for this OSD | |
146 | // \todo c++20: use at() | |
147 | relevant_fix = p->second; | |
148 | } | |
149 | ||
150 | // create a possibly-corrupted copy of the "real object" | |
151 | auto modified_obj = (relevant_fix)(real_obj, osd_num); | |
152 | ||
153 | std::cout << fmt::format("{}: modified: osd:{} ho:{} key:{}", | |
154 | __func__, | |
155 | osd_num, | |
156 | modified_obj.ghobj.hobj, | |
157 | modified_obj.ghobj.hobj.get_key()) | |
158 | << std::endl; | |
159 | ||
160 | auto entry = make_smobject(modified_obj, osd_num); | |
161 | std::cout << fmt::format("{}: osd:{} smap entry: {} {}", | |
162 | __func__, | |
163 | osd_num, | |
164 | entry.smobj.size, | |
165 | entry.smobj.attrs.size()) | |
166 | << std::endl; | |
167 | map.objects[entry.ghobj.hobj] = entry.smobj; | |
168 | } |