* @returns true if there are any objects in the store which match
* the prefix, false if there are no more
*/
-bool ObjBencher::more_objects_matching_prefix(const std::string& prefix, std::list<std::string>* objects) {
- std::list<std::string> unfiltered_objects;
+bool ObjBencher::more_objects_matching_prefix(const std::string& prefix, std::list<Object>* objects) {
+ std::list<Object> unfiltered_objects;
objects->clear();
if (!objects_remain)
return false;
- std::list<std::string>::const_iterator i = unfiltered_objects.begin();
+ std::list<Object>::const_iterator i = unfiltered_objects.begin();
for ( ; i != unfiltered_objects.end(); ++i) {
- const std::string& next = *i;
-
- if (next.substr(0, prefix.length()) == prefix) {
- objects->push_back(next);
+ if (i->first.substr(0, prefix.length()) == prefix) {
+ objects->push_back(*i);
}
}
}
if (concurrentios <= 0)
return -EINVAL;
- std::vector<string> name(concurrentios);
- std::string newName;
+ std::vector<Object> name(concurrentios);
+ Object newName;
int r = 0;
utime_t runtime;
int slot = 0;
- std::list<std::string> objects;
+ std::list<Object> objects;
bool objects_remain = true;
lock.Lock();
//start initial removes
for (int i = 0; i < concurrentios; ++i) {
create_completion(i, _aio_cb, (void *)&lc);
- r = aio_remove(name[i], i);
+ set_namespace(name[i].second);
+ r = aio_remove(name[i].first, i);
if (r < 0) { //naughty, doesn't clean up heap
cerr << "r = " << r << std::endl;
goto ERR;
//start new remove and check data if requested
create_completion(slot, _aio_cb, (void *)&lc);
- r = aio_remove(newName, slot);
+ set_namespace(newName.second);
+ r = aio_remove(newName.first, slot);
if (r < 0) {
goto ERR;
}
const int OP_SEQ_READ = 2;
const int OP_RAND_READ = 3;
+// Object is composed of <oid,namespace>
+typedef std::pair<std::string, std::string> Object;
+
class ObjBencher {
bool show_time;
public:
int rand_read_bench(int secondsToRun, int num_objects, int concurrentios, int writePid, bool no_verify=false);
int clean_up(int num_objects, int prevPid, int concurrentios);
- int clean_up_slow(const std::string& prefix, int concurrentios);
- bool more_objects_matching_prefix(const std::string& prefix, std::list<std::string>* name);
+ bool more_objects_matching_prefix(const std::string& prefix, std::list<Object>* name);
virtual int completions_init(int concurrentios) = 0;
virtual void completions_done() = 0;
virtual int sync_write(const std::string& oid, bufferlist& bl, size_t len) = 0;
virtual int sync_remove(const std::string& oid) = 0;
- virtual bool get_objects(std::list<std::string>* objects, int num) = 0;
+ virtual bool get_objects(std::list< std::pair<std::string, std::string> >* objects, int num) = 0;
+ virtual void set_namespace(const std::string&) {}
ostream& out(ostream& os);
ostream& out(ostream& os, utime_t& t);
void set_show_time(bool dt) {
show_time = dt;
}
+ int clean_up_slow(const std::string& prefix, int concurrentios);
};
# inaccessible import src should fail
run_expect_fail "$RADOS_TOOL" -p "$POOL" import "$TDIR/dir_nonexistent"
+# export an empty pool to test purge
+run_expect_succ "$RADOS_TOOL" purge "$POOL" --yes-i-really-really-mean-it
+run_expect_succ "$RADOS_TOOL" -p "$POOL" export "$TDIR/empty"
+cmp -s "$TDIR/expb" "$TDIR/empty" \
+ || die "failed to export the same stuff we imported!"
+rm -f "$TDIR/empty"
+
# import some stuff with extended attributes on it
run_expect_succ "$RADOS_TOOL" -p "$POOL" import "$TDIR/expc"
VAL=`"$RADOS_TOOL" -p "$POOL" getxattr foo "rados.toothbrush"`
" cppool <pool-name> <dest-pool> copy content of a pool\n"
" rmpool <pool-name> [<pool-name> --yes-i-really-really-mean-it]\n"
" remove pool <pool-name>'\n"
+" purge <pool-name> --yes-i-really-really-mean-it\n"
+" remove all objects from pool <pool-name> without removing it\n"
" df show per-pool and total usage\n"
" ls list objects in pool\n\n"
" chown 123 change the pool owner to auid 123\n"
return completions[slot]->get_return_value();
}
- bool get_objects(std::list<std::string>* objects, int num) {
+ bool get_objects(std::list<Object>* objects, int num) {
int count = 0;
if (!iterator_valid) {
objects->clear();
for ( ; oi != ei && count < num; ++oi) {
- objects->push_back(oi->get_oid());
+ Object obj(oi->get_oid(), oi->get_nspace());
+ objects->push_back(obj);
++count;
}
return true;
}
+ void set_namespace( const std::string& ns) {
+ io_ctx.set_namespace(ns);
+ }
+
public:
RadosBencher(CephContext *cct_, librados::Rados& _r, librados::IoCtx& _i)
: ObjBencher(cct_), completions(NULL), rados(_r), io_ctx(_i), iterator_valid(false) {}
cerr << "pool " << nargs[1] << " could not be removed" << std::endl;
}
}
+ else if (strcmp(nargs[0], "purge") == 0) {
+ if (nargs.size() < 2)
+ usage_exit();
+ if (nargs.size() < 3 ||
+ strcmp(nargs[2], "--yes-i-really-really-mean-it") != 0) {
+ cerr << "WARNING:\n"
+ << " This will PERMANENTLY DESTROY all objects from a pool with no way back.\n"
+ << " To confirm, follow pool with --yes-i-really-really-mean-it" << std::endl;
+ ret = -1;
+ goto out;
+ }
+ ret = rados.ioctx_create(nargs[1], io_ctx);
+ if (ret < 0) {
+ cerr << "error pool " << nargs[1] << ": "
+ << cpp_strerror(ret) << std::endl;
+ goto out;
+ }
+ io_ctx.set_namespace(all_nspaces);
+ RadosBencher bencher(g_ceph_context, rados, io_ctx);
+ ret = bencher.clean_up_slow("", concurrent_ios);
+ if (ret >= 0) {
+ cout << "successfully purged pool " << nargs[1] << std::endl;
+ } else { //error
+ cerr << "pool " << nargs[1] << " could not be purged" << std::endl;
+ }
+ }
else if (strcmp(nargs[0], "lssnap") == 0) {
if (!pool_name || nargs.size() != 1)
usage_exit();
uint64_t off;
uint64_t len;
const char *list_start;
- std::list<std::string>* list_objects;
+ std::list<Object>* list_objects;
int list_count;
string oid;
Mutex lock;
ctx->list_start = next_marker;
for (int i = 0; i < count; ++i) {
- ctx->list_objects->push_back(objects[i].key);
+ // RGW doesn't support namespaces yet
+ ctx->list_objects->push_back(Object(objects[i].key, ""));
}
return S3StatusOK;
return ret;
}
- bool get_objects(std::list<std::string>* objects, int num) {
+ bool get_objects(std::list<Object>* objects, int num) {
if (bucket_list_done) {
bucket_list_done = false;
return false;