コード例 #1
0
int main ()
{
   std::atomic <uint16_t> response_count (0);

   paxos::server::callback_type callback =
      [& response_count](int64_t, std::string const & workload) -> std::string
      {
         ++response_count;

         return "bar";
      };

   paxos::configuration configuration;
   configuration.set_strategy_factory (new test_strategy_factory (configuration.durable_storage ()));

   paxos::server server1 ("127.0.0.1", 1337, callback);
   paxos::server server2 ("127.0.0.1", 1338, callback);
   paxos::server server3 ("127.0.0.1", 1339, callback, configuration);
   paxos::client client;

   server1.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});
   server2.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});
   server3.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});
   client.add  ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});

   /*!
     This would be retried and shouldn't cause any troubles.
    */
   PAXOS_ASSERT_EQ (client.send ("foo").get (), "bar");
   PAXOS_ASSERT_EQ (response_count, 2);

   PAXOS_INFO ("test succeeded");   
}
コード例 #2
0
int main ()
{
   paxos::configuration configuration1;
   paxos::configuration configuration2;
   paxos::configuration configuration3;

   configuration1.durable_storage ().set_history_size (5);
   configuration2.durable_storage ().set_history_size (5);
   configuration3.durable_storage ().set_history_size (5);

   paxos::server::callback_type callback = 
      [](
         int64_t                promise_id,
         std::string const &    workload) -> std::string
      {
         return "bar";
      };

   paxos::client client;
   client.add  ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});

   paxos::server server1 ("127.0.0.1", 1337, callback, configuration1);
   paxos::server server2 ("127.0.0.1", 1338, callback, configuration2);
   
   server1.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});
   server2.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});

   {
      paxos::server server3 ("127.0.0.1", 1339, callback, configuration3);
      server3.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});
    
      /*!
        Issue 10 calls, so we can verify that the lowest proposal id is in fact 10.
       */
      for (size_t i = 0; i < 15; ++i)
      {
         PAXOS_ASSERT_EQ (client.send ("foo").get (), "bar");
      }

      PAXOS_ASSERT_EQ (configuration1.durable_storage ().lowest_proposal_id (), 11);
      PAXOS_ASSERT_EQ (configuration2.durable_storage ().lowest_proposal_id (), 11);
      PAXOS_ASSERT_EQ (configuration3.durable_storage ().lowest_proposal_id (), 11);
   }
   
   /*!
     Now, since one host in our quorum is currently down, logs should *not* be cleaned
     up further than the proposal that has been previously accepted by that host.
    */

   for (size_t i = 0; i < 30; ++i)
   {
      PAXOS_ASSERT_EQ (client.send ("foo").get (), "bar");
   }

   PAXOS_ASSERT_GE (configuration1.durable_storage ().lowest_proposal_id (), 15);
   PAXOS_ASSERT_GE (configuration2.durable_storage ().lowest_proposal_id (), 15);
   PAXOS_ASSERT_EQ (configuration3.durable_storage ().lowest_proposal_id (), 11);

   boost::this_thread::sleep (
      boost::posix_time::milliseconds (
         paxos::configuration ().timeout ()));

   {
      /*!
        And after our server is back online, the history can be cleared again.
       */

      paxos::server server3 ("127.0.0.1", 1339, callback, configuration3);
      server3.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});
    
      for (size_t i = 0; i < 15; ++i)
      {
         PAXOS_ASSERT_EQ (client.send ("foo").get (), "bar");
      }

      PAXOS_ASSERT_EQ (configuration1.durable_storage ().lowest_proposal_id (), 56);
      PAXOS_ASSERT_EQ (configuration2.durable_storage ().lowest_proposal_id (), 56);
      PAXOS_ASSERT_EQ (configuration3.durable_storage ().lowest_proposal_id (), 56);
   }


   
   PAXOS_INFO ("test succeeded");
}
コード例 #3
0
ファイル: initiate_request.cpp プロジェクト: ailidani/PMDS
/*! static */ void
initiate_request::step1 (
   std::string const &                  byte_array,
   detail::quorum::client_view &        quorum,
   callback_type                        callback,
   queue_guard_type                     guard)
{
   boost::optional <boost::asio::ip::tcp::endpoint> leader = quorum.select_leader ();
   if (leader.is_initialized () == false)
   {
      PAXOS_DEBUG ("leader.is_initialized () == false");
      callback (detail::error_no_leader, "");
      quorum.advance_leader ();
      return;
   }

   PAXOS_DEBUG ("leader.is_initialized () == true");

   quorum::server & server = quorum.lookup_server (*leader);

   if (server.has_connection () == false)
   {
      PAXOS_DEBUG ("server.has_connection () == false");
      callback (detail::error_no_leader, "");
      quorum.advance_leader ();
      return;
   }

   PAXOS_DEBUG ("server.has_connection () == true");
   PAXOS_DEBUG ("sending request to host " << server.endpoint () << " with id = " << server.id ());

   detail::tcp_connection_ptr connection = server.connection ();
 
   /*!
     Now that we have our leader's connection, let's send it our command to initiate
     the request. 
   */
   command command;
   command.set_type (command::type_request_initiate);
   command.set_workload (byte_array);
   connection->write_command (command);

   PAXOS_INFO ("client initiating request!");

   connection->read_command (
      [connection, 
       & quorum,
       & server,
       callback,
       guard] (
          boost::optional <enum detail::error_code>     error,
          detail::command const &                       c)
      {
         if (error)
         {
            PAXOS_WARN ("client had problems communicating with leader: " << detail::to_string (*error));
            quorum.connection_died (server.endpoint ());
            quorum.advance_leader ();

            callback (*error, "");
         }
         else
         {
            quorum.lookup_server (c.host_endpoint ()).set_id (c.host_id ());
            quorum.lookup_server (c.host_endpoint ()).set_highest_proposal_id (c.highest_proposal_id ());

            switch (c.type ())
            {
                  case command::type_request_accepted:
                     PAXOS_DEBUG ("received command with workload = " << c.workload () << ", "
                                  "now calling callback!");
                     callback (boost::none, c.workload ());
                     break;
                  
                  case command::type_request_error:
                     if (c.error_code () == detail::error_no_leader)
                     {
                        quorum.advance_leader ();
                     }

                     PAXOS_WARN ("request error occured");
                     callback (c.error_code (), c.workload ());
                     break;

                  default:
                     PAXOS_UNREACHABLE ();
            };
         }
      });
}
コード例 #4
0
ファイル: durability2.cpp プロジェクト: xjump/c_cxx_repo
int main ()
{
   std::map <int64_t, uint16_t> responses;

   /*!
     Synchronizes access to responses
    */
   boost::mutex mutex;

   paxos::configuration configuration1;
   paxos::configuration configuration2;
   paxos::configuration configuration3;

   /*!
     Note that the configuration objects below outlive the server objects declared later in
     the test, thus providing semi-durable storage.
    */
   configuration1.set_durable_storage (
      new paxos::durable::heap ());
   configuration2.set_durable_storage (
      new paxos::durable::heap ());
   configuration3.set_durable_storage (
      new paxos::durable::heap ());

   paxos::server::callback_type callback = 
      [& responses,
       & mutex](
         int64_t                promise_id,
         std::string const &    workload) -> std::string
      {
         boost::mutex::scoped_lock lock (mutex);

         if (responses.find (promise_id) == responses.end ())
         {
            responses[promise_id] = 1;
         }
         else
         {
            responses[promise_id]++;
         }

         PAXOS_ASSERT (responses[promise_id] <= 3);

         return "bar";
      };

   paxos::client client;
   client.add  ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});

   {
      paxos::server server1 ("127.0.0.1", 1337, callback, configuration1);

      server1.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});

      {
         paxos::server server2 ("127.0.0.1", 1338, callback, configuration2);

         server2.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});

         {
            paxos::server server3 ("127.0.0.1", 1339, callback, configuration3);

            server3.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});

            PAXOS_ASSERT_EQ (client.send ("foo").get (), "bar");
            PAXOS_ASSERT_EQ (client.send ("foo").get (), "bar");
            PAXOS_ASSERT_EQ (all_responses_equal (responses, 3), true);
         }



         PAXOS_ASSERT_EQ (client.send ("foo").get (), "bar");
         PAXOS_ASSERT_EQ (client.send ("foo").get (), "bar");
         PAXOS_ASSERT_EQ (all_responses_equal (responses, 3), false);
      }

      PAXOS_ASSERT_THROW (client.send ("foo").get (), paxos::exception::no_majority);
   }

   /*!
     Note that we're re-adding servers in reverse order here; this is to ensure that
     server3 doesn't become our leader while it's lagging behind.
    */
   paxos::server server3 ("127.0.0.1", 1339, callback, configuration3);
   server3.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});
   
   PAXOS_ASSERT_THROW (client.send ("foo").get (), paxos::exception::no_majority);

   paxos::server server2 ("127.0.0.1", 1338, callback, configuration2);
   server2.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});
   boost::this_thread::sleep (
      boost::posix_time::milliseconds (
         paxos::configuration ().timeout ()));

   PAXOS_ASSERT_EQ (client.send ("foo").get (), "bar");
   PAXOS_ASSERT_EQ (client.send ("foo").get (), "bar");

   paxos::server server1 ("127.0.0.1", 1337, callback, configuration1);
   server1.add ({{"127.0.0.1", 1337}, {"127.0.0.1", 1338}, {"127.0.0.1", 1339}});


   boost::this_thread::sleep (
      boost::posix_time::milliseconds (
         paxos::configuration ().timeout ()));

   do
   {
      PAXOS_ASSERT_EQ (client.send ("foo").get (), "bar");   
      
   } while (all_responses_equal (responses, 3) == false);

   PAXOS_INFO ("test succeeded");
}