From 19828cb89e6d1e1f4c92b2a4674f92b0776a4601 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Tue, 2 Jul 2013 15:38:49 -0700 Subject: [PATCH] cls_log: store info in header, new op to retrieve it Keep max_timestamp, max_marker. Add a new op to retrieve header. Signed-off-by: Yehuda Sadeh --- src/cls/log/cls_log.cc | 85 +++++++++++++++++++++++++++++++++-- src/cls/log/cls_log_client.cc | 29 ++++++++++++ src/cls/log/cls_log_client.h | 2 + src/cls/log/cls_log_ops.h | 34 ++++++++++++++ src/cls/log/cls_log_types.h | 20 +++++++++ 5 files changed, 167 insertions(+), 3 deletions(-) diff --git a/src/cls/log/cls_log.cc b/src/cls/log/cls_log.cc index 8c62b5a9a688e..46ba357480c5d 100644 --- a/src/cls/log/cls_log.cc +++ b/src/cls/log/cls_log.cc @@ -23,6 +23,7 @@ cls_handle_t h_class; cls_method_handle_t h_log_add; cls_method_handle_t h_log_list; cls_method_handle_t h_log_trim; +cls_method_handle_t h_log_info; static string log_index_prefix = "1_"; @@ -47,6 +48,41 @@ static void get_index_time_prefix(utime_t& ts, string& index) index = log_index_prefix + buf; } +static int read_header(cls_method_context_t hctx, cls_log_header& header) +{ + bufferlist header_bl; + + int ret = cls_cxx_map_read_header(hctx, &header_bl); + if (ret < 0) + return ret; + + if (header_bl.length() == 0) { + header = cls_log_header(); + return 0; + } + + bufferlist::iterator iter = header_bl.begin(); + try { + ::decode(header, iter); + } catch (buffer::error& err) { + CLS_LOG(0, "ERROR: read_header(): failed to decode header"); + } + + return 0; +} + +static int write_header(cls_method_context_t hctx, cls_log_header& header) +{ + bufferlist header_bl; + ::encode(header, header_bl); + + int ret = cls_cxx_map_write_header(hctx, &header_bl); + if (ret < 0) + return ret; + + return 0; +} + static void get_index(cls_method_context_t hctx, utime_t& ts, string& index) { get_index_time_prefix(ts, index); @@ -70,23 +106,42 @@ static int cls_log_add(cls_method_context_t hctx, bufferlist *in, bufferlist *ou return -EINVAL; } + cls_log_header header; + + int ret = read_header(hctx, header); + if (ret < 0) + return ret; + for (list::iterator iter = op.entries.begin(); iter != op.entries.end(); ++iter) { cls_log_entry& entry = *iter; string index; - get_index(hctx, entry.timestamp, index); + utime_t timestamp = entry.timestamp; + if (timestamp < header.max_time) + timestamp = header.max_time; + else if (timestamp > header.max_time) + header.max_time = timestamp; + + get_index(hctx, timestamp, index); CLS_LOG(0, "storing entry at %s", index.c_str()); entry.id = index; - int ret = write_log_entry(hctx, index, entry); + if (index > header.max_marker) + header.max_marker = index; + + ret = write_log_entry(hctx, index, entry); if (ret < 0) return ret; } - + + ret = write_header(hctx, header); + if (ret < 0) + return ret; + return 0; } @@ -230,6 +285,29 @@ static int cls_log_trim(cls_method_context_t hctx, bufferlist *in, bufferlist *o return 0; } +static int cls_log_info(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + bufferlist::iterator in_iter = in->begin(); + + cls_log_info_op op; + try { + ::decode(op, in_iter); + } catch (buffer::error& err) { + CLS_LOG(1, "ERROR: cls_log_add_op(): failed to decode op"); + return -EINVAL; + } + + cls_log_info_ret ret; + + int rc = read_header(hctx, ret.header); + if (rc < 0) + return rc; + + ::encode(ret, *out); + + return 0; +} + void __cls_init() { CLS_LOG(1, "Loaded log class!"); @@ -240,6 +318,7 @@ void __cls_init() cls_register_cxx_method(h_class, "add", CLS_METHOD_RD | CLS_METHOD_WR, cls_log_add, &h_log_add); cls_register_cxx_method(h_class, "list", CLS_METHOD_RD, cls_log_list, &h_log_list); cls_register_cxx_method(h_class, "trim", CLS_METHOD_RD | CLS_METHOD_WR, cls_log_trim, &h_log_trim); + cls_register_cxx_method(h_class, "info", CLS_METHOD_RD, cls_log_info, &h_log_info); return; } diff --git a/src/cls/log/cls_log_client.cc b/src/cls/log/cls_log_client.cc index 0e3aa85b827b2..ea8adf11145de 100644 --- a/src/cls/log/cls_log_client.cc +++ b/src/cls/log/cls_log_client.cc @@ -122,3 +122,32 @@ void cls_log_list(librados::ObjectReadOperation& op, utime_t& from, utime_t& to, op.exec("log", "list", inbl, new LogListCtx(&entries, out_marker, truncated)); } +class LogInfoCtx : public ObjectOperationCompletion { + cls_log_header *header; +public: + LogInfoCtx(cls_log_header *_header) : header(_header) {} + void handle_completion(int r, bufferlist& outbl) { + if (r >= 0) { + cls_log_info_ret ret; + try { + bufferlist::iterator iter = outbl.begin(); + ::decode(ret, iter); + if (header) + *header = ret.header; + } catch (buffer::error& err) { + // nothing we can do about it atm + } + } + } +}; + +void cls_log_info(librados::ObjectReadOperation& op, cls_log_header *header) +{ + bufferlist inbl; + cls_log_info_op call; + + ::encode(call, inbl); + + op.exec("log", "info", inbl, new LogInfoCtx(header)); +} + diff --git a/src/cls/log/cls_log_client.h b/src/cls/log/cls_log_client.h index afda05597c2ad..3b4c96d1d3a13 100644 --- a/src/cls/log/cls_log_client.h +++ b/src/cls/log/cls_log_client.h @@ -26,4 +26,6 @@ void cls_log_trim(librados::ObjectWriteOperation& op, const utime_t& from_time, int cls_log_trim(librados::IoCtx& io_ctx, const string& oid, const utime_t& from_time, const utime_t& to_time, const string& from_marker, const string& to_marker); +void cls_log_info(librados::ObjectReadOperation& op, cls_log_header *header); + #endif diff --git a/src/cls/log/cls_log_ops.h b/src/cls/log/cls_log_ops.h index dac232d76d2ca..6bcb69d1334f7 100644 --- a/src/cls/log/cls_log_ops.h +++ b/src/cls/log/cls_log_ops.h @@ -115,4 +115,38 @@ struct cls_log_trim_op { }; WRITE_CLASS_ENCODER(cls_log_trim_op) +struct cls_log_info_op { + cls_log_info_op() {} + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + // currently empty request + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + // currently empty request + DECODE_FINISH(bl); + } +}; +WRITE_CLASS_ENCODER(cls_log_info_op) + +struct cls_log_info_ret { + cls_log_header header; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(header, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + ::decode(header, bl); + DECODE_FINISH(bl); + } +}; +WRITE_CLASS_ENCODER(cls_log_info_ret) + #endif diff --git a/src/cls/log/cls_log_types.h b/src/cls/log/cls_log_types.h index 13dd7a34a9590..7d9679488ddcd 100644 --- a/src/cls/log/cls_log_types.h +++ b/src/cls/log/cls_log_types.h @@ -41,6 +41,26 @@ struct cls_log_entry { }; WRITE_CLASS_ENCODER(cls_log_entry) +struct cls_log_header { + string max_marker; + utime_t max_time; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + ::encode(max_marker, bl); + ::encode(max_time, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + ::decode(max_marker, bl); + ::decode(max_time, bl); + DECODE_FINISH(bl); + } +}; +WRITE_CLASS_ENCODER(cls_log_header) + #endif -- 2.39.5