summaryrefslogtreecommitdiffstats
path: root/src/test/osd/scrubber_generators.cc
blob: 0f2f371e714b9e87e9ae1d5954f36cc7d4c992d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#include "test/osd/scrubber_generators.h"

#include <fmt/ranges.h>

using namespace ScrubGenerator;

// ref: PGLogTestRebuildMissing()
bufferptr create_object_info(const ScrubGenerator::RealObj& objver)
{
  object_info_t oi{};
  oi.soid = objver.ghobj.hobj;
  oi.version = eversion_t(objver.ghobj.generation, 0);
  oi.size = objver.data.size;

  bufferlist bl;
  oi.encode(bl,
	    0 /*get_osdmap()->get_features(CEPH_ENTITY_TYPE_OSD, nullptr)*/);
  bufferptr bp(bl.c_str(), bl.length());
  return bp;
}

std::pair<bufferptr, std::vector<snapid_t>> create_object_snapset(
  const ScrubGenerator::RealObj& robj,
  const SnapsetMockData* snapset_mock_data)
{
  if (!snapset_mock_data) {
    return {bufferptr(), {}};
  }
  /// \todo fill in missing version/osd details from the robj
  auto sns = snapset_mock_data->make_snapset();
  bufferlist bl;
  encode(sns, bl);
  bufferptr bp = bufferptr(bl.c_str(), bl.length());

  // extract the set of object snaps
  return {bp, sns.snaps};
}

RealObjsConfList ScrubGenerator::make_real_objs_conf(
  int64_t pool_id,
  const RealObjsConf& blueprint,
  std::vector<int32_t> active_osds)
{
  RealObjsConfList all_osds;

  for (auto osd : active_osds) {
    RealObjsConfRef this_osd_fakes = std::make_unique<RealObjsConf>(blueprint);
    // now - fix & corrupt every "object" in the blueprint
    for (RealObj& robj : this_osd_fakes->objs) {

      robj.ghobj.hobj.pool = pool_id;
    }

    all_osds[osd] = std::move(this_osd_fakes);
  }
  return all_osds;  // reconsider (maybe add a move ctor?)
}

///\todo dispose of the created buffer pointers

ScrubGenerator::SmapEntry ScrubGenerator::make_smobject(
  const ScrubGenerator::RealObj& blueprint,
  int osd_num)
{
  ScrubGenerator::SmapEntry ret;

  ret.ghobj = blueprint.ghobj;
  ret.smobj.attrs[OI_ATTR] = create_object_info(blueprint);
  if (blueprint.snapset_mock_data) {
    auto [bp, snaps] =
      create_object_snapset(blueprint, blueprint.snapset_mock_data);
    ret.smobj.attrs[SS_ATTR] = bp;
    std::cout << fmt::format("{}: ({}) osd:{} snaps:{}",
			     __func__,
			     ret.ghobj.hobj,
			     osd_num,
			     snaps)
	      << std::endl;
  }

  for (const auto& [at_k, at_v] : blueprint.data.attrs) {
    ret.smobj.attrs[at_k] = ceph::buffer::copy(at_v.c_str(), at_v.size());
    {
      // verifying (to be removed after dev phase)
      auto bk = ret.smobj.attrs[at_k].begin_deep().get_ptr(
	ret.smobj.attrs[at_k].length());
      std::string bkstr{bk.raw_c_str(), bk.raw_length()};
      std::cout << fmt::format("{}: verification: {}", __func__, bkstr)
		<< std::endl;
    }
  }
  ret.smobj.size = blueprint.data.size;
  ret.smobj.digest = blueprint.data.hash;
  /// \todo handle the 'present' etc'

  ret.smobj.object_omap_keys = blueprint.data.omap.size();
  ret.smobj.object_omap_bytes = blueprint.data.omap_bytes;
  return ret;
}

all_clones_snaps_t ScrubGenerator::all_clones(
  const ScrubGenerator::RealObj& head_obj)
{
  std::cout << fmt::format("{}: head_obj.ghobj.hobj:{}",
			   __func__,
			   head_obj.ghobj.hobj)
	    << std::endl;

  std::map<hobject_t, std::vector<snapid_t>> ret;

  for (const auto& clone : head_obj.snapset_mock_data->clones) {
    auto clone_set_it = head_obj.snapset_mock_data->clone_snaps.find(clone);
    if (clone_set_it == head_obj.snapset_mock_data->clone_snaps.end()) {
      std::cout << "note: no clone_snaps for " << clone << std::endl;
      continue;
    }
    auto clone_set = clone_set_it->second;
    hobject_t clone_hobj{head_obj.ghobj.hobj};
    clone_hobj.snap = clone;

    ret[clone_hobj] = clone_set_it->second;
    std::cout << fmt::format("{}: clone:{} clone_set:{}",
			     __func__,
			     clone_hobj,
			     clone_set)
	      << std::endl;
  }

  return ret;
}

void ScrubGenerator::add_object(ScrubMap& map,
				const ScrubGenerator::RealObj& real_obj,
				int osd_num)
{
  // do we have data corruption recipe for this OSD?
  /// \todo c++20: use contains()
  CorruptFunc relevant_fix = crpt_do_nothing;

  auto p = real_obj.corrupt_funcs->find(osd_num);
  if (p != real_obj.corrupt_funcs->end()) {
    // yes, we have a corruption recepie for this OSD
    // \todo c++20: use at()
    relevant_fix = p->second;
  }

  // create a possibly-corrupted copy of the "real object"
  auto modified_obj = (relevant_fix)(real_obj, osd_num);

  std::cout << fmt::format("{}: modified: osd:{} ho:{} key:{}",
			   __func__,
			   osd_num,
			   modified_obj.ghobj.hobj,
			   modified_obj.ghobj.hobj.get_key())
	    << std::endl;

  auto entry = make_smobject(modified_obj, osd_num);
  std::cout << fmt::format("{}: osd:{} smap entry: {} {}",
			   __func__,
			   osd_num,
			   entry.smobj.size,
			   entry.smobj.attrs.size())
	    << std::endl;
  map.objects[entry.ghobj.hobj] = entry.smobj;
}