{"action":"created","comment":{"url":"https://api.github.com/repos/ceph/ceph/pulls/comments/188255032","pull_request_review_id":120193639,"id":188255032,"diff_hunk":"@@ -0,0 +1,938 @@\n+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-\n+// vim: ts=8 sw=2 smarttab\n+/*\n+ * Ceph - scalable distributed file system\n+ *\n+ * Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>\n+ * Copyright (C) 2014 Red Hat <contact@redhat.com>\n+ *\n+ * Author: Myna Vajha <mynaramana@gmail.com>\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU Lesser General Public\n+ *  License as published by the Free Software Foundation; either\n+ *  version 2.1 of the License, or (at your option) any later version.\n+ *\n+ */\n+\n+#include <errno.h>\n+#include <algorithm>\n+\n+#include \"include/str_map.h\"\n+#include \"common/debug.h\"\n+#include \"osd/osd_types.h\"\n+#include \"include/stringify.h\"\n+#include \"erasure-code/ErasureCodePlugin.h\"\n+\n+#include \"ErasureCodeClay.h\"\n+#include \"include/assert.h\"\n+\n+#define dout_context g_ceph_context\n+#define dout_subsys ceph_subsys_osd\n+#undef dout_prefix\n+#define dout_prefix _prefix(_dout)\n+\n+#define LARGEST_VECTOR_WORDSIZE 16\n+#define talloc(type, num) (type *) malloc(sizeof(type)*(num))\n+\n+using namespace std;\n+\n+static ostream& _prefix(std::ostream* _dout)\n+{\n+  return *_dout << \"ErasureCodeClay: \";\n+}\n+\n+static int pow_int(int a, int x){\n+  int power = 1;\n+  while (x)\n+    {\n+      if (x & 1) power *= a;\n+      x /= 2;\n+      a *= a;\n+    }\n+  return power;\n+}\n+\n+int ErasureCodeClay::init(ErasureCodeProfile &profile,\n+\t\t\t  ostream *ss)\n+{\n+  int r;\n+  r = parse(profile, ss);\n+  if (r)\n+    return r;\n+\n+  ErasureCode::init(profile, ss);\n+  ErasureCodePluginRegistry &registry = ErasureCodePluginRegistry::instance();\n+  r = registry.factory(mds.profile[\"plugin\"],\n+\t\t       directory,\n+\t\t       mds.profile,\n+\t\t       &mds.erasure_code,\n+\t\t       ss);\n+  if (r) return r;\n+  r = registry.factory(pft.profile[\"plugin\"],\n+\t\t       directory,\n+\t\t       pft.profile,\n+\t\t       &pft.erasure_code,\n+\t\t       ss);\n+  return r;\n+\n+}\n+\n+unsigned int ErasureCodeClay::get_chunk_size(unsigned int object_size) const\n+{\n+  unsigned alignment = get_alignment();\n+  unsigned tail = object_size % alignment;\n+  unsigned padded_length = object_size + ( tail ?  ( alignment - tail ) : 0 );\n+  \n+  assert(padded_length % (k*sub_chunk_no) == 0);\n+  \n+  return padded_length/k;\n+}\n+\n+int ErasureCodeClay::minimum_to_decode(const set<int> &want_to_read,\n+\t\t\t\t       const set<int> &available,\n+\t\t\t\t       map<int, vector<pair<int, int>>> *minimum)\n+{\n+  set<int> minimum_shard_ids;\n+\n+  if (is_repair(want_to_read, available)) {\n+    int r = minimum_to_repair(want_to_read, available, &minimum_shard_ids);\n+    map<int, int> repair_subchunks;\n+    get_repair_subchunks(want_to_read, minimum_shard_ids,\n+\t\t\t 0, repair_subchunks);\n+    vector<pair<int,int>> grouped_repair_subchunks;\n+    group_repair_subchunks(repair_subchunks, grouped_repair_subchunks);\n+\n+    for (set<int>::iterator i=minimum_shard_ids.begin();\n+\t i != minimum_shard_ids.end(); ++i) {\n+      minimum->insert(make_pair(*i, grouped_repair_subchunks));\n+    }\n+    return r;\n+  } else {\n+    return ErasureCode::minimum_to_decode(want_to_read, available, minimum);\n+  }\n+}\n+\n+int ErasureCodeClay::decode(const set<int> &want_to_read,\n+\t\t\t    const map<int, bufferlist> &chunks,\n+\t\t\t    map<int, bufferlist> *decoded, int chunk_size)\n+{\n+  set<int> avail;\n+  for (map<int, bufferlist>::const_iterator i = chunks.begin();\n+       i != chunks.end(); ++i) {\n+    avail.insert(i->first);\n+  }\n+\n+  if (is_repair(want_to_read, avail)) {\n+    return repair(want_to_read, chunks, decoded);\n+  } else {\n+    return ErasureCode::_decode(want_to_read, chunks, decoded);\n+  }\n+}\n+\n+void p(const set<int> &s) { cerr << s; } // for gdb\n+\n+int ErasureCodeClay::encode_chunks(const set<int> &want_to_encode,\n+\t\t\t\t   map<int, bufferlist> *encoded)\n+{\n+  map<int, bufferlist> chunks;\n+  set<int> parity_chunks;\n+  int chunk_size = (*encoded)[0].length();\n+  \n+  for (int i = 0; i < k + m; i++) {\n+    if (i < k) {\n+      chunks[i] = (*encoded)[i];\n+    } else {\n+      chunks[i+nu] = (*encoded)[i];\n+      parity_chunks.insert(i+nu);\n+    }\n+  }\n+  \n+  for (int i = k; i < k+nu; i++) {\n+    bufferptr buf(buffer::create_aligned(chunk_size, SIMD_ALIGN));\n+    buf.zero();\n+    chunks[i].push_back(std::move(buf));  \n+  }\n+  \n+  int res = decode_layered(parity_chunks, &chunks);\n+  for (int i = k ; i < k+nu; i++) {\n+    //need to clean some of the intermediate chunks here!!\n+    chunks[i].clear();\n+  }\n+  return res;\n+}\n+\n+int ErasureCodeClay::decode_chunks(const set<int> &want_to_read,\n+\t\t\t\t   const map<int, bufferlist> &chunks,\n+\t\t\t\t   map<int, bufferlist> *decoded)\n+{\n+  set<int> erasures;\n+  map<int, bufferlist> coded_chunks;\n+ \n+  dout(10)<< __func__ << \" want_to_read:\" << want_to_read << \" chunks:\"<< chunks << \" decoded:\" << *decoded << dendl;\n+  for (int i = 0; i < k + m; i++) {\n+    if (chunks.find(i) == chunks.end()) {\n+      erasures.insert(i < k ? i : i+nu);\n+    }\n+    assert((*decoded).find(i) != (*decoded).end());\n+    coded_chunks[i < k ? i : i+nu] = (*decoded)[i];\n+  }\n+  int chunk_size = coded_chunks[0].length();\n+  \n+  for (int i = k; i < k+nu; i++) {\n+    bufferptr buf(buffer::create_aligned(chunk_size, SIMD_ALIGN));\n+    buf.zero();\n+    coded_chunks[i].push_back(std::move(buf));  \n+  }\n+\t\n+  int res = decode_layered(erasures, &coded_chunks);\n+  for (int i = k; i < k+nu; i++) {\n+    coded_chunks[i].clear();  \n+  }\n+  return res;\n+}\n+\n+unsigned int ErasureCodeClay::get_alignment() const\n+{\n+  unsigned alignment = k*sub_chunk_no*w*sizeof(int);\n+  if ((w*sizeof(int))%LARGEST_VECTOR_WORDSIZE)\n+    alignment = k*sub_chunk_no*w*LARGEST_VECTOR_WORDSIZE;\n+  return alignment;\n+}\n+\n+int ErasureCodeClay::parse(ErasureCodeProfile &profile,\n+\t\t\t   ostream *ss)\n+{\n+  int err = 0;\n+  err = ErasureCode::parse(profile, ss);\n+  err |= to_int(\"k\", profile, &k, DEFAULT_K, ss);\n+  err |= to_int(\"m\", profile, &m, DEFAULT_M, ss);\n+  err |= to_int(\"w\", profile, &w, DEFAULT_W, ss);\n+  \n+  err |= sanity_check_k(k, ss);\n+\n+  err |= to_int(\"d\", profile, &d, std::to_string(k+m-1), ss);\n+\n+  //check for mds block input\n+  if (profile.find(\"scalar_mds\") == profile.end() ||\n+      profile.find(\"scalar_mds\")->second.size() == 0) {\n+    mds.profile[\"plugin\"] = \"jerasure\";\n+    pft.profile[\"plugin\"] = \"jerasure\";\n+    *ss << \"scalar_mds not found in profile picking default jerasure\" << std::endl;\n+  } else {\n+    std::string p = profile.find(\"scalar_mds\")->second;\n+    *ss << \"recieved scalar_mds as \" << p << std::endl;\n+\n+    if ((p == \"jerasure\") || (p == \"isal\")) {\n+      mds.profile[\"plugin\"] = p;\n+      pft.profile[\"plugin\"] = p;\n+    }\n+    else {\n+      mds.profile[\"plugin\"] = \"jerasure\";\n+      pft.profile[\"plugin\"] = \"jerasure\";\n+      *ss << \"scalar_mds \" << p << \"is not currently supported using the default reed_sol_van\" << std::endl;\n+    }\n+  }\n+\n+  if (profile.find(\"technique\") == profile.end() ||\n+      profile.find(\"technique\")->second.size() == 0) {\n+    mds.profile[\"technique\"] = \"reed_sol_van\";\n+    pft.profile[\"technique\"] = \"reed_sol_van\";\n+    *ss << \"technique not found in profile picking default reed_sol_van\" << std::endl;\n+  } else {\n+    std::string p = profile.find(\"technique\")->second;\n+    *ss << \"recieved technique as \" << p << std::endl;\n+    mds.profile[\"technique\"] = p;\n+    pft.profile[\"technique\"] = p;\n+  }\n+  \n+  if ((d < k) || (d > k+m-1)) {\n+    *ss << \"value of d \" << d\n+        << \" must be within [ \" << k << \",\" << k+m-1 << \"]\" << std::endl;\n+    err = -EINVAL;\n+    return err;\n+  }\n+  \n+  q = d-k+1;\n+  if ((k+m)%q) {\n+    nu = q - (k+m)%q;\n+    *ss << \"Clay: (k+m)%q=\" << (k+m)%q\n+\t<< \"q doesn't divide k+m, to use shortening\" << std::endl;\n+  } else {\n+    nu = 0;\n+  }\n+\n+  if (k+m+nu > 254) {\n+    err = -EINVAL;\n+    return err;\n+  }\n+  \n+  mds.profile[\"k\"] = std::to_string(k+nu);\n+  mds.profile[\"m\"] = std::to_string(m);\n+  mds.profile[\"w\"] = '8';\n+  \n+  pft.profile[\"k\"] = '2';\n+  pft.profile[\"m\"] = '2';\n+  pft.profile[\"w\"] = '8';\n+  \n+  dout(10) << __func__ << \" k:\" << k << \" m: \" << m << \" w:\" << w << dendl;\n+    \n+  t = (k+m+nu)/q;\n+  sub_chunk_no = pow_int(q, t); \n+\n+  return 0;\n+}\n+\n+int ErasureCodeClay::get_repair_sub_chunk_count(const set<int> &want_to_read)\n+{\n+  int repair_subchunks_count = 1;\n+\n+  int weight_vector[t];\n+  memset(weight_vector, 0, t*sizeof(int));\n+\n+  for (set<int>::iterator i = want_to_read.begin();\n+       i != want_to_read.end(); ++i) {\n+    weight_vector[(*i)/q]++;\n+  }\n+\n+  for (int y = 0; y < t; y++) repair_subchunks_count = repair_subchunks_count*(q-weight_vector[y]);\n+\n+  return sub_chunk_no - repair_subchunks_count;\n+}\n+\n+int ErasureCodeClay::is_repair(const set<int> &want_to_read,\n+\t\t\t       const set<int> &available_chunks) {\n+\n+  if (includes(\n+\t       available_chunks.begin(), available_chunks.end(), want_to_read.begin(), want_to_read.end())) return 0;\n+\n+  if (want_to_read.size() > 1) return 0;","path":"src/erasure-code/clay/ErasureCodeClay.cc","position":309,"original_position":309,"commit_id":"32ebc530b99153ed33abdd2230096869cda38ca2","original_commit_id":"32ebc530b99153ed33abdd2230096869cda38ca2","user":{"login":"bbaiyhaor","id":6240241,"avatar_url":"https://avatars2.githubusercontent.com/u/6240241?v=4","gravatar_id":"","url":"https://api.github.com/users/bbaiyhaor","html_url":"https://github.com/bbaiyhaor","followers_url":"https://api.github.com/users/bbaiyhaor/followers","following_url":"https://api.github.com/users/bbaiyhaor/following{/other_user}","gists_url":"https://api.github.com/users/bbaiyhaor/gists{/gist_id}","starred_url":"https://api.github.com/users/bbaiyhaor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bbaiyhaor/subscriptions","organizations_url":"https://api.github.com/users/bbaiyhaor/orgs","repos_url":"https://api.github.com/users/bbaiyhaor/repos","events_url":"https://api.github.com/users/bbaiyhaor/events{/privacy}","received_events_url":"https://api.github.com/users/bbaiyhaor/received_events","type":"User","site_admin":false},"body":"Excuse me, I have questions that why if want_to_read.size() > 1 then return 0? If so it does not repair in the example in the appendix of 'Clay Codes: Moulding MDS Codes to Yield an MSR Code, two failures (0,0) and (0,1), if both stored in want_to_read, in different y-section with parameters(n=14, k=10, d=11)? And if want_to_read.size() = 1 then the code between line 311 and line 321 can be optimized to the following？\r\n\r\nint i =*want_to_read.begin();\r\nint lost_node_id = (i < k) ? i: i+nu;\r\nfor (int x = 0; x < q; x++) {\r\n&nbsp;&nbsp;&nbsp;&nbsp;int node = (lost_node_id/q)*q+x;\r\n&nbsp;&nbsp;&nbsp;&nbsp;node = (node < k) ? node : node-nu;\r\n&nbsp;&nbsp;&nbsp;&nbsp;if (node != lost_node_id) {//node from same group not erased\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (available_chunks.find(node) == available_chunks.end()) return 0;//node from same group not available as well\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n}\r\n","created_at":"2018-05-15T11:40:33Z","updated_at":"2018-05-15T11:40:42Z","html_url":"https://github.com/ceph/ceph/pull/14300#discussion_r188255032","pull_request_url":"https://api.github.com/repos/ceph/ceph/pulls/14300","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/ceph/ceph/pulls/comments/188255032"},"html":{"href":"https://github.com/ceph/ceph/pull/14300#discussion_r188255032"},"pull_request":{"href":"https://api.github.com/repos/ceph/ceph/pulls/14300"}}},"pull_request":{"url":"https://api.github.com/repos/ceph/ceph/pulls/14300","id":113918907,"html_url":"https://github.com/ceph/ceph/pull/14300","diff_url":"https://github.com/ceph/ceph/pull/14300.diff","patch_url":"https://github.com/ceph/ceph/pull/14300.patch","issue_url":"https://api.github.com/repos/ceph/ceph/issues/14300","number":14300,"state":"open","locked":false,"title":"Coupled Layer MSR codes (Optimal Repair Network, Disk Traffic).","user":{"login":"mynaramana","id":7104445,"avatar_url":"https://avatars1.githubusercontent.com/u/7104445?v=4","gravatar_id":"","url":"https://api.github.com/users/mynaramana","html_url":"https://github.com/mynaramana","followers_url":"https://api.github.com/users/mynaramana/followers","following_url":"https://api.github.com/users/mynaramana/following{/other_user}","gists_url":"https://api.github.com/users/mynaramana/gists{/gist_id}","starred_url":"https://api.github.com/users/mynaramana/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mynaramana/subscriptions","organizations_url":"https://api.github.com/users/mynaramana/orgs","repos_url":"https://api.github.com/users/mynaramana/repos","events_url":"https://api.github.com/users/mynaramana/events{/privacy}","received_events_url":"https://api.github.com/users/mynaramana/received_events","type":"User","site_admin":false},"body":"Introducing Coupled Layer MSR codes to ceph. These codes are optimal\r\nin terms of network, disk traffic utilized during repair of a lost chunk.\r\nThis feature also provides gradual increase in network, disk traffic with\r\nrespect to the number of lost chunks.\r\n\r\nThe code introduced in ECBackend, ErasureCodeInterface, eases implementation\r\nof any new array codes.\r\n\r\nAuthors: Myna, Elita.\r\n\r\nhttp://tracker.ceph.com/issues/19278","created_at":"2017-04-03T12:28:04Z","updated_at":"2018-05-15T11:40:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3b39bcbf75087343f45ee530b618e12be7fe0b41","assignee":{"login":"liewegas","id":433031,"avatar_url":"https://avatars1.githubusercontent.com/u/433031?v=4","gravatar_id":"","url":"https://api.github.com/users/liewegas","html_url":"https://github.com/liewegas","followers_url":"https://api.github.com/users/liewegas/followers","following_url":"https://api.github.com/users/liewegas/following{/other_user}","gists_url":"https://api.github.com/users/liewegas/gists{/gist_id}","starred_url":"https://api.github.com/users/liewegas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liewegas/subscriptions","organizations_url":"https://api.github.com/users/liewegas/orgs","repos_url":"https://api.github.com/users/liewegas/repos","events_url":"https://api.github.com/users/liewegas/events{/privacy}","received_events_url":"https://api.github.com/users/liewegas/received_events","type":"User","site_admin":false},"assignees":[{"login":"liewegas","id":433031,"avatar_url":"https://avatars1.githubusercontent.com/u/433031?v=4","gravatar_id":"","url":"https://api.github.com/users/liewegas","html_url":"https://github.com/liewegas","followers_url":"https://api.github.com/users/liewegas/followers","following_url":"https://api.github.com/users/liewegas/following{/other_user}","gists_url":"https://api.github.com/users/liewegas/gists{/gist_id}","starred_url":"https://api.github.com/users/liewegas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liewegas/subscriptions","organizations_url":"https://api.github.com/users/liewegas/orgs","repos_url":"https://api.github.com/users/liewegas/repos","events_url":"https://api.github.com/users/liewegas/events{/privacy}","received_events_url":"https://api.github.com/users/liewegas/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":144329561,"url":"https://api.github.com/repos/ceph/ceph/labels/core","name":"core","color":"0041a2","default":false},{"id":134774006,"url":"https://api.github.com/repos/ceph/ceph/labels/feature","name":"feature","color":"00ff24","default":false},{"id":340048817,"url":"https://api.github.com/repos/ceph/ceph/labels/needs-review","name":"needs-review","color":"d4c5f9","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/ceph/ceph/pulls/14300/commits","review_comments_url":"https://api.github.com/repos/ceph/ceph/pulls/14300/comments","review_comment_url":"https://api.github.com/repos/ceph/ceph/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ceph/ceph/issues/14300/comments","statuses_url":"https://api.github.com/repos/ceph/ceph/statuses/32ebc530b99153ed33abdd2230096869cda38ca2","head":{"label":"mynaramana:fix_1","ref":"fix_1","sha":"32ebc530b99153ed33abdd2230096869cda38ca2","user":{"login":"mynaramana","id":7104445,"avatar_url":"https://avatars1.githubusercontent.com/u/7104445?v=4","gravatar_id":"","url":"https://api.github.com/users/mynaramana","html_url":"https://github.com/mynaramana","followers_url":"https://api.github.com/users/mynaramana/followers","following_url":"https://api.github.com/users/mynaramana/following{/other_user}","gists_url":"https://api.github.com/users/mynaramana/gists{/gist_id}","starred_url":"https://api.github.com/users/mynaramana/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mynaramana/subscriptions","organizations_url":"https://api.github.com/users/mynaramana/orgs","repos_url":"https://api.github.com/users/mynaramana/repos","events_url":"https://api.github.com/users/mynaramana/events{/privacy}","received_events_url":"https://api.github.com/users/mynaramana/received_events","type":"User","site_admin":false},"repo":{"id":81206996,"name":"ceph","full_name":"mynaramana/ceph","owner":{"login":"mynaramana","id":7104445,"avatar_url":"https://avatars1.githubusercontent.com/u/7104445?v=4","gravatar_id":"","url":"https://api.github.com/users/mynaramana","html_url":"https://github.com/mynaramana","followers_url":"https://api.github.com/users/mynaramana/followers","following_url":"https://api.github.com/users/mynaramana/following{/other_user}","gists_url":"https://api.github.com/users/mynaramana/gists{/gist_id}","starred_url":"https://api.github.com/users/mynaramana/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mynaramana/subscriptions","organizations_url":"https://api.github.com/users/mynaramana/orgs","repos_url":"https://api.github.com/users/mynaramana/repos","events_url":"https://api.github.com/users/mynaramana/events{/privacy}","received_events_url":"https://api.github.com/users/mynaramana/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mynaramana/ceph","description":"Ceph is a distributed object, block, and file storage platform ","fork":true,"url":"https://api.github.com/repos/mynaramana/ceph","forks_url":"https://api.github.com/repos/mynaramana/ceph/forks","keys_url":"https://api.github.com/repos/mynaramana/ceph/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mynaramana/ceph/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mynaramana/ceph/teams","hooks_url":"https://api.github.com/repos/mynaramana/ceph/hooks","issue_events_url":"https://api.github.com/repos/mynaramana/ceph/issues/events{/number}","events_url":"https://api.github.com/repos/mynaramana/ceph/events","assignees_url":"https://api.github.com/repos/mynaramana/ceph/assignees{/user}","branches_url":"https://api.github.com/repos/mynaramana/ceph/branches{/branch}","tags_url":"https://api.github.com/repos/mynaramana/ceph/tags","blobs_url":"https://api.github.com/repos/mynaramana/ceph/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mynaramana/ceph/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mynaramana/ceph/git/refs{/sha}","trees_url":"https://api.github.com/repos/mynaramana/ceph/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mynaramana/ceph/statuses/{sha}","languages_url":"https://api.github.com/repos/mynaramana/ceph/languages","stargazers_url":"https://api.github.com/repos/mynaramana/ceph/stargazers","contributors_url":"https://api.github.com/repos/mynaramana/ceph/contributors","subscribers_url":"https://api.github.com/repos/mynaramana/ceph/subscribers","subscription_url":"https://api.github.com/repos/mynaramana/ceph/subscription","commits_url":"https://api.github.com/repos/mynaramana/ceph/commits{/sha}","git_commits_url":"https://api.github.com/repos/mynaramana/ceph/git/commits{/sha}","comments_url":"https://api.github.com/repos/mynaramana/ceph/comments{/number}","issue_comment_url":"https://api.github.com/repos/mynaramana/ceph/issues/comments{/number}","contents_url":"https://api.github.com/repos/mynaramana/ceph/contents/{+path}","compare_url":"https://api.github.com/repos/mynaramana/ceph/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mynaramana/ceph/merges","archive_url":"https://api.github.com/repos/mynaramana/ceph/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mynaramana/ceph/downloads","issues_url":"https://api.github.com/repos/mynaramana/ceph/issues{/number}","pulls_url":"https://api.github.com/repos/mynaramana/ceph/pulls{/number}","milestones_url":"https://api.github.com/repos/mynaramana/ceph/milestones{/number}","notifications_url":"https://api.github.com/repos/mynaramana/ceph/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mynaramana/ceph/labels{/name}","releases_url":"https://api.github.com/repos/mynaramana/ceph/releases{/id}","deployments_url":"https://api.github.com/repos/mynaramana/ceph/deployments","created_at":"2017-02-07T12:44:58Z","updated_at":"2018-04-13T02:19:52Z","pushed_at":"2018-05-03T01:19:29Z","git_url":"git://github.com/mynaramana/ceph.git","ssh_url":"git@github.com:mynaramana/ceph.git","clone_url":"https://github.com/mynaramana/ceph.git","svn_url":"https://github.com/mynaramana/ceph","homepage":"http://ceph.com","size":253687,"stargazers_count":1,"watchers_count":1,"language":"C++","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":3,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"ceph:master","ref":"master","sha":"135fe40dee2ec3db22a43a9c30ef7a10b482c596","user":{"login":"ceph","id":1015767,"avatar_url":"https://avatars3.githubusercontent.com/u/1015767?v=4","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://avatars3.githubusercontent.com/u/1015767?v=4","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":"2018-05-15T10:21:56Z","pushed_at":"2018-05-15T11:35:27Z","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":282638,"stargazers_count":4491,"watchers_count":4491,"language":"C++","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2436,"mirror_url":null,"archived":false,"open_issues_count":690,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":2436,"open_issues":690,"watchers":4491,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ceph/ceph/pulls/14300"},"html":{"href":"https://github.com/ceph/ceph/pull/14300"},"issue":{"href":"https://api.github.com/repos/ceph/ceph/issues/14300"},"comments":{"href":"https://api.github.com/repos/ceph/ceph/issues/14300/comments"},"review_comments":{"href":"https://api.github.com/repos/ceph/ceph/pulls/14300/comments"},"review_comment":{"href":"https://api.github.com/repos/ceph/ceph/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ceph/ceph/pulls/14300/commits"},"statuses":{"href":"https://api.github.com/repos/ceph/ceph/statuses/32ebc530b99153ed33abdd2230096869cda38ca2"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"bbaiyhaor"}}