Skip to content
Snippets Groups Projects
Select Git revision
  • d16ee4fa0e335b0e4493f5767a06327ec3ab6e4f
  • master default protected
  • develop
  • 4.22.1
  • 4.22.0
  • 1.5.0
  • 1.4.0
  • 1.3.0
  • 1.2.1
  • 1.2.0
  • 1.1.1
  • 1.1.0
  • 1.0.0
13 results

setup.sh

Blame
  • http_server.cpp 8.00 KiB
    #include "http_server.hpp"
    
    #include <algorithm>
    #include <iostream>
    #include <regex>
    #include <unordered_set>
    
    #include "data_storage.hpp"
    
    namespace insite {
    
    HttpServer::HttpServer(web::http::uri address, DataStorage* storage,
                           std::string database_uri)
        : http_listener_{address},
          storage_(storage),
          database_uri_(database_uri) {
      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.reply(GetMultimeterMeasurement(request));
        } else if (request.method() == "GET" &&
                   request.relative_uri().path() == "/current_simulation_time") {
          request.reply(GetCurrentSimulationTime(request));
        } else {
          std::cerr << "Invalid request: " << request.to_string() << "\n";
          request.reply(web::http::status_codes::NotFound);
        }
      });
    
      http_listener_.open().wait();
      std::cout << "HTTP server is listening...\n";
    }
    
    web::http::http_response HttpServer::GetCurrentSimulationTime(
        const web::http::http_request& request) {
      web::http::http_response response(web::http::status_codes::OK);
      web::json::value simulation_time = storage_->GetCurrentSimulationTime();
      response.set_body(simulation_time);
      return response;
    }
    
    web::http::http_response HttpServer::GetSpikes(
        const web::http::http_request& request) {
      const auto parameters = web::uri::split_query(request.request_uri().query());
    
      web::http::http_response response(web::http::status_codes::OK);
      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::connection connection(database_uri_);
        pqxx::work txn(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,
                                        spike_happened_before);
      }
    
      if (to != parameters.end()) {
        const auto to_number = std::stoll(to->second);
        spikes_end = std::lower_bound(spikes.begin(), spikes.end(), to_number,
                                      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);
    
      {
        size_t index = 0;
        for (auto spike = spikes_begin; spike != spikes_end; ++spike, ++index) {
          gids[index] = spike->gid;
          simulation_times[index] = spike->simulation_time;
        }
      }
    
      response.set_body(web::json::value::object(
          {{"simulation_times", simulation_times}, {"gids", gids}}));
      return response;
    }
    
    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");
      const auto parameter_from = parameters.find("from");
      const auto parameter_to = parameters.find("to");
      const auto parameter_gids = parameters.find("gids");
      const auto parameter_offset = parameters.find("offset");
      const auto parameter_limit = parameters.find("limit");
    
      const auto multimeter_id = std::stoll(parameter_multimeter_id->second);
      const auto attribute = parameter_attribute->second;
    
      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::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::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()) {
        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));
        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);
        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);
    
        auto gids_begin = filter_gids.empty() ? gids.begin() : filter_gids.begin();
        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)));
        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)
          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]];
    
        body["simulation_times"] = web::json::value::array(simulation_times_subset);
        body["gids"] = web::json::value::array(gids_subset);
        body["values"] = web::json::value::array(values_subset);
      }
    
      response.set_body(body);
      return response;
    }
    }  // namespace insite