From: Venky Shankar Date: Thu, 19 May 2016 17:15:34 +0000 (+0530) Subject: cls_journal: Select min commit position for new clients X-Git-Tag: v10.2.2~45^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8fbb555befb1415ef5218c8aaa149ca44017d73d;p=ceph.git cls_journal: Select min commit position for new clients When a new client registers, its commit position is initialized to the least commit position of all other clients. Fixes: http://tracker.ceph.com/issues/15757 Signed-off-by: Venky Shankar (cherry picked from commit dd2e3dae8adb3778e7e381db5dbfca0948571c55) --- diff --git a/src/cls/journal/cls_journal.cc b/src/cls/journal/cls_journal.cc index d5cdfe3ececf..2d36296f1885 100644 --- a/src/cls/journal/cls_journal.cc +++ b/src/cls/journal/cls_journal.cc @@ -224,6 +224,83 @@ int expire_tags(cls_method_context_t hctx, const std::string *skip_client_id) { return 0; } +int get_client_list_range(cls_method_context_t hctx, + std::set *clients, + std::string start_after, uint64_t max_return) { + std::string last_read; + if (!start_after.empty()) { + last_read = key_from_client_id(start_after); + } + + std::map vals; + int r = cls_cxx_map_get_vals(hctx, last_read, HEADER_KEY_CLIENT_PREFIX, + max_return, &vals); + if (r < 0) { + CLS_ERR("failed to retrieve omap values: %s", cpp_strerror(r).c_str()); + return r; + } + + for (std::map::iterator it = vals.begin(); + it != vals.end(); ++it) { + try { + bufferlist::iterator iter = it->second.begin(); + + cls::journal::Client client; + ::decode(client, iter); + clients->insert(client); + } catch (const buffer::error &err) { + CLS_ERR("could not decode client '%s': %s", it->first.c_str(), + err.what()); + return -EIO; + } + } + + return 0; +} + +int find_min_commit_position(cls_method_context_t hctx, + cls::journal::ObjectSetPosition *minset) { + int r; + bool valid = false; + std::string start_after = ""; + uint64_t tag_tid = 0, entry_tid = 0; + + while (true) { + std::set batch; + + r = get_client_list_range(hctx, &batch, start_after, cls::journal::JOURNAL_MAX_RETURN); + if ((r < 0) || batch.empty()) { + break; + } + + start_after = batch.rbegin()->id; + + // update the (minimum) commit position from this batch of clients + for(std::set::iterator it = batch.begin(); + it != batch.end(); ++it) { + cls::journal::ObjectSetPosition object_set_position = (*it).commit_position; + if (!object_set_position.object_positions.empty()) { + cls::journal::ObjectPosition first = object_set_position.object_positions.front(); + + // least tag_tid (or least entry_tid for matching tag_tid) + if (!valid || (tag_tid > first.tag_tid) || ((tag_tid == first.tag_tid) && (entry_tid > first.entry_tid))) { + tag_tid = first.tag_tid; + entry_tid = first.entry_tid; + *minset = cls::journal::ObjectSetPosition(object_set_position); + valid = true; + } + } + } + + // got the last batch, we're done + if (batch.size() < cls::journal::JOURNAL_MAX_RETURN) { + break; + } + } + + return r; +} + } // anonymous namespace /** @@ -565,7 +642,12 @@ int journal_client_register(cls_method_context_t hctx, bufferlist *in, return r; } - cls::journal::Client client(id, data); + cls::journal::ObjectSetPosition minset; + r = find_min_commit_position(hctx, &minset); + if (r < 0) + return r; + + cls::journal::Client client(id, data, minset); r = write_key(hctx, key, client); if (r < 0) { return r; @@ -760,34 +842,10 @@ int journal_client_list(cls_method_context_t hctx, bufferlist *in, return -EINVAL; } - std::string last_read; - if (!start_after.empty()) { - last_read = key_from_client_id(start_after); - } - - std::map vals; - int r = cls_cxx_map_get_vals(hctx, last_read, HEADER_KEY_CLIENT_PREFIX, - max_return, &vals); - if (r < 0) { - CLS_ERR("failed to retrieve omap values: %s", cpp_strerror(r).c_str()); - return r; - } - std::set clients; - for (std::map::iterator it = vals.begin(); - it != vals.end(); ++it) { - try { - bufferlist::iterator iter = it->second.begin(); - - cls::journal::Client client; - ::decode(client, iter); - clients.insert(client); - } catch (const buffer::error &err) { - CLS_ERR("could not decode client '%s': %s", it->first.c_str(), - err.what()); - return -EIO; - } - } + int r = get_client_list_range(hctx, &clients, start_after, max_return); + if (r < 0) + return r; ::encode(clients, *out); return 0; diff --git a/src/cls/journal/cls_journal_client.cc b/src/cls/journal/cls_journal_client.cc index 7fbfb517a69a..50549dc4061d 100644 --- a/src/cls/journal/cls_journal_client.cc +++ b/src/cls/journal/cls_journal_client.cc @@ -14,8 +14,6 @@ namespace client { namespace { -static const uint64_t JOURNAL_MAX_RETURN = 256; - struct C_AioExec : public Context { librados::IoCtx ioctx; std::string oid; diff --git a/src/cls/journal/cls_journal_types.h b/src/cls/journal/cls_journal_types.h index 0381aff93c6b..4e1f2d7fd6e1 100644 --- a/src/cls/journal/cls_journal_types.h +++ b/src/cls/journal/cls_journal_types.h @@ -19,6 +19,8 @@ class Formatter; namespace cls { namespace journal { +static const uint64_t JOURNAL_MAX_RETURN = 256; + struct ObjectPosition { uint64_t object_number; uint64_t tag_tid;