{"action":"created","comment":{"url":"https://api.github.com/repos/pingcap/tikv/pulls/comments/79300580","id":79300580,"diff_hunk":"@@ -0,0 +1,157 @@\n+// Copyright 2016 PingCAP, Inc.\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+// See the License for the specific language governing permissions and\n+// limitations under the License.\n+\n+// Copyright 2016 The etcd Authors\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+use kvproto::eraftpb::Message;\n+use std::collections::{HashSet, HashMap};\n+\n+#[derive(Debug, PartialEq, Clone, Copy)]\n+pub enum ReadOnlyOption {\n+    /// Safe guarantees the linearizability of the read only request by\n+    /// communicating with the quorum. It is the default and suggested option.\n+    Safe,\n+    /// LeaseBased ensures linearizability of the read only request by\n+    /// relying on the leader lease. It can be affected by clock drift.\n+    /// If the clock drift is unbounded, leader might keep the lease longer than it\n+    /// should (clock can move backward/pause without any bound). ReadIndex is not safe\n+    /// in that case.\n+    LeaseBased,\n+}\n+\n+impl Default for ReadOnlyOption {\n+    fn default() -> ReadOnlyOption {\n+        ReadOnlyOption::Safe\n+    }\n+}\n+\n+// ReadState provides state for read only query.\n+// It's caller's responsibility to send MsgReadIndex first before getting\n+// this state from ready. It's also caller's duty to differentiate if this\n+// state is what it requests through request_ctx, e.g. given a unique id as\n+// request_ctx.\n+#[derive(Default, Debug, PartialEq, Clone)]\n+pub struct ReadState {\n+    pub index: u64,\n+    pub request_ctx: Vec<u8>,\n+}\n+\n+#[derive(Default, Debug, Clone)]\n+pub struct ReadIndexStatus {\n+    pub req: Message,\n+    pub index: u64,\n+    pub acks: HashSet<u64>,\n+}\n+\n+#[derive(Default, Debug, Clone)]\n+pub struct ReadOnly {\n+    pub option: ReadOnlyOption,\n+    pub pending_read_index: HashMap<Vec<u8>, ReadIndexStatus>,\n+    pub read_index_queue: Vec<Vec<u8>>,\n+}\n+\n+impl ReadOnly {\n+    pub fn new(option: ReadOnlyOption) -> ReadOnly {\n+        ReadOnly {\n+            option: option,\n+            pending_read_index: HashMap::new(),\n+            read_index_queue: vec![],\n+        }\n+    }\n+\n+    /// add_request adds a read only request into readonly struct.\n+    /// `index` is the commit index of the raft state machine when it received\n+    /// the read only request.\n+    /// `m` is the original read only request message from the local or remote node.\n+    pub fn add_request(&mut self, index: u64, m: Message) {\n+        let ctx = m.get_entries()[0].get_data().to_vec();\n+        if self.pending_read_index.contains_key(&ctx) {\n+            return;\n+        }\n+        let status = ReadIndexStatus {\n+            req: m,\n+            index: index,\n+            acks: HashSet::new(),\n+        };\n+        self.pending_read_index.insert(ctx.clone(), status);\n+        self.read_index_queue.push(ctx);\n+    }\n+\n+    /// rev_ack notifies the ReadOnly struct that the raft state machine received\n+    /// an acknowledgment of the heartbeat that attached with the read only request\n+    /// context.\n+    pub fn recv_ack(&mut self, m: &Message) -> usize {\n+        match self.pending_read_index.get_mut(&m.get_context().to_vec()) {\n+            None => 0,\n+            Some(rs) => {\n+                rs.acks.insert(m.get_from());\n+                // add one to include an ack from local node\n+                rs.acks.len() + 1\n+            }\n+        }\n+    }\n+\n+    /// advance advances the read only request queue kept by the ReadOnly struct.\n+    /// It dequeues the requests until it finds the read only request that has\n+    /// the same context as the given `m`.\n+    pub fn advance(&mut self, m: &Message) -> Vec<ReadIndexStatus> {\n+        let mut i = 0;\n+        let mut found = false;\n+        let ctx = m.get_context().to_vec();\n+\n+        for c in &self.read_index_queue {\n+            i += 1;\n+            if !self.pending_read_index.contains_key(c) {\n+                panic!(\"cannot find correspond read state from pending map\");\n+            }\n+            if *c == ctx {\n+                found = true;\n+                break;\n+            }\n+        }\n+\n+        let mut rss = vec![];\n+        if found {\n+            let to_keep = self.read_index_queue.split_off(i);\n+            for rs in &self.read_index_queue {\n+                match self.pending_read_index.remove(rs) {\n+                    Some(status) => rss.push(status),\n+                    None => panic!(\"cannot find correspond read state from pending map\"),\n+                }\n+            }\n+            self.read_index_queue = to_keep;\n+        }\n+        rss\n+    }\n+\n+    /// last_pending_request_ctx returns the context of the last pending read only\n+    /// request in ReadOnly struct.\n+    pub fn last_pending_request_ctx(&self) -> Option<Vec<u8>> {\n+        match self.read_index_queue.last() {","path":"src/raft/read_only.rs","position":null,"original_position":152,"commit_id":"135c189e4e4a8e1d93eae70e0989274757e6ee1a","original_commit_id":"d4478936da9018ad74b3997ec6bc4d5333123a1d","user":{"login":"hhkbp2","id":1933824,"avatar_url":"https://avatars.githubusercontent.com/u/1933824?v=3","gravatar_id":"","url":"https://api.github.com/users/hhkbp2","html_url":"https://github.com/hhkbp2","followers_url":"https://api.github.com/users/hhkbp2/followers","following_url":"https://api.github.com/users/hhkbp2/following{/other_user}","gists_url":"https://api.github.com/users/hhkbp2/gists{/gist_id}","starred_url":"https://api.github.com/users/hhkbp2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hhkbp2/subscriptions","organizations_url":"https://api.github.com/users/hhkbp2/orgs","repos_url":"https://api.github.com/users/hhkbp2/repos","events_url":"https://api.github.com/users/hhkbp2/events{/privacy}","received_events_url":"https://api.github.com/users/hhkbp2/received_events","type":"User","site_admin":false},"body":"Address comment.","created_at":"2016-09-18T08:24:10Z","updated_at":"2016-09-18T08:24:10Z","html_url":"https://github.com/pingcap/tikv/pull/1032#discussion_r79300580","pull_request_url":"https://api.github.com/repos/pingcap/tikv/pulls/1032","_links":{"self":{"href":"https://api.github.com/repos/pingcap/tikv/pulls/comments/79300580"},"html":{"href":"https://github.com/pingcap/tikv/pull/1032#discussion_r79300580"},"pull_request":{"href":"https://api.github.com/repos/pingcap/tikv/pulls/1032"}}},"pull_request":{"url":"https://api.github.com/repos/pingcap/tikv/pulls/1032","id":84055136,"html_url":"https://github.com/pingcap/tikv/pull/1032","diff_url":"https://github.com/pingcap/tikv/pull/1032.diff","patch_url":"https://github.com/pingcap/tikv/pull/1032.patch","issue_url":"https://api.github.com/repos/pingcap/tikv/issues/1032","number":1032,"state":"open","locked":false,"title":"raft: port read index request on quorum check","user":{"login":"hhkbp2","id":1933824,"avatar_url":"https://avatars.githubusercontent.com/u/1933824?v=3","gravatar_id":"","url":"https://api.github.com/users/hhkbp2","html_url":"https://github.com/hhkbp2","followers_url":"https://api.github.com/users/hhkbp2/followers","following_url":"https://api.github.com/users/hhkbp2/following{/other_user}","gists_url":"https://api.github.com/users/hhkbp2/gists{/gist_id}","starred_url":"https://api.github.com/users/hhkbp2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hhkbp2/subscriptions","organizations_url":"https://api.github.com/users/hhkbp2/orgs","repos_url":"https://api.github.com/users/hhkbp2/repos","events_url":"https://api.github.com/users/hhkbp2/events{/privacy}","received_events_url":"https://api.github.com/users/hhkbp2/received_events","type":"User","site_admin":false},"body":"For issue #960 ","created_at":"2016-09-06T03:20:07Z","updated_at":"2016-09-18T08:24:10Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0186667d6b7e5d007399c4f529b5f13ac593a189","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/pingcap/tikv/pulls/1032/commits","review_comments_url":"https://api.github.com/repos/pingcap/tikv/pulls/1032/comments","review_comment_url":"https://api.github.com/repos/pingcap/tikv/pulls/comments{/number}","comments_url":"https://api.github.com/repos/pingcap/tikv/issues/1032/comments","statuses_url":"https://api.github.com/repos/pingcap/tikv/statuses/135c189e4e4a8e1d93eae70e0989274757e6ee1a","head":{"label":"pingcap:hhkbp2/port-read-index-request-on-quorum-check","ref":"hhkbp2/port-read-index-request-on-quorum-check","sha":"135c189e4e4a8e1d93eae70e0989274757e6ee1a","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 transactional key value database powered by Rust and Raft","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-09-18T07:54:07Z","pushed_at":"2016-09-18T08:21:26Z","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":6011,"stargazers_count":1019,"watchers_count":1019,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":83,"mirror_url":null,"open_issues_count":53,"forks":83,"open_issues":53,"watchers":1019,"default_branch":"master"}},"base":{"label":"pingcap:master","ref":"master","sha":"d7b7038fb82056b4b12afa86787275b88dee467c","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 transactional key value database powered by Rust and Raft","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-09-18T07:54:07Z","pushed_at":"2016-09-18T08:21:26Z","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":6011,"stargazers_count":1019,"watchers_count":1019,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":83,"mirror_url":null,"open_issues_count":53,"forks":83,"open_issues":53,"watchers":1019,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/pingcap/tikv/pulls/1032"},"html":{"href":"https://github.com/pingcap/tikv/pull/1032"},"issue":{"href":"https://api.github.com/repos/pingcap/tikv/issues/1032"},"comments":{"href":"https://api.github.com/repos/pingcap/tikv/issues/1032/comments"},"review_comments":{"href":"https://api.github.com/repos/pingcap/tikv/pulls/1032/comments"},"review_comment":{"href":"https://api.github.com/repos/pingcap/tikv/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/pingcap/tikv/pulls/1032/commits"},"statuses":{"href":"https://api.github.com/repos/pingcap/tikv/statuses/135c189e4e4a8e1d93eae70e0989274757e6ee1a"}}}}
{"actor":{"display_login":"hhkbp2"}}