return ((unsigned char)s[0] != BI_PREFIX_CHAR);
}
-static int bi_entry_type(const string& s)
+int bi_entry_type(const string& s)
{
if (bi_is_objs_index(s)) {
return BI_BUCKET_OBJS_INDEX;
*key = buf;
}
-static void bi_log_index_key(string& key, utime_t& t, string& obj)
+static void get_index_ver_key(cls_method_context_t hctx, uint64_t index_ver, string *key)
+{
+ char buf[48];
+ snprintf(buf, sizeof(buf), "%011llu.%llu.%d", (unsigned long long)index_ver,
+ (unsigned long long)cls_current_version(hctx),
+ cls_current_subop_num(hctx));
+ *key = buf;
+}
+
+static void bi_log_index_key(cls_method_context_t hctx, string& key, uint64_t index_ver)
{
key = BI_PREFIX_CHAR;
key.append(bucket_index_prefixes[BI_BUCKET_LOG_INDEX]);
- string tk;
- get_time_key(t, &tk);
- key.append(tk);
+ string k;
+ get_index_ver_key(hctx, index_ver, &k);
+ key.append(k);
}
-static int log_index_operation(cls_method_context_t hctx, string& obj, RGWModifyOp op, rgw_bucket_entry_ver& ver, RGWPendingState state)
+static int log_index_operation(cls_method_context_t hctx, string& obj, RGWModifyOp op, rgw_bucket_entry_ver& ver, RGWPendingState state, uint64_t index_ver)
{
bufferlist bl;
entry.op = op;
entry.ver = ver;
entry.state = state;
+ entry.index_ver = index_ver;
::encode(entry, bl);
string key;
- bi_log_index_key(key, entry.timestamp, obj);
+ bi_log_index_key(hctx, key, index_ver);
return cls_cxx_map_set_val(hctx, key, &bl);
}
}
calc_header->tag_timeout = existing_header->tag_timeout;
+ calc_header->ver = existing_header->ver;
bufferlist bl;
return 0;
}
+static int write_bucket_header(cls_method_context_t hctx, struct rgw_bucket_dir_header *header)
+{
+ header->ver++;
+
+ bufferlist header_bl;
+ ::encode(*header, header_bl);
+ return cls_cxx_map_write_header(hctx, &header_bl);
+}
+
+
int rgw_bucket_rebuild_index(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
{
struct rgw_bucket_dir_header existing_header;
if (rc < 0)
return rc;
- bufferlist header_bl;
- ::encode(calc_header, header_bl);
- rc = cls_cxx_map_write_header(hctx, &header_bl);
- return rc;
+ return write_bucket_header(hctx, &calc_header);
}
}
rgw_bucket_dir dir;
- ::encode(dir.header, header_bl);
- rc = cls_cxx_map_write_header(hctx, &header_bl);
- return rc;
+
+ return write_bucket_header(hctx, &dir.header);
}
int rgw_bucket_set_tag_timeout(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
header.tag_timeout = op.tag_timeout;
- header_bl.clear();
- ::encode(header, header_bl);
- rc = cls_cxx_map_write_header(hctx, &header_bl);
- return rc;
+ return write_bucket_header(hctx, &header);
}
int rgw_bucket_prepare_op(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
info.state = CLS_RGW_STATE_PENDING_MODIFY;
info.op = op.op;
- rc = log_index_operation(hctx, op.name, op.op, entry.ver, info.state);
+
+ bufferlist header_bl;
+ struct rgw_bucket_dir_header header;
+ rc = cls_cxx_map_read_header(hctx, &header_bl);
+ if (rc < 0)
+ return rc;
+
+ bufferlist::iterator header_iter = header_bl.begin();
+ try {
+ ::decode(header, header_iter);
+ } catch (buffer::error& err) {
+ CLS_LOG(1, "ERROR: rgw_bucket_complete_op(): failed to decode header\n");
+ return -EINVAL;
+ }
+
+ rc = log_index_operation(hctx, op.name, op.op, entry.ver, info.state, header.ver);
if (rc < 0)
return rc;
bufferlist info_bl;
::encode(entry, info_bl);
rc = cls_cxx_map_set_val(hctx, op.name, &info_bl);
- return rc;
+ if (rc < 0)
+ return rc;
+
+ return write_bucket_header(hctx, &header);
}
static void unaccount_entry(struct rgw_bucket_dir_header& header, struct rgw_bucket_dir_entry& entry)
return rc;
}
+ entry.index_ver = header.ver;
+
if (op.tag.size()) {
map<string, struct rgw_bucket_pending_info>::iterator pinter = entry.pending_map.find(op.tag);
if (pinter == entry.pending_map.end()) {
bufferlist op_bl;
if (cancel) {
- rc = log_index_operation(hctx, op.name, op.op, entry.ver, CLS_RGW_STATE_COMPLETE);
+ rc = log_index_operation(hctx, op.name, op.op, entry.ver, CLS_RGW_STATE_COMPLETE, header.ver);
if (rc < 0)
return rc;
break;
}
- rc = log_index_operation(hctx, op.name, op.op, entry.ver, CLS_RGW_STATE_COMPLETE);
+ rc = log_index_operation(hctx, op.name, op.op, entry.ver, CLS_RGW_STATE_COMPLETE, header.ver);
if (rc < 0)
return rc;
CLS_LOG(0, "rgw_bucket_complete_op(): entry.name=%s entry.meta.category=%d\n", remove_entry.name.c_str(), remove_entry.meta.category);
unaccount_entry(header, remove_entry);
- rc = log_index_operation(hctx, op.name, CLS_RGW_OP_DEL, remove_entry.ver, CLS_RGW_STATE_COMPLETE);
+ rc = log_index_operation(hctx, op.name, CLS_RGW_OP_DEL, remove_entry.ver, CLS_RGW_STATE_COMPLETE, header.ver);
if (rc < 0)
continue;
}
}
- bufferlist new_header_bl;
- ::encode(header, new_header_bl);
- return cls_cxx_map_write_header(hctx, &new_header_bl);
+ return write_bucket_header(hctx, &header);
}
int rgw_dir_suggest_changes(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
stats.total_size += cur_change.meta.size;
stats.total_size_rounded += get_rounded_size(cur_change.meta.size);
header_changed = true;
+ cur_change.index_ver = header.ver;
bufferlist cur_state_bl;
::encode(cur_change, cur_state_bl);
ret = cls_cxx_map_set_val(hctx, cur_change.name, &cur_state_bl);
}
}
- bufferlist update_bl;
if (header_changed) {
- bufferlist new_header_bl;
- ::encode(header, new_header_bl);
- return cls_cxx_map_write_header(hctx, &new_header_bl);
+ return write_bucket_header(hctx, &header);
}
return 0;
}
bool exists;
struct rgw_bucket_dir_entry_meta meta;
map<string, struct rgw_bucket_pending_info> pending_map;
+ uint64_t index_ver;
rgw_bucket_dir_entry() :
exists(false) {}
void encode(bufferlist &bl) const {
- ENCODE_START(4, 3, bl);
+ ENCODE_START(5, 3, bl);
::encode(name, bl);
::encode(ver, bl);
::encode(exists, bl);
::encode(meta, bl);
::encode(pending_map, bl);
::encode(locator, bl);
+ ::encode_packed_val(index_ver, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::iterator &bl) {
- DECODE_START_LEGACY_COMPAT_LEN(4, 3, 3, bl);
+ DECODE_START_LEGACY_COMPAT_LEN(5, 3, 3, bl);
::decode(name, bl);
if (struct_v >= 4) {
::decode(ver, bl);
if (struct_v >= 2) {
::decode(locator, bl);
}
+ if (struct_v >= 5) {
+ ::decode_packed_val(index_ver, bl);
+ }
DECODE_FINISH(bl);
}
void dump(Formatter *f) const;
WRITE_CLASS_ENCODER(rgw_bucket_dir_entry)
struct rgw_bi_log_entry {
+ string id;
string object;
utime_t timestamp;
rgw_bucket_entry_ver ver;
RGWModifyOp op;
RGWPendingState state;
+ uint64_t index_ver;
- rgw_bi_log_entry() : op(CLS_RGW_OP_UNKNOWN) {}
+ rgw_bi_log_entry() : op(CLS_RGW_OP_UNKNOWN), index_ver(0) {}
void encode(bufferlist &bl) const {
ENCODE_START(1, 1, bl);
+ ::encode(id, bl);
::encode(object, bl);
::encode(timestamp, bl);
::encode(ver, bl);
::encode(c, bl);
c = (uint8_t)state;
::encode(state, bl);
+ encode_packed_val(index_ver, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::iterator &bl) {
DECODE_START(1, bl);
+ ::decode(id, bl);
::decode(object, bl);
::decode(timestamp, bl);
::decode(ver, bl);
op = (RGWModifyOp)c;
::decode(c, bl);
state = (RGWPendingState)c;
+ decode_packed_val(index_ver, bl);
DECODE_FINISH(bl);
}
void dump(Formatter *f) const;
struct rgw_bucket_dir_header {
map<uint8_t, rgw_bucket_category_stats> stats;
uint64_t tag_timeout;
+ uint64_t ver;
+ uint64_t master_ver;
- rgw_bucket_dir_header() : tag_timeout(0) {}
+ rgw_bucket_dir_header() : tag_timeout(0), ver(0), master_ver(0) {}
void encode(bufferlist &bl) const {
- ENCODE_START(3, 2, bl);
+ ENCODE_START(4, 2, bl);
::encode(stats, bl);
::encode(tag_timeout, bl);
+ ::encode(ver, bl);
+ ::encode(master_ver, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::iterator &bl) {
} else {
tag_timeout = 0;
}
+ if (struct_v >= 4) {
+ ::decode(ver, bl);
+ ::decode(master_ver, bl);
+ } else {
+ ver = 0;
+ }
DECODE_FINISH(bl);
}
void dump(Formatter *f) const;