TEST(ReplicaTest, Promise) { const std::string path = utils::os::getcwd() + "/.log"; utils::os::rmdir(path); Replica replica(path); PromiseRequest request; PromiseResponse response; Future<PromiseResponse> future; request.set_id(2); future = protocol::promise(replica.pid(), request); future.await(2.0); ASSERT_TRUE(future.isReady()); response = future.get(); EXPECT_TRUE(response.okay()); EXPECT_EQ(2, response.id()); EXPECT_TRUE(response.has_position()); EXPECT_EQ(0, response.position()); EXPECT_FALSE(response.has_action()); request.set_id(1); future = protocol::promise(replica.pid(), request); future.await(2.0); ASSERT_TRUE(future.isReady()); response = future.get(); EXPECT_FALSE(response.okay()); EXPECT_EQ(1, response.id()); EXPECT_FALSE(response.has_position()); EXPECT_FALSE(response.has_action()); request.set_id(3); future = protocol::promise(replica.pid(), request); future.await(2.0); ASSERT_TRUE(future.isReady()); response = future.get(); EXPECT_TRUE(response.okay()); EXPECT_EQ(3, response.id()); EXPECT_TRUE(response.has_position()); EXPECT_EQ(0, response.position()); EXPECT_FALSE(response.has_action()); utils::os::rmdir(path); }
TEST_F(ReplicaTest, Promise) { const string path = os::getcwd() + "/.log"; initializer.flags.path = path; initializer.execute(); Replica replica(path); PromiseRequest request; PromiseResponse response; Future<PromiseResponse> future; request.set_proposal(2); future = protocol::promise(replica.pid(), request); AWAIT_READY(future); response = future.get(); EXPECT_TRUE(response.okay()); EXPECT_EQ(2u, response.proposal()); EXPECT_TRUE(response.has_position()); EXPECT_EQ(0u, response.position()); EXPECT_FALSE(response.has_action()); request.set_proposal(1); future = protocol::promise(replica.pid(), request); AWAIT_READY(future); response = future.get(); EXPECT_FALSE(response.okay()); EXPECT_EQ(2u, response.proposal()); // Highest proposal seen so far. EXPECT_FALSE(response.has_position()); EXPECT_FALSE(response.has_action()); request.set_proposal(3); future = protocol::promise(replica.pid(), request); AWAIT_READY(future); response = future.get(); EXPECT_TRUE(response.okay()); EXPECT_EQ(3u, response.proposal()); EXPECT_TRUE(response.has_position()); EXPECT_EQ(0u, response.position()); EXPECT_FALSE(response.has_action()); }
Future<Option<uint64_t> > CoordinatorProcess::checkPromisePhase( const PromiseResponse& response) { if (!response.okay()) { // Lost an election, but can be retried. We save the proposal // number here so that most likely we will have a high enough // proposal number when we retry. CHECK_LE(proposal, response.proposal()); proposal = response.proposal(); return None(); } else { CHECK(response.has_position()); index = response.position(); // Need to "catch-up" local replica (i.e., fill in any unlearned // and/or missing positions) so that we can do local reads. // Usually we could do this lazily, however, a local learned // position might have been truncated, so we actually need to // catch-up the local replica all the way to the end of the log // before we can perform any up-to-date local reads. return getMissingPositions() .then(defer(self(), &Self::catchupMissingPositions, lambda::_1)) .then(defer(self(), &Self::updateIndexAfterElected)); } }