22#include <glog/logging.h>
26#include "platform/proto/viewchange_message.pb.h"
31 : proxy_id(0), is_complaining(false), timeout_length_(10000000) {}
34 : proxy_id(proxy_id), is_complaining(false), timeout_length_(10000000) {}
37 std::string hash, uint64_t view) {
40 auto info = std::make_shared<ViewChangeTimeout>(
90 std::thread(&ViewChangeManager::MonitoringViewChangeTimeOut,
this);
92 std::thread(&ViewChangeManager::MonitoringCheckpointState,
this);
115 .type() == CertificateKeyInfo::CLIENT) {
116 LOG(ERROR) <<
"client type not process view change";
132 auto viewchange_timer = std::make_shared<ViewChangeTimeout>(
136 std::lock_guard<std::mutex> lk(
vc_mutex_);
147bool ViewChangeManager::ChangeStatue(ViewChangeStatus status) {
162bool ViewChangeManager::IsValidViewChangeMsg(
163 const ViewChangeMessage& view_change_message) {
165 LOG(ERROR) <<
"View number is not greater than current view:"
166 << view_change_message.view_number() <<
"("
172 view_change_message.stable_ckpt())) {
173 LOG(ERROR) <<
"stable checkpoint invalid";
177 uint64_t stable_seq = view_change_message.stable_ckpt().seq();
179 for (
const auto& prepared_msg : view_change_message.prepared_msg()) {
180 if (prepared_msg.seq() <= stable_seq) {
185 LOG(ERROR) <<
"proof[" << prepared_msg.proof_size()
189 for (
const auto& proof : prepared_msg.proof()) {
190 if (proof.request().seq() != prepared_msg.seq()) {
191 LOG(ERROR) <<
"proof seq not match";
195 proof.request().SerializeToString(&
data);
197 LOG(ERROR) <<
"proof signature not valid";
205uint32_t ViewChangeManager::AddRequest(
206 const ViewChangeMessage& viewchange_message, uint32_t sender) {
207 std::lock_guard<std::mutex> lk(
vc_mutex_);
213bool ViewChangeManager::IsNextPrimary(uint64_t view_number) {
214 std::lock_guard<std::mutex> lk(
mutex_);
220void ViewChangeManager::SetCurrentViewAndNewPrimary(uint64_t view_number) {
229std::vector<std::unique_ptr<Request>> ViewChangeManager::GetPrepareMsg(
230 const NewViewMessage& new_view_message,
bool need_sign) {
231 std::map<uint64_t, Request> prepared_msg;
232 for (
const auto& msg : new_view_message.viewchange_messages()) {
233 for (
const auto& msg : msg.prepared_msg()) {
234 uint64_t seq = msg.seq();
235 prepared_msg[seq] = msg.proof(0).request();
239 uint64_t min_s = std::numeric_limits<uint64_t>::max();
240 for (
const auto& msg : new_view_message.viewchange_messages()) {
241 min_s = std::min(min_s, msg.stable_ckpt().seq());
244 uint64_t max_seq = 1;
245 if (prepared_msg.size() > 0) {
246 max_seq = (--prepared_msg.end())->first;
249 LOG(INFO) <<
"[GP] min_s: " << min_s <<
" max_seq: " << max_seq;
251 std::vector<std::unique_ptr<Request>> redo_request;
253 for (
auto i = min_s + 1; i <= max_seq; ++i) {
254 if (prepared_msg.find(i) == prepared_msg.end()) {
259 user_request->set_seq(i);
260 user_request->set_current_view(new_view_message.view_number());
261 user_request->set_hash(
"null" + std::to_string(i));
266 if (!signature_or.ok()) {
267 LOG(ERROR) <<
"Sign message fail";
270 *user_request->mutable_data_signature() = *signature_or;
272 redo_request.push_back(std::move(user_request));
276 commit_request->set_seq(i);
277 commit_request->set_current_view(new_view_message.view_number());
278 redo_request.push_back(std::move(commit_request));
286 std::unique_ptr<Request> request) {
287 NewViewMessage new_view_message;
288 if (!new_view_message.ParseFromString(request->data())) {
289 LOG(ERROR) <<
"Parsing new_view_msg failed.";
292 LOG(INFO) <<
"Received NEW-VIEW for view " << new_view_message.view_number();
294 if (new_view_message.view_number() !=
296 LOG(ERROR) <<
"View number " << new_view_message.view_number()
297 <<
" is not the same as expected: "
302 uint64_t min_s = std::numeric_limits<uint64_t>::max(), max_s = 0;
304 for (
const auto& msg : new_view_message.viewchange_messages()) {
305 min_s = std::min(min_s, msg.stable_ckpt().seq());
306 max_s = std::max(max_s, msg.stable_ckpt().seq());
307 if (!IsValidViewChangeMsg(msg)) {
308 LOG(ERROR) <<
"view change message in the new-view message is invalid";
314 auto request_list = GetPrepareMsg(new_view_message,
false);
315 if (request_list.size() !=
316 static_cast<size_t>(new_view_message.request_size())) {
317 LOG(ERROR) <<
"redo request list size not match:" << request_list.size()
318 <<
"- " << new_view_message.request_size();
322 std::set<uint64_t> seq_set;
324 for (
size_t i = 0; i < request_list.size(); ++i) {
325 if (request_list[i]->
data() != new_view_message.request(i).data()) {
326 LOG(ERROR) <<
"data not match";
329 seq_set.insert(request_list[i]->seq());
332 LOG(ERROR) <<
"min_s: " << min_s <<
" max_s: " << max_s;
335 for (uint64_t i = min_s + 1; i <= max_s; i++) {
336 if (seq_set.find(i) == seq_set.end()) {
337 LOG(ERROR) <<
"Committed msg :" << i <<
" does exist";
342 uint64_t max_seq = seq_set.empty() ? max_s : *(--seq_set.end());
344 SetCurrentViewAndNewPrimary(new_view_message.view_number());
346 LOG(INFO) <<
"SetNexSeq: " << max_seq + 1;
349 for (
size_t i = 0; i < request_list.size(); ++i) {
350 if (new_view_message.request(i).type() ==
351 static_cast<int>(Request::TYPE_PRE_PREPARE)) {
352 new_view_message.request(i);
353 auto non_proposed_hashes =
356 for (
auto& hash : non_proposed_hashes) {
362 if (new_view_message.request(i).seq() >
365 new_view_message.request(i).seq());
376 std::unique_ptr<Request> request) {
377 ViewChangeMessage viewchange_message;
378 if (!viewchange_message.ParseFromString(request->data())) {
379 LOG(ERROR) <<
"pase view change data fail";
383 if (!IsValidViewChangeMsg(viewchange_message)) {
384 LOG(ERROR) <<
"view change msg not valid from:" << request->sender_id();
388 LOG(ERROR) <<
"ViewChange message from " << request->sender_id();
390 size_t request_size = AddRequest(viewchange_message, request->sender_id());
393 if (IsNextPrimary(viewchange_message.view_number())) {
394 std::lock_guard<std::mutex> lk(
mutex_);
395 SendNewViewMsg(viewchange_message.view_number());
397 auto newview_timer = std::make_shared<ViewChangeTimeout>(
401 std::lock_guard<std::mutex> lk(
vc_mutex_);
414void ViewChangeManager::SendNewViewMsg(uint64_t view_number) {
425 std::lock_guard<std::mutex> lk(
vc_mutex_);
428 NewViewMessage new_view_message;
429 new_view_message.set_view_number(view_number);
431 std::map<uint64_t, std::string> new_view_request;
432 for (
auto& it : requests) {
433 ViewChangeMessage& msg = it.second;
434 LOG(ERROR) <<
"msg.view_number(): " << msg.view_number()
435 <<
" view_number: " << view_number <<
" sender: " << it.first
436 <<
" msg.stable_ckpt(): " << msg.stable_ckpt().seq();
437 msg.set_view_number(view_number);
438 *new_view_message.add_viewchange_messages() = msg;
445 std::vector<std::unique_ptr<Request>> request_list =
446 GetPrepareMsg(new_view_message);
447 for (
const auto& request : request_list) {
448 *new_view_message.add_request() = *request;
452 std::unique_ptr<Request> request =
454 new_view_message.SerializeToString(request->mutable_data());
458void ViewChangeManager::SendViewChangeMsg() {
460 ViewChangeMessage view_change_message;
466 <<
" view number: " << view_change_message.view_number()
468 assert(view_change_message.view_number() ==
473 *view_change_message.mutable_stable_ckpt() =
479 LOG(INFO) <<
"Check prepared or committed txns from "
480 << view_change_message.stable_ckpt().seq() + 1 <<
" to " << max_seq;
482 for (
int i = view_change_message.stable_ckpt().seq() + 1; i <= max_seq; ++i) {
486 std::vector<RequestInfo> proof_info =
489 auto txn = view_change_message.add_prepared_msg();
491 for (
const auto& info : proof_info) {
492 auto proof = txn->add_proof();
493 *proof->mutable_request() = *info.request;
494 *proof->mutable_signature() = info.signature;
500 std::unique_ptr<Request> request =
NewRequest(
502 view_change_message.SerializeToString(request->mutable_data());
507 std::lock_guard<std::mutex> lk(
vc_mutex_);
522void ViewChangeManager::MonitoringViewChangeTimeOut() {
529 std::shared_ptr<ViewChangeTimeout> viewchange_timeout;
531 if (!heap.second.empty()) {
532 viewchange_timeout = heap.second.top();
544 if (viewchange_timeout->timeout_time > current_time) {
545 usleep(viewchange_timeout->timeout_time - current_time);
556 LOG(ERROR) <<
"It is time to start a new viewchange";
559 }
else if (viewchange_timeout->type ==
566 LOG(ERROR) <<
"It is time to rebroacast viewchange messages";
570 }
else if (viewchange_timeout->type ==
575 .CountViewChangeTimeout(viewchange_timeout->hash)) {
577 .EraseViewChangeTimeout(viewchange_timeout->hash);
582 if (viewchange_timeout->start_time >=
584 viewchange_timeout->proxy_id)) {
585 LOG(ERROR) <<
"It is time to start a viewchange";
594void ViewChangeManager::MonitoringCheckpointState() {
595 uint64_t last_seq_value = 0;
599 if (last_seq_value != value) {
600 last_seq_value = value;
MockReplicaCommunicator replica_communicator_
void SetTimeoutHandler(std::function< void()> timeout_handler)
uint64_t GetHighestPreparedSeq()
bool IsValidCheckpointProof(const StableCheckPoint &stable_ckpt)
uint64_t GetCommittableSeq()
sem_t * CommitableSeqSignal()
StableCheckPoint GetStableCheckpointWithVotes()
void SetHighestPreparedSeq(uint64_t seq)
void EraseViewChangeTimeout(std::string hash)
uint CountViewChangeTimeout(std::string hash)
std::shared_ptr< ViewChangeTimeout > SetComplaining(std::string hash, uint64_t view)
std::set< std::string > viewchange_timeout_set
void ReleaseComplaining(std::string hash)
std::mutex complain_state_lock
void EraseProposed(const std::string &hash)
TransactionCollector * GetCollector(uint64_t seq)
TransactionStatue GetTransactionState(uint64_t seq)
uint64_t GetLastCommittedTime(uint64_t proxy_id)
std::vector< RequestInfo > GetPreparedProof(uint64_t seq)
void SetNextSeq(uint64_t seq)
LockFreeCollectorPool * GetCollectorPool()
virtual void BroadCast(const google::protobuf::Message &message)
virtual int SendMessage(const google::protobuf::Message &message)
int GetMinDataReceiveNum() const
ResConfigData GetConfigData() const
CertificateInfo GetPublicKeyCertificateInfo() const
const ReplicaInfo & GetSelfInfo() const
const std::vector< ReplicaInfo > & GetReplicaInfos() const
uint32_t GetMaxClientComplaintNum() const
virtual absl::StatusOr< SignatureInfo > SignMessage(const std::string &message)
virtual bool VerifyMessage(const std::string &message, const SignatureInfo &sign)
void SetCurrentView(uint64_t)
uint32_t GetPrimaryId() const
void SetPrimary(uint32_t id)
uint64_t GetCurrentView() const
std::vector< std::string > GetAllStoredHash()
int ProcessViewChange(std::unique_ptr< Context > context, std::unique_ptr< Request > request)
DuplicateManager * duplicate_manager_
std::map< uint64_t, std::map< uint32_t, ViewChangeMessage > > viewchange_request_
int ProcessNewView(std::unique_ptr< Context > context, std::unique_ptr< Request > request)
std::atomic< bool > stop_
MessageManager * message_manager_
SystemInfo * system_info_
std::map< uint64_t, std::priority_queue< std::shared_ptr< ViewChangeTimeout > > > viewchange_timeout_min_heap_
SignatureVerifier * verifier_
virtual ~ViewChangeManager()
uint32_t view_change_counter_
std::atomic< bool > started_
std::map< uint64_t, ComplaningClients > complaining_clients_
ViewChangeManager(const ResDBConfig &config, CheckPointManager *checkpoint_manager, MessageManager *message_manager, SystemInfo *system_info, ReplicaCommunicator *replica_communicator, SignatureVerifier *verifier)
ReplicaCommunicator * replica_communicator_
sem_t viewchange_timer_signal_
std::thread checkpoint_state_thread_
void SetDuplicateManager(DuplicateManager *manager)
LockFreeCollectorPool * collector_pool_
CheckPointManager * checkpoint_manager_
void AddComplaintTimer(uint64_t proxy_id, std::string hash)
std::thread server_checking_timeout_thread_
CheckPointManager checkpoint_manager_
std::unique_ptr< MessageManager > message_manager_
MockSignatureVerifier verifier_
std::unique_ptr< Request > NewRequest(Request::Type type, const Request &request, int sender_id)
uint64_t GetCurrentTime()
std::unique_ptr< ResDBConfig > config_