payload: {"action":"created","comment":{"url":"https://api.github.com/repos/daos-stack/daos/pulls/comments/267584064","pull_request_review_id":217028583,"id":267584064,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI2NzU4NDA2NA==","diff_hunk":"@@ -0,0 +1,814 @@\n+/**\n+ *\n+ *\n+ * (C) Copyright 2016-2019 Intel Corporation.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *    http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ *\n+ * GOVERNMENT LICENSE RIGHTS-OPEN SOURCE SOFTWARE\n+ * The Government's rights to use, modify, reproduce, release, perform, display,\n+ * or disclose this software are subject to the terms of the Apache License as\n+ * provided in Contract No. B609815.\n+ * Any reproduction of computer software, computer software documentation, or\n+ * portions thereof marked with this legend must also reproduce the markings.\n+ */\n+/**\n+ * This file is part of DSR\n+ *\n+ * src/placement/mapless_jump_map.c\n+ */\n+#define D_LOGFAC        DD_FAC(placement)\n+\n+#include \"pl_map.h\"\n+#include \"mapless_jump_map.h\"\n+#include <inttypes.h>\n+#include <daos/pool_map.h>\n+\n+/**\n+ * This struct contains information used in determining\n+ * where the information is that denotes whether or not this\n+ * node has already been used.\n+ *\n+ * This structure must be updated every time there is a\n+ * change to the pool map.\n+ */\n+struct coll_map {\n+\t/** number of nodes for this level (targets or domains) */\n+\tunsigned int    do_node_cnt;\n+\t/** child nodes for collision map */\n+\tstruct coll_map *do_children;\n+\t/** number unused children domains */\n+\tuint32_t        cnt_used_offset;\n+\t/** the offset for the location in the \"used\" array */\n+\tuint32_t        coll_offset;\n+};\n+\n+struct remap_node {\n+\tuint32_t rank;\n+\tuint32_t id;\n+};\n+\n+/**\n+ * This is the Mapless placement map structure used to place objects.\n+ * The map is returned as a struct pl_map and then converted back into a\n+ * pl_mapless_map once passed from the caller into the object placement\n+ * functions.\n+ */\n+struct pl_mapless_map {\n+\t/** placement map interface */\n+\tstruct pl_map   mmp_map;\n+\t/** the total length of the array used for bookkeeping */\n+\tuint32_t        dom_used_length;\n+\n+\tuint32_t        cnt_used_length;\n+\t/** the collision map used during placement to avoid collisions */\n+\tstruct coll_map *co_map_root;\n+};\n+\n+/**\n+ * This function converts a generic pl_map pointer into the\n+ * proper placement map. This function assumes that the original\n+ * map was allocated as a pl_mapless_map with a pl_map as it's\n+ * first member.\n+ *\n+ * \\param[in]   *map    A pointer to a pl_map which is the first\n+ *                      member of the specific placement map we're\n+ *                      converting to.\n+ *\n+ * \\return      A pointer to the full pl_mapless_map used for\n+ *              object placement, rebuild, and reintegration\n+ */\n+static inline struct pl_mapless_map *\n+pl_map2mplmap(struct pl_map *map)\n+{\n+\treturn container_of(map, struct pl_mapless_map, mmp_map);\n+}\n+\n+/**\n+ * This function recursively creates a collision map that is used to\n+ * keep track of which nodes in a given domain have been used. The collision\n+ * map mirrors the pool maps structure,\n+ *\n+ * \\param[in]   *domain         A pointer to the root node of the pool map\n+ *                              domains.\n+ * \\param[out]  *co_map         A pointer to the collision map that will\n+ *                              be created.\n+ * \\param[in]   *offset_start   The index in the array of utilized targets\n+ *                              where the information related to this node is\n+ *                              located (Generally starts at n = number\n+ *                              of targets)\n+ *\n+ * \\return      void\n+ */\n+static void\n+create_collision_tree(struct pool_domain *dom, struct coll_map *co_map,\n+                      uint32_t *used_currnt, uint32_t *cnt_currnt)\n+{\n+\tuint32_t i;\n+\n+\t/* There should always be targets in the pool map */\n+\tD_ASSERT(dom->do_targets != NULL);\n+\n+\t/* these are the offsets into their respective book-keeping arrays */\n+\tco_map->coll_offset = *used_currnt;\n+\tco_map->cnt_used_offset = *cnt_currnt;\n+\n+\t/* Every domain has a count for how many node have been used */\n+\t(*cnt_currnt)++;\n+\n+\t/* If this is non-target level domain */\n+\tif (dom->do_children != NULL) {\n+\t\tD_ALLOC_ARRAY(co_map->do_children, dom->do_child_nr);\n+\n+\t\t/* Keep track of number of children in a single place */\n+\t\tco_map->do_node_cnt = dom->do_child_nr;\n+\t\t*used_currnt += dom->do_child_nr;\n+\n+\t\t/* Recursively build the collision map */\n+\t\tfor (i = 0; i < dom->do_child_nr; i++)\n+\t\t\tcreate_collision_tree(&dom->do_children[i],\n+\t\t\t                      &co_map->do_children[i],\n+\t\t\t                      used_currnt, cnt_currnt);\n+\t} else {\n+\t\t/* We don't used a byte map for individual targets */\n+\t\tco_map->coll_offset = 0;\n+\t\tco_map->do_node_cnt = dom->do_target_nr;\n+\t}\n+}\n+/**\n+ * This function recursively frees all the children in the collision tree.\n+ *\n+ * \\param[in]   co_map         The collision tree to be freed.\n+ *\n+ * \\return      void\n+ */\n+static void\n+free_collision_tree(struct coll_map *co_map)\n+{\n+\tuint32_t i;\n+\n+\t/* If this is non-target level domain */\n+\tif (co_map->do_children != NULL) {\n+\n+\t\t/* Recursively free the collision map */\n+\t\tfor (i = 0; i < co_map->do_node_cnt; i++)\n+\t\t\tfree_collision_tree(&co_map->do_children[i]);\n+\n+\t\tD_FREE(co_map->do_children);\n+\t}\n+}\n+\n+\n+/**\n+ * This function recursively chooses a single target to be used in the\n+ * object shard layout. This function is called for every shard that needs a\n+ * placement location.\n+ *\n+ * \\param[in]   curr_dom        The current domain that is being used to\n+ *                              determine the target location for this shard.\n+ *                              initially the root node of the pool map.\n+ * \\param[out]  target          This variable is used when returning the\n+ *                              selected target for this shard.\n+ * \\param[in]   co_map          The collision map used for book keeping\n+ *                              purposes when selecting targets. Contains\n+ *                              additional information about the pool map.\n+ * \\param[in]   obj_key         a unique key generated using the object ID.\n+ *                              This is used in jump consistent hash.\n+ * \\param[in]   dom_used        This is a contiguous array that contains\n+ *                              information on whether or not an internal node\n+ *                              (non-target) in a domain has been used.\n+ * \\param[in]   next_dom        The \"stack\" used when iterating down the pool\n+ *                              map. This is required because there is a\n+ *                              chance we may need to iterate back up the pool\n+ *                              map.\n+ * \\param[in]   next_co_map     A stack similar to the next dom variable.\n+ * \\param[in]   dom_count       An array that contains the number of targets\n+ *                              previously used that will be cleared when all\n+ *                              the domains have been used. Important for the\n+ *                              case that we must place more shards than\n+ *                              domains in a particular fault domain.\n+ * \\param[in]   used_targets    A list of the targets that have been used. We\n+ *                              iterate through this when selecting the next\n+ *                              target in a placement to determine if that\n+ *                              location is valid.\n+ * \\param[in]   shard_num       the current shard number. This is used when\n+ *                              selecting a target to determine if repeated\n+ *                              targets are allowed in the case that there\n+ *                              are more shards than targets\n+ *\n+ * \\return      an int value indicating if the returned target is available (0)\n+ *              or failed (1)\n+ */\n+static void\n+get_target(struct pool_domain *curr_dom, struct pool_target **target,\n+           struct coll_map *co_map, uint64_t obj_key, uint8_t *dom_used,\n+           struct pool_domain **next_dom, struct coll_map **next_co_map,\n+           uint32_t *dom_count, uint32_t *used_targets, int shard_num)\n+{\n+\tuint8_t         found_target = 0;\n+\tuint8_t         top = 0;\n+\tuint8_t         *coll_dom_start;\n+\tuint32_t        i;\n+\tuint32_t        fail_num = 0;\n+\tuint32_t        selected_dom;\n+\tuint32_t        num_doms;\n+\tuint64_t        key;\n+\tuint64_t        total_tgts;\n+\n+\t/* Used to determine if there are fewer targets than shards */\n+\ttotal_tgts = curr_dom->do_target_nr;\n+\n+\t/* top of the \"call\" stack */\n+\tnext_dom[top] = curr_dom;\n+\tnext_co_map[top] = co_map;\n+\n+\tdo {\n+\t\tcurr_dom = next_dom[top];\n+\t\tco_map = next_co_map[top];\n+\n+\t\t/* Retrieve number of nodes in this domain */\n+\t\tnum_doms = co_map->do_node_cnt;\n+\t\t/* Get the start position of bookkeeping array for domain */\n+\t\tcoll_dom_start = &dom_used[co_map->coll_offset];\n+\n+\t\t/*\n+\t\t * If all of the nodes have been used for shards but we\n+\t\t * still have shards to place mark all nodes as unused\n+\t\t * so duplicates can be chosen\n+\t\t */\n+\t\tif (dom_count[co_map->cnt_used_offset] == num_doms &&\n+\t\t    curr_dom->do_children != NULL) {\n+\n+\t\t\tdom_count[co_map->cnt_used_offset] = 0;\n+\t\t\tfor (i = 0; i < num_doms; ++i)\n+\t\t\t\tcoll_dom_start[i] = 0;\n+\t\t}\n+\n+\t\tkey = obj_key;\n+\t\t/* If choosing target in lowest fault domain level */\n+\t\tif (curr_dom->do_children == NULL) {\n+\t\t\tuint32_t dom_id;\n+\t\t\t/*\n+\t\t\t * Number of repeats allowed when sharding is wider\n+\t\t\t * than stripe count\n+\t\t\t *\n+\t\t\t * 0 if placing fewer shards than available targets\n+\t\t\t */\n+\t\t\tuint16_t num_repeats = (shard_num / total_tgts);\n+\n+\t\t\tdo {\n+\t\t\t\tuint16_t repeats = 0;\n+\n+\t\t\t\t/*\n+\t\t\t\t * Must crc key because jump consistent hash\n+\t\t\t\t * requires an even distribution or it will\n+\t\t\t\t * not work\n+\t\t\t\t */\n+\t\t\t\tkey = crc(key, fail_num++);\n+\n+\t\t\t\t/* Get target for shard */\n+\t\t\t\tselected_dom = jump_consistent_hash(key,\n+\t\t\t\t                                    num_doms);","path":"src/placement/mapless_jump_map.c","position":281,"original_position":281,"commit_id":"b337eef9a32958cc4df998872f1f4baca8b387df","original_commit_id":"b337eef9a32958cc4df998872f1f4baca8b387df","user":{"login":"daosbuild1","id":47433925,"node_id":"MDQ6VXNlcjQ3NDMzOTI1","avatar_url":"https://avatars0.githubusercontent.com/u/47433925?v=4","gravatar_id":"","url":"https://api.github.com/users/daosbuild1","html_url":"https://github.com/daosbuild1","followers_url":"https://api.github.com/users/daosbuild1/followers","following_url":"https://api.github.com/users/daosbuild1/following{/other_user}","gists_url":"https://api.github.com/users/daosbuild1/gists{/gist_id}","starred_url":"https://api.github.com/users/daosbuild1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/daosbuild1/subscriptions","organizations_url":"https://api.github.com/users/daosbuild1/orgs","repos_url":"https://api.github.com/users/daosbuild1/repos","events_url":"https://api.github.com/users/daosbuild1/events{/privacy}","received_events_url":"https://api.github.com/users/daosbuild1/received_events","type":"User","site_admin":false},"body":"(style)  code indent should use tabs where possible\n","created_at":"2019-03-20T23:21:22Z","updated_at":"2019-03-20T23:21:24Z","html_url":"https://github.com/daos-stack/daos/pull/291#discussion_r267584064","pull_request_url":"https://api.github.com/repos/daos-stack/daos/pulls/291","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/daos-stack/daos/pulls/comments/267584064"},"html":{"href":"https://github.com/daos-stack/daos/pull/291#discussion_r267584064"},"pull_request":{"href":"https://api.github.com/repos/daos-stack/daos/pulls/291"}}},"pull_request":{"url":"https://api.github.com/repos/daos-stack/daos/pulls/291","id":263071481,"node_id":"MDExOlB1bGxSZXF1ZXN0MjYzMDcxNDgx","html_url":"https://github.com/daos-stack/daos/pull/291","diff_url":"https://github.com/daos-stack/daos/pull/291.diff","patch_url":"https://github.com/daos-stack/daos/pull/291.patch","issue_url":"https://api.github.com/repos/daos-stack/daos/issues/291","number":291,"state":"open","locked":false,"title":"DAOS-2101 placement: Mapless placement algorithm","user":{"login":"PetFet","id":46941515,"node_id":"MDQ6VXNlcjQ2OTQxNTE1","avatar_url":"https://avatars2.githubusercontent.com/u/46941515?v=4","gravatar_id":"","url":"https://api.github.com/users/PetFet","html_url":"https://github.com/PetFet","followers_url":"https://api.github.com/users/PetFet/followers","following_url":"https://api.github.com/users/PetFet/following{/other_user}","gists_url":"https://api.github.com/users/PetFet/gists{/gist_id}","starred_url":"https://api.github.com/users/PetFet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PetFet/subscriptions","organizations_url":"https://api.github.com/users/PetFet/orgs","repos_url":"https://api.github.com/users/PetFet/repos","events_url":"https://api.github.com/users/PetFet/events{/privacy}","received_events_url":"https://api.github.com/users/PetFet/received_events","type":"User","site_admin":false},"body":"The first version of the Mapless placement map.  This placement map minimizes the\r\ndata movement on pool reorganization such as server addition, reintegration, and\r\nrebuild.\r\n\r\nSigned-off-by: Peter Fetros <peter.fetros@intel.com>","created_at":"2019-03-20T23:18:53Z","updated_at":"2019-03-20T23:21:24Z","closed_at":null,"merged_at":null,"merge_commit_sha":"563ad1160b72ef14c0a16637ea6244609b6c69bc","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/daos-stack/daos/pulls/291/commits","review_comments_url":"https://api.github.com/repos/daos-stack/daos/pulls/291/comments","review_comment_url":"https://api.github.com/repos/daos-stack/daos/pulls/comments{/number}","comments_url":"https://api.github.com/repos/daos-stack/daos/issues/291/comments","statuses_url":"https://api.github.com/repos/daos-stack/daos/statuses/b337eef9a32958cc4df998872f1f4baca8b387df","head":{"label":"daos-stack:mapless_placement","ref":"mapless_placement","sha":"b337eef9a32958cc4df998872f1f4baca8b387df","user":{"login":"daos-stack","id":20561043,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIwNTYxMDQz","avatar_url":"https://avatars1.githubusercontent.com/u/20561043?v=4","gravatar_id":"","url":"https://api.github.com/users/daos-stack","html_url":"https://github.com/daos-stack","followers_url":"https://api.github.com/users/daos-stack/followers","following_url":"https://api.github.com/users/daos-stack/following{/other_user}","gists_url":"https://api.github.com/users/daos-stack/gists{/gist_id}","starred_url":"https://api.github.com/users/daos-stack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/daos-stack/subscriptions","organizations_url":"https://api.github.com/users/daos-stack/orgs","repos_url":"https://api.github.com/users/daos-stack/repos","events_url":"https://api.github.com/users/daos-stack/events{/privacy}","received_events_url":"https://api.github.com/users/daos-stack/received_events","type":"Organization","site_admin":false},"repo":{"id":69390670,"node_id":"MDEwOlJlcG9zaXRvcnk2OTM5MDY3MA==","name":"daos","full_name":"daos-stack/daos","private":false,"owner":{"login":"daos-stack","id":20561043,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIwNTYxMDQz","avatar_url":"https://avatars1.githubusercontent.com/u/20561043?v=4","gravatar_id":"","url":"https://api.github.com/users/daos-stack","html_url":"https://github.com/daos-stack","followers_url":"https://api.github.com/users/daos-stack/followers","following_url":"https://api.github.com/users/daos-stack/following{/other_user}","gists_url":"https://api.github.com/users/daos-stack/gists{/gist_id}","starred_url":"https://api.github.com/users/daos-stack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/daos-stack/subscriptions","organizations_url":"https://api.github.com/users/daos-stack/orgs","repos_url":"https://api.github.com/users/daos-stack/repos","events_url":"https://api.github.com/users/daos-stack/events{/privacy}","received_events_url":"https://api.github.com/users/daos-stack/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/daos-stack/daos","description":"DAOS Storage Engine","fork":false,"url":"https://api.github.com/repos/daos-stack/daos","forks_url":"https://api.github.com/repos/daos-stack/daos/forks","keys_url":"https://api.github.com/repos/daos-stack/daos/keys{/key_id}","collaborators_url":"https://api.github.com/repos/daos-stack/daos/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/daos-stack/daos/teams","hooks_url":"https://api.github.com/repos/daos-stack/daos/hooks","issue_events_url":"https://api.github.com/repos/daos-stack/daos/issues/events{/number}","events_url":"https://api.github.com/repos/daos-stack/daos/events","assignees_url":"https://api.github.com/repos/daos-stack/daos/assignees{/user}","branches_url":"https://api.github.com/repos/daos-stack/daos/branches{/branch}","tags_url":"https://api.github.com/repos/daos-stack/daos/tags","blobs_url":"https://api.github.com/repos/daos-stack/daos/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/daos-stack/daos/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/daos-stack/daos/git/refs{/sha}","trees_url":"https://api.github.com/repos/daos-stack/daos/git/trees{/sha}","statuses_url":"https://api.github.com/repos/daos-stack/daos/statuses/{sha}","languages_url":"https://api.github.com/repos/daos-stack/daos/languages","stargazers_url":"https://api.github.com/repos/daos-stack/daos/stargazers","contributors_url":"https://api.github.com/repos/daos-stack/daos/contributors","subscribers_url":"https://api.github.com/repos/daos-stack/daos/subscribers","subscription_url":"https://api.github.com/repos/daos-stack/daos/subscription","commits_url":"https://api.github.com/repos/daos-stack/daos/commits{/sha}","git_commits_url":"https://api.github.com/repos/daos-stack/daos/git/commits{/sha}","comments_url":"https://api.github.com/repos/daos-stack/daos/comments{/number}","issue_comment_url":"https://api.github.com/repos/daos-stack/daos/issues/comments{/number}","contents_url":"https://api.github.com/repos/daos-stack/daos/contents/{+path}","compare_url":"https://api.github.com/repos/daos-stack/daos/compare/{base}...{head}","merges_url":"https://api.github.com/repos/daos-stack/daos/merges","archive_url":"https://api.github.com/repos/daos-stack/daos/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/daos-stack/daos/downloads","issues_url":"https://api.github.com/repos/daos-stack/daos/issues{/number}","pulls_url":"https://api.github.com/repos/daos-stack/daos/pulls{/number}","milestones_url":"https://api.github.com/repos/daos-stack/daos/milestones{/number}","notifications_url":"https://api.github.com/repos/daos-stack/daos/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/daos-stack/daos/labels{/name}","releases_url":"https://api.github.com/repos/daos-stack/daos/releases{/id}","deployments_url":"https://api.github.com/repos/daos-stack/daos/deployments","created_at":"2016-09-27T19:21:29Z","updated_at":"2019-03-20T12:11:35Z","pushed_at":"2019-03-20T23:18:54Z","git_url":"git://github.com/daos-stack/daos.git","ssh_url":"git@github.com:daos-stack/daos.git","clone_url":"https://github.com/daos-stack/daos.git","svn_url":"https://github.com/daos-stack/daos","homepage":"http://daos.io","size":19338,"stargazers_count":85,"watchers_count":85,"language":"C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":34,"mirror_url":null,"archived":false,"open_issues_count":47,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":34,"open_issues":47,"watchers":85,"default_branch":"master"}},"base":{"label":"daos-stack:master","ref":"master","sha":"8ac10fccc7925a834e93d5c0ee41160750866dcf","user":{"login":"daos-stack","id":20561043,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIwNTYxMDQz","avatar_url":"https://avatars1.githubusercontent.com/u/20561043?v=4","gravatar_id":"","url":"https://api.github.com/users/daos-stack","html_url":"https://github.com/daos-stack","followers_url":"https://api.github.com/users/daos-stack/followers","following_url":"https://api.github.com/users/daos-stack/following{/other_user}","gists_url":"https://api.github.com/users/daos-stack/gists{/gist_id}","starred_url":"https://api.github.com/users/daos-stack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/daos-stack/subscriptions","organizations_url":"https://api.github.com/users/daos-stack/orgs","repos_url":"https://api.github.com/users/daos-stack/repos","events_url":"https://api.github.com/users/daos-stack/events{/privacy}","received_events_url":"https://api.github.com/users/daos-stack/received_events","type":"Organization","site_admin":false},"repo":{"id":69390670,"node_id":"MDEwOlJlcG9zaXRvcnk2OTM5MDY3MA==","name":"daos","full_name":"daos-stack/daos","private":false,"owner":{"login":"daos-stack","id":20561043,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIwNTYxMDQz","avatar_url":"https://avatars1.githubusercontent.com/u/20561043?v=4","gravatar_id":"","url":"https://api.github.com/users/daos-stack","html_url":"https://github.com/daos-stack","followers_url":"https://api.github.com/users/daos-stack/followers","following_url":"https://api.github.com/users/daos-stack/following{/other_user}","gists_url":"https://api.github.com/users/daos-stack/gists{/gist_id}","starred_url":"https://api.github.com/users/daos-stack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/daos-stack/subscriptions","organizations_url":"https://api.github.com/users/daos-stack/orgs","repos_url":"https://api.github.com/users/daos-stack/repos","events_url":"https://api.github.com/users/daos-stack/events{/privacy}","received_events_url":"https://api.github.com/users/daos-stack/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/daos-stack/daos","description":"DAOS Storage Engine","fork":false,"url":"https://api.github.com/repos/daos-stack/daos","forks_url":"https://api.github.com/repos/daos-stack/daos/forks","keys_url":"https://api.github.com/repos/daos-stack/daos/keys{/key_id}","collaborators_url":"https://api.github.com/repos/daos-stack/daos/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/daos-stack/daos/teams","hooks_url":"https://api.github.com/repos/daos-stack/daos/hooks","issue_events_url":"https://api.github.com/repos/daos-stack/daos/issues/events{/number}","events_url":"https://api.github.com/repos/daos-stack/daos/events","assignees_url":"https://api.github.com/repos/daos-stack/daos/assignees{/user}","branches_url":"https://api.github.com/repos/daos-stack/daos/branches{/branch}","tags_url":"https://api.github.com/repos/daos-stack/daos/tags","blobs_url":"https://api.github.com/repos/daos-stack/daos/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/daos-stack/daos/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/daos-stack/daos/git/refs{/sha}","trees_url":"https://api.github.com/repos/daos-stack/daos/git/trees{/sha}","statuses_url":"https://api.github.com/repos/daos-stack/daos/statuses/{sha}","languages_url":"https://api.github.com/repos/daos-stack/daos/languages","stargazers_url":"https://api.github.com/repos/daos-stack/daos/stargazers","contributors_url":"https://api.github.com/repos/daos-stack/daos/contributors","subscribers_url":"https://api.github.com/repos/daos-stack/daos/subscribers","subscription_url":"https://api.github.com/repos/daos-stack/daos/subscription","commits_url":"https://api.github.com/repos/daos-stack/daos/commits{/sha}","git_commits_url":"https://api.github.com/repos/daos-stack/daos/git/commits{/sha}","comments_url":"https://api.github.com/repos/daos-stack/daos/comments{/number}","issue_comment_url":"https://api.github.com/repos/daos-stack/daos/issues/comments{/number}","contents_url":"https://api.github.com/repos/daos-stack/daos/contents/{+path}","compare_url":"https://api.github.com/repos/daos-stack/daos/compare/{base}...{head}","merges_url":"https://api.github.com/repos/daos-stack/daos/merges","archive_url":"https://api.github.com/repos/daos-stack/daos/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/daos-stack/daos/downloads","issues_url":"https://api.github.com/repos/daos-stack/daos/issues{/number}","pulls_url":"https://api.github.com/repos/daos-stack/daos/pulls{/number}","milestones_url":"https://api.github.com/repos/daos-stack/daos/milestones{/number}","notifications_url":"https://api.github.com/repos/daos-stack/daos/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/daos-stack/daos/labels{/name}","releases_url":"https://api.github.com/repos/daos-stack/daos/releases{/id}","deployments_url":"https://api.github.com/repos/daos-stack/daos/deployments","created_at":"2016-09-27T19:21:29Z","updated_at":"2019-03-20T12:11:35Z","pushed_at":"2019-03-20T23:18:54Z","git_url":"git://github.com/daos-stack/daos.git","ssh_url":"git@github.com:daos-stack/daos.git","clone_url":"https://github.com/daos-stack/daos.git","svn_url":"https://github.com/daos-stack/daos","homepage":"http://daos.io","size":19338,"stargazers_count":85,"watchers_count":85,"language":"C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":34,"mirror_url":null,"archived":false,"open_issues_count":47,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":34,"open_issues":47,"watchers":85,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/daos-stack/daos/pulls/291"},"html":{"href":"https://github.com/daos-stack/daos/pull/291"},"issue":{"href":"https://api.github.com/repos/daos-stack/daos/issues/291"},"comments":{"href":"https://api.github.com/repos/daos-stack/daos/issues/291/comments"},"review_comments":{"href":"https://api.github.com/repos/daos-stack/daos/pulls/291/comments"},"review_comment":{"href":"https://api.github.com/repos/daos-stack/daos/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/daos-stack/daos/pulls/291/commits"},"statuses":{"href":"https://api.github.com/repos/daos-stack/daos/statuses/b337eef9a32958cc4df998872f1f4baca8b387df"}},"author_association":"CONTRIBUTOR"}}
other: {"actor":{"display_login":"daosbuild1"}}