static void update_olh_log(struct rgw_bucket_olh_entry& olh_data_entry, OLHLogOp op, const string& op_tag,
cls_rgw_obj_key& key, bool delete_marker)
{
- rgw_bucket_olh_log_entry& log_entry = olh_data_entry.pending_log[olh_data_entry.epoch];
+ vector<rgw_bucket_olh_log_entry>& log = olh_data_entry.pending_log[olh_data_entry.epoch];
+ rgw_bucket_olh_log_entry log_entry;
log_entry.epoch = olh_data_entry.epoch;
log_entry.op = op;
log_entry.op_tag = op_tag;
log_entry.key = key;
log_entry.delete_marker = delete_marker;
+ log.push_back(log_entry);
}
static string escape_str(const string& s)
rgw_cls_read_olh_log_ret op_ret;
#define MAX_OLH_LOG_ENTRIES 1000
- map<uint64_t, rgw_bucket_olh_log_entry>& log = olh_data_entry.pending_log;
+ map<uint64_t, vector<rgw_bucket_olh_log_entry> >& log = olh_data_entry.pending_log;
if (log.begin()->first > op.ver_marker && log.size() <= MAX_OLH_LOG_ENTRIES) {
op_ret.log = log;
op_ret.is_truncated = false;
} else {
- map<uint64_t, rgw_bucket_olh_log_entry>::iterator iter = log.upper_bound(op.ver_marker);
+ map<uint64_t, vector<rgw_bucket_olh_log_entry> >::iterator iter = log.upper_bound(op.ver_marker);
for (int i = 0; i < MAX_OLH_LOG_ENTRIES && iter != log.end(); ++i, ++iter) {
op_ret.log[iter->first] = iter->second;
}
/* remove all versions up to and including ver from the pending map */
- map<uint64_t, rgw_bucket_olh_log_entry>& log = olh_data_entry.pending_log;
- map<uint64_t, rgw_bucket_olh_log_entry>::iterator liter = log.begin();
+ map<uint64_t, vector<rgw_bucket_olh_log_entry> >& log = olh_data_entry.pending_log;
+ map<uint64_t, vector<rgw_bucket_olh_log_entry> >::iterator liter = log.begin();
while (liter != log.end() && liter->first <= op.ver) {
- map<uint64_t, rgw_bucket_olh_log_entry>::iterator rm_iter = liter;
+ map<uint64_t, vector<rgw_bucket_olh_log_entry> >::iterator rm_iter = liter;
++liter;
log.erase(rm_iter);
}
int cls_rgw_get_olh_log(IoCtx& io_ctx, string& oid, librados::ObjectReadOperation& op, const cls_rgw_obj_key& olh, uint64_t ver_marker,
const string& olh_tag,
- map<uint64_t, struct rgw_bucket_olh_log_entry> *log, bool *is_truncated)
+ map<uint64_t, vector<struct rgw_bucket_olh_log_entry> > *log, bool *is_truncated)
{
bufferlist in, out;
struct rgw_cls_read_olh_log_op call;
int cls_rgw_bucket_unlink_instance(librados::IoCtx& io_ctx, const string& oid, const cls_rgw_obj_key& key, const string& op_tag);
int cls_rgw_get_olh_log(librados::IoCtx& io_ctx, string& oid, librados::ObjectReadOperation& op, const cls_rgw_obj_key& olh, uint64_t ver_marker,
const string& olh_tag,
- map<uint64_t, struct rgw_bucket_olh_log_entry> *log, bool *is_truncated);
+ map<uint64_t, vector<struct rgw_bucket_olh_log_entry> > *log, bool *is_truncated);
void cls_rgw_trim_olh_log(librados::ObjectWriteOperation& op, string& oid, const cls_rgw_obj_key& olh, uint64_t ver, const string& olh_tag);
int cls_rgw_bucket_check_index_op(librados::IoCtx& io_ctx, string& oid,
list<rgw_bucket_olh_log_entry *> l;
rgw_bucket_olh_log_entry::generate_test_instances(l);
list<rgw_bucket_olh_log_entry *>::iterator iter = l.begin();
- r->log[1] = *(*iter);
+ r->log[1].push_back(*(*iter));
o.push_back(r);
struct rgw_cls_read_olh_log_ret
{
- map<uint64_t, struct rgw_bucket_olh_log_entry> log;
+ map<uint64_t, vector<struct rgw_bucket_olh_log_entry> > log;
bool is_truncated;
rgw_cls_read_olh_log_ret() : is_truncated(false) {}
cls_rgw_obj_key key;
bool delete_marker;
uint64_t epoch;
- map<uint64_t, struct rgw_bucket_olh_log_entry> pending_log;
+ map<uint64_t, vector<struct rgw_bucket_olh_log_entry> > pending_log;
string tag;
bool exists;
}
}
+template<class T>
+void decode_json_obj(vector<T>& l, JSONObj *obj)
+{
+ l.clear();
+
+ JSONObjIter iter = obj->find_first();
+
+ for (; !iter.end(); ++iter) {
+ T val;
+ JSONObj *o = *iter;
+ decode_json_obj(val, o);
+ l.push_back(val);
+ }
+}
+
template<class K, class V>
void decode_json_obj(map<K, V>& m, JSONObj *obj)
{
f->close_section();
}
+template<class T>
+static void encode_json(const char *name, const std::vector<T>& l, ceph::Formatter *f)
+{
+ f->open_array_section(name);
+ for (typename std::vector<T>::const_iterator iter = l.begin(); iter != l.end(); ++iter) {
+ encode_json("obj", *iter, f);
+ }
+ f->close_section();
+}
+
template<class K, class V>
void encode_json_map(const char *name, const map<K, V>& m, ceph::Formatter *f)
{
}
if (opt_cmd == OPT_OLH_READLOG) {
- map<uint64_t, rgw_bucket_olh_log_entry> log;
+ map<uint64_t, vector<rgw_bucket_olh_log_entry> > log;
bool is_truncated;
RGWObjectCtx rctx(store);
}
int RGWRados::bucket_index_read_olh_log(RGWObjState& state, rgw_obj& obj_instance, uint64_t ver_marker,
- map<uint64_t, rgw_bucket_olh_log_entry> *log,
+ map<uint64_t, vector<rgw_bucket_olh_log_entry> > *log,
bool *is_truncated)
{
rgw_rados_ref ref;
}
int RGWRados::apply_olh_log(RGWObjectCtx& obj_ctx, RGWObjState& state, const string& bucket_owner, rgw_obj& obj,
- bufferlist& olh_tag, map<uint64_t, rgw_bucket_olh_log_entry>& log,
+ bufferlist& olh_tag, map<uint64_t, vector<rgw_bucket_olh_log_entry> >& log,
uint64_t *plast_ver)
{
if (log.empty()) {
uint64_t last_ver = log.rbegin()->first;
*plast_ver = last_ver;
- map<uint64_t, rgw_bucket_olh_log_entry>::iterator iter = log.begin();
+ map<uint64_t, vector<rgw_bucket_olh_log_entry> >::iterator iter = log.begin();
op.cmpxattr(RGW_ATTR_OLH_ID_TAG, CEPH_OSD_CMPXATTR_OP_EQ, olh_tag);
op.cmpxattr(RGW_ATTR_OLH_VER, CEPH_OSD_CMPXATTR_OP_GT, last_ver);
list<cls_rgw_obj_key> remove_instances;
for (iter = log.begin(); iter != log.end(); ++iter) {
- rgw_bucket_olh_log_entry& entry = iter->second;
- ldout(cct, 20) << "olh_log_entry: op=" << (int)entry.op
- << " key=" << entry.key.name << "[" << entry.key.instance << "] "
- << (entry.delete_marker ? "(delete)" : "") << dendl;
- switch (entry.op) {
- case CLS_RGW_OLH_OP_REMOVE_INSTANCE:
- remove_instances.push_back(entry.key);
- break;
- case CLS_RGW_OLH_OP_LINK_OLH:
- need_to_link = true;
- key = entry.key;
- delete_marker = entry.delete_marker;
- break;
- case CLS_RGW_OLH_OP_UNLINK_OLH:
- /* treat this as linking into a delete marker */
- need_to_link = true;
- key = entry.key;
- delete_marker = true;
- break;
- default:
- ldout(cct, 0) << "ERROR: apply_olh_log: invalid op: " << (int)entry.op << dendl;
- return -EIO;
+ vector<rgw_bucket_olh_log_entry>::iterator viter = iter->second.begin();
+ for (; viter != iter->second.end(); ++viter) {
+ rgw_bucket_olh_log_entry& entry = *viter;
+ ldout(cct, 20) << "olh_log_entry: op=" << (int)entry.op
+ << " key=" << entry.key.name << "[" << entry.key.instance << "] "
+ << (entry.delete_marker ? "(delete)" : "") << dendl;
+ switch (entry.op) {
+ case CLS_RGW_OLH_OP_REMOVE_INSTANCE:
+ remove_instances.push_back(entry.key);
+ break;
+ case CLS_RGW_OLH_OP_LINK_OLH:
+ need_to_link = true;
+ key = entry.key;
+ delete_marker = entry.delete_marker;
+ break;
+ case CLS_RGW_OLH_OP_UNLINK_OLH:
+ /* treat this as linking into a delete marker */
+ need_to_link = true;
+ key = entry.key;
+ delete_marker = true;
+ break;
+ default:
+ ldout(cct, 0) << "ERROR: apply_olh_log: invalid op: " << (int)entry.op << dendl;
+ return -EIO;
+ }
+ string attr_name = RGW_ATTR_OLH_PENDING_PREFIX;
+ attr_name.append(entry.op_tag);
+ op.rmxattr(attr_name.c_str());
}
- string attr_name = RGW_ATTR_OLH_PENDING_PREFIX;
- attr_name.append(entry.op_tag);
- op.rmxattr(attr_name.c_str());
}
rgw_rados_ref ref;
*/
int RGWRados::update_olh(RGWObjectCtx& obj_ctx, RGWObjState *state, const string& bucket_owner, rgw_obj& obj)
{
- map<uint64_t, rgw_bucket_olh_log_entry> log;
+ map<uint64_t, vector<rgw_bucket_olh_log_entry> > log;
bool is_truncated;
uint64_t ver_marker = 0;
const string& op_tag, struct rgw_bucket_dir_entry_meta *meta);
int bucket_index_unlink_instance(rgw_obj& obj_instance, const string& op_tag);
int bucket_index_read_olh_log(RGWObjState& state, rgw_obj& obj_instance, uint64_t ver_marker,
- map<uint64_t, rgw_bucket_olh_log_entry> *log, bool *is_truncated);
+ map<uint64_t, vector<rgw_bucket_olh_log_entry> > *log, bool *is_truncated);
int bucket_index_trim_olh_log(RGWObjState& obj_state, rgw_obj& obj_instance, uint64_t ver);
int apply_olh_log(RGWObjectCtx& ctx, RGWObjState& obj_state, const string& bucket_owner, rgw_obj& obj,
- bufferlist& obj_tag, map<uint64_t, rgw_bucket_olh_log_entry>& log,
+ bufferlist& obj_tag, map<uint64_t, vector<rgw_bucket_olh_log_entry> >& log,
uint64_t *plast_ver);
int update_olh(RGWObjectCtx& obj_ctx, RGWObjState *state, const string& bucket_owner, rgw_obj& obj);
int set_olh(RGWObjectCtx& obj_ctx, const string& bucket_owner, rgw_obj& target_obj, bool delete_marker, rgw_bucket_dir_entry_meta *meta);