diff --git a/http_server.cpp b/http_server.cpp index 7acd6425655111f03795471c15bb56fad835f943..81a478ba3c2f6eddca3c1f6fe7094b36ca54e61a 100644 --- a/http_server.cpp +++ b/http_server.cpp @@ -1,21 +1,28 @@ #include "http_server.hpp" -#include "data_storage.hpp" +#include <algorithm> +#include <iostream> #include <regex> +#include <unordered_set> + +#include "data_storage.hpp" namespace insite { -HttpServer::HttpServer(web::http::uri address, DataStorage* storage) - : http_listener_{address}, storage_(storage) { +HttpServer::HttpServer(web::http::uri address, DataStorage* storage, + pqxx::connection* database_connection) + : http_listener_{address}, + storage_(storage), + database_connection_(database_connection) { http_listener_.support([this](web::http::http_request request) { if (request.method() == "GET" && request.relative_uri().path() == "/spikes") { request.reply(GetSpikes(request)); } else if (request.method() == "GET" && - request.relative_uri().path() == "/multimeter_measurement") { + request.relative_uri().path() == "/multimeter_measurement") { request.reply(GetMultimeterMeasurement(request)); } else if (request.method() == "GET" && - request.relative_uri().path() == "/current_simulation_time") { + request.relative_uri().path() == "/current_simulation_time") { request.reply(GetCurrentSimulationTime(request)); } else { std::cerr << "Invalid request: " << request.to_string() << "\n"; @@ -40,18 +47,38 @@ web::http::http_response HttpServer::GetSpikes( const auto parameters = web::uri::split_query(request.request_uri().query()); web::http::http_response response(web::http::status_codes::OK); - const auto spikes = storage_->GetSpikes(); - auto spikes_begin = spikes.begin(); - auto spikes_end = spikes.end(); + auto spikes = storage_->GetSpikes(); const auto from = parameters.find("from"); const auto to = parameters.find("to"); + const auto population = parameters.find("population"); + + std::unordered_set<uint64_t> population_node_ids; + if (population != parameters.end()) { + pqxx::work txn(*database_connection_); + const auto population_node_ids_result = txn.exec( + "SELECT id FROM nest_neuron WHERE nest_neuron.population_id = " + + population->second); + txn.commit(); + + population_node_ids.reserve(population_node_ids_result.size()); + + for (const auto& node_id : population_node_ids_result) { + population_node_ids.insert(node_id[0].as<uint64_t>()); + } + + spikes.erase(std::remove_if(spikes.begin(), spikes.end(), [&population_node_ids](const Spike& spike) { + return population_node_ids.count(spike.gid) == 0; + }), spikes.end()); + } const auto spike_happened_before = [](const Spike& spike, double simulation_time) { return spike.simulation_time < simulation_time; }; + auto spikes_begin = spikes.begin(); + auto spikes_end = spikes.end(); if (from != parameters.end()) { const auto from_number = std::stoll(from->second); spikes_begin = std::lower_bound(spikes.begin(), spikes.end(), from_number, @@ -64,6 +91,7 @@ web::http::http_response HttpServer::GetSpikes( spike_happened_before); } + const auto element_count = spikes_end - spikes_begin; web::json::value gids = web::json::value::array(element_count); web::json::value simulation_times = web::json::value::array(element_count); @@ -73,7 +101,10 @@ web::http::http_response HttpServer::GetSpikes( for (auto spike = spikes_begin; spike != spikes_end; ++spike, ++index) { gids[index] = spike->gid; simulation_times[index] = spike->simulation_time; + + std::cout << population_node_ids.count(spike->gid) << " " << gids[index] << "\n"; } + std::cout << std::endl; } response.set_body(web::json::value::object( @@ -85,7 +116,7 @@ web::http::http_response HttpServer::GetMultimeterMeasurement( const web::http::http_request& request) { web::http::http_response response(web::http::status_codes::OK); web::json::value body = web::json::value::object(); - + const auto parameters = web::uri::split_query(request.request_uri().query()); const auto parameter_multimeter_id = parameters.find("multimeter_id"); const auto parameter_attribute = parameters.find("attribute"); @@ -101,63 +132,67 @@ web::http::http_response HttpServer::GetMultimeterMeasurement( auto filter_gids = std::vector<std::uint64_t>(); if (parameter_gids != parameters.end()) { std::regex regex{R"([\s,]+)"}; - std::sregex_token_iterator it{parameter_gids->second.begin(), - parameter_gids->second.end(), regex, -1}; + std::sregex_token_iterator it{parameter_gids->second.begin(), + parameter_gids->second.end(), regex, -1}; std::vector<std::string> filter_gid_strings{it, {}}; - std::transform(filter_gid_strings.begin(), filter_gid_strings.end(), - std::back_inserter(filter_gids), [ ] (const std::string& str) { - return std::stoll(str); - }); + std::transform(filter_gid_strings.begin(), filter_gid_strings.end(), + std::back_inserter(filter_gids), + [](const std::string& str) { return std::stoll(str); }); } std::cout << "Filter GID count: " << filter_gids.size() << "\n"; const auto measurements = storage_->GetMultimeterMeasurements(); if (measurements.find(multimeter_id) != measurements.end() && - measurements.at(multimeter_id).find(attribute) - != measurements.at(multimeter_id).end()) { + measurements.at(multimeter_id).find(attribute) != + measurements.at(multimeter_id).end()) { auto& measurement = measurements.at(multimeter_id).at(attribute); auto& simulation_times = measurement.simulation_times; auto& gids = measurement.gids; auto& values = measurement.values; - auto simulation_times_begin = parameter_from == parameters.end() - ? simulation_times.begin() : std::lower_bound(simulation_times.begin(), - simulation_times.end(), std::stoll(parameter_from->second)); - auto simulation_times_end = parameter_to == parameters.end() - ? simulation_times.end() : std::lower_bound(simulation_times.begin(), - simulation_times.end(), std::stoll(parameter_to->second)); + auto simulation_times_begin = + parameter_from == parameters.end() + ? simulation_times.begin() + : std::lower_bound(simulation_times.begin(), simulation_times.end(), + std::stoll(parameter_from->second)); + auto simulation_times_end = + parameter_to == parameters.end() + ? simulation_times.end() + : std::lower_bound(simulation_times.begin(), simulation_times.end(), + std::stoll(parameter_to->second)); if (parameter_offset != parameters.end()) simulation_times_begin += std::stoll(parameter_offset->second); if (parameter_limit != parameters.end()) - simulation_times_end = simulation_times_begin + - std::stoll(parameter_limit->second); + simulation_times_end = + simulation_times_begin + std::stoll(parameter_limit->second); auto simulation_times_subset = std::vector<web::json::value>( - simulation_times_begin, simulation_times_end); - std::size_t simulation_start_index = std::distance(simulation_times.begin(), - simulation_times_begin); - std::size_t simulation_end_index = std::distance(simulation_times.begin(), - simulation_times_end); - + simulation_times_begin, simulation_times_end); + std::size_t simulation_start_index = + std::distance(simulation_times.begin(), simulation_times_begin); + std::size_t simulation_end_index = + std::distance(simulation_times.begin(), simulation_times_end); + auto gids_begin = filter_gids.empty() ? gids.begin() : filter_gids.begin(); - auto gids_end = filter_gids.empty() ? gids.end() : filter_gids.end(); + auto gids_end = filter_gids.empty() ? gids.end() : filter_gids.end(); auto gids_subset = std::vector<web::json::value>(gids_begin, gids_end); auto gid_indices = std::vector<std::size_t>(); if (!filter_gids.empty()) for (auto& filter_gid : filter_gids) - gid_indices.push_back(std::distance(gids.begin(), - std::lower_bound(gids.begin(), gids.end(), filter_gid))); + gid_indices.push_back(std::distance( + gids.begin(), + std::lower_bound(gids.begin(), gids.end(), filter_gid))); else { gid_indices.resize(gids.size()); std::iota(gid_indices.begin(), gid_indices.end(), 0); } - + auto values_subset = std::vector<web::json::value>( - simulation_times_subset.size() * gids_subset.size()); - for (std::size_t t = 0, vt = simulation_start_index; - vt < simulation_end_index; ++t, ++vt) + simulation_times_subset.size() * gids_subset.size()); + for (std::size_t t = 0, vt = simulation_start_index; + vt < simulation_end_index; ++t, ++vt) for (std::size_t g = 0; g < gid_indices.size(); ++g) - values_subset[t * gids_subset.size() + g] = - values[vt * gids.size() + gid_indices[g]]; + values_subset[t * gids_subset.size() + g] = + values[vt * gids.size() + gid_indices[g]]; body["simulation_times"] = web::json::value::array(simulation_times_subset); body["gids"] = web::json::value::array(gids_subset); diff --git a/http_server.hpp b/http_server.hpp index 7e9a73447e996f71c94ff5e7ec0f03f7edad5cb2..ccf4c8b58d8df64709acd9446af62cb5850d8cc4 100644 --- a/http_server.hpp +++ b/http_server.hpp @@ -3,6 +3,7 @@ #include <cpprest/http_listener.h> #include <string> +#include <pqxx/pqxx> namespace insite { @@ -10,11 +11,12 @@ class DataStorage; class HttpServer { public: - HttpServer(web::http::uri address, DataStorage* storage); + HttpServer(web::http::uri address, DataStorage* storage, pqxx::connection* database_connection); private: web::http::experimental::listener::http_listener http_listener_; DataStorage* storage_; + pqxx::connection* database_connection_; web::http::http_response GetCurrentSimulationTime(const web::http::http_request& request);