Loading BuilderQueue/include/BuilderQueue.h +10 −2 Original line number Diff line number Diff line Loading @@ -5,28 +5,36 @@ #include "boost/optional.hpp" #include <list> #include <queue> #include <set> class BuilderQueue { public: explicit BuilderQueue(asio::io_service &io_service) : io_service(io_service), max_builders(1), max_available_builders(max_builders) max_available_builders(max_builders), update_in_progress(false) {} // Create a new queue reservation and return it to the requester Reservation& enter(); // Attempt to process the queue after an event that adds/removes builders or requests void tick(asio::yield_context yield); void tick(); private: asio::io_service &io_service; // Hold reservations that are to be fulfilled std::list<Reservation> reservations; // List of currently available builders std::set<Builder> available_builders; // Maximum number of active and cached builders const std::size_t max_builders; // Maximum number of builders to spin and keep up in reserve const std::size_t max_available_builders; // Flag to determine if an update is already in progress bool update_in_progress; }; No newline at end of file BuilderQueue/src/BuilderQueue.cpp +45 −33 Original line number Diff line number Diff line #include "BuilderQueue.h" #include "Logger.h" #include "OpenStackBuilder.h" #include <set> Reservation &BuilderQueue::enter() { reservations.emplace_back(io_service); return reservations.back(); } // TODO handle error state builders void BuilderQueue::tick(asio::yield_context yield) { // Update OpenStack builder list void BuilderQueue::tick() { // Process pending reservations for (auto &reservation : reservations) { if (reservation.pending() && !available_builders.empty()) { reservation.ready(*available_builders.begin()); available_builders.erase(available_builders.begin()); } } // Update OpenStack by creating and removing builders as required // This section can take quite some time so is done in a coroutine if (!update_in_progress) { update_in_progress = true; asio::spawn(io_service, [&](asio::yield_context yield) { auto all_builders = OpenStackBuilder::get_builders(io_service, yield); std::set<Builder> unavailable_builders; Loading @@ -20,20 +33,18 @@ void BuilderQueue::tick(asio::yield_context yield) { unavailable_builders.insert(reservation.builder.get()); } if (reservation.complete()) { asio::spawn(io_service, [&](asio::yield_context yield) { OpenStackBuilder::destroy(reservation.builder.get(), io_service, yield); }); } }; } // TODO handle error state builders - potentially in destroy script? // Remove all completed reservations reservations.remove_if([](const auto &res) { return res.complete(); }); // Available_builders = all_builders - unavailable_builders std::set<Builder> available_builders; std::set_difference(all_builders.begin(), all_builders.end(), unavailable_builders.begin(), unavailable_builders.end(), std::inserter(available_builders, available_builders.begin())); Loading @@ -42,10 +53,11 @@ void BuilderQueue::tick(asio::yield_context yield) { auto open_slots = max_builders - all_builders.size(); auto open_available_slots = max_available_builders - available_builders.size(); auto request_count = std::min(open_slots, open_available_slots); for (int i = 0; i < request_count; i++) { asio::spawn(io_service, [&](asio::yield_context yield) { for (auto i = 0; i < request_count; i++) { OpenStackBuilder::request_create(io_service, yield); } update_in_progress = false; }); } } No newline at end of file BuilderQueue/src/main.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -36,11 +36,14 @@ int main(int argc, char *argv[]) { }); // Start the queue which ticks at the specified interval boost::asio::deadline_timer timer(io_service); asio::spawn(io_service, [&](asio::yield_context yield) { for (;;) { try { builder_queue.tick(yield); builder_queue.tick(); timer.expires_from_now(boost::posix_time::seconds(1)); timer.async_wait(yield); } catch (std::exception &e) { logger::write(std::string() + "Queue tick error: " + e.what()); } Loading Scripts/DestroyBuilder +1 −1 Original line number Diff line number Diff line Loading @@ -3,4 +3,4 @@ # OpenStack credentials source /home/queue/openrc.sh openstack server delete $1 No newline at end of file openstack server delete --wait $1 No newline at end of file Scripts/GetBuilders +1 −1 Original line number Diff line number Diff line Loading @@ -3,4 +3,4 @@ # OpenStack credentials source /home/queue/openrc.sh openstack server list -f json --name Builder No newline at end of file openstack server list -f json --name "^Builder$" --status Active No newline at end of file Loading
BuilderQueue/include/BuilderQueue.h +10 −2 Original line number Diff line number Diff line Loading @@ -5,28 +5,36 @@ #include "boost/optional.hpp" #include <list> #include <queue> #include <set> class BuilderQueue { public: explicit BuilderQueue(asio::io_service &io_service) : io_service(io_service), max_builders(1), max_available_builders(max_builders) max_available_builders(max_builders), update_in_progress(false) {} // Create a new queue reservation and return it to the requester Reservation& enter(); // Attempt to process the queue after an event that adds/removes builders or requests void tick(asio::yield_context yield); void tick(); private: asio::io_service &io_service; // Hold reservations that are to be fulfilled std::list<Reservation> reservations; // List of currently available builders std::set<Builder> available_builders; // Maximum number of active and cached builders const std::size_t max_builders; // Maximum number of builders to spin and keep up in reserve const std::size_t max_available_builders; // Flag to determine if an update is already in progress bool update_in_progress; }; No newline at end of file
BuilderQueue/src/BuilderQueue.cpp +45 −33 Original line number Diff line number Diff line #include "BuilderQueue.h" #include "Logger.h" #include "OpenStackBuilder.h" #include <set> Reservation &BuilderQueue::enter() { reservations.emplace_back(io_service); return reservations.back(); } // TODO handle error state builders void BuilderQueue::tick(asio::yield_context yield) { // Update OpenStack builder list void BuilderQueue::tick() { // Process pending reservations for (auto &reservation : reservations) { if (reservation.pending() && !available_builders.empty()) { reservation.ready(*available_builders.begin()); available_builders.erase(available_builders.begin()); } } // Update OpenStack by creating and removing builders as required // This section can take quite some time so is done in a coroutine if (!update_in_progress) { update_in_progress = true; asio::spawn(io_service, [&](asio::yield_context yield) { auto all_builders = OpenStackBuilder::get_builders(io_service, yield); std::set<Builder> unavailable_builders; Loading @@ -20,20 +33,18 @@ void BuilderQueue::tick(asio::yield_context yield) { unavailable_builders.insert(reservation.builder.get()); } if (reservation.complete()) { asio::spawn(io_service, [&](asio::yield_context yield) { OpenStackBuilder::destroy(reservation.builder.get(), io_service, yield); }); } }; } // TODO handle error state builders - potentially in destroy script? // Remove all completed reservations reservations.remove_if([](const auto &res) { return res.complete(); }); // Available_builders = all_builders - unavailable_builders std::set<Builder> available_builders; std::set_difference(all_builders.begin(), all_builders.end(), unavailable_builders.begin(), unavailable_builders.end(), std::inserter(available_builders, available_builders.begin())); Loading @@ -42,10 +53,11 @@ void BuilderQueue::tick(asio::yield_context yield) { auto open_slots = max_builders - all_builders.size(); auto open_available_slots = max_available_builders - available_builders.size(); auto request_count = std::min(open_slots, open_available_slots); for (int i = 0; i < request_count; i++) { asio::spawn(io_service, [&](asio::yield_context yield) { for (auto i = 0; i < request_count; i++) { OpenStackBuilder::request_create(io_service, yield); } update_in_progress = false; }); } } No newline at end of file
BuilderQueue/src/main.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -36,11 +36,14 @@ int main(int argc, char *argv[]) { }); // Start the queue which ticks at the specified interval boost::asio::deadline_timer timer(io_service); asio::spawn(io_service, [&](asio::yield_context yield) { for (;;) { try { builder_queue.tick(yield); builder_queue.tick(); timer.expires_from_now(boost::posix_time::seconds(1)); timer.async_wait(yield); } catch (std::exception &e) { logger::write(std::string() + "Queue tick error: " + e.what()); } Loading
Scripts/DestroyBuilder +1 −1 Original line number Diff line number Diff line Loading @@ -3,4 +3,4 @@ # OpenStack credentials source /home/queue/openrc.sh openstack server delete $1 No newline at end of file openstack server delete --wait $1 No newline at end of file
Scripts/GetBuilders +1 −1 Original line number Diff line number Diff line Loading @@ -3,4 +3,4 @@ # OpenStack credentials source /home/queue/openrc.sh openstack server list -f json --name Builder No newline at end of file openstack server list -f json --name "^Builder$" --status Active No newline at end of file