From 9e58d1b79b4ab4a433dd6e3f7e48330344569d7a Mon Sep 17 00:00:00 2001 From: Mike Ryan Date: Thu, 21 Jun 2012 10:08:53 -0700 Subject: [PATCH] obj_bencher: remove benchmark objects by prefix This intelligently removes objects from a rados or rest benchmark run by using parameters from the metadata file. Signed-off-by: Mike Ryan --- src/common/obj_bencher.cc | 54 +++++++++++++++++++++++++++++++-------- src/common/obj_bencher.h | 3 ++- src/rados.cc | 10 ++++++++ src/tools/rest_bench.cc | 22 +++++++++++++--- 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/src/common/obj_bencher.cc b/src/common/obj_bencher.cc index f8a598d0be869..12818fde1b341 100644 --- a/src/common/obj_bencher.cc +++ b/src/common/obj_bencher.cc @@ -27,7 +27,7 @@ #include -const char *BENCH_METADATA = "benchmark_write_metadata"; +const std::string BENCH_LASTRUN_METADATA = "benchmark_last_metadata"; const std::string BENCH_PREFIX = "benchmark_data"; static std::string generate_object_prefix(int pid = 0) { @@ -170,8 +170,8 @@ int ObjBencher::aio_bench(int operation, int secondsToRun, int concurrentios, in //get data from previous write run, if available if (operation != OP_WRITE) { - r = fetch_bench_metadata(&object_size, &num_objects, &prevPid); - if (r <= 0) { + r = fetch_bench_metadata(BENCH_LASTRUN_METADATA, &object_size, &num_objects, &prevPid); + if (r < 0) { delete[] contentsChars; if (r == -ENOENT) cerr << "Must write data before running a read benchmark!" << std::endl; @@ -213,8 +213,8 @@ int ObjBencher::aio_bench(int operation, int secondsToRun, int concurrentios, in } if (OP_WRITE == operation && cleanup) { - r = fetch_bench_metadata(&object_size, &num_objects, &prevPid); - if (r <= 0) { + r = fetch_bench_metadata(BENCH_LASTRUN_METADATA, &object_size, &num_objects, &prevPid); + if (r < 0) { if (r == -ENOENT) cerr << "Should never happen: bench metadata missing for current run!" << std::endl; goto out; @@ -223,9 +223,11 @@ int ObjBencher::aio_bench(int operation, int secondsToRun, int concurrentios, in r = clean_up(num_objects, prevPid); if (r != 0) goto out; - r = sync_remove(BENCH_METADATA); + // lastrun file + r = sync_remove(BENCH_LASTRUN_METADATA); if (r != 0) goto out; + // prefix-based file r = sync_remove(generate_metadata_name()); } @@ -271,12 +273,16 @@ static double vec_stddev(vector& v) return sqrt(stddev); } -int ObjBencher::fetch_bench_metadata(int* object_size, int* num_objects, int* prevPid) { +int ObjBencher::fetch_bench_metadata(const std::string& metadata_file, int* object_size, int* num_objects, int* prevPid) { int r = 0; bufferlist object_data; - r = sync_read(BENCH_METADATA, object_data, sizeof(int)*3); + r = sync_read(metadata_file, object_data, sizeof(int)*3); if (r <= 0) { + // treat an empty file as a file that does not exist + if (r == 0) { + r = -ENOENT; + } return r; } bufferlist::iterator p = object_data.begin(); @@ -284,7 +290,7 @@ int ObjBencher::fetch_bench_metadata(int* object_size, int* num_objects, int* pr ::decode(*num_objects, p); ::decode(*prevPid, p); - return 1; + return 0; } int ObjBencher::write_bench(int secondsToRun, int concurrentios) { @@ -461,8 +467,11 @@ int ObjBencher::write_bench(int secondsToRun, int concurrentios) { ::encode(data.object_size, b_write); ::encode(data.finished, b_write); ::encode(getpid(), b_write); - sync_write(BENCH_METADATA, b_write, sizeof(int)*3); + // lastrun file + sync_write(BENCH_LASTRUN_METADATA, b_write, sizeof(int)*3); + + // PID-specific run sync_write(generate_metadata_name(), b_write, sizeof(int)*3); completions_done(); @@ -676,3 +685,28 @@ int ObjBencher::clean_up(int num_objects, int prevPid) { } +int ObjBencher::clean_up(const std::string& prefix, int concurrent_ios) { + int r = 0; + int object_size; + int num_objects; + int prevPid; + + std::string metadata_name = prefix; + metadata_name.append("_metadata"); + + r = fetch_bench_metadata(metadata_name, &object_size, &num_objects, &prevPid); + if (r < 0) { + return r; + } + // if this file is not found we should try to do a linear search on the prefix + + r = clean_up(num_objects, prevPid); + if (r != 0) return r; + + r = sync_remove(metadata_name); + if (r != 0) return r; + + return 0; +} + + diff --git a/src/common/obj_bencher.h b/src/common/obj_bencher.h index 5802b53af09f2..f766462e93cfd 100644 --- a/src/common/obj_bencher.h +++ b/src/common/obj_bencher.h @@ -58,7 +58,7 @@ protected: struct bench_data data; - int fetch_bench_metadata(int* object_size, int* num_objects, int* prevPid); + int fetch_bench_metadata(const std::string& metadata_file, int* object_size, int* num_objects, int* prevPid); int write_bench(int secondsToRun, int concurrentios); int seq_read_bench(int secondsToRun, int concurrentios, int num_objects, int writePid); @@ -88,6 +88,7 @@ public: ObjBencher() : show_time(false), lock("ObjBencher::lock") {} virtual ~ObjBencher() {} int aio_bench(int operation, int secondsToRun, int concurrentios, int op_size, bool cleanup); + int clean_up(const std::string& prefix, int concurrent_ios); void set_show_time(bool dt) { show_time = dt; diff --git a/src/rados.cc b/src/rados.cc index 323d403e53e8d..f02badd6809d5 100644 --- a/src/rados.cc +++ b/src/rados.cc @@ -87,6 +87,7 @@ void usage(ostream& out) " bench write|seq|rand [-t concurrent_operations] [--no-cleanup]\n" " default is 16 concurrent IOs and 4 MB ops\n" " default is to clean up after write benchmark\n" +" cleanup clean up a previous benchmark operation\n" " load-gen [options] generate load on the cluster\n" " listomapkeys list the keys in the object map\n" " getomapval show the value for the specified key\n" @@ -1836,6 +1837,15 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, if (ret != 0) cerr << "error during benchmark: " << ret << std::endl; } + else if (strcmp(nargs[0], "cleanup") == 0) { + if (!pool_name || nargs.size() < 2) + usage_exit(); + const char *prefix = nargs[1]; + RadosBencher bencher(rados, io_ctx); + ret = bencher.clean_up(prefix, concurrent_ios); + if (ret != 0) + cerr << "error during cleanup: " << ret << std::endl; + } else if (strcmp(nargs[0], "watch") == 0) { if (!pool_name || nargs.size() < 2) usage_exit(); diff --git a/src/tools/rest_bench.cc b/src/tools/rest_bench.cc index 1903907a3caf1..99d222fc87810 100644 --- a/src/tools/rest_bench.cc +++ b/src/tools/rest_bench.cc @@ -36,6 +36,7 @@ void usage(ostream& out) { out << \ "usage: rest-bench [options] \n" +" rest-bench [options] cleanup \n" "BENCHMARK OPTIONS\n" " --seconds\n" " benchmak length (default: 60)\n" @@ -75,6 +76,7 @@ enum OpType { OP_GET_OBJ = 1, OP_PUT_OBJ = 2, OP_DELETE_OBJ = 3, + OP_CLEANUP = 4, }; struct req_context : public RefCountedObject { @@ -657,13 +659,19 @@ int main(int argc, const char **argv) if (args.size() < 1) usage_exit(); int operation = 0; + const char *prefix = NULL; if (strcmp(args[0], "write") == 0) operation = OP_WRITE; else if (strcmp(args[0], "seq") == 0) operation = OP_SEQ_READ; else if (strcmp(args[0], "rand") == 0) operation = OP_RAND_READ; - else + else if (strcmp(args[0], "cleanup") == 0) { + if (args.size() < 2) + usage_exit(); + operation = OP_CLEANUP; + prefix = argv[1]; + } else usage_exit(); if (host.empty()) { @@ -694,9 +702,15 @@ int main(int argc, const char **argv) exit(1); } - ret = bencher.aio_bench(operation, seconds, concurrent_ios, op_size, cleanup); - if (ret != 0) { - cerr << "error during benchmark: " << ret << std::endl; + if (operation == OP_CLEANUP) { + ret = bencher.clean_up(prefix, concurrent_ios); + if (ret != 0) + cerr << "error during cleanup: " << ret << std::endl; + } else { + ret = bencher.aio_bench(operation, seconds, concurrent_ios, op_size, cleanup); + if (ret != 0) { + cerr << "error during benchmark: " << ret << std::endl; + } } return 0; -- 2.39.5