{"action":"created","comment":{"url":"https://api.github.com/repos/NVIDIA/dfcpub/pulls/comments/187140410","pull_request_review_id":118860824,"id":187140410,"diff_hunk":"@@ -0,0 +1,719 @@\n+// Package dfc is a scalable object-storage based caching system with Amazon and Google Cloud backends.\n+/*\n+ * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.\n+ *\n+ */\n+package dfc\n+\n+import (\n+\t\"encoding/json\"\n+\t\"fmt\"\n+\t\"net/http\"\n+\t\"os\"\n+\t\"path/filepath\"\n+\t\"sync\"\n+\t\"time\"\n+\n+\t\"github.com/golang/glog\"\n+)\n+\n+// enumerated REVS types (opaque TBD)\n+const (\n+\tsmaptag  = \"smaptag\"\n+\tlbmaptag = \"lbmaptag\"\n+\t//\n+\tactiontag = \"-action\" // to make a pair (revs, action)\n+)\n+\n+// =================== A Brief Theory of Operation =================================\n+//\n+// REVS (interface below) stands for REplicated, Versioned and Shared/Synchronized.\n+//\n+// A REVS is, typically, an object that represents some sort of cluster-wide metadata\n+// and, therefore, must be consistently replicated across the entire cluster.\n+// To that end, the \"metasyncer\" (metasync.go) provides a generic transport to send\n+// an arbitrary payload that combines any number of data units that look as follows:\n+//\n+//         (shared-object, associated action-message)\n+//\n+// The action message (ActionMsg), if present, provides receivers with a context as\n+// to what exactly to do with the newly received versioned replica.\n+//\n+// In addition, storage target in particular make use of the previously synchronized\n+// version of the cluster map delivered to them by the metasyncer itself (as part of\n+// the aforementioned action message). Having both the current and the previous\n+// cluster maps allows targets to figure out whether to rebalance the cluster, and\n+// how to execute the rebalancing.\n+//\n+// In addition, the metasyncer:\n+//\n+// 1) tracks already synchronized REVS objects\n+// 2) validates REVS versions - in particular, prevents attempts to downgrade a\n+//    newer version\n+// 3) makes sure that nodes that join the cluster get updated with the current set\n+//    of REVS replicas\n+// 4) handles failures to reach existing cluster members - by periodically retrying\n+//    to update them with the current REVS versions (as long and if those members\n+//    remain listed in the most current/recent cluster map).\n+//\n+// The usage is easy - there is a single sync() method that accepts variable\n+// number of parameters. Example sync-ing asynchronously without action messages:\n+//\n+// \tsync(false, newsmap, p.lbmap.cloneL())\n+//\n+// To sync with action message(s) and to block until all the replicas are delivered,\n+// do:\n+//\n+//  \tpair := &revspair{ p.smap.cloneU(), &ActionMsg{...} }\n+//  \tsync(true, pair)\n+//\n+// On the receiving side, the metasyncer-generated payload gets extracted,\n+// validated, version-compared, and the corresponding Rx handler gets then called\n+// with the corresponding REVS replica and additional information that includes\n+// the action message (and the previous version of the cluster map, if applicable).\n+//\n+// =================== end of A Brief Theory of Operation ==========================\n+\n+type revs interface {\n+\ttag() string                    // known tags enumerated above\n+\tcloneL() interface{}            // clone self - the impl. must take lock if need be\n+\tversion() int64                 // version - locking not required\n+\tmarshal() (b []byte, err error) // json-marshal - ditto\n+}\n+\n+// REVS paired with an action message to provide receivers with additional context\n+type revspair struct {\n+\trevs revs\n+\tmsg  *ActionMsg\n+}\n+\n+type metasyncer struct {\n+\tnamedrunner\n+\tp      *proxyrunner\n+\tt      *targetrunner\n+\th      *httprunner\n+\tsynced struct {\n+\t\tcopies map[string]revs // by tag\n+\t}\n+\tpending struct {\n+\t\tlock     *sync.Mutex\n+\t\tdiamonds map[string]*daemonInfo\n+\t\trefused  map[string]*daemonInfo\n+\t}\n+\tchfeed     chan []interface{}\n+\tchfeedwait chan []interface{}\n+\tchstop     chan struct{}\n+\tticker     *time.Ticker\n+}\n+\n+// c-tor\n+func newmetasyncer(p *proxyrunner, t *targetrunner) (y *metasyncer) {\n+\ty = &metasyncer{p: p, t: t}\n+\tif p == nil {\n+\t\ty.h = &t.httprunner\n+\t\treturn\n+\t}\n+\tassert(t == nil)\n+\ty.h = &p.httprunner\n+\ty.synced.copies = make(map[string]revs)\n+\ty.pending.diamonds = make(map[string]*daemonInfo)\n+\ty.pending.lock = &sync.Mutex{}\n+\ty.chstop = make(chan struct{}, 4)\n+\ty.chfeed = make(chan []interface{}, 16)\n+\ty.chfeedwait = make(chan []interface{}, 16)\n+\treturn\n+}\n+\n+func (y *metasyncer) sync(wait bool, revsvec ...interface{}) {\n+\tassert(y.p != nil)\n+\tif !y.p.primary {\n+\t\tlead := \"?\"\n+\t\tif y.p.proxysi != nil {\n+\t\t\tlead = y.p.proxysi.DaemonID\n+\t\t}\n+\t\tassert(false, fmt.Sprintf(\"%s (self) is not the primary proxy (%s) - cannot distribute REVS\", y.p.si.DaemonID, lead))\n+\t}\n+\t// validate\n+\tfor _, metaif := range revsvec {\n+\t\tif _, ok := metaif.(revs); !ok {\n+\t\t\tif _, ok = metaif.(*revspair); !ok {\n+\t\t\t\tassert(false, fmt.Sprintf(\"Expecting revs or revspair, getting %T instead\", metaif))\n+\t\t\t}\n+\t\t}\n+\t}\n+\t// feed\n+\tif wait {\n+\t\ty.chfeedwait <- revsvec\n+\t\t<-y.chfeedwait\n+\t} else {\n+\t\ty.chfeed <- revsvec\n+\t}\n+\treturn\n+}\n+\n+func (y *metasyncer) run() error {\n+\tglog.Infof(\"Starting %s\", y.name)\n+\tvar (\n+\t\tticking, stopped bool\n+\t)\n+\tfor !stopped {\n+\t\tif ticking {\n+\t\t\tticking, stopped = y.selectWithTicker()\n+\t\t} else {\n+\t\t\tticking, stopped = y.selectWithoutTicker()\n+\t\t}\n+\t}\n+\treturn nil\n+}\n+\n+func (y *metasyncer) selectWithTicker() (ticking, stopped bool) {\n+\tvar npending int\n+\tticking = true\n+\tselect {\n+\tcase revsvec := <-y.chfeedwait:\n+\t\tnpending = y.dosync(revsvec)\n+\t\tvar s []interface{}\n+\t\ty.chfeedwait <- s\n+\tcase revsvec := <-y.chfeed:\n+\t\tnpending = y.dosync(revsvec)\n+\tcase <-y.ticker.C:\n+\t\tnpending = y.handlePending()\n+\tcase <-y.chstop:\n+\t\tstopped = true\n+\t}\n+\tif npending == 0 {\n+\t\ty.ticker.Stop()\n+\t\tticking = false\n+\t}\n+\treturn\n+}\n+\n+func (y *metasyncer) selectWithoutTicker() (ticking, stopped bool) {\n+\tvar npending int\n+\tselect {\n+\tcase revsvec := <-y.chfeedwait:\n+\t\tnpending = y.dosync(revsvec)\n+\t\tvar s []interface{}\n+\t\ty.chfeedwait <- s\n+\tcase revsvec := <-y.chfeed:\n+\t\tnpending = y.dosync(revsvec)\n+\tcase <-y.chstop:\n+\t\tstopped = true\n+\t}\n+\tif npending > 0 && !stopped {\n+\t\ty.ticker = time.NewTicker(ctx.config.Periodic.RetrySyncTime)\n+\t\tticking = true\n+\t}\n+\treturn\n+}\n+\n+func (y *metasyncer) stop(err error) {\n+\tglog.Infof(\"Stopping %s, err: %v\", y.name, err)\n+\tvar v struct{}\n+\ty.chstop <- v\n+\tclose(y.chstop)\n+}\n+\n+func (y *metasyncer) dosync(revsvec []interface{}) int {\n+\tvar (\n+\t\tsmap4bcast, smapSynced *Smap\n+\t\tjsbytes, jsmsg         []byte\n+\t\terr                    error\n+\t\tpayload                = make(map[string]string)\n+\t\tnewversions            = make(map[string]revs)\n+\t\tcheck4newmembers       bool\n+\t)\n+\tif _, ok := y.synced.copies[smaptag]; ok {","path":"dfc/metasync.go","position":226,"original_position":226,"commit_id":"08f12760d909e8768066f9279e15888a5c49a6c0","original_commit_id":"08f12760d909e8768066f9279e15888a5c49a6c0","user":{"login":"VladimirMarkelov","id":1577186,"avatar_url":"https://avatars2.githubusercontent.com/u/1577186?v=4","gravatar_id":"","url":"https://api.github.com/users/VladimirMarkelov","html_url":"https://github.com/VladimirMarkelov","followers_url":"https://api.github.com/users/VladimirMarkelov/followers","following_url":"https://api.github.com/users/VladimirMarkelov/following{/other_user}","gists_url":"https://api.github.com/users/VladimirMarkelov/gists{/gist_id}","starred_url":"https://api.github.com/users/VladimirMarkelov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VladimirMarkelov/subscriptions","organizations_url":"https://api.github.com/users/VladimirMarkelov/orgs","repos_url":"https://api.github.com/users/VladimirMarkelov/repos","events_url":"https://api.github.com/users/VladimirMarkelov/events{/privacy}","received_events_url":"https://api.github.com/users/VladimirMarkelov/received_events","type":"User","site_admin":false},"body":"I saw the similar double-get-from-hash way in a few other places. ","created_at":"2018-05-09T18:51:20Z","updated_at":"2018-05-09T18:51:20Z","html_url":"https://github.com/NVIDIA/dfcpub/pull/7#discussion_r187140410","pull_request_url":"https://api.github.com/repos/NVIDIA/dfcpub/pulls/7","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/NVIDIA/dfcpub/pulls/comments/187140410"},"html":{"href":"https://github.com/NVIDIA/dfcpub/pull/7#discussion_r187140410"},"pull_request":{"href":"https://api.github.com/repos/NVIDIA/dfcpub/pulls/7"}},"in_reply_to_id":187095132},"pull_request":{"url":"https://api.github.com/repos/NVIDIA/dfcpub/pulls/7","id":186967784,"html_url":"https://github.com/NVIDIA/dfcpub/pull/7","diff_url":"https://github.com/NVIDIA/dfcpub/pull/7.diff","patch_url":"https://github.com/NVIDIA/dfcpub/pull/7.patch","issue_url":"https://api.github.com/repos/NVIDIA/dfcpub/issues/7","number":7,"state":"open","locked":false,"title":"reviewing metasyncer code","user":{"login":"usmanong","id":18450310,"avatar_url":"https://avatars3.githubusercontent.com/u/18450310?v=4","gravatar_id":"","url":"https://api.github.com/users/usmanong","html_url":"https://github.com/usmanong","followers_url":"https://api.github.com/users/usmanong/followers","following_url":"https://api.github.com/users/usmanong/following{/other_user}","gists_url":"https://api.github.com/users/usmanong/gists{/gist_id}","starred_url":"https://api.github.com/users/usmanong/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/usmanong/subscriptions","organizations_url":"https://api.github.com/users/usmanong/orgs","repos_url":"https://api.github.com/users/usmanong/repos","events_url":"https://api.github.com/users/usmanong/events{/privacy}","received_events_url":"https://api.github.com/users/usmanong/received_events","type":"User","site_admin":false},"body":"Branch based on metasync merged with master","created_at":"2018-05-09T16:02:04Z","updated_at":"2018-05-09T18:51:20Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5f8821b98ec5dba8ba4bc274ea9ea7b90b991220","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/NVIDIA/dfcpub/pulls/7/commits","review_comments_url":"https://api.github.com/repos/NVIDIA/dfcpub/pulls/7/comments","review_comment_url":"https://api.github.com/repos/NVIDIA/dfcpub/pulls/comments{/number}","comments_url":"https://api.github.com/repos/NVIDIA/dfcpub/issues/7/comments","statuses_url":"https://api.github.com/repos/NVIDIA/dfcpub/statuses/08f12760d909e8768066f9279e15888a5c49a6c0","head":{"label":"NVIDIA:liding-metasyncer","ref":"liding-metasyncer","sha":"08f12760d909e8768066f9279e15888a5c49a6c0","user":{"login":"NVIDIA","id":1728152,"avatar_url":"https://avatars2.githubusercontent.com/u/1728152?v=4","gravatar_id":"","url":"https://api.github.com/users/NVIDIA","html_url":"https://github.com/NVIDIA","followers_url":"https://api.github.com/users/NVIDIA/followers","following_url":"https://api.github.com/users/NVIDIA/following{/other_user}","gists_url":"https://api.github.com/users/NVIDIA/gists{/gist_id}","starred_url":"https://api.github.com/users/NVIDIA/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NVIDIA/subscriptions","organizations_url":"https://api.github.com/users/NVIDIA/orgs","repos_url":"https://api.github.com/users/NVIDIA/repos","events_url":"https://api.github.com/users/NVIDIA/events{/privacy}","received_events_url":"https://api.github.com/users/NVIDIA/received_events","type":"Organization","site_admin":false},"repo":{"id":114185437,"name":"dfcpub","full_name":"NVIDIA/dfcpub","owner":{"login":"NVIDIA","id":1728152,"avatar_url":"https://avatars2.githubusercontent.com/u/1728152?v=4","gravatar_id":"","url":"https://api.github.com/users/NVIDIA","html_url":"https://github.com/NVIDIA","followers_url":"https://api.github.com/users/NVIDIA/followers","following_url":"https://api.github.com/users/NVIDIA/following{/other_user}","gists_url":"https://api.github.com/users/NVIDIA/gists{/gist_id}","starred_url":"https://api.github.com/users/NVIDIA/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NVIDIA/subscriptions","organizations_url":"https://api.github.com/users/NVIDIA/orgs","repos_url":"https://api.github.com/users/NVIDIA/repos","events_url":"https://api.github.com/users/NVIDIA/events{/privacy}","received_events_url":"https://api.github.com/users/NVIDIA/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/NVIDIA/dfcpub","description":null,"fork":false,"url":"https://api.github.com/repos/NVIDIA/dfcpub","forks_url":"https://api.github.com/repos/NVIDIA/dfcpub/forks","keys_url":"https://api.github.com/repos/NVIDIA/dfcpub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/NVIDIA/dfcpub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/NVIDIA/dfcpub/teams","hooks_url":"https://api.github.com/repos/NVIDIA/dfcpub/hooks","issue_events_url":"https://api.github.com/repos/NVIDIA/dfcpub/issues/events{/number}","events_url":"https://api.github.com/repos/NVIDIA/dfcpub/events","assignees_url":"https://api.github.com/repos/NVIDIA/dfcpub/assignees{/user}","branches_url":"https://api.github.com/repos/NVIDIA/dfcpub/branches{/branch}","tags_url":"https://api.github.com/repos/NVIDIA/dfcpub/tags","blobs_url":"https://api.github.com/repos/NVIDIA/dfcpub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/NVIDIA/dfcpub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/NVIDIA/dfcpub/git/refs{/sha}","trees_url":"https://api.github.com/repos/NVIDIA/dfcpub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/NVIDIA/dfcpub/statuses/{sha}","languages_url":"https://api.github.com/repos/NVIDIA/dfcpub/languages","stargazers_url":"https://api.github.com/repos/NVIDIA/dfcpub/stargazers","contributors_url":"https://api.github.com/repos/NVIDIA/dfcpub/contributors","subscribers_url":"https://api.github.com/repos/NVIDIA/dfcpub/subscribers","subscription_url":"https://api.github.com/repos/NVIDIA/dfcpub/subscription","commits_url":"https://api.github.com/repos/NVIDIA/dfcpub/commits{/sha}","git_commits_url":"https://api.github.com/repos/NVIDIA/dfcpub/git/commits{/sha}","comments_url":"https://api.github.com/repos/NVIDIA/dfcpub/comments{/number}","issue_comment_url":"https://api.github.com/repos/NVIDIA/dfcpub/issues/comments{/number}","contents_url":"https://api.github.com/repos/NVIDIA/dfcpub/contents/{+path}","compare_url":"https://api.github.com/repos/NVIDIA/dfcpub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/NVIDIA/dfcpub/merges","archive_url":"https://api.github.com/repos/NVIDIA/dfcpub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/NVIDIA/dfcpub/downloads","issues_url":"https://api.github.com/repos/NVIDIA/dfcpub/issues{/number}","pulls_url":"https://api.github.com/repos/NVIDIA/dfcpub/pulls{/number}","milestones_url":"https://api.github.com/repos/NVIDIA/dfcpub/milestones{/number}","notifications_url":"https://api.github.com/repos/NVIDIA/dfcpub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/NVIDIA/dfcpub/labels{/name}","releases_url":"https://api.github.com/repos/NVIDIA/dfcpub/releases{/id}","deployments_url":"https://api.github.com/repos/NVIDIA/dfcpub/deployments","created_at":"2017-12-14T01:07:30Z","updated_at":"2018-05-09T00:45:33Z","pushed_at":"2018-05-09T17:10:04Z","git_url":"git://github.com/NVIDIA/dfcpub.git","ssh_url":"git@github.com:NVIDIA/dfcpub.git","clone_url":"https://github.com/NVIDIA/dfcpub.git","svn_url":"https://github.com/NVIDIA/dfcpub","homepage":null,"size":3665,"stargazers_count":24,"watchers_count":24,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":6,"open_issues":1,"watchers":24,"default_branch":"master"}},"base":{"label":"NVIDIA:master","ref":"master","sha":"ad139ba11ce71da7351360b90f27f5c6f442e39a","user":{"login":"NVIDIA","id":1728152,"avatar_url":"https://avatars2.githubusercontent.com/u/1728152?v=4","gravatar_id":"","url":"https://api.github.com/users/NVIDIA","html_url":"https://github.com/NVIDIA","followers_url":"https://api.github.com/users/NVIDIA/followers","following_url":"https://api.github.com/users/NVIDIA/following{/other_user}","gists_url":"https://api.github.com/users/NVIDIA/gists{/gist_id}","starred_url":"https://api.github.com/users/NVIDIA/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NVIDIA/subscriptions","organizations_url":"https://api.github.com/users/NVIDIA/orgs","repos_url":"https://api.github.com/users/NVIDIA/repos","events_url":"https://api.github.com/users/NVIDIA/events{/privacy}","received_events_url":"https://api.github.com/users/NVIDIA/received_events","type":"Organization","site_admin":false},"repo":{"id":114185437,"name":"dfcpub","full_name":"NVIDIA/dfcpub","owner":{"login":"NVIDIA","id":1728152,"avatar_url":"https://avatars2.githubusercontent.com/u/1728152?v=4","gravatar_id":"","url":"https://api.github.com/users/NVIDIA","html_url":"https://github.com/NVIDIA","followers_url":"https://api.github.com/users/NVIDIA/followers","following_url":"https://api.github.com/users/NVIDIA/following{/other_user}","gists_url":"https://api.github.com/users/NVIDIA/gists{/gist_id}","starred_url":"https://api.github.com/users/NVIDIA/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NVIDIA/subscriptions","organizations_url":"https://api.github.com/users/NVIDIA/orgs","repos_url":"https://api.github.com/users/NVIDIA/repos","events_url":"https://api.github.com/users/NVIDIA/events{/privacy}","received_events_url":"https://api.github.com/users/NVIDIA/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/NVIDIA/dfcpub","description":null,"fork":false,"url":"https://api.github.com/repos/NVIDIA/dfcpub","forks_url":"https://api.github.com/repos/NVIDIA/dfcpub/forks","keys_url":"https://api.github.com/repos/NVIDIA/dfcpub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/NVIDIA/dfcpub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/NVIDIA/dfcpub/teams","hooks_url":"https://api.github.com/repos/NVIDIA/dfcpub/hooks","issue_events_url":"https://api.github.com/repos/NVIDIA/dfcpub/issues/events{/number}","events_url":"https://api.github.com/repos/NVIDIA/dfcpub/events","assignees_url":"https://api.github.com/repos/NVIDIA/dfcpub/assignees{/user}","branches_url":"https://api.github.com/repos/NVIDIA/dfcpub/branches{/branch}","tags_url":"https://api.github.com/repos/NVIDIA/dfcpub/tags","blobs_url":"https://api.github.com/repos/NVIDIA/dfcpub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/NVIDIA/dfcpub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/NVIDIA/dfcpub/git/refs{/sha}","trees_url":"https://api.github.com/repos/NVIDIA/dfcpub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/NVIDIA/dfcpub/statuses/{sha}","languages_url":"https://api.github.com/repos/NVIDIA/dfcpub/languages","stargazers_url":"https://api.github.com/repos/NVIDIA/dfcpub/stargazers","contributors_url":"https://api.github.com/repos/NVIDIA/dfcpub/contributors","subscribers_url":"https://api.github.com/repos/NVIDIA/dfcpub/subscribers","subscription_url":"https://api.github.com/repos/NVIDIA/dfcpub/subscription","commits_url":"https://api.github.com/repos/NVIDIA/dfcpub/commits{/sha}","git_commits_url":"https://api.github.com/repos/NVIDIA/dfcpub/git/commits{/sha}","comments_url":"https://api.github.com/repos/NVIDIA/dfcpub/comments{/number}","issue_comment_url":"https://api.github.com/repos/NVIDIA/dfcpub/issues/comments{/number}","contents_url":"https://api.github.com/repos/NVIDIA/dfcpub/contents/{+path}","compare_url":"https://api.github.com/repos/NVIDIA/dfcpub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/NVIDIA/dfcpub/merges","archive_url":"https://api.github.com/repos/NVIDIA/dfcpub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/NVIDIA/dfcpub/downloads","issues_url":"https://api.github.com/repos/NVIDIA/dfcpub/issues{/number}","pulls_url":"https://api.github.com/repos/NVIDIA/dfcpub/pulls{/number}","milestones_url":"https://api.github.com/repos/NVIDIA/dfcpub/milestones{/number}","notifications_url":"https://api.github.com/repos/NVIDIA/dfcpub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/NVIDIA/dfcpub/labels{/name}","releases_url":"https://api.github.com/repos/NVIDIA/dfcpub/releases{/id}","deployments_url":"https://api.github.com/repos/NVIDIA/dfcpub/deployments","created_at":"2017-12-14T01:07:30Z","updated_at":"2018-05-09T00:45:33Z","pushed_at":"2018-05-09T17:10:04Z","git_url":"git://github.com/NVIDIA/dfcpub.git","ssh_url":"git@github.com:NVIDIA/dfcpub.git","clone_url":"https://github.com/NVIDIA/dfcpub.git","svn_url":"https://github.com/NVIDIA/dfcpub","homepage":null,"size":3665,"stargazers_count":24,"watchers_count":24,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":6,"open_issues":1,"watchers":24,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/NVIDIA/dfcpub/pulls/7"},"html":{"href":"https://github.com/NVIDIA/dfcpub/pull/7"},"issue":{"href":"https://api.github.com/repos/NVIDIA/dfcpub/issues/7"},"comments":{"href":"https://api.github.com/repos/NVIDIA/dfcpub/issues/7/comments"},"review_comments":{"href":"https://api.github.com/repos/NVIDIA/dfcpub/pulls/7/comments"},"review_comment":{"href":"https://api.github.com/repos/NVIDIA/dfcpub/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/NVIDIA/dfcpub/pulls/7/commits"},"statuses":{"href":"https://api.github.com/repos/NVIDIA/dfcpub/statuses/08f12760d909e8768066f9279e15888a5c49a6c0"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"VladimirMarkelov"}}