{"action":"created","comment":{"url":"https://api.github.com/repos/ceph/ceph/pulls/comments/90652291","pull_request_review_id":11168594,"id":90652291,"diff_hunk":"@@ -0,0 +1,661 @@\n+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-\n+// vim: ts=8 sw=2 smarttab\n+\n+#include \"librbd/ManagedLock.h\"\n+#include \"librbd/managed_lock/AcquireRequest.h\"\n+#include \"librbd/managed_lock/ReleaseRequest.h\"\n+#include \"librbd/managed_lock/ReacquireRequest.h\"\n+#include \"librbd/Watcher.h\"\n+#include \"librbd/ImageCtx.h\"\n+#include \"cls/lock/cls_lock_client.h\"\n+#include \"common/dout.h\"\n+#include \"common/errno.h\"\n+#include \"common/WorkQueue.h\"\n+#include \"librbd/Utils.h\"\n+#include <sstream>\n+\n+#define dout_subsys ceph_subsys_rbd\n+#undef dout_prefix\n+#define dout_prefix *_dout << \"librbd::ManagedLock: \" << this << \" \" <<  __func__\n+\n+namespace librbd {\n+\n+using std::string;\n+\n+namespace {\n+\n+const std::string WATCHER_LOCK_COOKIE_PREFIX = \"auto\";\n+\n+template <typename R>\n+struct C_SendLockRequest : public Context {\n+  R* request;\n+  explicit C_SendLockRequest(R* request) : request(request) {\n+  }\n+  virtual void finish(int r) override {\n+    request->send();\n+  }\n+};\n+\n+} // anonymous namespace\n+\n+template <typename I>\n+const std::string ManagedLock<I>::WATCHER_LOCK_TAG(\"internal\");\n+\n+template <typename I>\n+ManagedLock<I>::ManagedLock(librados::IoCtx &ioctx, ContextWQ *work_queue,\n+                            const string& oid, Watcher *watcher)\n+  : m_ioctx(ioctx), m_cct(reinterpret_cast<CephContext *>(ioctx.cct())),\n+    m_work_queue(work_queue),\n+    m_oid(oid),\n+    m_watcher(watcher),\n+    m_lock(util::unique_lock_name(\"librbd::ManagedLock<I>::m_lock\", this)),\n+    m_state(STATE_UNLOCKED) {\n+}\n+\n+template <typename I>\n+ManagedLock<I>::~ManagedLock() {\n+  Mutex::Locker locker(m_lock);\n+  assert(m_state == STATE_SHUTDOWN || m_state == STATE_UNLOCKED);\n+}\n+\n+template <typename I>\n+bool ManagedLock<I>::is_lock_owner() const {\n+  Mutex::Locker locker(m_lock);\n+\n+  bool lock_owner;\n+\n+  switch (m_state) {\n+  case STATE_LOCKED:\n+  case STATE_REACQUIRING:\n+  case STATE_PRE_SHUTTING_DOWN:\n+  case STATE_POST_ACQUIRING:\n+  case STATE_PRE_RELEASING:\n+    lock_owner = true;\n+    break;\n+  default:\n+    lock_owner = false;\n+    break;\n+  }\n+\n+  ldout(m_cct, 20) << \"=\" << lock_owner << dendl;\n+  return lock_owner;\n+}\n+\n+template <typename I>\n+void ManagedLock<I>::shut_down(Context *on_shut_down) {\n+  ldout(m_cct, 10) << dendl;\n+\n+  Mutex::Locker locker(m_lock);\n+  assert(!is_shutdown_locked());\n+  execute_action(ACTION_SHUT_DOWN, on_shut_down);\n+}\n+\n+template <typename I>\n+void ManagedLock<I>::acquire_lock(Context *on_acquired) {\n+  int r = 0;\n+  {\n+    Mutex::Locker locker(m_lock);\n+    if (is_shutdown_locked()) {\n+      r = -ESHUTDOWN;\n+    } else if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {\n+      ldout(m_cct, 10) << dendl;\n+      execute_action(ACTION_ACQUIRE_LOCK, on_acquired);\n+      return;\n+    }\n+  }\n+\n+  on_acquired->complete(r);\n+}\n+\n+template <typename I>\n+void ManagedLock<I>::try_acquire_lock(Context *on_acquired) {\n+  int r = 0;\n+  {\n+    Mutex::Locker locker(m_lock);\n+    if (is_shutdown_locked()) {\n+      r = -ESHUTDOWN;\n+    } else if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {\n+      ldout(m_cct, 10) << dendl;\n+      execute_action(ACTION_TRY_LOCK, on_acquired);\n+      return;\n+    }\n+  }\n+\n+  on_acquired->complete(r);\n+}\n+\n+template <typename I>\n+void ManagedLock<I>::release_lock(Context *on_released) {\n+  int r = 0;\n+  {\n+    Mutex::Locker locker(m_lock);\n+    if (is_shutdown_locked()) {\n+      r = -ESHUTDOWN;\n+    } else if (m_state != STATE_UNLOCKED || !m_actions_contexts.empty()) {\n+      ldout(m_cct, 10) << dendl;\n+      execute_action(ACTION_RELEASE_LOCK, on_released);\n+      return;\n+    }\n+  }\n+\n+  on_released->complete(r);\n+}\n+\n+template <typename I>\n+void ManagedLock<I>::reacquire_lock(Context *on_reacquired) {\n+  {\n+    Mutex::Locker locker(m_lock);\n+\n+    if (m_state == STATE_WAITING_FOR_REGISTER) {\n+      // restart the acquire lock process now that watch is valid\n+      ldout(m_cct, 10) << \": \" << \"woke up waiting acquire\" << dendl;\n+      Action active_action = get_active_action();\n+      assert(active_action == ACTION_TRY_LOCK ||\n+             active_action == ACTION_ACQUIRE_LOCK);\n+      execute_next_action();\n+    } else if (!is_shutdown_locked() &&\n+        (m_state == STATE_LOCKED || m_state == STATE_ACQUIRING)) {\n+      // interlock the lock operation with other state ops\n+      ldout(m_cct, 10) << dendl;\n+      execute_action(ACTION_REACQUIRE_LOCK, on_reacquired);\n+      return;\n+    }\n+  }\n+\n+  // ignore request if shutdown or not in a locked-related state\n+  if (on_reacquired != nullptr) {\n+    on_reacquired->complete(0);\n+  }\n+}\n+\n+template <typename I>\n+void ManagedLock<I>::shutdown_handler(int r, Context *on_finish) {\n+  on_finish->complete(r);\n+}\n+\n+template <typename I>\n+void ManagedLock<I>::pre_acquire_lock_handler(Context *on_finish) {\n+  m_work_queue->queue(on_finish);\n+}\n+\n+template <typename I>\n+void  ManagedLock<I>::post_acquire_lock_handler(int r, Context *on_finish) {\n+  on_finish->complete(r);\n+}\n+\n+template <typename I>\n+void  ManagedLock<I>::pre_release_lock_handler(bool shutting_down,\n+                                               Context *on_finish) {\n+  m_work_queue->queue(on_finish);\n+}\n+\n+template <typename I>\n+void  ManagedLock<I>::post_release_lock_handler(bool shutting_down, int r,\n+                                                Context *on_finish) {\n+  on_finish->complete(r);\n+}\n+\n+template <typename I>\n+void ManagedLock<I>::assert_locked(librados::ObjectWriteOperation *op,\n+                          ClsLockType type) {\n+  Mutex::Locker locker(m_lock);\n+  rados::cls::lock::assert_locked(op, RBD_LOCK_NAME, type, m_cookie,\n+                                  WATCHER_LOCK_TAG);\n+}\n+\n+template <typename I>\n+bool ManagedLock<I>::decode_lock_cookie(const std::string &tag,\n+                                        uint64_t *handle) {\n+  std::string prefix;\n+  std::istringstream ss(tag);\n+  if (!(ss >> prefix >> *handle) || prefix != WATCHER_LOCK_COOKIE_PREFIX) {\n+    return false;\n+  }\n+  return true;\n+}\n+\n+template <typename I>\n+string ManagedLock<I>::encode_lock_cookie(uint64_t watch_handle) {\n+  assert(watch_handle != 0);\n+  std::ostringstream ss;\n+  ss << WATCHER_LOCK_COOKIE_PREFIX << \" \" << watch_handle;\n+  return ss.str();\n+}\n+\n+template <typename I>\n+bool ManagedLock<I>::is_transition_state() const {\n+  switch (m_state) {\n+  case STATE_ACQUIRING:\n+  case STATE_WAITING_FOR_REGISTER:\n+  case STATE_REACQUIRING:\n+  case STATE_RELEASING:\n+  case STATE_PRE_SHUTTING_DOWN:\n+  case STATE_SHUTTING_DOWN:\n+","path":"src/librbd/ManagedLock.cc","position":234,"original_position":234,"commit_id":"cdf028cc68cbc52caf8452f3b9b2d352af968716","original_commit_id":"cdf028cc68cbc52caf8452f3b9b2d352af968716","user":{"login":"dillaman","id":4739042,"avatar_url":"https://avatars.githubusercontent.com/u/4739042?v=3","gravatar_id":"","url":"https://api.github.com/users/dillaman","html_url":"https://github.com/dillaman","followers_url":"https://api.github.com/users/dillaman/followers","following_url":"https://api.github.com/users/dillaman/following{/other_user}","gists_url":"https://api.github.com/users/dillaman/gists{/gist_id}","starred_url":"https://api.github.com/users/dillaman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dillaman/subscriptions","organizations_url":"https://api.github.com/users/dillaman/orgs","repos_url":"https://api.github.com/users/dillaman/repos","events_url":"https://api.github.com/users/dillaman/events{/privacy}","received_events_url":"https://api.github.com/users/dillaman/received_events","type":"User","site_admin":false},"body":"Minor: why the added line breaks here and below?","created_at":"2016-12-02T14:41:01Z","updated_at":"2016-12-02T14:41:01Z","html_url":"https://github.com/ceph/ceph/pull/11592#discussion_r90652291","pull_request_url":"https://api.github.com/repos/ceph/ceph/pulls/11592","_links":{"self":{"href":"https://api.github.com/repos/ceph/ceph/pulls/comments/90652291"},"html":{"href":"https://github.com/ceph/ceph/pull/11592#discussion_r90652291"},"pull_request":{"href":"https://api.github.com/repos/ceph/ceph/pulls/11592"}}},"pull_request":{"url":"https://api.github.com/repos/ceph/ceph/pulls/11592","id":90384480,"html_url":"https://github.com/ceph/ceph/pull/11592","diff_url":"https://github.com/ceph/ceph/pull/11592.diff","patch_url":"https://github.com/ceph/ceph/pull/11592.patch","issue_url":"https://api.github.com/repos/ceph/ceph/issues/11592","number":11592,"state":"open","locked":false,"title":"rbd-mirror HA: create a generic/re-usable managed lock class","user":{"login":"rjfd","id":17119885,"avatar_url":"https://avatars.githubusercontent.com/u/17119885?v=3","gravatar_id":"","url":"https://api.github.com/users/rjfd","html_url":"https://github.com/rjfd","followers_url":"https://api.github.com/users/rjfd/followers","following_url":"https://api.github.com/users/rjfd/following{/other_user}","gists_url":"https://api.github.com/users/rjfd/gists{/gist_id}","starred_url":"https://api.github.com/users/rjfd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rjfd/subscriptions","organizations_url":"https://api.github.com/users/rjfd/orgs","repos_url":"https://api.github.com/users/rjfd/repos","events_url":"https://api.github.com/users/rjfd/events{/privacy}","received_events_url":"https://api.github.com/users/rjfd/received_events","type":"User","site_admin":false},"body":"Fixes: http://tracker.ceph.com/issues/17016\n\nSigned-off-by: Ricardo Dias rdias@suse.com\n","created_at":"2016-10-21T13:37:30Z","updated_at":"2016-12-02T14:51:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a7106bfb85fb21ce6b78107d54cc960e0a5c61ae","assignee":{"login":"dillaman","id":4739042,"avatar_url":"https://avatars.githubusercontent.com/u/4739042?v=3","gravatar_id":"","url":"https://api.github.com/users/dillaman","html_url":"https://github.com/dillaman","followers_url":"https://api.github.com/users/dillaman/followers","following_url":"https://api.github.com/users/dillaman/following{/other_user}","gists_url":"https://api.github.com/users/dillaman/gists{/gist_id}","starred_url":"https://api.github.com/users/dillaman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dillaman/subscriptions","organizations_url":"https://api.github.com/users/dillaman/orgs","repos_url":"https://api.github.com/users/dillaman/repos","events_url":"https://api.github.com/users/dillaman/events{/privacy}","received_events_url":"https://api.github.com/users/dillaman/received_events","type":"User","site_admin":false},"assignees":[{"login":"dillaman","id":4739042,"avatar_url":"https://avatars.githubusercontent.com/u/4739042?v=3","gravatar_id":"","url":"https://api.github.com/users/dillaman","html_url":"https://github.com/dillaman","followers_url":"https://api.github.com/users/dillaman/followers","following_url":"https://api.github.com/users/dillaman/following{/other_user}","gists_url":"https://api.github.com/users/dillaman/gists{/gist_id}","starred_url":"https://api.github.com/users/dillaman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dillaman/subscriptions","organizations_url":"https://api.github.com/users/dillaman/orgs","repos_url":"https://api.github.com/users/dillaman/repos","events_url":"https://api.github.com/users/dillaman/events{/privacy}","received_events_url":"https://api.github.com/users/dillaman/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/ceph/ceph/pulls/11592/commits","review_comments_url":"https://api.github.com/repos/ceph/ceph/pulls/11592/comments","review_comment_url":"https://api.github.com/repos/ceph/ceph/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ceph/ceph/issues/11592/comments","statuses_url":"https://api.github.com/repos/ceph/ceph/statuses/cdf028cc68cbc52caf8452f3b9b2d352af968716","head":{"label":"rjfd:wip-17016","ref":"wip-17016","sha":"cdf028cc68cbc52caf8452f3b9b2d352af968716","user":{"login":"rjfd","id":17119885,"avatar_url":"https://avatars.githubusercontent.com/u/17119885?v=3","gravatar_id":"","url":"https://api.github.com/users/rjfd","html_url":"https://github.com/rjfd","followers_url":"https://api.github.com/users/rjfd/followers","following_url":"https://api.github.com/users/rjfd/following{/other_user}","gists_url":"https://api.github.com/users/rjfd/gists{/gist_id}","starred_url":"https://api.github.com/users/rjfd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rjfd/subscriptions","organizations_url":"https://api.github.com/users/rjfd/orgs","repos_url":"https://api.github.com/users/rjfd/repos","events_url":"https://api.github.com/users/rjfd/events{/privacy}","received_events_url":"https://api.github.com/users/rjfd/received_events","type":"User","site_admin":false},"repo":{"id":51286925,"name":"ceph","full_name":"rjfd/ceph","owner":{"login":"rjfd","id":17119885,"avatar_url":"https://avatars.githubusercontent.com/u/17119885?v=3","gravatar_id":"","url":"https://api.github.com/users/rjfd","html_url":"https://github.com/rjfd","followers_url":"https://api.github.com/users/rjfd/followers","following_url":"https://api.github.com/users/rjfd/following{/other_user}","gists_url":"https://api.github.com/users/rjfd/gists{/gist_id}","starred_url":"https://api.github.com/users/rjfd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rjfd/subscriptions","organizations_url":"https://api.github.com/users/rjfd/orgs","repos_url":"https://api.github.com/users/rjfd/repos","events_url":"https://api.github.com/users/rjfd/events{/privacy}","received_events_url":"https://api.github.com/users/rjfd/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rjfd/ceph","description":"Ceph is a distributed object, block, and file storage platform ","fork":true,"url":"https://api.github.com/repos/rjfd/ceph","forks_url":"https://api.github.com/repos/rjfd/ceph/forks","keys_url":"https://api.github.com/repos/rjfd/ceph/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rjfd/ceph/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rjfd/ceph/teams","hooks_url":"https://api.github.com/repos/rjfd/ceph/hooks","issue_events_url":"https://api.github.com/repos/rjfd/ceph/issues/events{/number}","events_url":"https://api.github.com/repos/rjfd/ceph/events","assignees_url":"https://api.github.com/repos/rjfd/ceph/assignees{/user}","branches_url":"https://api.github.com/repos/rjfd/ceph/branches{/branch}","tags_url":"https://api.github.com/repos/rjfd/ceph/tags","blobs_url":"https://api.github.com/repos/rjfd/ceph/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rjfd/ceph/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rjfd/ceph/git/refs{/sha}","trees_url":"https://api.github.com/repos/rjfd/ceph/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rjfd/ceph/statuses/{sha}","languages_url":"https://api.github.com/repos/rjfd/ceph/languages","stargazers_url":"https://api.github.com/repos/rjfd/ceph/stargazers","contributors_url":"https://api.github.com/repos/rjfd/ceph/contributors","subscribers_url":"https://api.github.com/repos/rjfd/ceph/subscribers","subscription_url":"https://api.github.com/repos/rjfd/ceph/subscription","commits_url":"https://api.github.com/repos/rjfd/ceph/commits{/sha}","git_commits_url":"https://api.github.com/repos/rjfd/ceph/git/commits{/sha}","comments_url":"https://api.github.com/repos/rjfd/ceph/comments{/number}","issue_comment_url":"https://api.github.com/repos/rjfd/ceph/issues/comments{/number}","contents_url":"https://api.github.com/repos/rjfd/ceph/contents/{+path}","compare_url":"https://api.github.com/repos/rjfd/ceph/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rjfd/ceph/merges","archive_url":"https://api.github.com/repos/rjfd/ceph/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rjfd/ceph/downloads","issues_url":"https://api.github.com/repos/rjfd/ceph/issues{/number}","pulls_url":"https://api.github.com/repos/rjfd/ceph/pulls{/number}","milestones_url":"https://api.github.com/repos/rjfd/ceph/milestones{/number}","notifications_url":"https://api.github.com/repos/rjfd/ceph/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rjfd/ceph/labels{/name}","releases_url":"https://api.github.com/repos/rjfd/ceph/releases{/id}","deployments_url":"https://api.github.com/repos/rjfd/ceph/deployments","created_at":"2016-02-08T08:44:21Z","updated_at":"2016-02-08T08:44:38Z","pushed_at":"2016-12-02T11:17:24Z","git_url":"git://github.com/rjfd/ceph.git","ssh_url":"git@github.com:rjfd/ceph.git","clone_url":"https://github.com/rjfd/ceph.git","svn_url":"https://github.com/rjfd/ceph","homepage":"http://ceph.com","size":184724,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"ceph:wip-rbd-mirror-ha","ref":"wip-rbd-mirror-ha","sha":"bddd074ccfc48f89ca2944df31081cfa6a9c446f","user":{"login":"ceph","id":1015767,"avatar_url":"https://avatars.githubusercontent.com/u/1015767?v=3","gravatar_id":"","url":"https://api.github.com/users/ceph","html_url":"https://github.com/ceph","followers_url":"https://api.github.com/users/ceph/followers","following_url":"https://api.github.com/users/ceph/following{/other_user}","gists_url":"https://api.github.com/users/ceph/gists{/gist_id}","starred_url":"https://api.github.com/users/ceph/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ceph/subscriptions","organizations_url":"https://api.github.com/users/ceph/orgs","repos_url":"https://api.github.com/users/ceph/repos","events_url":"https://api.github.com/users/ceph/events{/privacy}","received_events_url":"https://api.github.com/users/ceph/received_events","type":"Organization","site_admin":false},"repo":{"id":2310495,"name":"ceph","full_name":"ceph/ceph","owner":{"login":"ceph","id":1015767,"avatar_url":"https://avatars.githubusercontent.com/u/1015767?v=3","gravatar_id":"","url":"https://api.github.com/users/ceph","html_url":"https://github.com/ceph","followers_url":"https://api.github.com/users/ceph/followers","following_url":"https://api.github.com/users/ceph/following{/other_user}","gists_url":"https://api.github.com/users/ceph/gists{/gist_id}","starred_url":"https://api.github.com/users/ceph/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ceph/subscriptions","organizations_url":"https://api.github.com/users/ceph/orgs","repos_url":"https://api.github.com/users/ceph/repos","events_url":"https://api.github.com/users/ceph/events{/privacy}","received_events_url":"https://api.github.com/users/ceph/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ceph/ceph","description":"Ceph is a distributed object, block, and file storage platform ","fork":false,"url":"https://api.github.com/repos/ceph/ceph","forks_url":"https://api.github.com/repos/ceph/ceph/forks","keys_url":"https://api.github.com/repos/ceph/ceph/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ceph/ceph/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ceph/ceph/teams","hooks_url":"https://api.github.com/repos/ceph/ceph/hooks","issue_events_url":"https://api.github.com/repos/ceph/ceph/issues/events{/number}","events_url":"https://api.github.com/repos/ceph/ceph/events","assignees_url":"https://api.github.com/repos/ceph/ceph/assignees{/user}","branches_url":"https://api.github.com/repos/ceph/ceph/branches{/branch}","tags_url":"https://api.github.com/repos/ceph/ceph/tags","blobs_url":"https://api.github.com/repos/ceph/ceph/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ceph/ceph/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ceph/ceph/git/refs{/sha}","trees_url":"https://api.github.com/repos/ceph/ceph/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ceph/ceph/statuses/{sha}","languages_url":"https://api.github.com/repos/ceph/ceph/languages","stargazers_url":"https://api.github.com/repos/ceph/ceph/stargazers","contributors_url":"https://api.github.com/repos/ceph/ceph/contributors","subscribers_url":"https://api.github.com/repos/ceph/ceph/subscribers","subscription_url":"https://api.github.com/repos/ceph/ceph/subscription","commits_url":"https://api.github.com/repos/ceph/ceph/commits{/sha}","git_commits_url":"https://api.github.com/repos/ceph/ceph/git/commits{/sha}","comments_url":"https://api.github.com/repos/ceph/ceph/comments{/number}","issue_comment_url":"https://api.github.com/repos/ceph/ceph/issues/comments{/number}","contents_url":"https://api.github.com/repos/ceph/ceph/contents/{+path}","compare_url":"https://api.github.com/repos/ceph/ceph/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ceph/ceph/merges","archive_url":"https://api.github.com/repos/ceph/ceph/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ceph/ceph/downloads","issues_url":"https://api.github.com/repos/ceph/ceph/issues{/number}","pulls_url":"https://api.github.com/repos/ceph/ceph/pulls{/number}","milestones_url":"https://api.github.com/repos/ceph/ceph/milestones{/number}","notifications_url":"https://api.github.com/repos/ceph/ceph/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ceph/ceph/labels{/name}","releases_url":"https://api.github.com/repos/ceph/ceph/releases{/id}","deployments_url":"https://api.github.com/repos/ceph/ceph/deployments","created_at":"2011-09-01T21:41:26Z","updated_at":"2016-12-02T09:47:50Z","pushed_at":"2016-12-02T14:46:40Z","git_url":"git://github.com/ceph/ceph.git","ssh_url":"git@github.com:ceph/ceph.git","clone_url":"https://github.com/ceph/ceph.git","svn_url":"https://github.com/ceph/ceph","homepage":"http://ceph.com","size":253133,"stargazers_count":2675,"watchers_count":2675,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1565,"mirror_url":null,"open_issues_count":333,"forks":1565,"open_issues":333,"watchers":2675,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ceph/ceph/pulls/11592"},"html":{"href":"https://github.com/ceph/ceph/pull/11592"},"issue":{"href":"https://api.github.com/repos/ceph/ceph/issues/11592"},"comments":{"href":"https://api.github.com/repos/ceph/ceph/issues/11592/comments"},"review_comments":{"href":"https://api.github.com/repos/ceph/ceph/pulls/11592/comments"},"review_comment":{"href":"https://api.github.com/repos/ceph/ceph/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ceph/ceph/pulls/11592/commits"},"statuses":{"href":"https://api.github.com/repos/ceph/ceph/statuses/cdf028cc68cbc52caf8452f3b9b2d352af968716"}}}}
{"actor":{"display_login":"dillaman"}}