22#include <glog/logging.h>
25#include "platform/proto/checkpoint_info.pb.h"
37 txn_accessor_(config),
38 highest_prepared_seq_(0) {
45 std::thread(&CheckPointManager::UpdateStableCheckPointStatus,
this);
47 std::thread(&CheckPointManager::UpdateCheckPointStatus,
this);
64std::string
GetHash(
const std::string& h1,
const std::string& h2) {
73 std::lock_guard<std::mutex> lk(
mutex_);
78 std::lock_guard<std::mutex> lk(
mutex_);
86 txn_db_->Put(std::move(request));
92 const StableCheckPoint& stable_ckpt) {
94 std::set<uint32_t> senders;
95 for (
const auto& signature :
stable_ckpt_.signatures()) {
99 senders.insert(signature.node_id());
103 (stable_ckpt.seq() == 0 && senders.size() == 0);
107 std::unique_ptr<Request> request) {
108 CheckPointData checkpoint_data;
109 if (!checkpoint_data.ParseFromString(request->data())) {
110 LOG(ERROR) <<
"parse checkpont data fail:";
113 uint64_t checkpoint_seq = checkpoint_data.seq();
114 uint32_t sender_id = request->sender_id();
116 if (checkpoint_seq % water_mark) {
117 LOG(ERROR) <<
"checkpoint seq not invalid:" << checkpoint_seq;
124 checkpoint_data.hash_signature());
126 LOG(ERROR) <<
"request is not valid:"
127 << checkpoint_data.hash_signature().DebugString();
133 std::lock_guard<std::mutex> lk(
mutex_);
135 sender_ckpt_[std::make_pair(checkpoint_seq, checkpoint_data.hash())]
138 sign_ckpt_[std::make_pair(checkpoint_seq, checkpoint_data.hash())]
139 .push_back(checkpoint_data.hash_signature());
142 if (
sender_ckpt_[std::make_pair(checkpoint_seq, checkpoint_data.hash())]
144 for (
auto& hash_ : checkpoint_data.hashs()) {
145 hash_ckpt_[std::make_pair(checkpoint_seq, checkpoint_data.hash())]
154void CheckPointManager::Notify() {
155 std::lock_guard<std::mutex> lk(
cv_mutex_);
159bool CheckPointManager::Wait() {
160 int timeout_ms = 1000;
161 std::unique_lock<std::mutex> lk(
cv_mutex_);
162 return cv_.wait_for(lk, std::chrono::milliseconds(timeout_ms),
166void CheckPointManager::UpdateStableCheckPointStatus() {
167 uint64_t last_committable_seq = 0;
172 uint64_t stable_seq = 0;
173 std::string stable_hash;
175 std::lock_guard<std::mutex> lk(
mutex_);
177 if (it.second.size() >=
181 std::set<uint32_t> senders_ =
188 std::string last_hash;
191 std::lock_guard<std::mutex> lk(
lt_mutex_);
197 if (senders_.count(replica_.id()) &&
205 for (
auto& request : *requests) {
209 <<
"The hash of the request does not match the data.";
213 last_hash =
GetHash(last_hash, request.hash());
218 LOG(ERROR) <<
"The hash of requests returned do not match. "
222 for (
auto& request : *requests) {
236 if (it.second.size() >=
238 stable_seq = it.first.first;
239 stable_hash = it.first.second;
247 std::vector<SignatureInfo> votes;
249 std::lock_guard<std::mutex> lk(
mutex_);
250 votes =
sign_ckpt_[std::make_pair(stable_seq, stable_hash)];
251 std::set<uint32_t> senders_ =
256 if (it->first.first <= stable_seq) {
267 for (
auto vote : votes) {
280 std::function<
void()> timeout_handler) {
290void CheckPointManager::UpdateCheckPointStatus() {
291 uint64_t last_ckpt_seq = 0;
294 std::vector<std::string> stable_hashs;
295 std::vector<uint64_t> stable_seqs;
298 if (request ==
nullptr) {
304 std::string hash_ = request->hash();
305 uint64_t current_seq = request->seq();
307 LOG(ERROR) <<
"seq invalid:" <<
last_seq_ <<
" current:" << current_seq;
311 std::lock_guard<std::mutex> lk(
lt_mutex_);
315 txn_db_->Put(std::move(request));
317 if (current_seq == last_ckpt_seq + water_mark) {
318 last_ckpt_seq = current_seq;
319 BroadcastCheckPoint(last_ckpt_seq,
last_hash_, stable_hashs, stable_seqs);
325void CheckPointManager::BroadcastCheckPoint(
326 uint64_t seq,
const std::string& hash,
327 const std::vector<std::string>& stable_hashs,
328 const std::vector<uint64_t>& stable_seqs) {
329 CheckPointData checkpoint_data;
330 std::unique_ptr<Request> checkpoint_request =
NewRequest(
332 checkpoint_data.set_seq(seq);
333 checkpoint_data.set_hash(hash);
336 if (!signature_or.ok()) {
337 LOG(ERROR) <<
"Sign message fail";
340 *checkpoint_data.mutable_hash_signature() = *signature_or;
343 checkpoint_data.SerializeToString(checkpoint_request->mutable_data());
348 std::unique_lock<std::mutex> lk(
mutex_);
352std::unique_ptr<std::pair<uint64_t, std::string>>
358 std::lock_guard<std::mutex> lk(
lt_mutex_);
363 std::lock_guard<std::mutex> lk(
lt_mutex_);
368 std::lock_guard<std::mutex> lk(
lt_mutex_);
373 std::lock_guard<std::mutex> lk(
lt_mutex_);
MockReplicaCommunicator replica_communicator_
virtual ~CheckPointManager()
void SetTimeoutHandler(std::function< void()> timeout_handler)
std::string committable_hash_
uint64_t GetHighestPreparedSeq()
std::map< std::pair< uint64_t, std::string >, std::set< uint32_t > > sender_ckpt_
SignatureVerifier * verifier_
bool IsValidCheckpointProof(const StableCheckPoint &stable_ckpt)
uint64_t GetCommittableSeq()
ResDBTxnAccessor txn_accessor_
std::unique_ptr< ChainState > txn_db_
LockFreeQueue< std::pair< uint64_t, std::string > > stable_hash_queue_
ReplicaCommunicator * replica_communicator_
sem_t * CommitableSeqSignal()
virtual void UpdateStableCheckPointCallback(int64_t current_stable_checkpoint)
StableCheckPoint stable_ckpt_
CheckPointManager(const ResDBConfig &config, ReplicaCommunicator *replica_communicator, SignatureVerifier *verifier)
std::condition_variable cv_
std::map< std::pair< uint64_t, std::string >, std::vector< SignatureInfo > > sign_ckpt_
std::atomic< uint64_t > highest_prepared_seq_
TransactionExecutor * executor_
std::unique_ptr< std::pair< uint64_t, std::string > > PopStableSeqHash()
std::function< void()> timeout_handler_
int ProcessCheckPoint(std::unique_ptr< Context > context, std::unique_ptr< Request > request)
uint64_t GetStableCheckpoint() override
std::thread checkpoint_thread_
StableCheckPoint GetStableCheckpointWithVotes()
std::atomic< bool > stop_
std::atomic< uint64_t > current_stable_seq_
void AddCommitData(std::unique_ptr< Request > request)
uint64_t committable_seq_
void SetHighestPreparedSeq(uint64_t seq)
std::map< std::pair< uint64_t, std::string >, std::vector< std::string > > hash_ckpt_
std::condition_variable signal_
sem_t committable_seq_signal_
LockFreeQueue< Request > data_queue_
std::thread stable_checkpoint_thread_
void Push(std::unique_ptr< T > data)
std::unique_ptr< T > Pop(int timeout_ms=100)
virtual void BroadCast(const google::protobuf::Message &message)
int GetMinDataReceiveNum() const
ResConfigData GetConfigData() const
int GetCheckPointWaterMark() const
int GetMinCheckpointReceiveNum() const
const ReplicaInfo & GetSelfInfo() const
bool IsCheckPointEnabled()
void EnableCheckPoint(bool is_enable)
const std::vector< ReplicaInfo > & GetReplicaInfos() const
uint32_t GetViewchangeCommitTimeout() const
virtual absl::StatusOr< std::vector< Request > > GetRequestFromReplica(uint64_t min_seq, uint64_t max_seq, const ReplicaInfo &replica)
static std::string CalculateHash(const std::string &str)
virtual absl::StatusOr< SignatureInfo > SignMessage(const std::string &message)
virtual bool VerifyMessage(const std::string &message, const SignatureInfo &sign)
int Commit(std::unique_ptr< Request > request)
MockSignatureVerifier verifier_
std::unique_ptr< Request > NewRequest(Request::Type type, const Request &request, int sender_id)
std::string GetHash(const std::string &h1, const std::string &h2)
std::vector< ReplicaInfo > replicas_
std::unique_ptr< ResDBConfig > config_