uint64_t num_rd, num_rd_kb, num_wr, num_wr_kb;
};
+ typedef std::map<std::string, pool_stat_t> stats_map;
+
typedef void *completion_t;
typedef void (*callback_t)(completion_t cb, void *arg);
/* listing objects */
int pool_list(std::list<std::string>& v);
int get_pool_stats(std::list<std::string>& v,
- std::map<std::string,pool_stat_t>& stats);
+ std::map<std::string, stats_map>& stats);
+ int get_pool_stats(std::list<std::string>& v,
+ std::string& category,
+ std::map<std::string, stats_map>& stats);
int cluster_stat(cluster_stat_t& result);
/* pool aio */
}
int librados::Rados::
-get_pool_stats(std::list<string>& v, std::map<string,pool_stat_t>& result)
+get_pool_stats(std::list<string>& v, std::map<string, stats_map>& result)
+{
+ string category;
+ return get_pool_stats(v, category, result);
+}
+
+int librados::Rados::
+get_pool_stats(std::list<string>& v, string& category, std::map<string, stats_map>& result)
{
map<string,::pool_stat_t> rawresult;
int r = client->get_pool_stats(v, rawresult);
for (map<string,::pool_stat_t>::iterator p = rawresult.begin();
p != rawresult.end();
p++) {
- pool_stat_t& v = result[p->first];
- v.num_kb = p->second.stats.sum.num_kb;
- v.num_bytes = p->second.stats.sum.num_bytes;
- v.num_objects = p->second.stats.sum.num_objects;
- v.num_object_clones = p->second.stats.sum.num_object_clones;
- v.num_object_copies = p->second.stats.sum.num_object_copies;
- v.num_objects_missing_on_primary = p->second.stats.sum.num_objects_missing_on_primary;
- v.num_objects_unfound = p->second.stats.sum.num_objects_unfound;
- v.num_objects_degraded = p->second.stats.sum.num_objects_degraded;
- v.num_rd = p->second.stats.sum.num_rd;
- v.num_rd_kb = p->second.stats.sum.num_rd_kb;
- v.num_wr = p->second.stats.sum.num_wr;
- v.num_wr_kb = p->second.stats.sum.num_wr_kb;
+ stats_map& c = result[p->first];
+
+ string cat;
+ vector<string> cats;
+
+ if (!category.size()) {
+ cats.push_back(cat);
+ map<string,object_stat_sum_t>::iterator iter;
+ for (iter = p->second.stats.cat_sum.begin(); iter != p->second.stats.cat_sum.end(); ++iter) {
+ cats.push_back(iter->first);
+ }
+ } else {
+ cats.push_back(category);
+ }
+
+ vector<string>::iterator cat_iter;
+ for (cat_iter = cats.begin(); cat_iter != cats.end(); ++cat_iter) {
+ string& cur_category = *cat_iter;
+ object_stat_sum_t *sum;
+
+ if (!cur_category.size()) {
+ sum = &p->second.stats.sum;
+ } else {
+ map<string,object_stat_sum_t>::iterator iter = p->second.stats.cat_sum.find(cur_category);
+ if (iter == p->second.stats.cat_sum.end())
+ continue;
+ sum = &iter->second;
+ }
+
+ pool_stat_t& v = c[cur_category];
+ v.num_kb = sum->num_kb;
+ v.num_bytes = sum->num_bytes;
+ v.num_objects = sum->num_objects;
+ v.num_object_clones = sum->num_object_clones;
+ v.num_object_copies = sum->num_object_copies;
+ v.num_objects_missing_on_primary = sum->num_objects_missing_on_primary;
+ v.num_objects_unfound = sum->num_objects_unfound;
+ v.num_objects_degraded = sum->num_objects_degraded;
+ v.num_rd = sum->num_rd;
+ v.num_rd_kb = sum->num_rd_kb;
+ v.num_wr = sum->num_wr;
+ v.num_wr_kb = sum->num_wr_kb;
+ }
}
return r;
}
bufferlist::iterator p = osd_op.data.begin();
string category;
::decode(category, p);
- if (obs.exists) {
- if (obs.oi.category != category)
- result = -EEXIST;
- } else {
- obs.oi.category = category;
- }
+ if (category.size()) {
+ if (obs.exists) {
+ if (obs.oi.category != category)
+ result = -EEXIST;
+ } else {
+ obs.oi.category = category;
+ }
+ }
}
}
break;
const char *snapname = NULL;
snap_t snapid = CEPH_NOSNAP;
std::map<std::string, std::string>::const_iterator i;
+ std::string category;
uint64_t min_obj_len = 0;
uint64_t max_obj_len = 0;
if (i != opts.end()) {
pool_name = i->second.c_str();
}
+ i = opts.find("category");
+ if (i != opts.end()) {
+ category = i->second;
+ }
i = opts.find("concurrent-ios");
if (i != opts.end()) {
concurrent_ios = strtol(i->second.c_str(), NULL, 10);
else if (strcmp(nargs[0], "df") == 0) {
// pools
list<string> vec;
- rados.pool_list(vec);
- map<string,pool_stat_t> stats;
- rados.get_pool_stats(vec, stats);
+ if (!pool_name)
+ rados.pool_list(vec);
+ else
+ vec.push_back(pool_name);
+
+ map<string, map<string, pool_stat_t> > stats;
+ rados.get_pool_stats(vec, category, stats);
- printf("%-15s "
+ printf("%-15s %-15s"
"%12s %12s %12s %12s "
"%12s %12s %12s %12s %12s\n",
"pool name",
+ "category",
"KB", "objects", "clones", "degraded",
"unfound", "rd", "rd KB", "wr", "wr KB");
- for (map<string,pool_stat_t>::iterator i = stats.begin(); i != stats.end(); ++i) {
- printf("%-15s "
- "%12lld %12lld %12lld %12lld"
- "%12lld %12lld %12lld %12lld %12lld\n",
- i->first.c_str(),
- (long long)i->second.num_kb,
- (long long)i->second.num_objects,
- (long long)i->second.num_object_clones,
- (long long)i->second.num_objects_degraded,
- (long long)i->second.num_objects_unfound,
- (long long)i->second.num_rd, (long long)i->second.num_rd_kb,
- (long long)i->second.num_wr, (long long)i->second.num_wr_kb);
+ for (map<string, librados::stats_map>::iterator c = stats.begin(); c != stats.end(); ++c) {
+ const string& pool_name = c->first;
+ stats_map& m = c->second;
+ for (stats_map::iterator i = m.begin(); i != m.end(); ++i) {
+ const char *category = (i->first.size() ? i->first.c_str() : "-");
+ printf("%-15s "
+ "%-15s "
+ "%12lld %12lld %12lld %12lld"
+ "%12lld %12lld %12lld %12lld %12lld\n",
+ pool_name.c_str(),
+ category,
+ (long long)i->second.num_kb,
+ (long long)i->second.num_objects,
+ (long long)i->second.num_object_clones,
+ (long long)i->second.num_objects_degraded,
+ (long long)i->second.num_objects_unfound,
+ (long long)i->second.num_rd, (long long)i->second.num_rd_kb,
+ (long long)i->second.num_wr, (long long)i->second.num_wr_kb);
+ }
}
// total
opts["create"] = "true";
} else if (ceph_argparse_witharg(args, i, &val, "-p", "--pool", (char*)NULL)) {
opts["pool"] = val;
+ } else if (ceph_argparse_witharg(args, i, &val, "--category", (char*)NULL)) {
+ opts["category"] = val;
} else if (ceph_argparse_witharg(args, i, &val, "-t", "--concurrent-ios", (char*)NULL)) {
opts["concurrent-ios"] = val;
} else if (ceph_argparse_witharg(args, i, &val, "--block-size", (char*)NULL)) {
/** write an object to the storage device in the appropriate pool
with the given stats */
virtual int put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, time_t *mtime,
- map<std::string, bufferlist>& attrs, bool exclusive) = 0;
+ map<std::string, bufferlist>& attrs, string& category, bool exclusive) = 0;
virtual int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
off_t ofs, size_t len) = 0;
virtual int aio_put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
off_t ofs, size_t len, void **handle) { return -ENOTSUP; }
+
+ /* note that put_obj doesn't set category on an object, only use it for none user objects */
int put_obj(void *ctx, std::string& id, rgw_obj& obj, const char *data, size_t len,
time_t *mtime, map<std::string, bufferlist>& attrs) {
int ret = put_obj_data(ctx, id, obj, data, -1, len);
if (ret >= 0) {
- ret = put_obj_meta(ctx, id, obj, mtime, attrs, false);
+ string category;
+ ret = put_obj_meta(ctx, id, obj, mtime, attrs, category, false);
}
return ret;
}
const time_t *unmod_ptr,
const char *if_match,
const char *if_nomatch,
- map<std::string, bufferlist>& attrs,
+ map<std::string, bufferlist>& attrs,
+ string& category,
struct rgw_err *err) = 0;
/**
* Delete a bucket.
virtual int clone_obj(void *ctx, rgw_obj& dst_obj, off_t dst_ofs,
rgw_obj& src_obj, off_t src_ofs,
uint64_t size, time_t *pmtime,
- map<string, bufferlist> attrs) {
+ map<string, bufferlist> attrs,
+ string& category) {
RGWCloneRangeInfo info;
vector<RGWCloneRangeInfo> v;
info.src = src_obj;
info.dst_ofs = dst_ofs;
info.len = size;
v.push_back(info);
- return clone_objs(ctx, dst_obj, v, attrs, pmtime, true);
+ return clone_objs(ctx, dst_obj, v, attrs, category, pmtime, true);
}
virtual int clone_objs(void *ctx, rgw_obj& dst_obj,
vector<RGWCloneRangeInfo>& ranges,
- map<string, bufferlist> attrs, time_t *pmtime,
+ map<string, bufferlist> attrs,
+ string& category,
+ time_t *pmtime,
bool truncate_dest) { return -ENOTSUP; }
/**
* a simple object read without keeping state
using namespace ceph::crypto;
+string rgw_obj_category_main = "rgw.main";
+string rgw_obj_category_shadow = "rgw.shadow";
+string rgw_obj_category_multimeta = "rgw.multimeta";
+string rgw_obj_category_none;
+
rgw_err::
rgw_err()
{
extern string rgw_root_bucket;
+extern string rgw_obj_category_main;
+extern string rgw_obj_category_shadow;
+extern string rgw_obj_category_multimeta;
+extern string rgw_obj_category_none;
+
#define RGW_ROOT_BUCKET ".rgw"
#define RGW_CONTROL_BUCKET ".rgw.control"
}
int RGWFS::put_obj_meta(void *ctx, std::string& id, rgw_obj& obj,
- time_t *mtime, map<string, bufferlist>& attrs, bool exclusive)
+ time_t *mtime, map<string, bufferlist>& attrs,
+ string& category, bool exclusive)
{
std::string& bucket = obj.bucket;
std::string& oid = obj.object;
const char *if_match,
const char *if_nomatch,
map<string, bufferlist>& attrs,
+ string& category,
struct rgw_err *err)
{
int ret;
int create_bucket(std::string& id, std::string& bucket, map<std::string, bufferlist>& attrs, bool exclusive, uint64_t auid=0);
int put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, time_t *mtime,
- map<std::string, bufferlist>& attrs, bool exclusive);
+ map<std::string, bufferlist>& attrs, string& category, bool exclusive);
int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
off_t ofs, size_t size);
int copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj,
const char *if_match,
const char *if_nomatch,
map<std::string, bufferlist>& attrs,
+ string& category,
struct rgw_err *err);
int delete_bucket(std::string& id, std::string& bucket);
int delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync);
if (!multipart) {
rgw_obj dst_obj(s->bucket_str, s->object_str);
rgwstore->set_atomic(s->obj_ctx, dst_obj);
- ret = rgwstore->clone_obj(s->obj_ctx, dst_obj, 0, obj, 0, s->obj_size, NULL, attrs);
+ ret = rgwstore->clone_obj(s->obj_ctx, dst_obj, 0, obj, 0, s->obj_size, NULL, attrs, rgw_obj_category_main);
if (ret < 0)
goto done_err;
if (created_obj) {
goto done;
}
} else {
- ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, NULL, attrs, false);
+ ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, NULL, attrs, rgw_obj_category_main, false);
if (ret < 0)
goto done_err;
rgw_obj meta_obj(s->bucket_str, multipart_meta_obj, s->object_str, mp_ns);
- ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, meta_obj, NULL, meta_attrs, false);
+ ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, meta_obj, NULL, meta_attrs, rgw_obj_category_multimeta, false);
}
}
done:
unmod_ptr,
if_match,
if_nomatch,
- attrs, &s->err);
+ attrs, rgw_obj_category_main, &s->err);
done:
send_response();
tmp_obj_name = mp.get_meta();
obj.init(s->bucket_str, tmp_obj_name, s->object_str, mp_ns);
- ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, NULL, attrs, true);
+ ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, NULL, attrs, rgw_obj_category_multimeta, true);
} while (ret == -EEXIST);
done:
send_response();
target_obj.init(s->bucket_str, s->object_str);
rgwstore->set_atomic(s->obj_ctx, target_obj);
- ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, target_obj, NULL, attrs, false);
+ ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, target_obj, NULL, attrs, rgw_obj_category_main, false);
if (ret < 0)
goto done;
ofs += obj_iter->second.size;
}
- ret = rgwstore->clone_objs(s->obj_ctx, target_obj, ranges, attrs, NULL, true);
+ ret = rgwstore->clone_objs(s->obj_ctx, target_obj, ranges, attrs, rgw_obj_category_main, NULL, true);
if (ret < 0)
goto done;
static string notify_oid = "notify";
static string shadow_ns = "shadow";
+static string shadow_category = "rgw.shadow";
+static string main_category = "rgw.main";
+
class RGWWatcher : public librados::WatchCtx {
RGWRados *rados;
public:
* Returns: 0 on success, -ERR# otherwise.
*/
int RGWRados::put_obj_meta(void *ctx, std::string& id, rgw_obj& obj,
- time_t *mtime, map<string, bufferlist>& attrs, bool exclusive)
+ time_t *mtime, map<string, bufferlist>& attrs, string& category, bool exclusive)
{
std::string& bucket = obj.bucket;
std::string& oid = obj.object;
ObjectWriteOperation op;
- if (exclusive) {
- op.create(true);
- }
+ if (category.size())
+ op.create(exclusive, category);
+ else
+ op.create(exclusive);
map<string, bufferlist>::iterator iter;
for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
* err: stores any errors resulting from the get of the original object
* Returns: 0 on success, -ERR# otherwise.
*/
-int RGWRados::copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj,
+int RGWRados::copy_obj(void *ctx, std::string& id,
+ rgw_obj& dest_obj,
rgw_obj& src_obj,
time_t *mtime,
const time_t *mod_ptr,
const char *if_match,
const char *if_nomatch,
map<string, bufferlist>& attrs, /* in/out */
+ string& category,
struct rgw_err *err)
{
int ret, r;
}
attrs = attrset;
- ret = clone_obj(ctx, dest_obj, 0, tmp_obj, 0, end + 1, NULL, attrs);
+ ret = clone_obj(ctx, dest_obj, 0, tmp_obj, 0, end + 1, NULL, attrs, category);
if (mtime)
obj_stat(ctx, tmp_obj, NULL, mtime);
/* FIXME: clone obj should be conditional, should check src object id-tag */
pair<string, bufferlist> cond(RGW_ATTR_ID_TAG, state->obj_tag);
- r = clone_obj_cond(NULL, dest_obj, 0, obj, 0, state->size, state->attrset, &state->mtime, &cond);
+ r = clone_obj_cond(NULL, dest_obj, 0, obj, 0, state->size, state->attrset, shadow_category, &state->mtime, &cond);
if (r == -ECANCELED) {
/* we lost in a race here, original object was replaced, we assume it was cloned
as required */
int RGWRados::clone_objs(void *ctx, rgw_obj& dst_obj,
vector<RGWCloneRangeInfo>& ranges,
map<string, bufferlist> attrs,
+ string& category,
time_t *pmtime,
bool truncate_dest,
pair<string, bufferlist> *xattr_cond)
io_ctx.locator_set_key(dst_obj.key);
ObjectWriteOperation op;
- op.create(false);
+
+ if (category.size())
+ op.create(false, category);
+ else
+ op.create(false);
+
if (truncate_dest)
op.truncate(0);
+
map<string, bufferlist>::iterator iter;
for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
const string& name = iter->first;
string bucket_name = iter->first;
buckets_list.push_back(bucket_name);
}
- map<std::string,librados::pool_stat_t> stats;
- int r = rados->get_pool_stats(buckets_list, stats);
+ map<std::string,librados::stats_map> sm;
+ int r = rados->get_pool_stats(buckets_list, rgw_obj_category_main, sm);
if (r < 0)
return r;
- map<string,pool_stat_t>::iterator stats_iter = stats.begin();
+ map<string, librados::stats_map>::iterator miter;
- for (iter = m.begin(); iter != m.end(); ++iter) {
- string bucket_name = iter->first;
- if (stats_iter->first.compare(bucket_name) == 0) {
- RGWBucketEnt& ent = iter->second;
- pool_stat_t stat = stats_iter->second;
- ent.count = stat.num_objects;
- ent.size = stat.num_bytes;
- stats_iter++;
- count++;
- }
+ for (miter = sm.begin(), iter = m.begin(); miter != sm.end(), iter != m.end(); ++iter, ++miter) {
+ stats_map stats = miter->second;
+ stats_map::iterator stats_iter = stats.begin();
+
+ string bucket_name = miter->first;
+ RGWBucketEnt& ent = iter->second;
+ if (bucket_name.compare(ent.name) != 0)
+ continue;
+
+ pool_stat_t stat = stats_iter->second;
+ ent.count = stat.num_objects;
+ ent.size = stat.num_bytes;
+ count++;
}
return count;
/** Write/overwrite an object to the bucket storage. */
virtual int put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, time_t *mtime,
- map<std::string, bufferlist>& attrs, bool exclusive);
+ map<std::string, bufferlist>& attrs, string& category, bool exclusive);
virtual int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
off_t ofs, size_t len);
virtual int aio_put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
virtual bool aio_completed(void *handle);
virtual int clone_objs(void *ctx, rgw_obj& dst_obj,
vector<RGWCloneRangeInfo>& ranges,
- map<string, bufferlist> attrs, time_t *pmtime, bool truncate_dest) {
- return clone_objs(ctx, dst_obj, ranges, attrs, pmtime, truncate_dest, NULL);
+ map<string, bufferlist> attrs,
+ string& category,
+ time_t *pmtime, bool truncate_dest) {
+ return clone_objs(ctx, dst_obj, ranges, attrs, category, pmtime, truncate_dest, NULL);
}
int clone_objs(void *ctx, rgw_obj& dst_obj,
vector<RGWCloneRangeInfo>& ranges,
map<string, bufferlist> attrs,
+ string& category,
time_t *pmtime,
bool truncate_dest,
pair<string, bufferlist> *cmp_xattr);
int clone_obj_cond(void *ctx, rgw_obj& dst_obj, off_t dst_ofs,
rgw_obj& src_obj, off_t src_ofs,
uint64_t size, map<string, bufferlist> attrs,
+ string& category,
time_t *pmtime,
pair<string, bufferlist> *xattr_cond) {
RGWCloneRangeInfo info;
info.dst_ofs = dst_ofs;
info.len = size;
v.push_back(info);
- return clone_objs(ctx, dst_obj, v, attrs, pmtime, true, xattr_cond);
+ return clone_objs(ctx, dst_obj, v, attrs, category, pmtime, true, xattr_cond);
}
/** Copy an object, with many extra options */
const char *if_match,
const char *if_nomatch,
map<std::string, bufferlist>& attrs,
+ string& category,
struct rgw_err *err);
/** delete a bucket*/
virtual int delete_bucket(std::string& id, std::string& bucket);