* Ceph distributed storage system
*
* Copyright (C) 2013,2014 Cloudwatt <libre.licensing@cloudwatt.com>
+ * Copyright (C) 2014 Red Hat <contact@redhat.com>
*
* Author: Loic Dachary <loic@dachary.org>
*
#include <boost/program_options/parsers.hpp>
#include <boost/algorithm/string.hpp>
-#include "ceph_erasure_code_benchmark.h"
#include "global/global_context.h"
#include "global/global_init.h"
#include "common/ceph_argparse.h"
#include "include/utime.h"
#include "erasure-code/ErasureCodePlugin.h"
#include "erasure-code/ErasureCode.h"
+#include "ceph_erasure_code_benchmark.h"
namespace po = boost::program_options;
"run either encode or decode")
("erasures,e", po::value<int>()->default_value(1),
"number of erasures when decoding")
+ ("erasures-generation,E", po::value<string>()->default_value("random"),
+ "If set to 'random', pick the number of chunks to recover (as specified by "
+ " --erasures) at random. If set to 'exhaustive' try all combinations of erasures "
+ " (i.e. k=4,m=3 with one erasure will try to recover from the erasure of "
+ " the first chunk, then the second etc.)")
("parameter,P", po::value<vector<string> >(),
"parameters")
;
plugin = vm["plugin"].as<string>();
workload = vm["workload"].as<string>();
erasures = vm["erasures"].as<int>();
+ if (vm.count("erasures-generation") > 0 &&
+ vm["erasures-generation"].as<string>() == "exhaustive")
+ exhaustive_erasures = true;
+ else
+ exhaustive_erasures = false;
k = atoi(parameters["k"].c_str());
m = atoi(parameters["m"].c_str());
return 0;
}
+int ErasureCodeBench::decode_erasures(const map<int,bufferlist> &all_chunks,
+ const map<int,bufferlist> &chunks,
+ unsigned i,
+ unsigned want_erasures,
+ ErasureCodeInterfaceRef erasure_code)
+{
+ int code = 0;
+
+ if (want_erasures <= 0) {
+ if (verbose)
+ cout << "chunks ";
+ set<int> want_to_read;
+ for (unsigned int chunk = 0; chunk < erasure_code->get_chunk_count(); chunk++) {
+ if (chunks.count(chunk) == 0) {
+ if (verbose)
+ cout << "(" << chunk << ")";
+ want_to_read.insert(chunk);
+ } else {
+ if (verbose)
+ cout << " " << chunk << " ";
+ }
+ if (verbose)
+ cout << " ";
+ }
+ if (verbose)
+ cout << "(X) is an erased chunk" << endl;
+
+ map<int,bufferlist> decoded;
+ code = erasure_code->decode(want_to_read, chunks, &decoded);
+ if (code)
+ return code;
+ for (set<int>::iterator chunk = want_to_read.begin();
+ chunk != want_to_read.end();
+ chunk++) {
+ if (all_chunks.find(*chunk)->second.length() != decoded[*chunk].length()) {
+ cerr << "chunk " << *chunk << " length=" << all_chunks.find(*chunk)->second.length()
+ << " decoded with length=" << decoded[*chunk].length() << endl;
+ return -1;
+ }
+ bufferlist tmp = all_chunks.find(*chunk)->second;
+ if (!tmp.contents_equal(decoded[*chunk])) {
+ cerr << "chunk " << *chunk
+ << " content and recovered content are different" << endl;
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ for (; i < erasure_code->get_chunk_count(); i++) {
+ map<int,bufferlist> one_less = chunks;
+ one_less.erase(i);
+ code = decode_erasures(all_chunks, one_less, i + 1, want_erasures - 1, erasure_code);
+ if (code)
+ return code;
+ }
+
+ return 0;
+}
+
int ErasureCodeBench::decode()
{
ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
utime_t begin_time = ceph_clock_now(g_ceph_context);
for (int i = 0; i < max_iterations; i++) {
- map<int,bufferlist> chunks = encoded;
- for (int j = 0; j < erasures; j++) {
- int erasure;
- do {
- erasure = rand() % ( k + m );
- } while(chunks.count(erasure) == 0);
- chunks.erase(erasure);
+ if (exhaustive_erasures) {
+ code = decode_erasures(encoded, encoded, 0, erasures, erasure_code);
+ if (code)
+ return code;
+ } else {
+ map<int,bufferlist> chunks = encoded;
+ for (int j = 0; j < erasures; j++) {
+ int erasure;
+ do {
+ erasure = rand() % ( k + m );
+ } while(chunks.count(erasure) == 0);
+ chunks.erase(erasure);
+ }
+ map<int,bufferlist> decoded;
+ code = erasure_code->decode(want_to_read, chunks, &decoded);
+ if (code)
+ return code;
}
- map<int,bufferlist> decoded;
- code = erasure_code->decode(want_to_read, chunks, &decoded);
- if (code)
- return code;
}
utime_t end_time = ceph_clock_now(g_ceph_context);
cout << (end_time - begin_time) << "\t" << (max_iterations * (in_size / 1024)) << endl;
/*
* Local Variables:
- * compile-command: "cd ../.. ; make -j4 &&
- * make ceph_erasure_code_benchmark &&
+ * compile-command: "cd ../.. ; make -j4 ceph_erasure_code_benchmark &&
* valgrind --tool=memcheck --leak-check=full \
* ./ceph_erasure_code_benchmark \
* --plugin jerasure \