return (size + ROUND_BLOCK_SIZE - 1) & ~(ROUND_BLOCK_SIZE - 1);
}
-static int read_bucket_dir(cls_method_context_t hctx, struct rgw_bucket_dir& dir)
-{
- bufferlist bl;
-
- uint64_t size;
- int rc = cls_cxx_stat(hctx, &size, NULL);
- if (rc < 0)
- return rc;
-
- rc = cls_cxx_map_read_full(hctx, &bl);
- if (rc < 0)
- return rc;
-
- try {
- bufferlist::iterator iter = bl.begin();
- bufferlist header_bl;
- ::decode(header_bl, iter);
- bufferlist::iterator header_iter = header_bl.begin();
- ::decode(dir.header, header_iter);
- __u32 nkeys = 0;
- ::decode(nkeys, iter);
- while (nkeys) {
- string key;
- bufferlist value;
- ::decode(key, iter);
- ::decode(value, iter);
- bufferlist::iterator val_iter = value.begin();
- ::decode(dir.m[key], val_iter);
- --nkeys;
- }
- } catch (buffer::error& err) {
- CLS_LOG("ERROR: read_bucket_dir(): failed to decode buffer\n");
- return -EIO;
- }
-
- return 0;
-}
-
int rgw_bucket_list(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
{
- bufferlist bl;
- struct rgw_bucket_dir dir;
- int rc = read_bucket_dir(hctx, dir);
- if (rc < 0)
- return rc;
-
bufferlist::iterator iter = in->begin();
struct rgw_cls_list_op op;
-
try {
::decode(op, iter);
} catch (buffer::error& err) {
struct rgw_cls_list_ret ret;
struct rgw_bucket_dir& new_dir = ret.dir;
- new_dir.header = dir.header;
+ bufferlist header_bl;
+ int rc = cls_cxx_map_read_header(hctx, &header_bl);
+ if (rc < 0)
+ return rc;
+ bufferlist::iterator header_iter = header_bl.begin();
+ try {
+ ::decode(new_dir.header, header_iter);
+ } catch (buffer::error& err) {
+ CLS_LOG("ERROR: rgw_bucket_complete_op(): failed to decode header\n");
+ return -EINVAL;
+ }
+
+ bufferlist bl;
+
+ map<string, bufferlist> keys;
+ rc = cls_cxx_map_read_keys(hctx, op.start_obj, op.num_entries + 1, &keys);
+ if (rc < 0)
+ return rc;
+
std::map<string, struct rgw_bucket_dir_entry>& m = new_dir.m;
- std::map<string, struct rgw_bucket_dir_entry>::iterator miter = dir.m.upper_bound(op.start_obj);
+ std::map<string, bufferlist>::iterator kiter = keys.begin();
uint32_t i;
- for (i = 0; i != op.num_entries && miter != dir.m.end(); ++i, ++miter) {
- m[miter->first] = miter->second;
+
+ for (i = 0; i < op.num_entries && kiter != keys.end(); ++i, ++kiter) {
+ struct rgw_bucket_dir_entry entry;
+ bufferlist& entrybl = kiter->second;
+ bufferlist::iterator eiter = entrybl.begin();
+ try {
+ ::decode(entry, eiter);
+ } catch (buffer::error& err) {
+ CLS_LOG("ERROR: rgw_bucket_list(): failed to decode entry, key=%s\n", kiter->first.c_str());
+ return -EINVAL;
+ }
+
+ m[kiter->first] = entry;
}
- ret.is_truncated = (miter != dir.m.end());
+ ret.is_truncated = (kiter != keys.end());
::encode(ret, *out);
bufferlist bl;
bufferlist::iterator iter;
- uint64_t size;
- int rc = cls_cxx_stat(hctx, &size, NULL);
- if (rc < 0)
- return rc;
- if (size != 0) {
+ bufferlist header_bl;
+ int rc = cls_cxx_map_read_header(hctx, &header_bl);
+ if (rc < 0) {
+ switch (rc) {
+ case -ENODATA:
+ case -ENOENT:
+ break;
+ default:
+ return rc;
+ }
+ }
+
+ if (header_bl.length() != 0) {
CLS_LOG("ERROR: index already initialized\n");
- return -EINVAL;
}
rgw_bucket_dir dir;
- bufferlist map_bl;
- bufferlist header_bl;
::encode(dir.header, header_bl);
- ::encode(header_bl, map_bl);
- __u32 num_keys = 0;
- ::encode(num_keys, map_bl);
- rc = cls_cxx_map_write_full(hctx, &map_bl);
+ rc = cls_cxx_map_write_header(hctx, &header_bl);
return rc;
}
if (rc < 0)
return rc;
bufferlist::iterator header_iter = header_bl.begin();
- ::decode(header, header_iter);
+ try {
+ ::decode(header, header_iter);
+ } catch (buffer::error& err) {
+ CLS_LOG("ERROR: rgw_bucket_complete_op(): failed to decode header\n");
+ return -EINVAL;
+ }
bufferlist current_entry;
struct rgw_bucket_dir_entry entry;
} else {
bufferlist::iterator cur_iter = current_entry.begin();
::decode(entry, cur_iter);
- CLS_LOG("rgw_bucket_complete_op(): existing entry: epoch=%lld\n", entry.epoch);
+ CLS_LOG("rgw_bucket_complete_op(): existing entry: epoch=%lld name=%s locator=%s\n", entry.epoch, entry.name.c_str(), entry.locator.c_str());
}
if (op.tag.size()) {
case CLS_RGW_OP_DEL:
if (ondisk) {
if (!entry.pending_map.size()) {
- op_bl.append(CEPH_OSD_TMAP_RM);
- ::encode(op.name, op_bl);
+ int ret = cls_cxx_map_remove_key(hctx, op.name);
+ if (ret < 0)
+ return ret;
} else {
entry.exists = false;
bufferlist new_key_bl;
::encode(entry, new_key_bl);
- op_bl.append(CEPH_OSD_TMAP_SET);
- ::encode(op.name, op_bl);
- ::encode(new_key_bl, op_bl);
+ int ret = cls_cxx_map_write_key(hctx, op.name, &new_key_bl);
+ if (ret < 0)
+ return ret;
}
} else {
return -ENOENT;
stats.total_size_rounded += get_rounded_size(meta.size);
bufferlist new_key_bl;
::encode(entry, new_key_bl);
- op_bl.append(CEPH_OSD_TMAP_SET);
- ::encode(op.name, op_bl);
- ::encode(new_key_bl, op_bl);
+ int ret = cls_cxx_map_write_key(hctx, op.name, &new_key_bl);
+ if (ret < 0)
+ return ret;
}
break;
}
- bufferlist update_bl;
bufferlist new_header_bl;
::encode(header, new_header_bl);
- update_bl.append(CEPH_OSD_TMAP_HDR);
- ::encode(new_header_bl, update_bl);
- update_bl.claim_append(op_bl);
- return cls_cxx_map_update(hctx, &update_bl);
+ return cls_cxx_map_write_header(hctx, &new_header_bl);
}
int rgw_dir_suggest_changes(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
}
}
+ int ret = 0;
+
if (cur_disk.pending_map.empty()) {
struct rgw_bucket_category_stats& stats =
header.stats[cur_disk.meta.category];
}
switch(op) {
case CEPH_RGW_REMOVE:
- op_bl.append(CEPH_OSD_TMAP_RM);
- ::encode(cur_change.name, op_bl);
+ ret = cls_cxx_map_remove_key(hctx, cur_change.name);
+ if (ret < 0)
+ return ret;
break;
case CEPH_RGW_UPDATE:
stats.num_entries++;
stats.total_size_rounded += get_rounded_size(cur_change.meta.size);
bufferlist cur_state_bl;
::encode(cur_change, cur_state_bl);
- op_bl.append(CEPH_OSD_TMAP_SET);
- ::encode(cur_state_bl, op_bl);
+ ret = cls_cxx_map_write_key(hctx, cur_change.name, &cur_state_bl);
+ if (ret < 0)
+ return ret;
break;
}
}
if (header_changed) {
bufferlist new_header_bl;
::encode(header, new_header_bl);
- update_bl.append(CEPH_OSD_TMAP_HDR);
- ::encode(new_header_bl, update_bl);
+ return cls_cxx_map_write_header(hctx, &new_header_bl);
}
- update_bl.claim_append(op_bl);
- return cls_cxx_map_update(hctx, &update_bl);
+ return 0;
}
void __cls_init()
return (*pctx)->pg->do_osd_ops(*pctx, ops);
}
-int cls_cxx_map_read_full(cls_method_context_t hctx, bufferlist* outbl)
+int cls_cxx_map_read_all_keys(cls_method_context_t hctx, map<string, bufferlist>* vals)
{
ReplicatedPG::OpContext **pctx = (ReplicatedPG::OpContext **)hctx;
vector<OSDOp> ops(1);
+ OSDOp& op = ops[0];
int ret;
- ops[0].op.op = CEPH_OSD_OP_TMAPGET;
+
+ string start_after;
+ uint64_t max = (uint64_t)-1;
+ bufferlist inbl;
+
+ ::encode(start_after, op.indata);
+ ::encode(max, op.indata);
+
+ op.op.op = CEPH_OSD_OP_OMAPGETVALS;
+
ret = (*pctx)->pg->do_osd_ops(*pctx, ops);
if (ret < 0)
return ret;
- outbl->claim(ops[0].outdata);
- return outbl->length();
+
+ bufferlist::iterator iter = op.outdata.begin();
+ try {
+ ::decode(*vals, iter);
+ } catch (buffer::error& err) {
+ return -EIO;
+ }
+ return vals->size();
}
-int cls_cxx_map_read_header(cls_method_context_t hctx, bufferlist *outbl)
+int cls_cxx_map_read_keys(cls_method_context_t hctx, string& start_obj, uint64_t max, map<string, bufferlist>* vals)
{
ReplicatedPG::OpContext **pctx = (ReplicatedPG::OpContext **)hctx;
vector<OSDOp> ops(1);
+ OSDOp& op = ops[0];
int ret;
- ops[0].op.op = CEPH_OSD_OP_TMAPGET;
+
+ string start_after;
+ bufferlist inbl;
+
+ ::encode(start_obj, op.indata);
+ ::encode(max, op.indata);
+
+ op.op.op = CEPH_OSD_OP_OMAPGETVALS;
+
ret = (*pctx)->pg->do_osd_ops(*pctx, ops);
if (ret < 0)
return ret;
+ bufferlist::iterator iter = op.outdata.begin();
try {
- //decode and return the header
- bufferlist::iterator map_iter = ops[0].outdata.begin();
- ::decode(*outbl, map_iter);
- } catch (buffer::error& e) {
- return -EINVAL;
+ ::decode(*vals, iter);
+ } catch (buffer::error& err) {
+ return -EIO;
}
+ return vals->size();
+}
+
+int cls_cxx_map_read_header(cls_method_context_t hctx, bufferlist *outbl)
+{
+ ReplicatedPG::OpContext **pctx = (ReplicatedPG::OpContext **)hctx;
+ vector<OSDOp> ops(1);
+ OSDOp& op = ops[0];
+ int ret;
+ op.op.op = CEPH_OSD_OP_OMAPGETHEADER;
+ ret = (*pctx)->pg->do_osd_ops(*pctx, ops);
+ if (ret < 0)
+ return ret;
+
+ outbl->claim(op.outdata);
+
return 0;
}
int cls_cxx_map_read_key(cls_method_context_t hctx, string key, bufferlist *outbl)
{
ReplicatedPG::OpContext **pctx = (ReplicatedPG::OpContext **)hctx;
vector<OSDOp> ops(1);
+ OSDOp& op = ops[0];
int ret;
- ops[0].op.op = CEPH_OSD_OP_TMAPGET;
+
+ set<string> k;
+ k.insert(key);
+ ::encode(k, op.indata);
+
+ op.op.op = CEPH_OSD_OP_OMAPGETVALSBYKEYS;
ret = (*pctx)->pg->do_osd_ops(*pctx, ops);
if (ret < 0)
return ret;
- //find and return just the requested key!
- bufferlist header;
- string next_key;
- bufferlist next_val;
- __u32 nkeys;
- bufferlist::iterator map_iter = ops[0].outdata.begin();
+ bufferlist::iterator iter = op.outdata.begin();
try {
- ::decode(header, map_iter);
- ::decode(nkeys, map_iter);
- while (nkeys) {
- ::decode(next_key, map_iter);
- ::decode(next_val, map_iter);
- if (next_key == key) {
- *outbl = next_val;
- return 0;
- }
- if (next_key > key)
- return -ENOENT;
- --nkeys;
- }
+ map<string, bufferlist> m;
+
+ ::decode(m, iter);
+ map<string, bufferlist>::iterator iter = m.begin();
+ if (iter == m.end())
+ return -ENOENT;
+
+ *outbl = iter->second;
} catch (buffer::error& e) {
- return -EINVAL;
+ return -EIO;
}
- return -ENOENT;
+ return 0;
}
-int cls_cxx_map_write_full(cls_method_context_t hctx, bufferlist* inbl)
+int cls_cxx_map_write_key(cls_method_context_t hctx, string key, bufferlist *inbl)
{
ReplicatedPG::OpContext **pctx = (ReplicatedPG::OpContext **)hctx;
vector<OSDOp> ops(1);
- ops[0].op.op = CEPH_OSD_OP_TMAPPUT;
- ops[0].indata = *inbl;
- return (*pctx)->pg->do_osd_ops(*pctx, ops);
-}
+ OSDOp& op = ops[0];
+ bufferlist& update_bl = op.indata;
+ map<string, bufferlist> m;
+ m[key] = *inbl;
+ ::encode(m, update_bl);
-int cls_cxx_map_write_key(cls_method_context_t hctx, string key, bufferlist *inbl)
-{
- bufferlist update_bl;
- update_bl.append(CEPH_OSD_TMAP_SET);
- ::encode(key, update_bl);
- ::encode(*inbl, update_bl);
- return cls_cxx_map_update(hctx, &update_bl);
+ op.op.op = CEPH_OSD_OP_OMAPSETVALS;
+
+ return (*pctx)->pg->do_osd_ops(*pctx, ops);
}
int cls_cxx_map_write_header(cls_method_context_t hctx, bufferlist *inbl)
{
- ReplicatedPG::OpContext **pctx = static_cast<ReplicatedPG::OpContext **>(hctx);
+ ReplicatedPG::OpContext **pctx = (ReplicatedPG::OpContext **)hctx;
vector<OSDOp> ops(1);
- bufferlist update_bl;
- update_bl.append(CEPH_OSD_TMAP_HDR);
+ OSDOp& op = ops[0];
+ bufferlist& update_bl = op.indata;
::encode(*inbl, update_bl);
- ops[0].op.op = CEPH_OSD_OP_TMAPUP;
- ops[0].indata = update_bl;
+ op.op.op = CEPH_OSD_OP_OMAPSETHEADER;
return (*pctx)->pg->do_osd_ops(*pctx, ops);
}
int cls_cxx_map_remove_key(cls_method_context_t hctx, string key)
-{
- bufferlist update_bl;
- update_bl.append(CEPH_OSD_TMAP_RM);
- ::encode(key, update_bl);
- return cls_cxx_map_update(hctx, &update_bl);
-}
-
-int cls_cxx_map_update(cls_method_context_t hctx, bufferlist* inbl)
{
ReplicatedPG::OpContext **pctx = (ReplicatedPG::OpContext **)hctx;
vector<OSDOp> ops(1);
- ops[0].op.op = CEPH_OSD_OP_TMAPUP;
- ops[0].indata = *inbl;
+ OSDOp& op = ops[0];
+ bufferlist& update_bl = op.indata;
+ set<string> to_rm;
+ to_rm.insert(key);
+
+ ::encode(to_rm, update_bl);
return (*pctx)->pg->do_osd_ops(*pctx, ops);
}
+