{"action":"created","comment":{"url":"https://api.github.com/repos/pingcap/tikv/pulls/comments/59131070","id":59131070,"diff_hunk":"@@ -12,35 +12,406 @@\n // limitations under the License.\n \n use std::sync::Arc;\n+use std::{result, error};\n+use std::thread::{self, JoinHandle};\n+use std::sync::mpsc::{self, Sender};\n use mio::Token;\n-use storage::{Engine, SnapshotStore};\n-use kvproto::kvrpcpb::Context;\n-use kvproto::coprocessor::Request;\n-use super::{Result, SendCh};\n+use tipb::select::{self, SelectRequest, SelectResponse, Row};\n+use tipb::schema::IndexInfo;\n+use protobuf::{Message as PbMsg, RepeatedField};\n+use byteorder::{BigEndian, ReadBytesExt};\n \n-#[allow(dead_code)]\n-pub struct SnapshotCoprocessor {\n-    engine: Arc<Box<Engine>>,\n-    ch: SendCh,\n+use storage::{Engine, SnapshotStore, engine, txn, mvcc};\n+use kvproto::kvrpcpb::{Context, LockInfo};\n+use kvproto::msgpb::{MessageType, Message};\n+use kvproto::coprocessor::{Request, Response, KeyRange};\n+use kvproto::errorpb;\n+use storage::Key;\n+use util::codec::{Datum, table, datum};\n+use util::xeval::Evaluator;\n+use server::{self, SendCh, Msg, ConnData};\n+\n+pub const REQ_TYPE_SELECT: i64 = 101;\n+pub const REQ_TYPE_INDEX: i64 = 102;\n+\n+quick_error! {\n+    #[derive(Debug)]\n+    pub enum Error {\n+        Region(err: errorpb::Error) {\n+            description(\"region related failure\")\n+            display(\"region {:?}\", err)\n+        }\n+        Locked(l: LockInfo) {\n+            description(\"key is locked\")\n+            display(\"locked {:?}\", l)\n+        }\n+        Other(err: Box<error::Error + Send + Sync>) {\n+            from()\n+            cause(err.as_ref())\n+            description(err.description())\n+            display(\"unknown error {:?}\", err)\n+        }\n+    }\n }\n \n-impl SnapshotCoprocessor {\n-    pub fn new(engine: Arc<Box<Engine>>, ch: SendCh) -> SnapshotCoprocessor {\n-        // TODO: Spawn a new thread for handling requests asynchronously.\n-        SnapshotCoprocessor {\n-            engine: engine,\n-            ch: ch,\n+pub type Result<T> = result::Result<T, Error>;\n+\n+impl From<engine::Error> for Error {\n+    fn from(e: engine::Error) -> Error {\n+        match e {\n+            engine::Error::Request(e) => Error::Region(e),\n+            _ => Error::Other(box e),\n         }\n     }\n+}\n+\n+impl From<txn::Error> for Error {\n+    fn from(e: txn::Error) -> Error {\n+        match e {\n+            txn::Error::Mvcc(mvcc::Error::KeyIsLocked { primary, ts, .. }) => {\n+                let mut info = LockInfo::new();\n+                info.set_primary_lock(primary);\n+                info.set_lock_version(ts);\n+                Error::Locked(info)\n+            }\n+            _ => Error::Other(box e),\n+        }\n+    }\n+}\n+\n+pub struct RegionEndPoint {\n+    tx: Sender<EndPointMessage>,\n+    handle: Option<JoinHandle<()>>,\n+}\n+\n+type ResponseHandler = Box<Fn(Response) -> ()>;\n+\n+#[derive(Debug)]\n+enum EndPointMessage {\n+    Job(Request, Token, u64),\n+    Close,\n+}\n+\n+impl RegionEndPoint {\n+    pub fn new(engine: Arc<Box<Engine>>, ch: SendCh) -> RegionEndPoint {\n+        let (tx, rx) = mpsc::channel();\n+        let builder = thread::Builder::new().name(\"EndPoint\".to_owned());\n+        let handle = builder.spawn(move || {\n+                                info!(\"EndPoint started.\");\n+                                let end_point = SnapshotEndPoint::new(engine);\n+                                loop {\n+                                    let res = rx.recv();\n+                                    if let Err(e) = res {\n+                                        error!(\"failed to receive job: {:?}\", e);\n+                                        break;\n+                                    }\n+                                    let msg = res.unwrap();\n+                                    debug!(\"recv req: {:?}\", msg);\n+                                    match msg {\n+                                        EndPointMessage::Job(req, token, msg_id) => {\n+                                            handle_request(req,\n+                                                           ch.clone(),\n+                                                           token,\n+                                                           msg_id,\n+                                                           &end_point)\n+                                        }\n+                                        EndPointMessage::Close => break,\n+                                    }\n+                                }\n+                                info!(\"EndPoint closing.\");\n+                            })\n+                            .unwrap();\n+        RegionEndPoint {\n+            tx: tx,\n+            handle: Some(handle),\n+        }\n+    }\n+\n+    pub fn on_request(&self, req: Request, token: Token, msg_id: u64) -> server::Result<()> {\n+        box_try!(self.tx.send(EndPointMessage::Job(req, token, msg_id)));\n+        Ok(())\n+    }\n+\n+    pub fn stop(&mut self) {\n+        if self.handle.is_none() {\n+            return;\n+        }\n+        if let Err(e) = self.tx.send(EndPointMessage::Close) {\n+            error!(\"failed to ask the coprocessor to stop: {:?}\", e);\n+        }\n+        if let Err(e) = self.handle.take().unwrap().join() {\n+            error!(\"failed to stop the coprocessor: {:?}\", e);\n+        }\n+    }\n+}\n+\n+fn handle_request(req: Request,\n+                  ch: SendCh,\n+                  token: Token,\n+                  msg_id: u64,\n+                  end_point: &SnapshotEndPoint) {\n+    let cb = box move |r| {\n+        let mut resp_msg = Message::new();\n+        resp_msg.set_msg_type(MessageType::CopResp);\n+        resp_msg.set_cop_resp(r);\n+        if let Err(e) = ch.send(Msg::WriteData {\n+            token: token,\n+            data: ConnData::new(msg_id, resp_msg),\n+        }) {\n+            error!(\"send cop resp failed with token {:?}, msg id {}, err {:?}\",\n+                   token,\n+                   msg_id,\n+                   e);\n+        }\n+    };\n+    match req.get_tp() {\n+        REQ_TYPE_SELECT | REQ_TYPE_INDEX => {\n+            let mut sel = SelectRequest::new();\n+            if let Err(e) = sel.merge_from_bytes(req.get_data()) {\n+                on_error(box_err!(e), cb);\n+                return;\n+            }\n+            match end_point.handle_select(req, sel) {\n+                Ok(r) => cb(r),\n+                Err(e) => on_error(e, cb),\n+            }\n+        }\n+        t => on_error(box_err!(\"unsupported tp {}\", t), cb),\n+    }\n+}\n+\n+fn on_error(e: Error, cb: ResponseHandler) {\n+    let mut resp = Response::new();\n+    match e {\n+        Error::Region(e) => resp.set_region_error(e),\n+        Error::Locked(info) => resp.set_locked(info),\n+        Error::Other(_) => resp.set_other_error(format!(\"{}\", e)),\n+    }\n+    cb(resp)\n+}\n+\n+pub struct SnapshotEndPoint {\n+    engine: Arc<Box<Engine>>,\n+}\n \n-    #[allow(unused_variables)]\n-    pub fn on_request(&self, req: Request, token: Token, msg_id: u64) -> Result<()> {\n-        unimplemented!();\n+impl SnapshotEndPoint {\n+    pub fn new(engine: Arc<Box<Engine>>) -> SnapshotEndPoint {\n+        // TODO: Spawn a new thread for handling requests asynchronously.\n+        SnapshotEndPoint { engine: engine }\n     }\n \n-    #[allow(dead_code)]\n     fn new_snapshot<'a>(&'a self, ctx: &Context, start_ts: u64) -> Result<SnapshotStore<'a>> {\n         let snapshot = try!(self.engine.snapshot(ctx));\n         Ok(SnapshotStore::new(snapshot, start_ts))\n     }\n }\n+\n+impl SnapshotEndPoint {\n+    pub fn handle_select(&self, mut req: Request, sel: SelectRequest) -> Result<Response> {\n+        let store = try!(self.new_snapshot(req.get_context(), sel.get_start_ts()));\n+        let range = req.take_ranges().into_vec();\n+        debug!(\"scanning range: {:?}\", range);\n+        let res = if req.get_tp() == REQ_TYPE_SELECT {\n+            get_rows_from_sel(&store, &sel, range)\n+        } else {\n+            get_rows_from_idx(&store, &sel, range)\n+        };\n+        let mut resp = Response::new();\n+        let mut sel_resp = SelectResponse::new();\n+        match res {\n+            Ok(rows) => sel_resp.set_rows(RepeatedField::from_vec(rows)),\n+            Err(e) => {\n+                if let Error::Other(_) = e {\n+                    // should we handle locked here too?\n+                    sel_resp.set_error(to_pb_error(&e));\n+                    // TODO add detail error\n+                    resp.set_other_error(format!(\"{}\", e));\n+                } else {\n+                    // other error should be handle by ti client.\n+                    return Err(e);\n+                }\n+            }\n+        }\n+        let data = box_try!(sel_resp.write_to_bytes());\n+        resp.set_data(data);\n+        Ok(resp)\n+    }\n+}\n+\n+fn to_pb_error(err: &Error) -> select::Error {\n+    let mut e = select::Error::new();\n+    e.set_code(1);","path":"src/server/coprocessor.rs","position":250,"original_position":250,"commit_id":"3383df50081628ea3eb610b799ce46f268e96a06","original_commit_id":"3383df50081628ea3eb610b799ce46f268e96a06","user":{"login":"ngaut","id":878009,"avatar_url":"https://avatars.githubusercontent.com/u/878009?v=3","gravatar_id":"","url":"https://api.github.com/users/ngaut","html_url":"https://github.com/ngaut","followers_url":"https://api.github.com/users/ngaut/followers","following_url":"https://api.github.com/users/ngaut/following{/other_user}","gists_url":"https://api.github.com/users/ngaut/gists{/gist_id}","starred_url":"https://api.github.com/users/ngaut/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ngaut/subscriptions","organizations_url":"https://api.github.com/users/ngaut/orgs","repos_url":"https://api.github.com/users/ngaut/repos","events_url":"https://api.github.com/users/ngaut/events{/privacy}","received_events_url":"https://api.github.com/users/ngaut/received_events","type":"User","site_admin":false},"body":"What does 1 mean ? Looks like a magic number.","created_at":"2016-04-10T10:14:42Z","updated_at":"2016-04-10T10:14:42Z","html_url":"https://github.com/pingcap/tikv/pull/379#discussion_r59131070","pull_request_url":"https://api.github.com/repos/pingcap/tikv/pulls/379","_links":{"self":{"href":"https://api.github.com/repos/pingcap/tikv/pulls/comments/59131070"},"html":{"href":"https://github.com/pingcap/tikv/pull/379#discussion_r59131070"},"pull_request":{"href":"https://api.github.com/repos/pingcap/tikv/pulls/379"}}},"pull_request":{"url":"https://api.github.com/repos/pingcap/tikv/pulls/379","id":65887148,"html_url":"https://github.com/pingcap/tikv/pull/379","diff_url":"https://github.com/pingcap/tikv/pull/379.diff","patch_url":"https://github.com/pingcap/tikv/pull/379.patch","issue_url":"https://api.github.com/repos/pingcap/tikv/issues/379","number":379,"state":"open","locked":false,"title":"[DNM] add push implement","user":{"login":"BusyJay","id":1701473,"avatar_url":"https://avatars.githubusercontent.com/u/1701473?v=3","gravatar_id":"","url":"https://api.github.com/users/BusyJay","html_url":"https://github.com/BusyJay","followers_url":"https://api.github.com/users/BusyJay/followers","following_url":"https://api.github.com/users/BusyJay/following{/other_user}","gists_url":"https://api.github.com/users/BusyJay/gists{/gist_id}","starred_url":"https://api.github.com/users/BusyJay/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BusyJay/subscriptions","organizations_url":"https://api.github.com/users/BusyJay/orgs","repos_url":"https://api.github.com/users/BusyJay/repos","events_url":"https://api.github.com/users/BusyJay/events{/privacy}","received_events_url":"https://api.github.com/users/BusyJay/received_events","type":"User","site_admin":false},"body":"tests will be added tomorrow","created_at":"2016-04-09T17:36:56Z","updated_at":"2016-04-10T10:14:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0d1d3ad9ef0958b3d8041483c7de41f1c7d3663d","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/pingcap/tikv/pulls/379/commits","review_comments_url":"https://api.github.com/repos/pingcap/tikv/pulls/379/comments","review_comment_url":"https://api.github.com/repos/pingcap/tikv/pulls/comments{/number}","comments_url":"https://api.github.com/repos/pingcap/tikv/issues/379/comments","statuses_url":"https://api.github.com/repos/pingcap/tikv/statuses/3383df50081628ea3eb610b799ce46f268e96a06","head":{"label":"pingcap:busyjay/impl-push-down","ref":"busyjay/impl-push-down","sha":"3383df50081628ea3eb610b799ce46f268e96a06","user":{"login":"pingcap","id":11855343,"avatar_url":"https://avatars.githubusercontent.com/u/11855343?v=3","gravatar_id":"","url":"https://api.github.com/users/pingcap","html_url":"https://github.com/pingcap","followers_url":"https://api.github.com/users/pingcap/followers","following_url":"https://api.github.com/users/pingcap/following{/other_user}","gists_url":"https://api.github.com/users/pingcap/gists{/gist_id}","starred_url":"https://api.github.com/users/pingcap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pingcap/subscriptions","organizations_url":"https://api.github.com/users/pingcap/orgs","repos_url":"https://api.github.com/users/pingcap/repos","events_url":"https://api.github.com/users/pingcap/events{/privacy}","received_events_url":"https://api.github.com/users/pingcap/received_events","type":"Organization","site_admin":false},"repo":{"id":48833910,"name":"tikv","full_name":"pingcap/tikv","owner":{"login":"pingcap","id":11855343,"avatar_url":"https://avatars.githubusercontent.com/u/11855343?v=3","gravatar_id":"","url":"https://api.github.com/users/pingcap","html_url":"https://github.com/pingcap","followers_url":"https://api.github.com/users/pingcap/followers","following_url":"https://api.github.com/users/pingcap/following{/other_user}","gists_url":"https://api.github.com/users/pingcap/gists{/gist_id}","starred_url":"https://api.github.com/users/pingcap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pingcap/subscriptions","organizations_url":"https://api.github.com/users/pingcap/orgs","repos_url":"https://api.github.com/users/pingcap/repos","events_url":"https://api.github.com/users/pingcap/events{/privacy}","received_events_url":"https://api.github.com/users/pingcap/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/pingcap/tikv","description":"Distributed key value store powered by rust","fork":false,"url":"https://api.github.com/repos/pingcap/tikv","forks_url":"https://api.github.com/repos/pingcap/tikv/forks","keys_url":"https://api.github.com/repos/pingcap/tikv/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pingcap/tikv/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pingcap/tikv/teams","hooks_url":"https://api.github.com/repos/pingcap/tikv/hooks","issue_events_url":"https://api.github.com/repos/pingcap/tikv/issues/events{/number}","events_url":"https://api.github.com/repos/pingcap/tikv/events","assignees_url":"https://api.github.com/repos/pingcap/tikv/assignees{/user}","branches_url":"https://api.github.com/repos/pingcap/tikv/branches{/branch}","tags_url":"https://api.github.com/repos/pingcap/tikv/tags","blobs_url":"https://api.github.com/repos/pingcap/tikv/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pingcap/tikv/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pingcap/tikv/git/refs{/sha}","trees_url":"https://api.github.com/repos/pingcap/tikv/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pingcap/tikv/statuses/{sha}","languages_url":"https://api.github.com/repos/pingcap/tikv/languages","stargazers_url":"https://api.github.com/repos/pingcap/tikv/stargazers","contributors_url":"https://api.github.com/repos/pingcap/tikv/contributors","subscribers_url":"https://api.github.com/repos/pingcap/tikv/subscribers","subscription_url":"https://api.github.com/repos/pingcap/tikv/subscription","commits_url":"https://api.github.com/repos/pingcap/tikv/commits{/sha}","git_commits_url":"https://api.github.com/repos/pingcap/tikv/git/commits{/sha}","comments_url":"https://api.github.com/repos/pingcap/tikv/comments{/number}","issue_comment_url":"https://api.github.com/repos/pingcap/tikv/issues/comments{/number}","contents_url":"https://api.github.com/repos/pingcap/tikv/contents/{+path}","compare_url":"https://api.github.com/repos/pingcap/tikv/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pingcap/tikv/merges","archive_url":"https://api.github.com/repos/pingcap/tikv/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pingcap/tikv/downloads","issues_url":"https://api.github.com/repos/pingcap/tikv/issues{/number}","pulls_url":"https://api.github.com/repos/pingcap/tikv/pulls{/number}","milestones_url":"https://api.github.com/repos/pingcap/tikv/milestones{/number}","notifications_url":"https://api.github.com/repos/pingcap/tikv/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pingcap/tikv/labels{/name}","releases_url":"https://api.github.com/repos/pingcap/tikv/releases{/id}","deployments_url":"https://api.github.com/repos/pingcap/tikv/deployments","created_at":"2015-12-31T04:51:32Z","updated_at":"2016-04-10T08:42:37Z","pushed_at":"2016-04-10T09:52:17Z","git_url":"git://github.com/pingcap/tikv.git","ssh_url":"git@github.com:pingcap/tikv.git","clone_url":"https://github.com/pingcap/tikv.git","svn_url":"https://github.com/pingcap/tikv","homepage":"","size":1759,"stargazers_count":477,"watchers_count":477,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":27,"mirror_url":null,"open_issues_count":18,"forks":27,"open_issues":18,"watchers":477,"default_branch":"master"}},"base":{"label":"pingcap:master","ref":"master","sha":"56299222cf52a9fc49de6cce8f15837dc7a5aacb","user":{"login":"pingcap","id":11855343,"avatar_url":"https://avatars.githubusercontent.com/u/11855343?v=3","gravatar_id":"","url":"https://api.github.com/users/pingcap","html_url":"https://github.com/pingcap","followers_url":"https://api.github.com/users/pingcap/followers","following_url":"https://api.github.com/users/pingcap/following{/other_user}","gists_url":"https://api.github.com/users/pingcap/gists{/gist_id}","starred_url":"https://api.github.com/users/pingcap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pingcap/subscriptions","organizations_url":"https://api.github.com/users/pingcap/orgs","repos_url":"https://api.github.com/users/pingcap/repos","events_url":"https://api.github.com/users/pingcap/events{/privacy}","received_events_url":"https://api.github.com/users/pingcap/received_events","type":"Organization","site_admin":false},"repo":{"id":48833910,"name":"tikv","full_name":"pingcap/tikv","owner":{"login":"pingcap","id":11855343,"avatar_url":"https://avatars.githubusercontent.com/u/11855343?v=3","gravatar_id":"","url":"https://api.github.com/users/pingcap","html_url":"https://github.com/pingcap","followers_url":"https://api.github.com/users/pingcap/followers","following_url":"https://api.github.com/users/pingcap/following{/other_user}","gists_url":"https://api.github.com/users/pingcap/gists{/gist_id}","starred_url":"https://api.github.com/users/pingcap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pingcap/subscriptions","organizations_url":"https://api.github.com/users/pingcap/orgs","repos_url":"https://api.github.com/users/pingcap/repos","events_url":"https://api.github.com/users/pingcap/events{/privacy}","received_events_url":"https://api.github.com/users/pingcap/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/pingcap/tikv","description":"Distributed key value store powered by rust","fork":false,"url":"https://api.github.com/repos/pingcap/tikv","forks_url":"https://api.github.com/repos/pingcap/tikv/forks","keys_url":"https://api.github.com/repos/pingcap/tikv/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pingcap/tikv/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pingcap/tikv/teams","hooks_url":"https://api.github.com/repos/pingcap/tikv/hooks","issue_events_url":"https://api.github.com/repos/pingcap/tikv/issues/events{/number}","events_url":"https://api.github.com/repos/pingcap/tikv/events","assignees_url":"https://api.github.com/repos/pingcap/tikv/assignees{/user}","branches_url":"https://api.github.com/repos/pingcap/tikv/branches{/branch}","tags_url":"https://api.github.com/repos/pingcap/tikv/tags","blobs_url":"https://api.github.com/repos/pingcap/tikv/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pingcap/tikv/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pingcap/tikv/git/refs{/sha}","trees_url":"https://api.github.com/repos/pingcap/tikv/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pingcap/tikv/statuses/{sha}","languages_url":"https://api.github.com/repos/pingcap/tikv/languages","stargazers_url":"https://api.github.com/repos/pingcap/tikv/stargazers","contributors_url":"https://api.github.com/repos/pingcap/tikv/contributors","subscribers_url":"https://api.github.com/repos/pingcap/tikv/subscribers","subscription_url":"https://api.github.com/repos/pingcap/tikv/subscription","commits_url":"https://api.github.com/repos/pingcap/tikv/commits{/sha}","git_commits_url":"https://api.github.com/repos/pingcap/tikv/git/commits{/sha}","comments_url":"https://api.github.com/repos/pingcap/tikv/comments{/number}","issue_comment_url":"https://api.github.com/repos/pingcap/tikv/issues/comments{/number}","contents_url":"https://api.github.com/repos/pingcap/tikv/contents/{+path}","compare_url":"https://api.github.com/repos/pingcap/tikv/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pingcap/tikv/merges","archive_url":"https://api.github.com/repos/pingcap/tikv/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pingcap/tikv/downloads","issues_url":"https://api.github.com/repos/pingcap/tikv/issues{/number}","pulls_url":"https://api.github.com/repos/pingcap/tikv/pulls{/number}","milestones_url":"https://api.github.com/repos/pingcap/tikv/milestones{/number}","notifications_url":"https://api.github.com/repos/pingcap/tikv/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pingcap/tikv/labels{/name}","releases_url":"https://api.github.com/repos/pingcap/tikv/releases{/id}","deployments_url":"https://api.github.com/repos/pingcap/tikv/deployments","created_at":"2015-12-31T04:51:32Z","updated_at":"2016-04-10T08:42:37Z","pushed_at":"2016-04-10T09:52:17Z","git_url":"git://github.com/pingcap/tikv.git","ssh_url":"git@github.com:pingcap/tikv.git","clone_url":"https://github.com/pingcap/tikv.git","svn_url":"https://github.com/pingcap/tikv","homepage":"","size":1759,"stargazers_count":477,"watchers_count":477,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":27,"mirror_url":null,"open_issues_count":18,"forks":27,"open_issues":18,"watchers":477,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/pingcap/tikv/pulls/379"},"html":{"href":"https://github.com/pingcap/tikv/pull/379"},"issue":{"href":"https://api.github.com/repos/pingcap/tikv/issues/379"},"comments":{"href":"https://api.github.com/repos/pingcap/tikv/issues/379/comments"},"review_comments":{"href":"https://api.github.com/repos/pingcap/tikv/pulls/379/comments"},"review_comment":{"href":"https://api.github.com/repos/pingcap/tikv/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/pingcap/tikv/pulls/379/commits"},"statuses":{"href":"https://api.github.com/repos/pingcap/tikv/statuses/3383df50081628ea3eb610b799ce46f268e96a06"}}}}