]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
obj_bencher: clean up objects after a write benchmark
authorMike Ryan <mike.ryan@inktank.com>
Wed, 20 Jun 2012 21:47:46 +0000 (14:47 -0700)
committerMike Ryan <mike.ryan@inktank.com>
Thu, 23 Aug 2012 22:51:39 +0000 (15:51 -0700)
Per #2477, objects created during rados or rest write benchmark are
automatically cleaned up after the test. They can optionally be left in
place.

Signed-off-by: Mike Ryan <mike.ryan@inktank.com>
src/common/obj_bencher.cc
src/common/obj_bencher.h
src/rados.cc
src/tools/rest_bench.cc

index c87eb22c729ed5235279008140ae9c9eb93e5816..2f78161b8b1c6f2da2ba5d5c7a9b9fbcf83ed369 100644 (file)
 #include <iostream>
 #include <fstream>
 
+#include <cerrno>
+
 #include <stdlib.h>
 #include <time.h>
 #include <sstream>
 
 
-const char *BENCH_DATA = "benchmark_write_data";
+const char *BENCH_METADATA = "benchmark_write_metadata";
 const std::string BENCH_PREFIX = "benchmark_data";
 
 static std::string generate_object_prefix(int pid = 0) {
@@ -145,7 +147,7 @@ void *ObjBencher::status_printer(void *_bencher) {
   return NULL;
 }
 
-int ObjBencher::aio_bench(int operation, int secondsToRun, int concurrentios, int op_size) {
+int ObjBencher::aio_bench(int operation, int secondsToRun, int concurrentios, int op_size, bool cleanup) {
   int object_size = op_size;
   int num_objects = 0;
   char* contentsChars = new char[op_size];
@@ -154,18 +156,13 @@ int ObjBencher::aio_bench(int operation, int secondsToRun, int concurrentios, in
 
   //get data from previous write run, if available
   if (operation != OP_WRITE) {
-    bufferlist object_data;
-    r = sync_read(BENCH_DATA, object_data, sizeof(int)*3);
+    r = fetch_bench_metadata(&object_size, &num_objects, &prevPid);
     if (r <= 0) {
       delete[] contentsChars;
-      if (r == -2)
+      if (r == -ENOENT)
        cerr << "Must write data before running a read benchmark!" << std::endl;
       return r;
     }
-    bufferlist::iterator p = object_data.begin();
-    ::decode(object_size, p);
-    ::decode(num_objects, p);
-    ::decode(prevPid, p);
   } else {
     object_size = op_size;
   }
@@ -201,6 +198,20 @@ int ObjBencher::aio_bench(int operation, int secondsToRun, int concurrentios, in
     r = -1;
   }
 
+  if (OP_WRITE == operation && cleanup) {
+    r = fetch_bench_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);
+  }
+
  out:
   delete[] contentsChars;
   return r;
@@ -243,6 +254,22 @@ static double vec_stddev(vector<double>& v)
   return sqrt(stddev);
 }
 
+int ObjBencher::fetch_bench_metadata(int* object_size, int* num_objects, int* prevPid) {
+  int r = 0;
+  bufferlist object_data;
+
+  r = sync_read(BENCH_METADATA, object_data, sizeof(int)*3);
+  if (r <= 0) {
+    return r;
+  }
+  bufferlist::iterator p = object_data.begin();
+  ::decode(*object_size, p);
+  ::decode(*num_objects, p);
+  ::decode(*prevPid, p);
+
+  return 1;
+}
+
 int ObjBencher::write_bench(int secondsToRun, int concurrentios) {
   out(cout) << "Maintaining " << concurrentios << " concurrent writes of "
        << data.object_size << " bytes for at least "
@@ -417,7 +444,7 @@ 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_DATA, b_write, sizeof(int)*3);
+  sync_write(BENCH_METADATA, b_write, sizeof(int)*3);
 
   completions_done();
 
@@ -614,4 +641,19 @@ int ObjBencher::seq_read_bench(int seconds_to_run, int num_objects, int concurre
   return -5;
 }
 
+int ObjBencher::clean_up(int num_objects, int prevPid) {
+  int r = 0;
+
+  for (int i = 0; i < num_objects; ++i) {
+      std::string name = generate_object_name(i, prevPid);
+      r = sync_remove(name);
+
+      if (r < 0) {
+          return r;
+      }
+  }
+
+  return 0;
+}
+
 
index cc98cda88f37b9eadb6a90967212de823b72b22c..5802b53af09f254c6b31d0d2753823a4ebefb304 100644 (file)
@@ -58,9 +58,13 @@ protected:
 
   struct bench_data data;
 
+  int fetch_bench_metadata(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);
 
+  int clean_up(int num_objects, int prevPid);
+
   virtual int completions_init(int concurrentios) = 0;
   virtual void completions_done() = 0;
 
@@ -76,13 +80,14 @@ protected:
   virtual int aio_remove(const std::string& oid, int slot) = 0;
   virtual int sync_read(const std::string& oid, bufferlist& bl, size_t len) = 0;
   virtual int sync_write(const std::string& oid, bufferlist& bl, size_t len) = 0;
+  virtual int sync_remove(const std::string& oid) = 0;
 
   ostream& out(ostream& os);
   ostream& out(ostream& os, utime_t& t);
 public:
   ObjBencher() : show_time(false), lock("ObjBencher::lock") {}
   virtual ~ObjBencher() {}
-  int aio_bench(int operation, int secondsToRun, int concurrentios, int op_size);
+  int aio_bench(int operation, int secondsToRun, int concurrentios, int op_size, bool cleanup);
 
   void set_show_time(bool dt) {
     show_time = dt;
index 6ee0e890aeed2e6bb778d0adab4fafea53fcb21c..323d403e53e8d6acbe3a36b9239fed95bd14e077 100644 (file)
@@ -84,8 +84,9 @@ void usage(ostream& out)
 "   rmsnap <snap-name>               remove snap <snap-name>\n"
 "   rollback <obj-name> <snap-name>  roll back object to snap <snap-name>\n"
 "\n"
-"   bench <seconds> write|seq|rand [-t concurrent_operations]\n"
+"   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"
 "   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"
@@ -794,6 +795,10 @@ protected:
     return io_ctx.write(oid, bl, len, 0);
   }
 
+  int sync_remove(const std::string& oid) {
+    return io_ctx.remove(oid);
+  }
+
   bool completion_is_done(int slot) {
     return completions[slot]->is_safe();
   }
@@ -980,6 +985,7 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
   string oloc, target_oloc;
   int concurrent_ios = 16;
   int op_size = 1 << 22;
+  bool cleanup = true;
   const char *snapname = NULL;
   snap_t snapid = CEPH_NOSNAP;
   std::map<std::string, std::string>::const_iterator i;
@@ -1085,6 +1091,10 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
   if (i != opts.end()) {
     show_time = true;
   }
+  i = opts.find("no-cleanup");
+  if (i != opts.end()) {
+    cleanup = false;
+  }
   i = opts.find("pretty-format");
   if (i != opts.end()) {
     pretty_format = true;
@@ -1822,7 +1832,7 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
       usage_exit();
     RadosBencher bencher(rados, io_ctx);
     bencher.set_show_time(show_time);
-    ret = bencher.aio_bench(operation, seconds, concurrent_ios, op_size);
+    ret = bencher.aio_bench(operation, seconds, concurrent_ios, op_size, cleanup);
     if (ret != 0)
       cerr << "error during benchmark: " << ret << std::endl;
   }
@@ -1952,6 +1962,8 @@ int main(int argc, const char **argv)
       opts["pretty-format"] = "true";
     } else if (ceph_argparse_flag(args, i, "--show-time", (char*)NULL)) {
       opts["show-time"] = "true";
+    } else if (ceph_argparse_flag(args, i, "--no-cleanup", (char*)NULL)) {
+      opts["no-cleanup"] = "true";
     } else if (ceph_argparse_witharg(args, i, &val, "-p", "--pool", (char*)NULL)) {
       opts["pool"] = val;
     } else if (ceph_argparse_witharg(args, i, &val, "--target-pool", (char*)NULL)) {
index 93ca6d8540a02d0865902a01ca085ba7881156c8..1903907a3caf1b2601421d3a3dcb530b97ecf7ae 100644 (file)
@@ -47,6 +47,8 @@ void usage(ostream& out)
 "        set the size of write ops for put or benchmarking\n"
 "   --show-time\n"
 "        prefix output lines with date and time\n"
+"   --no-cleanup\n"
+"        do not clean up data after write bench\n"
 "REST CONFIG OPTIONS\n"
 "   --api-host=bhost\n"
 "        host name\n"
@@ -252,6 +254,7 @@ public:
   void process_context(req_context *ctx);
   void get_obj(req_context *ctx);
   void put_obj(req_context *ctx);
+  void delete_obj(req_context *ctx);
 
   void queue(req_context *ctx) {
     req_wq.queue(ctx);
@@ -273,6 +276,9 @@ void RESTDispatcher::process_context(req_context *ctx)
     case OP_PUT_OBJ:
       put_obj(ctx);
       break;
+    case OP_DELETE_OBJ:
+      delete_obj(ctx);
+      break;
     default:
       assert(0);
   }
@@ -309,6 +315,13 @@ void RESTDispatcher::get_obj(req_context *ctx)
                 &get_obj_handler, ctx);
 }
 
+void RESTDispatcher::delete_obj(req_context *ctx)
+{
+
+  S3_delete_object(ctx->bucket_ctx, ctx->oid.c_str(),
+                   ctx->ctx, &response_handler, ctx);
+}
+
 class RESTBencher : public ObjBencher {
   RESTDispatcher *dispatcher;
   struct req_context **completions;
@@ -457,6 +470,22 @@ protected:
     ctx->put();
     return ret;
   }
+  int sync_remove(const std::string& oid) {
+    struct req_context *ctx = new req_context;
+    int ret = ctx->init_ctx();
+    if (ret < 0) {
+      return ret;
+    }
+    ctx->get();
+    ctx->bucket_ctx = &bucket_ctx;
+    ctx->oid = oid;
+    ctx->op = OP_DELETE_OBJ;
+
+    dispatcher->process_context(ctx);
+    ret = ctx->ret();
+    ctx->put();
+    return ret;
+  }
 
   bool completion_is_done(int slot) {
     return completions[slot]->complete;
@@ -565,6 +594,7 @@ int main(int argc, const char **argv)
   int seconds = 60;
 
   bool show_time = false;
+  bool cleanup = true;
 
 
   for (i = args.begin(); i != args.end(); ) {
@@ -575,6 +605,8 @@ int main(int argc, const char **argv)
       exit(0);
     } else if (ceph_argparse_flag(args, i, "--show-time", (char*)NULL)) {
       show_time = true;
+    } else if (ceph_argparse_flag(args, i, "--no-cleanup", (char*)NULL)) {
+      cleanup = false;
     } else if (ceph_argparse_witharg(args, i, &user_agent, "--agent", (char*)NULL)) {
       /* nothing */
     } else if (ceph_argparse_witharg(args, i, &access_key, "--access-key", (char*)NULL)) {
@@ -662,7 +694,7 @@ int main(int argc, const char **argv)
     exit(1);
   }
 
-  ret = bencher.aio_bench(operation, seconds, concurrent_ios, op_size);
+  ret = bencher.aio_bench(operation, seconds, concurrent_ios, op_size, cleanup);
   if (ret != 0) {
       cerr << "error during benchmark: " << ret << std::endl;
   }