#include <sstream>
-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) {
//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;
}
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;
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());
}
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();
::decode(*num_objects, p);
::decode(*prevPid, p);
- return 1;
+ return 0;
}
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();
}
+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;
+}
+
+
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);
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;
" bench <seconds> 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 <prefix> clean up a previous benchmark operation\n"
" load-gen [options] generate load on the cluster\n"
" listomapkeys <obj-name> list the keys in the object map\n"
" getomapval <obj-name> <key> show the value for the specified key\n"
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();
{
out << \
"usage: rest-bench [options] <write|seq>\n"
+" rest-bench [options] cleanup <prefix>\n"
"BENCHMARK OPTIONS\n"
" --seconds\n"
" benchmak length (default: 60)\n"
OP_GET_OBJ = 1,
OP_PUT_OBJ = 2,
OP_DELETE_OBJ = 3,
+ OP_CLEANUP = 4,
};
struct req_context : public RefCountedObject {
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()) {
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;