return 0;
}
-static int bi_log_iterate_entries(cls_method_context_t hctx, const string& marker,
+static int bi_log_iterate_entries(cls_method_context_t hctx, const string& marker, const string& end_marker,
string& key_iter, uint32_t max_entries, bool *truncated,
int (*cb)(cls_method_context_t, const string&, rgw_bi_log_entry&, void *),
void *param)
start_key = key_iter;
}
- end_key = BI_PREFIX_CHAR;
- end_key.append(bucket_index_prefixes[BI_BUCKET_LAST_INDEX]);
+ if (end_marker.empty()) {
+ end_key = BI_PREFIX_CHAR;
+ end_key.append(bucket_index_prefixes[BI_BUCKET_LAST_INDEX]);
+ } else {
+ end_key = BI_PREFIX_CHAR;
+ end_key.append(bucket_index_prefixes[BI_BUCKET_LOG_INDEX]);
+ end_key.append(end_marker);
+ }
- CLS_LOG(0, "bi_log_iterate_entries end_key=%s\n", end_key.c_str());
+ CLS_LOG(0, "bi_log_iterate_entries start_key=%s end_key=%s\n", start_key.c_str(), end_key.c_str());
string filter;
uint32_t max, list<rgw_bi_log_entry>& entries, bool *truncated)
{
string key_iter;
- int ret = bi_log_iterate_entries(hctx, marker,
+ string end_marker;
+ int ret = bi_log_iterate_entries(hctx, marker, end_marker,
key_iter, max, truncated,
bi_log_list_cb, &entries);
return ret;
return 0;
}
+static int bi_log_list_trim_cb(cls_method_context_t hctx, const string& key, rgw_bi_log_entry& info, void *param)
+{
+ list<rgw_bi_log_entry> *entries = (list<rgw_bi_log_entry> *)param;
+
+ entries->push_back(info);
+ return 0;
+}
+
+static int bi_log_remove_entry(cls_method_context_t hctx, rgw_bi_log_entry& entry)
+{
+ string key;
+ key = BI_PREFIX_CHAR;
+ key.append(bucket_index_prefixes[BI_BUCKET_LOG_INDEX]);
+ key.append(entry.id);
+ return cls_cxx_map_remove_key(hctx, key);
+}
+
+static int bi_log_list_trim_entries(cls_method_context_t hctx,
+ const string& start_marker, const string& end_marker,
+ list<rgw_bi_log_entry>& entries, bool *truncated)
+{
+ string key_iter;
+#define MAX_TRIM_ENTRIES 1000 /* max entries to trim in a single operation */
+ int ret = bi_log_iterate_entries(hctx, start_marker, end_marker,
+ key_iter, MAX_TRIM_ENTRIES, truncated,
+ bi_log_list_trim_cb, &entries);
+ return ret;
+}
+
+static int rgw_bi_log_trim(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+ bufferlist::iterator in_iter = in->begin();
+
+ cls_rgw_bi_log_trim_op op;
+ try {
+ ::decode(op, in_iter);
+ } catch (buffer::error& err) {
+ CLS_LOG(1, "ERROR: rgw_bi_log_list(): failed to decode entry\n");
+ return -EINVAL;
+ }
+
+ cls_rgw_bi_log_list_ret op_ret;
+ list<rgw_bi_log_entry> entries;
+#define MAX_TRIM_ENTRIES 1000 /* don't do more than that in a single operation */
+ bool truncated;
+ int ret = bi_log_list_trim_entries(hctx, op.start_marker, op.end_marker, entries, &truncated);
+ if (ret < 0)
+ return ret;
+
+ if (entries.size() == 0)
+ return -ENODATA;
+
+ list<rgw_bi_log_entry>::iterator iter;
+ for (iter = entries.begin(); iter != entries.end(); ++iter) {
+ rgw_bi_log_entry& entry = *iter;
+
+ ret = bi_log_remove_entry(hctx, entry);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
static void usage_record_prefix_by_time(uint64_t epoch, string& key)
{
char buf[32];
cls_register_cxx_method(h_class, "bucket_prepare_op", CLS_METHOD_RD | CLS_METHOD_WR, rgw_bucket_prepare_op, &h_rgw_bucket_prepare_op);
cls_register_cxx_method(h_class, "bucket_complete_op", CLS_METHOD_RD | CLS_METHOD_WR, rgw_bucket_complete_op, &h_rgw_bucket_complete_op);
cls_register_cxx_method(h_class, "bi_log_list", CLS_METHOD_RD, rgw_bi_log_list, &h_rgw_bi_log_list_op);
+ cls_register_cxx_method(h_class, "bi_log_trim", CLS_METHOD_RD | CLS_METHOD_WR, rgw_bi_log_trim, &h_rgw_bi_log_list_op);
cls_register_cxx_method(h_class, "dir_suggest_changes", CLS_METHOD_RD | CLS_METHOD_WR, rgw_dir_suggest_changes, &h_rgw_dir_suggest_changes);
/* usage logging */
return r;
}
+int cls_rgw_bi_log_trim(IoCtx& io_ctx, string& oid, string& start_marker, string& end_marker)
+{
+ int r;
+ do {
+ bufferlist in, out;
+ cls_rgw_bi_log_trim_op call;
+ call.start_marker = start_marker;
+ call.end_marker = end_marker;
+ ::encode(call, in);
+ r = io_ctx.exec(oid, "rgw", "bi_log_trim", in, out);
+
+ if (r == -ENODATA)
+ return 0;
+
+ if (r < 0)
+ return r;
+
+ } while (r != -ENODATA);
+
+ return 0;
+}
+
int cls_rgw_usage_log_read(IoCtx& io_ctx, string& oid, string& user,
uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries,
string& read_iter, map<rgw_user_bucket, rgw_usage_log_entry>& usage,
int cls_rgw_bi_log_list(librados::IoCtx& io_ctx, string& oid, string& marker, uint32_t max,
list<rgw_bi_log_entry>& entries, bool *truncated);
+int cls_rgw_bi_log_trim(librados::IoCtx& io_ctx, string& oid, string& start_marker, string& end_marker);
/* usage logging */
int cls_rgw_usage_log_read(librados::IoCtx& io_ctx, string& oid, string& user,
};
WRITE_CLASS_ENCODER(cls_rgw_bi_log_list_op)
+struct cls_rgw_bi_log_trim_op {
+ string start_marker;
+ string end_marker;
+
+ cls_rgw_bi_log_trim_op() {}
+
+ void encode(bufferlist& bl) const {
+ ENCODE_START(1, 1, bl);
+ ::encode(start_marker, bl);
+ ::encode(end_marker, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(bufferlist::iterator& bl) {
+ DECODE_START(1, bl);
+ ::decode(start_marker, bl);
+ ::decode(end_marker, bl);
+ DECODE_FINISH(bl);
+ }
+};
+WRITE_CLASS_ENCODER(cls_rgw_bi_log_trim_op)
+
struct cls_rgw_bi_log_list_ret {
list<rgw_bi_log_entry> entries;
bool truncated;
cerr << " mdlog list list metadata log\n";
cerr << " mdlog trim trim metadata log\n";
cerr << " bilog list list bucket index log\n";
+ cerr << " bilog trim trim bucket index log (use start-marker, end-marker)\n";
cerr << " datalog list list data log\n";
cerr << "options:\n";
cerr << " --uid=<id> user id\n";
OPT_MDLOG_LIST,
OPT_MDLOG_TRIM,
OPT_BILOG_LIST,
+ OPT_BILOG_TRIM,
OPT_DATALOG_LIST,
};
} else if (strcmp(prev_cmd, "bilog") == 0) {
if (strcmp(cmd, "list") == 0)
return OPT_BILOG_LIST;
+ if (strcmp(cmd, "trim") == 0)
+ return OPT_BILOG_TRIM;
} else if (strcmp(prev_cmd, "datalog") == 0) {
if (strcmp(cmd, "list") == 0)
return OPT_DATALOG_LIST;
string metadata_key;
RGWObjVersionTracker objv_tracker;
string marker;
+ string start_marker;
+ string end_marker;
int max_entries = -1;
std::string val;
metadata_key = val;
} else if (ceph_argparse_witharg(args, i, &val, "--marker", (char*)NULL)) {
marker = val;
+ } else if (ceph_argparse_witharg(args, i, &val, "--start-marker", (char*)NULL)) {
+ start_marker = val;
+ } else if (ceph_argparse_witharg(args, i, &val, "--end-marker", (char*)NULL)) {
+ end_marker = val;
} else {
++i;
}
formatter->flush(cout);
}
+ if (opt_cmd == OPT_BILOG_TRIM) {
+ if (bucket_name.empty()) {
+ cerr << "ERROR: bucket not specified" << std::endl;
+ return -EINVAL;
+ }
+ int ret = init_bucket(bucket_name, bucket);
+ if (ret < 0) {
+ cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
+ return -ret;
+ }
+ ret = store->trim_bi_log_entries(bucket, start_marker, end_marker);
+ if (ret < 0) {
+ cerr << "ERROR: trim_bi_log_entries(): " << cpp_strerror(-ret) << std::endl;
+ return -ret;
+ }
+ }
+
if (opt_cmd == OPT_DATALOG_LIST) {
formatter->open_array_section("entries");
bool truncated;
return 0;
}
+int RGWRados::trim_bi_log_entries(rgw_bucket& bucket, string& start_marker, string& end_marker)
+{
+ librados::IoCtx index_ctx;
+ string oid;
+ int r = open_bucket_index(bucket, index_ctx, oid);
+ if (r < 0)
+ return r;
+
+ int ret = cls_rgw_bi_log_trim(index_ctx, oid, start_marker, end_marker);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
int RGWRados::gc_operate(string& oid, librados::ObjectWriteOperation *op)
{
return gc_pool_ctx.operate(oid, op);
return cls_obj_complete_cancel(bucket, tag, oid);
}
int list_bi_log_entries(rgw_bucket& bucket, string& marker, uint32_t max, std::list<rgw_bi_log_entry>& result, bool *truncated);
+ int trim_bi_log_entries(rgw_bucket& bucket, string& marker, string& end_marker);
int cls_obj_usage_log_add(const string& oid, rgw_usage_log_info& info);
int cls_obj_usage_log_read(string& oid, string& user, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries,