| 158 | } |
| 159 | |
| 160 | void read(const BlockRequest *request, BlockResponse* response, |
| 161 | butil::IOBuf* buf) { |
| 162 | // In consideration of consistency. GetRequest to follower should be |
| 163 | // rejected. |
| 164 | if (!is_leader()) { |
| 165 | // This node is a follower or it's not up-to-date. Redirect to |
| 166 | // the leader if possible. |
| 167 | return redirect(response); |
| 168 | } |
| 169 | |
| 170 | if (request->offset() < 0) { |
| 171 | response->set_success(false); |
| 172 | return; |
| 173 | } |
| 174 | |
| 175 | // This is the leader and is up-to-date. It's safe to respond client |
| 176 | scoped_fd fd = get_fd(); |
| 177 | butil::IOPortal portal; |
| 178 | const ssize_t nr = braft::file_pread( |
| 179 | &portal, fd->fd(), request->offset(), request->size()); |
| 180 | if (nr < 0) { |
| 181 | // Some disk error occurred, shutdown this node and another leader |
| 182 | // will be elected |
| 183 | PLOG(ERROR) << "Fail to read from fd=" << fd->fd(); |
| 184 | _node->shutdown(NULL); |
| 185 | response->set_success(false); |
| 186 | return; |
| 187 | } |
| 188 | buf->swap(portal); |
| 189 | if (buf->length() < (size_t)request->size()) { |
| 190 | buf->resize(request->size()); |
| 191 | } |
| 192 | response->set_success(true); |
| 193 | } |
| 194 | |
| 195 | bool is_leader() const |
| 196 | { return _leader_term.load(butil::memory_order_acquire) > 0; } |