/Users/deen/code/yugabyte-db/src/yb/tserver/remote_bootstrap_client.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // |
18 | | // The following only applies to changes made to this file as part of YugaByte development. |
19 | | // |
20 | | // Portions Copyright (c) YugaByte, Inc. |
21 | | // |
22 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
23 | | // in compliance with the License. You may obtain a copy of the License at |
24 | | // |
25 | | // http://www.apache.org/licenses/LICENSE-2.0 |
26 | | // |
27 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
28 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
29 | | // or implied. See the License for the specific language governing permissions and limitations |
30 | | // under the License. |
31 | | // |
32 | | #ifndef YB_TSERVER_REMOTE_BOOTSTRAP_CLIENT_H |
33 | | #define YB_TSERVER_REMOTE_BOOTSTRAP_CLIENT_H |
34 | | |
35 | | #include <atomic> |
36 | | #include <string> |
37 | | #include <memory> |
38 | | #include <vector> |
39 | | #include <unordered_map> |
40 | | |
41 | | #include <gtest/gtest_prod.h> |
42 | | |
43 | | #include "yb/consensus/consensus_fwd.h" |
44 | | #include "yb/gutil/macros.h" |
45 | | #include "yb/gutil/ref_counted.h" |
46 | | #include "yb/rpc/rpc_fwd.h" |
47 | | #include "yb/tserver/remote_bootstrap.pb.h" |
48 | | #include "yb/tserver/remote_bootstrap_file_downloader.h" |
49 | | #include "yb/util/status_fwd.h" |
50 | | |
51 | | namespace yb { |
52 | | |
53 | | class BlockIdPB; |
54 | | class Env; |
55 | | class FsManager; |
56 | | class HostPort; |
57 | | class RemoteBootstrapITest; |
58 | | |
59 | | namespace consensus { |
60 | | class ConsensusMetadata; |
61 | | class ConsensusStatePB; |
62 | | class RaftConfigPB; |
63 | | class RaftPeerPB; |
64 | | } // namespace consensus |
65 | | |
66 | | namespace tablet { |
67 | | class RaftGroupMetadata; |
68 | | class TabletPeer; |
69 | | class TabletStatusListener; |
70 | | class RaftGroupReplicaSuperBlockPB; |
71 | | } // namespace tablet |
72 | | |
73 | | namespace tserver { |
74 | | class DataIdPB; |
75 | | class DataChunkPB; |
76 | | class RemoteBootstrapServiceProxy; |
77 | | class TSTabletManager; |
78 | | |
79 | | class RemoteBootstrapComponent { |
80 | | public: |
81 | | virtual CHECKED_STATUS CreateDirectories(const std::string& db_dir, FsManager* fs) = 0; |
82 | | virtual CHECKED_STATUS Download() = 0; |
83 | | |
84 | 1.43k | virtual ~RemoteBootstrapComponent() = default; |
85 | | }; |
86 | | |
87 | | // Client class for using remote bootstrap to copy a tablet from another host. |
88 | | // This class is not thread-safe. |
89 | | // |
90 | | // TODO: |
91 | | // * Parallelize download of blocks and WAL segments. |
92 | | // |
93 | | class RemoteBootstrapClient { |
94 | | public: |
95 | | |
96 | | // Construct the remote bootstrap client. |
97 | | // 'fs_manager' and 'messenger' must remain valid until this object is destroyed. |
98 | | RemoteBootstrapClient(std::string tablet_id, FsManager* fs_manager); |
99 | | |
100 | | // Attempt to clean up resources on the remote end by sending an |
101 | | // EndRemoteBootstrapSession() RPC |
102 | | ~RemoteBootstrapClient(); |
103 | | |
104 | | // Pass in the existing metadata for a tombstoned tablet, which will be |
105 | | // replaced if validation checks pass in Start(). |
106 | | // 'meta' is the metadata for the tombstoned tablet and 'caller_term' is the |
107 | | // term provided by the caller (assumed to be the current leader of the |
108 | | // consensus config) for validation purposes. |
109 | | // If the consensus metadata exists on disk for this tablet, and if |
110 | | // 'caller_term' is lower than the current term stored in that consensus |
111 | | // metadata, then this method will fail with a Status::InvalidArgument error. |
112 | | CHECKED_STATUS SetTabletToReplace(const scoped_refptr<tablet::RaftGroupMetadata>& meta, |
113 | | int64_t caller_term); |
114 | | |
115 | | // Start up a remote bootstrap session to bootstrap from the specified |
116 | | // bootstrap peer. Place a new superblock indicating that remote bootstrap is |
117 | | // in progress. If the 'metadata' pointer is passed as NULL, it is ignored, |
118 | | // otherwise the RaftGroupMetadata object resulting from the initial remote |
119 | | // bootstrap response is returned. |
120 | | // ts_manager pointer allows the bootstrap function to assign non-random |
121 | | // data and wal directories for the bootstrapped tablets. |
122 | | // TODO: Rename these parameters to bootstrap_source_*. |
123 | | CHECKED_STATUS Start(const std::string& bootstrap_peer_uuid, |
124 | | rpc::ProxyCache* proxy_cache, |
125 | | const HostPort& bootstrap_peer_addr, |
126 | | scoped_refptr<tablet::RaftGroupMetadata>* metadata, |
127 | | TSTabletManager* ts_manager = nullptr); |
128 | | |
129 | | // Runs a "full" remote bootstrap, copying the physical layout of a tablet |
130 | | // from the leader of the specified consensus configuration. |
131 | | CHECKED_STATUS FetchAll(tablet::TabletStatusListener* status_listener); |
132 | | |
133 | | // After downloading all files successfully, write out the completed |
134 | | // replacement superblock. |
135 | | CHECKED_STATUS Finish(); |
136 | | |
137 | | // Verify that the remote bootstrap was completed successfully by verifying that the ChangeConfig |
138 | | // request was propagated. |
139 | | CHECKED_STATUS VerifyChangeRoleSucceeded( |
140 | | const std::shared_ptr<consensus::Consensus>& shared_consensus); |
141 | | |
142 | | // Removes session at server. |
143 | | CHECKED_STATUS Remove(); |
144 | | |
145 | | private: |
146 | | FRIEND_TEST(RemoteBootstrapRocksDBClientTest, TestBeginEndSession); |
147 | | friend class yb::RemoteBootstrapITest; |
148 | | |
149 | | template <class Component> |
150 | 1.44k | void AddComponent() { |
151 | 1.44k | components_.push_back(std::make_unique<Component>(&downloader_, &new_superblock_)); |
152 | 1.44k | } |
153 | | |
154 | | // Update the bootstrap StatusListener with a message. |
155 | | // The string "RemoteBootstrap: " will be prepended to each message. |
156 | | void UpdateStatusMessage(const std::string& message); |
157 | | |
158 | | // Download all WAL files sequentially. |
159 | | CHECKED_STATUS DownloadWALs(); |
160 | | |
161 | | // Download a single WAL file. |
162 | | // Assumes the WAL directories have already been created. |
163 | | // WAL file is opened with options so that it will fsync() on close. |
164 | | CHECKED_STATUS DownloadWAL(uint64_t wal_segment_seqno); |
165 | | |
166 | | // Write out the Consensus Metadata file based on the ConsensusStatePB |
167 | | // downloaded as part of initiating the remote bootstrap session. |
168 | | CHECKED_STATUS WriteConsensusMetadata(); |
169 | | |
170 | | CHECKED_STATUS CreateTabletDirectories(const std::string& db_dir, FsManager* fs); |
171 | | |
172 | | CHECKED_STATUS DownloadRocksDBFiles(); |
173 | | |
174 | | // End the remote bootstrap session. |
175 | | CHECKED_STATUS EndRemoteSession(); |
176 | | |
177 | | // Return standard log prefix. |
178 | 20.8k | const std::string& LogPrefix() const { |
179 | 20.8k | return log_prefix_; |
180 | 20.8k | } |
181 | | |
182 | 7.72k | const std::string& session_id() const { |
183 | 7.72k | return downloader_.session_id(); |
184 | 7.72k | } |
185 | | |
186 | 139M | FsManager& fs_manager() const { |
187 | 139M | return downloader_.fs_manager(); |
188 | 139M | } |
189 | | |
190 | | Env& env() const; |
191 | | |
192 | | const std::string& permanent_uuid() const; |
193 | | |
194 | | // Set-once members. |
195 | | const std::string tablet_id_; |
196 | | |
197 | | // State flags that enforce the progress of remote bootstrap. |
198 | | bool started_ = false; // Session started. |
199 | | // Total number of remote bootstrap sessions. Used to calculate the transmission rate across all |
200 | | // the sessions. |
201 | | bool downloaded_wal_ = false; // WAL segments downloaded. |
202 | | bool downloaded_blocks_ = false; // Data blocks downloaded. |
203 | | bool downloaded_rocksdb_files_ = false; |
204 | | |
205 | | // Session-specific data items. |
206 | | bool replace_tombstoned_tablet_ = false; |
207 | | |
208 | | bool remove_required_ = false; |
209 | | |
210 | | // Local tablet metadata file. |
211 | | scoped_refptr<tablet::RaftGroupMetadata> meta_; |
212 | | |
213 | | // Local Consensus metadata file. This may initially be NULL if this is |
214 | | // bootstrapping a new replica (rather than replacing an old one). |
215 | | std::unique_ptr<consensus::ConsensusMetadata> cmeta_; |
216 | | |
217 | | tablet::TabletStatusListener* status_listener_ = nullptr; |
218 | | std::shared_ptr<RemoteBootstrapServiceProxy> proxy_; |
219 | | std::unique_ptr<tablet::RaftGroupReplicaSuperBlockPB> superblock_; |
220 | | tablet::RaftGroupReplicaSuperBlockPB new_superblock_; |
221 | | std::unique_ptr<consensus::ConsensusStatePB> remote_committed_cstate_; |
222 | | tablet::TabletDataState remote_tablet_data_state_; |
223 | | |
224 | | std::vector<uint64_t> wal_seqnos_; |
225 | | |
226 | | // Components of this remote bootstrap client. |
227 | | std::vector<std::unique_ptr<RemoteBootstrapComponent>> components_; |
228 | | |
229 | | // First available WAL segment. |
230 | | uint64_t first_wal_seqno_ = 0; |
231 | | |
232 | | int64_t start_time_micros_ = 0; |
233 | | |
234 | | // We track whether this session succeeded and send this information as part of the |
235 | | // EndRemoteBootstrapSessionRequestPB request. |
236 | | bool succeeded_ = false; |
237 | | |
238 | | const std::string log_prefix_; |
239 | | RemoteBootstrapFileDownloader downloader_; |
240 | | |
241 | | DISALLOW_COPY_AND_ASSIGN(RemoteBootstrapClient); |
242 | | }; |
243 | | |
244 | | } // namespace tserver |
245 | | } // namespace yb |
246 | | |
247 | | #endif // YB_TSERVER_REMOTE_BOOTSTRAP_CLIENT_H |