{"action":"created","comment":{"url":"https://api.github.com/repos/ceph/ceph/pulls/comments/67555332","id":67555332,"diff_hunk":"@@ -0,0 +1,546 @@\n+#include <string.h>\n+#include <iostream>\n+#include <map>\n+\n+#include \"include/types.h\"\n+\n+#include \"common/Formatter.h\"\n+#include <common/errno.h>\n+#include \"auth/Crypto.h\"\n+#include \"include/rados/librados.hpp\"\n+#include \"cls/rgw/cls_rgw_client.h\"\n+#include \"cls/refcount/cls_refcount_client.h\"\n+#include \"cls/lock/cls_lock_client.h\"\n+#include <common/dout.h>\n+#include \"rgw_common.h\"\n+#include \"rgw_bucket.h\"\n+#include \"rgw_lc.h\"\n+#include \"rgw_lc_s3.h\"\n+\n+\n+\n+#define dout_subsys ceph_subsys_rgw\n+\n+const char* LC_STATUS[] = {\n+      \"UNINITIAL\",\n+      \"PROCESSING\",\n+      \"FAILED\",\n+      \"COMPLETE\"\n+};\n+\n+using namespace std;\n+using namespace librados;\n+void RGWLifecycleConfiguration::add_rule(LCRule *rule)\n+{\n+  string id;\n+  rule->get_id(id); // not that this will return false for groups, but that's ok, we won't search groups\n+  rule_map.insert(pair<string, LCRule>(id, *rule));\n+  _add_rule(rule);\n+}\n+\n+void RGWLifecycleConfiguration::_add_rule(LCRule *rule)\n+{\n+  string prefix;\n+  LCExpiration expiration;\n+  int days;\n+  if (!rule->get_prefix(prefix)) {\n+    ldout(cct, 5) << \"ERROR: rule->get_prefix() failed\" << dendl;\n+  }\n+  if (!rule->get_expiration(expiration)) {\n+    ldout(cct, 5) << \"ERROR: rule->get_expiration() failed\" << dendl;\n+  }\n+  if (!expiration.get_days(&days)) {\n+    ldout(cct, 5) << \"ERROR: expiration->get_days() failed\" << dendl;\n+  }\n+  prefix_map[prefix] = days;\n+}\n+\n+void *RGWLC::LCWorker::entry() {\n+  do {\n+    utime_t start = ceph_clock_now(cct);\n+    if (should_work(start)) {\n+      dout(5) << \"life cycle: start\" << dendl;\n+      int r = lc->process();\n+      if (r < 0) {\n+        dout(0) << \"ERROR: do life cycle process() returned error r=\" << r << dendl;\n+      }\n+      dout(5) << \"life cycle: stop\" << dendl;\n+    }\n+    if (lc->going_down())\n+      break;\n+\n+    utime_t end = ceph_clock_now(cct);   \n+    int secs = shedule_next_start_time(end);\n+    time_t next_time = end + secs;\n+    char buf[30];\n+    char *nt = ctime_r(&next_time, buf);\n+    dout(5) << \"shedule life cycle next start time: \" << nt <<dendl;\n+\n+    lock.Lock();\n+    cond.WaitInterval(cct, lock, utime_t(secs, 0));\n+    lock.Unlock();\n+  } while (!lc->going_down());\n+\n+  return NULL;\n+}\n+\n+void RGWLC::initialize(CephContext *_cct, RGWRados *_store) {\n+  cct = _cct;\n+  store = _store;\n+  max_objs = cct->_conf->rgw_lc_max_objs;\n+  if (max_objs > HASH_PRIME)\n+    max_objs = HASH_PRIME;\n+\n+  obj_names = new string[max_objs];\n+\n+  for (int i = 0; i < max_objs; i++) {\n+    obj_names[i] = lc_oid_prefix;\n+    char buf[32];\n+    snprintf(buf, 32, \".%d\", i);\n+    obj_names[i].append(buf);\n+  }\n+}\n+\n+void RGWLC::finalize()\n+{\n+  delete[] obj_names;\n+}\n+\n+bool RGWLC::if_already_run_today(time_t& start_date)\n+{\n+  struct tm bdt;\n+  time_t begin_of_day;\n+  utime_t now = ceph_clock_now(cct);\n+  localtime_r(&start_date, &bdt);\n+  bdt.tm_hour = 0;\n+  bdt.tm_min = 0;\n+  bdt.tm_sec = 0;\n+  begin_of_day = mktime(&bdt);\n+  if (now - begin_of_day < 24*60*60)\n+    return true;\n+  else   \n+    return false;\n+}\n+\n+static std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {\n+  std::stringstream ss(s);\n+  std::string item;\n+  while (std::getline(ss, item, delim)) {\n+      elems.push_back(item);\n+  }\n+  return elems;\n+}\n+\n+static std::vector<std::string> split(const std::string &s, char delim) {\n+  std::vector<std::string> elems;\n+  split(s, delim, elems);\n+  return elems;\n+}\n+\n+int RGWLC::bucket_lc_prepare(int index)\n+{\n+  map<string, int > entries;\n+\n+  string marker;\n+\n+#define MAX_LC_LIST_ENTRIES 100\n+  do {\n+    int ret = cls_rgw_lc_list(store->lc_pool_ctx, obj_names[index], marker, MAX_LC_LIST_ENTRIES, entries);\n+    if (ret < 0)\n+      return ret;\n+    map<string, int>::iterator iter;\n+    for (iter = entries.begin(); iter != entries.end(); ++iter) {\n+      pair<string, int > entry(iter->first, lc_uninitial);\n+      ret = cls_rgw_lc_set_entry(store->lc_pool_ctx, obj_names[index],  entry);\n+      if (ret < 0) {\n+        dout(0) << \"RGWLC::bucket_lc_prepare() failed to set entry \" << obj_names[index] << dendl;\n+        break;\n+      }\n+      marker = iter->first;\n+    }\n+  } while (!entries.empty());\n+\n+  return 0;\n+}\n+\n+int RGWLC::bucket_lc_process(string& shard_id)\n+{\n+  RGWLifecycleConfiguration  config(cct);\n+  RGWBucketInfo bucket_info;\n+  map<string, bufferlist> bucket_attrs;\n+  string prefix, delimiter, marker, next_marker, no_ns, end_marker, list_versions;\n+  bool is_truncated;\n+  bool default_config = false;\n+  int default_days = 0;\n+  vector<RGWObjEnt> objs; \n+  RGWObjectCtx obj_ctx(store);\n+  map<string, bool> common_prefixes;\n+  vector<std::string> result;\n+  result = split(shard_id, ':');\n+  string bucket_tenant = result[0];\n+  string bucket_name = result[1];\n+  string bucket_id = result[2];\n+  int ret = store->get_bucket_info(obj_ctx, bucket_tenant, bucket_name, bucket_info, NULL, &bucket_attrs);\n+  if (ret < 0) {\n+    ldout(cct, 0) << \"LC:get_bucket_info failed\" << bucket_name <<dendl;\n+    return ret;\n+  }\n+\n+  ret = bucket_info.bucket.bucket_id.compare(bucket_id) ;\n+  if (ret !=0) {\n+    ldout(cct, 0) << \"LC:old bucket id find, should be delete\" << bucket_name <<dendl;\n+    return -ENOENT;\n+  }\n+  \n+  RGWRados::Bucket target(store, bucket_info);\n+  RGWRados::Bucket::List list_op(&target);\n+\n+  list_op.params.prefix = prefix;\n+  list_op.params.delim = delimiter;\n+  list_op.params.marker = marker;\n+  list_op.params.end_marker = end_marker;\n+  list_op.params.list_versions = false;\n+   \n+  map<string, bufferlist>::iterator aiter = bucket_attrs.find(RGW_ATTR_LC);\n+  if (aiter == bucket_attrs.end())\n+    return 0;\n+  \n+  bufferlist::iterator iter(&aiter->second);\n+  try {\n+      config.decode(iter);\n+    } catch (const buffer::error& e) {\n+      ldout(cct, 0) << __func__ <<  \"decode life cycle config failed\" << dendl;\n+      return -1;\n+    }\n+\n+  map<string, int>& prefix_map = config.get_prefix_map();\n+  for(map<string, int>::iterator prefix_iter = prefix_map.begin(); prefix_iter != prefix_map.end();  prefix_iter++) {\n+    if (prefix_iter->first.empty()) {\n+      default_config = true;\n+      default_days = prefix_iter->second;\n+      continue;\n+    }\n+  }\n+\n+  if (default_config) { \n+    do {\n+      \n+      objs.clear();\n+      list_op.params.marker = list_op.get_next_marker();\n+      ret = list_op.list_objects(1000, &objs, &common_prefixes, &is_truncated);    \n+      if (ret < 0) {\n+        if (ret == -ENOENT)\n+          return 0;\n+        ldout(cct, 0) << \"ERROR: store->list_objects():\" <<dendl;\n+        return ret;\n+      }\n+\n+      vector<RGWObjEnt>::iterator obj_iter;\n+      int pos = 0;\n+      utime_t now = ceph_clock_now(cct);\n+      for (obj_iter = objs.begin(); obj_iter != objs.end(); obj_iter++) {\n+        bool prefix_match = false;\n+        int match_days = 0;        \n+        map<string, int>& prefix_map = config.get_prefix_map();\n+        \n+        for(map<string, int>::iterator prefix_iter = prefix_map.begin(); prefix_iter != prefix_map.end();  prefix_iter++) {\n+          if (prefix_iter->first.empty()) {\n+            continue;\n+          }\n+          pos = (*obj_iter).key.name.find(prefix_iter->first, 0);\n+          if (pos != 0) {\n+            continue;\n+          }\n+          prefix_match = true;\n+          match_days = prefix_iter->second;\n+          break;\n+        }\n+        int days = 0;      \n+        if (prefix_match) {\n+          days = match_days;\n+        } else if (default_config) {\n+          days = default_days;\n+        } else {\n+          continue;\n+        }        \n+        if (now - ceph::real_clock::to_time_t((*obj_iter).mtime) >= days*24*60*60) {\n+          RGWObjectCtx rctx(store);\n+          rgw_obj obj(bucket_info.bucket, (*obj_iter).key.name);\n+          RGWObjState *state;\n+          int ret = store->get_obj_state(&rctx, obj, &state, false);\n+          if (ret < 0) {\n+            return ret;\n+          }\n+          if (state->mtime != (*obj_iter).mtime) //Check mtime again to avoid delete a recently update object as much as possible\n+            continue;\n+          ret = rgw_remove_object(store, bucket_info, bucket_info.bucket, (*obj_iter).key);\n+          if (ret < 0) {\n+            ldout(cct, 0) << \"ERROR: rgw_remove_object \" << dendl;\n+          } else {\n+            ldout(cct, 10) << \"DELETED:\" << bucket_name << \":\" << (*obj_iter).key.name <<dendl;\n+          }\n+        }\n+      }    \n+    } while (is_truncated);\n+  } else {\n+    for(map<string, int>::iterator prefix_iter = prefix_map.begin(); prefix_iter != prefix_map.end();  prefix_iter++) {\n+      if (prefix_iter->first.empty()) {\n+        continue;\n+      }\n+      list_op.params.prefix = prefix_iter->first;\n+\n+      do {\n+\n+        objs.clear();\n+        list_op.params.marker = list_op.get_next_marker();          \n+        ret = list_op.list_objects(1000, &objs, &common_prefixes, &is_truncated); \n+\n+        if (ret < 0) {\n+          if (ret == (-ENOENT))\n+            return 0;\n+          ldout(cct, 0) << \"ERROR: store->list_objects():\" <<dendl;\n+          return ret;\n+        }\n+\n+        vector<RGWObjEnt>::iterator obj_iter;\n+        int days = prefix_iter->second;           \n+        utime_t now = ceph_clock_now(cct);\n+\n+        for (obj_iter = objs.begin(); obj_iter != objs.end(); obj_iter++) {                  \n+          if (now - ceph::real_clock::to_time_t((*obj_iter).mtime) >= days*24*60*60) {\n+            RGWObjectCtx rctx(store);\n+            rgw_obj obj(bucket_info.bucket, (*obj_iter).key.name);\n+            RGWObjState *state;\n+            int ret = store->get_obj_state(&rctx, obj, &state, false); \n+            if (ret < 0) {\n+              return ret;\n+            }\n+            if (state->mtime != (*obj_iter).mtime)//Check mtime again to avoid delete a recently update object as much as possible\n+              continue;\n+            ret = rgw_remove_object(store, bucket_info, bucket_info.bucket, (*obj_iter).key);\n+            if (ret < 0) {\n+              ldout(cct, 0) << \"ERROR: rgw_remove_object \" << dendl;\n+            } else {\n+              ldout(cct, 10) << \"DELETED:\" << bucket_name << \":\" << (*obj_iter).key.name << dendl;\n+            }\n+          }\n+        }\n+      } while (is_truncated);\n+    }     \n+  }\n+\n+  return ret;\n+}\n+\n+int RGWLC::bucket_lc_post(int index, int max_lock_sec, cls_rgw_lc_obj_head& head, ","path":"src/rgw/rgw_lc.cc","position":335,"original_position":335,"commit_id":"c84f59f1d286ac58c2e799f92bbf791cfdaa09a6","original_commit_id":"c84f59f1d286ac58c2e799f92bbf791cfdaa09a6","user":{"login":"dang","id":7334,"avatar_url":"https://avatars.githubusercontent.com/u/7334?v=3","gravatar_id":"","url":"https://api.github.com/users/dang","html_url":"https://github.com/dang","followers_url":"https://api.github.com/users/dang/followers","following_url":"https://api.github.com/users/dang/following{/other_user}","gists_url":"https://api.github.com/users/dang/gists{/gist_id}","starred_url":"https://api.github.com/users/dang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dang/subscriptions","organizations_url":"https://api.github.com/users/dang/orgs","repos_url":"https://api.github.com/users/dang/repos","events_url":"https://api.github.com/users/dang/events{/privacy}","received_events_url":"https://api.github.com/users/dang/received_events","type":"User","site_admin":false},"body":"This only returns 0, even on error.  If this is on purpose, why not a void return?","created_at":"2016-06-17T18:31:01Z","updated_at":"2016-06-17T18:31:01Z","html_url":"https://github.com/ceph/ceph/pull/9737#discussion_r67555332","pull_request_url":"https://api.github.com/repos/ceph/ceph/pulls/9737","_links":{"self":{"href":"https://api.github.com/repos/ceph/ceph/pulls/comments/67555332"},"html":{"href":"https://github.com/ceph/ceph/pull/9737#discussion_r67555332"},"pull_request":{"href":"https://api.github.com/repos/ceph/ceph/pulls/9737"}}},"pull_request":{"url":"https://api.github.com/repos/ceph/ceph/pulls/9737","id":74018273,"html_url":"https://github.com/ceph/ceph/pull/9737","diff_url":"https://github.com/ceph/ceph/pull/9737.diff","patch_url":"https://github.com/ceph/ceph/pull/9737.patch","issue_url":"https://api.github.com/repos/ceph/ceph/issues/9737","number":9737,"state":"open","locked":false,"title":"rgw:lifecycle feature [rebased]","user":{"login":"chenji-kael","id":13363408,"avatar_url":"https://avatars.githubusercontent.com/u/13363408?v=3","gravatar_id":"","url":"https://api.github.com/users/chenji-kael","html_url":"https://github.com/chenji-kael","followers_url":"https://api.github.com/users/chenji-kael/followers","following_url":"https://api.github.com/users/chenji-kael/following{/other_user}","gists_url":"https://api.github.com/users/chenji-kael/gists{/gist_id}","starred_url":"https://api.github.com/users/chenji-kael/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chenji-kael/subscriptions","organizations_url":"https://api.github.com/users/chenji-kael/orgs","repos_url":"https://api.github.com/users/chenji-kael/repos","events_url":"https://api.github.com/users/chenji-kael/events{/privacy}","received_events_url":"https://api.github.com/users/chenji-kael/received_events","type":"User","site_admin":false},"body":"old PR was closed due to my git Erroneous operation, now it works well again: \r\nI hope it could be merged soon\r\n\r\n","created_at":"2016-06-16T03:45:18Z","updated_at":"2016-06-17T18:31:01Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e2be6cb00ec3e7d72ad3a957490d533fb772eb07","assignee":{"login":"dang","id":7334,"avatar_url":"https://avatars.githubusercontent.com/u/7334?v=3","gravatar_id":"","url":"https://api.github.com/users/dang","html_url":"https://github.com/dang","followers_url":"https://api.github.com/users/dang/followers","following_url":"https://api.github.com/users/dang/following{/other_user}","gists_url":"https://api.github.com/users/dang/gists{/gist_id}","starred_url":"https://api.github.com/users/dang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dang/subscriptions","organizations_url":"https://api.github.com/users/dang/orgs","repos_url":"https://api.github.com/users/dang/repos","events_url":"https://api.github.com/users/dang/events{/privacy}","received_events_url":"https://api.github.com/users/dang/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/ceph/ceph/pulls/9737/commits","review_comments_url":"https://api.github.com/repos/ceph/ceph/pulls/9737/comments","review_comment_url":"https://api.github.com/repos/ceph/ceph/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ceph/ceph/issues/9737/comments","statuses_url":"https://api.github.com/repos/ceph/ceph/statuses/c84f59f1d286ac58c2e799f92bbf791cfdaa09a6","head":{"label":"chenji-kael:wip-rgw-lifecycle","ref":"wip-rgw-lifecycle","sha":"c84f59f1d286ac58c2e799f92bbf791cfdaa09a6","user":{"login":"chenji-kael","id":13363408,"avatar_url":"https://avatars.githubusercontent.com/u/13363408?v=3","gravatar_id":"","url":"https://api.github.com/users/chenji-kael","html_url":"https://github.com/chenji-kael","followers_url":"https://api.github.com/users/chenji-kael/followers","following_url":"https://api.github.com/users/chenji-kael/following{/other_user}","gists_url":"https://api.github.com/users/chenji-kael/gists{/gist_id}","starred_url":"https://api.github.com/users/chenji-kael/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chenji-kael/subscriptions","organizations_url":"https://api.github.com/users/chenji-kael/orgs","repos_url":"https://api.github.com/users/chenji-kael/repos","events_url":"https://api.github.com/users/chenji-kael/events{/privacy}","received_events_url":"https://api.github.com/users/chenji-kael/received_events","type":"User","site_admin":false},"repo":{"id":44518289,"name":"ceph","full_name":"chenji-kael/ceph","owner":{"login":"chenji-kael","id":13363408,"avatar_url":"https://avatars.githubusercontent.com/u/13363408?v=3","gravatar_id":"","url":"https://api.github.com/users/chenji-kael","html_url":"https://github.com/chenji-kael","followers_url":"https://api.github.com/users/chenji-kael/followers","following_url":"https://api.github.com/users/chenji-kael/following{/other_user}","gists_url":"https://api.github.com/users/chenji-kael/gists{/gist_id}","starred_url":"https://api.github.com/users/chenji-kael/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chenji-kael/subscriptions","organizations_url":"https://api.github.com/users/chenji-kael/orgs","repos_url":"https://api.github.com/users/chenji-kael/repos","events_url":"https://api.github.com/users/chenji-kael/events{/privacy}","received_events_url":"https://api.github.com/users/chenji-kael/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/chenji-kael/ceph","description":"Ceph is a distributed object, block, and file storage platform ","fork":true,"url":"https://api.github.com/repos/chenji-kael/ceph","forks_url":"https://api.github.com/repos/chenji-kael/ceph/forks","keys_url":"https://api.github.com/repos/chenji-kael/ceph/keys{/key_id}","collaborators_url":"https://api.github.com/repos/chenji-kael/ceph/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/chenji-kael/ceph/teams","hooks_url":"https://api.github.com/repos/chenji-kael/ceph/hooks","issue_events_url":"https://api.github.com/repos/chenji-kael/ceph/issues/events{/number}","events_url":"https://api.github.com/repos/chenji-kael/ceph/events","assignees_url":"https://api.github.com/repos/chenji-kael/ceph/assignees{/user}","branches_url":"https://api.github.com/repos/chenji-kael/ceph/branches{/branch}","tags_url":"https://api.github.com/repos/chenji-kael/ceph/tags","blobs_url":"https://api.github.com/repos/chenji-kael/ceph/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/chenji-kael/ceph/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/chenji-kael/ceph/git/refs{/sha}","trees_url":"https://api.github.com/repos/chenji-kael/ceph/git/trees{/sha}","statuses_url":"https://api.github.com/repos/chenji-kael/ceph/statuses/{sha}","languages_url":"https://api.github.com/repos/chenji-kael/ceph/languages","stargazers_url":"https://api.github.com/repos/chenji-kael/ceph/stargazers","contributors_url":"https://api.github.com/repos/chenji-kael/ceph/contributors","subscribers_url":"https://api.github.com/repos/chenji-kael/ceph/subscribers","subscription_url":"https://api.github.com/repos/chenji-kael/ceph/subscription","commits_url":"https://api.github.com/repos/chenji-kael/ceph/commits{/sha}","git_commits_url":"https://api.github.com/repos/chenji-kael/ceph/git/commits{/sha}","comments_url":"https://api.github.com/repos/chenji-kael/ceph/comments{/number}","issue_comment_url":"https://api.github.com/repos/chenji-kael/ceph/issues/comments{/number}","contents_url":"https://api.github.com/repos/chenji-kael/ceph/contents/{+path}","compare_url":"https://api.github.com/repos/chenji-kael/ceph/compare/{base}...{head}","merges_url":"https://api.github.com/repos/chenji-kael/ceph/merges","archive_url":"https://api.github.com/repos/chenji-kael/ceph/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/chenji-kael/ceph/downloads","issues_url":"https://api.github.com/repos/chenji-kael/ceph/issues{/number}","pulls_url":"https://api.github.com/repos/chenji-kael/ceph/pulls{/number}","milestones_url":"https://api.github.com/repos/chenji-kael/ceph/milestones{/number}","notifications_url":"https://api.github.com/repos/chenji-kael/ceph/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/chenji-kael/ceph/labels{/name}","releases_url":"https://api.github.com/repos/chenji-kael/ceph/releases{/id}","deployments_url":"https://api.github.com/repos/chenji-kael/ceph/deployments","created_at":"2015-10-19T07:32:17Z","updated_at":"2016-01-12T03:39:09Z","pushed_at":"2016-06-16T02:48:06Z","git_url":"git://github.com/chenji-kael/ceph.git","ssh_url":"git@github.com:chenji-kael/ceph.git","clone_url":"https://github.com/chenji-kael/ceph.git","svn_url":"https://github.com/chenji-kael/ceph","homepage":"http://ceph.com","size":163521,"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:master","ref":"master","sha":"2380351e1679b4e111a7019aa76877639d66d1ff","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-06-17T08:07:21Z","pushed_at":"2016-06-17T18:12:03Z","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":220548,"stargazers_count":2237,"watchers_count":2237,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1332,"mirror_url":null,"open_issues_count":391,"forks":1332,"open_issues":391,"watchers":2237,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ceph/ceph/pulls/9737"},"html":{"href":"https://github.com/ceph/ceph/pull/9737"},"issue":{"href":"https://api.github.com/repos/ceph/ceph/issues/9737"},"comments":{"href":"https://api.github.com/repos/ceph/ceph/issues/9737/comments"},"review_comments":{"href":"https://api.github.com/repos/ceph/ceph/pulls/9737/comments"},"review_comment":{"href":"https://api.github.com/repos/ceph/ceph/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ceph/ceph/pulls/9737/commits"},"statuses":{"href":"https://api.github.com/repos/ceph/ceph/statuses/c84f59f1d286ac58c2e799f92bbf791cfdaa09a6"}}}}
{"actor":{"display_login":"dang"}}