return;
}
-bool ObjectDesc::check(bufferlist &to_check) {
+bool ObjectDesc::check(bufferlist &to_check,
+ const std::pair<uint64_t, uint64_t>& offlen) {
iterator objiter = begin();
+ const auto [offset, size] = offlen;
+ objiter.seek(offset);
+ std::cout << "seeking to " << offset << std::endl;
uint64_t error_at = 0;
if (!objiter.check_bl_advance(to_check, &error_at)) {
std::cout << "incorrect buffer at pos " << error_at << std::endl;
return false;
}
- uint64_t size = layers.begin()->first->get_length(layers.begin()->second);
if (to_check.length() < size) {
std::cout << "only read " << to_check.length()
<< " out of size " << size << std::endl;
}
bool ObjectDesc::check_sparse(const std::map<uint64_t, uint64_t>& extents,
- bufferlist &to_check)
+ bufferlist &to_check,
+ const std::pair<uint64_t, uint64_t>& offlen)
{
+ const auto [offset_to_skip, _] = offlen;
+ uint64_t pos = offset_to_skip;
uint64_t off = 0;
- uint64_t pos = 0;
auto objiter = begin();
+ objiter.seek(pos);
for (auto &&extiter : extents) {
// verify hole
{
// takes ownership of gen
void update(ContentsGenerator *gen, const ContDesc &next);
- bool check(bufferlist &to_check);
+ bool check(bufferlist &to_check,
+ const std::pair<uint64_t, uint64_t>& offlen);
bool check_sparse(const std::map<uint64_t, uint64_t>& extends,
- bufferlist &to_check);
+ bufferlist &to_check,
+ const std::pair<uint64_t, uint64_t>& offlen);
const ContDesc &most_recent();
ContentsGenerator *most_recent_gen() {
return layers.begin()->first.get();
int snap;
bool balance_reads;
bool localize_reads;
+ uint8_t offlen_randomization_ratio;
std::shared_ptr<int> in_use;
std::vector<bufferlist> results;
+ std::vector<std::pair<uint64_t, uint64_t>> offlens;
std::vector<int> retvals;
std::vector<std::map<uint64_t, uint64_t>> extent_results;
std::vector<bool> is_sparse_read;
const std::string &oid,
bool balance_reads,
bool localize_reads,
+ uint8_t offlen_randomization_ratio,
TestOpStat *stat = 0)
: TestOp(n, context, stat),
completions(3),
snap(0),
balance_reads(balance_reads),
localize_reads(localize_reads),
+ offlen_randomization_ratio(offlen_randomization_ratio),
results(3),
+ offlens(3),
retvals(3),
extent_results(3),
is_sparse_read(3, false),
attrretval(0)
{}
+ static std::pair<uint64_t, uint64_t> maybe_randomize_offlen(
+ uint8_t offlen_randomization_ratio,
+ uint64_t max_len)
+ {
+ if ((rand() % 100) < offlen_randomization_ratio && max_len > 0) {
+ // the random offset here is de dacto "first n bytes to skip in
+ // a chhunk" -- it doesn't care about good distrubution across
+ // entire object. imperfect but should be good enough for parital
+ // read testing.
+ const auto off = rand() % max_len;
+ return {off, max_len - off};
+ } else {
+ return {0, max_len};
+ }
+ }
+
void _do_read(librados::ObjectReadOperation& read_op, int index) {
- uint64_t len = 0;
- if (old_value.has_contents())
- len = old_value.most_recent_gen()->get_length(old_value.most_recent());
+ uint64_t max_len = 0;
+ if (old_value.has_contents()) {
+ max_len =
+ old_value.most_recent_gen()->get_length(old_value.most_recent());
+ }
+ offlens[index] =
+ maybe_randomize_offlen(offlen_randomization_ratio, max_len);
+ const auto [offset, length] = offlens[index];
if (context->no_sparse || rand() % 2) {
is_sparse_read[index] = false;
- read_op.read(0,
- len,
+ read_op.read(offset,
+ length,
&results[index],
&retvals[index]);
bufferlist init_value_bl;
encode(static_cast<uint32_t>(-1), init_value_bl);
- read_op.checksum(LIBRADOS_CHECKSUM_TYPE_CRC32C, init_value_bl, 0, len,
+ read_op.checksum(LIBRADOS_CHECKSUM_TYPE_CRC32C, init_value_bl, offset, length,
0, &checksums[index], &checksum_retvals[index]);
} else {
is_sparse_read[index] = true;
- read_op.sparse_read(0,
- len,
+ read_op.sparse_read(offset,
+ length,
&extent_results[index],
&results[index],
&retvals[index]);
}
for (unsigned i = 0; i < results.size(); i++) {
if (is_sparse_read[i]) {
- if (!old_value.check_sparse(extent_results[i], results[i])) {
+ if (!old_value.check_sparse(extent_results[i], results[i], offlens[i])) {
std::cerr << num << ": oid " << oid << " contents " << to_check << " corrupt" << std::endl;
context->errors++;
}
} else {
- if (!old_value.check(results[i])) {
+ if (!old_value.check(results[i], offlens[i])) {
std::cerr << num << ": oid " << oid << " contents " << to_check << " corrupt" << std::endl;
context->errors++;
}
{}
void _do_read(librados::ObjectReadOperation& read_op, uint32_t offset, uint32_t length, int index) {
+ std::cout << __func__ << ":" << __LINE__ << std::endl;
read_op.read(offset,
length,
&results[index],
bool ec_pool,
bool balance_reads,
bool localize_reads,
+ uint8_t offlen_randomization_ratio,
bool set_redirect,
bool set_chunk,
bool enable_dedup) :
m_ec_pool(ec_pool),
m_balance_reads(balance_reads),
m_localize_reads(localize_reads),
+ m_offlen_randomization_ratio(offlen_randomization_ratio),
m_set_redirect(set_redirect),
m_set_chunk(set_chunk),
m_enable_dedup(enable_dedup)
case TEST_OP_READ:
oid = *(rand_choose(context.oid_not_in_use));
return new ReadOp(m_op, &context, oid, m_balance_reads, m_localize_reads,
- m_stats);
+ m_offlen_randomization_ratio, m_stats);
case TEST_OP_WRITE:
oid = *(rand_choose(context.oid_not_in_use));
bool m_ec_pool;
bool m_balance_reads;
bool m_localize_reads;
+ uint8_t m_offlen_randomization_ratio;
bool m_set_redirect;
bool m_set_chunk;
bool m_enable_dedup;
bool no_sparse = false;
bool balance_reads = false;
bool localize_reads = false;
+ uint8_t offlen_randomization_ratio = 50;
bool set_redirect = false;
bool set_chunk = false;
bool enable_dedup = false;
balance_reads = true;
else if (strcmp(argv[i], "--localize-reads") == 0)
localize_reads = true;
+ else if (strcmp(argv[i], "--offlen_randomization_ratio") == 0)
+ offlen_randomization_ratio = atoi(argv[++i]);
else if (strcmp(argv[i], "--pool-snaps") == 0)
pool_snaps = true;
else if (strcmp(argv[i], "--write-fadvise-dontneed") == 0)
ops, objects,
op_weights, &stats, max_seconds,
ec_pool, balance_reads, localize_reads,
+ offlen_randomization_ratio,
set_redirect, set_chunk, enable_dedup);
int r = context.init();
if (r < 0) {