diff --git a/recording_backend_insite.cpp b/recording_backend_insite.cpp index 60c7578de8a726822fdfb218fecdf23f4c96735f..c76ce068aaffab785bc15edf9d7192efc90c316c 100644 --- a/recording_backend_insite.cpp +++ b/recording_backend_insite.cpp @@ -20,12 +20,7 @@ namespace insite { RecordingBackendInsite::RecordingBackendInsite() : data_storage_("tgest"), http_server_("http://0.0.0.0:" + get_port_string(), &data_storage_), - database_connection_("postgresql://postgres@database"), - address_("insite-nest-module:" + get_port_string()) { - web::uri_builder builder("/node"); - builder.append_query("node_type", "nest_simulation", true); - builder.append_query("address", address_, true); - + database_connection_("postgresql://postgres@database") { pqxx::work txn(database_connection_); simulation_node_id_ = txn.exec1( "INSERT INTO nest_simulation_node (address) " @@ -69,13 +64,34 @@ void RecordingBackendInsite::set_value_names( if (device.get_type() == nest::RecordingDevice::MULTIMETER) { auto& multimeter = multimeter_infos_.at(device.get_node_id()); + + std::stringstream multimeter_query; + multimeter_query + << "INSERT INTO nest_multimeter (id, attributes) " + << "VALUES (" << device.get_node_id() << ",\'{"; - for (auto& name : double_value_names) - multimeter.double_attributes.push_back(name.toString()); - for (auto& name : long_value_names) - multimeter.long_attributes.push_back(name.toString()); + bool first = true; + for (auto& name : double_value_names) { + const auto& name_string = name.toString(); + multimeter.double_attributes.push_back(name_string); + + multimeter_query << (first ? "" : ",") << '\"' << name_string << "\""; + first = false; + } + for (auto& name : long_value_names) { + const auto& name_string = name.toString(); + multimeter.long_attributes.push_back(name_string); + + multimeter_query << (first ? "" : ",") << '\"' << name_string << "\""; + first = false; + } + multimeter_query << "}\') ON CONFLICT DO NOTHING;"; - multimeter.needs_update = true; + multimeter.needs_update = true; + + pqxx::work txn(database_connection_); + txn.exec0(multimeter_query.str()); + txn.commit(); } } @@ -106,47 +122,36 @@ void RecordingBackendInsite::post_step_hook() { } if (new_neuron_infos_.size() > 0) { - // Send new gids - web::uri_builder builder("/gids"); + std::stringstream neuron_query; + neuron_query + << "INSERT INTO nest_neuron (id, simulation_node_id, population_id, position_x, position_y, position_z) " + << "VALUES "; for (auto& neuron_info : new_neuron_infos_) { - builder.append_query("gids", neuron_info.gid, false); - } - builder.append_query("address", address_, true); - - // info_node_.request(web::http::methods::PUT, builder.to_string()) - // .then([](const web::http::http_response& response) { - // if (response.status_code() != web::http::status_codes::OK) { - // std::cerr << "Failed to send gids to info node: \n" - // << response.to_string() << "\n" - // << std::endl; - // throw std::runtime_error(response.to_string()); - // } - // }).wait(); - - // Send new properties - builder = web::uri_builder("/neuron_properties"); - web::json::value request_body = - web::json::value::array(new_neuron_infos_.size()); - for (std::size_t i = 0; i < new_neuron_infos_.size(); ++i) { - auto& neuron_info = new_neuron_infos_[i]; - request_body[i]["gid"] = neuron_info.gid; - request_body[i]["properties"] = web::json::value(); - if (!neuron_info.position.empty()) - request_body[i]["properties"]["position"] = - web::json::value::array(std::vector<web::json::value>( - neuron_info.position.begin(), neuron_info.position.end())); + const bool first = neuron_info.gid == new_neuron_infos_[0].gid; + if (!first) { + neuron_query << ","; + } + + uint64_t population_id = 0; + for (const nest::NodeIDTriple& node_id_triple : *neuron_info.gid_collection.get()) { + population_id ^= node_id_triple.node_id * 938831; + } + + neuron_query << "(" << neuron_info.gid << "," << simulation_node_id_ << "," << population_id % 0x800000; + for (const auto position_entry : neuron_info.position) { + neuron_query << "," << position_entry; + } + assert(neuron_info.position.size() <= 3); + for (auto i = 3 - neuron_info.position.size(); i != 0; --i) { + neuron_query << ",NULL"; + } + neuron_query << ")"; } + neuron_query << ";"; - // info_node_ - // .request(web::http::methods::PUT, builder.to_string(), request_body) - // .then([](const web::http::http_response& response) { - // if (response.status_code() != web::http::status_codes::OK) { - // std::cerr << "Failed to send neuron properties to info node: \n" - // << response.to_string() << "\n" - // << std::endl; - // throw std::runtime_error(response.to_string()); - // } - // }).wait(); + pqxx::work txn(database_connection_); + txn.exec0(neuron_query.str()); + txn.commit(); neuron_infos_.insert(neuron_infos_.end(), new_neuron_infos_.begin(), new_neuron_infos_.end()); @@ -160,61 +165,25 @@ void RecordingBackendInsite::post_step_hook() { if (!multimeter.needs_update) continue; multimeter.needs_update = false; - - web::uri_builder builder("/multimeter_info"); - builder.append_query("id", multimeter.device_id, true); - for (auto attribute : multimeter.double_attributes) - builder.append_query("attributes", attribute, true); - for (auto attribute : multimeter.long_attributes) - builder.append_query("attributes", attribute, true); - for (auto gid : multimeter.gids) - builder.append_query("gids", gid, false); - - // try { - // info_node_.request(web::http::methods::PUT, builder.to_string()) - // .then([](const web::http::http_response& response) { - // if (response.status_code() != web::http::status_codes::OK) { - // throw std::runtime_error(response.to_string()); - // } - // }) - // .wait(); - // } catch (const std::exception& exception) { - // std::cerr << "Failed to put multimeter info: \n" - // << exception.what() << "\n" - // << std::endl; - // throw; - // } - } - // Send new collections - for (const auto& node_collection : node_collections_to_register_) { - web::uri_builder builder("/populations"); - for (auto node_id_triple : *node_collection) { - builder.append_query("gids", node_id_triple.node_id, false); - } - // Initialize to "invalid" state - registered_node_collections_[node_collection] = -1; - // info_node_.request(web::http::methods::PUT, builder.to_string()) - // .then([this, - // node_collection](const web::http::http_response& response) { - // if (response.status_code() != web::http::status_codes::OK) { - // std::cerr << "Failed to send population to info node: \n" - // << response.to_string() << "\n" - // << std::endl; - // throw std::runtime_error(response.to_string()); - // } else { - // response.extract_json().then( - // [this, node_collection](const web::json::value& population_id) { - // std::cout << "Got id for node collection " << node_collection - // << ": " << population_id << std::endl; - // registered_node_collections_[node_collection] = - // population_id.as_number().to_int64(); - // }); - // } - // }) - // .wait(); // Wait because it may cause a race condition + if (multimeter.gids.size() > 0) { + std::stringstream neuron_multimeter_query; + neuron_multimeter_query + << "INSERT INTO nest_neuron_multimeter (neuron_id, multimeter_id) " + << "VALUES "; + + for (const auto& neuron_id : multimeter.gids) { + const bool first = neuron_id == multimeter.gids[0]; + neuron_multimeter_query << (first ? "" : ",") << "(" << neuron_id << "," << multimeter.device_id << ")"; + } + + neuron_multimeter_query << " ON CONFLICT DO NOTHING;"; + + pqxx::work txn(database_connection_); + txn.exec0(neuron_multimeter_query.str()); + txn.commit(); + } } - node_collections_to_register_.clear(); } void RecordingBackendInsite::write(const nest::RecordingDevice& device, @@ -266,20 +235,6 @@ void RecordingBackendInsite::write(const nest::RecordingDevice& device, std::lower_bound(new_neuron_infos_.begin(), new_neuron_infos_.end(), neuron_info), neuron_info); - - // Check if the node collection (population) is already sent to the - // info-node - const auto sender_node_collection = event.get_sender().get_nc(); - if (registered_node_collections_.count(sender_node_collection) == 0 && - !binary_search(node_collections_to_register_.begin(), - node_collections_to_register_.end(), - sender_node_collection)) { - node_collections_to_register_.insert( - std::lower_bound(node_collections_to_register_.begin(), - node_collections_to_register_.end(), - sender_node_collection), - sender_node_collection); - } } } diff --git a/recording_backend_insite.h b/recording_backend_insite.h index fd7389c9667fb9754ac62bdbe692bbcd22193660..aa8ec277c0b42494f00ca8a632c7cf690c100d52 100644 --- a/recording_backend_insite.h +++ b/recording_backend_insite.h @@ -64,12 +64,9 @@ class RecordingBackendInsite : public nest::RecordingBackend { DataStorage data_storage_; HttpServer http_server_; pqxx::connection database_connection_; - std::string address_; int simulation_node_id_; std::vector<NeuronInfo> neuron_infos_; std::vector<NeuronInfo> new_neuron_infos_; - std::unordered_map<nest::NodeCollectionPTR, int64_t> registered_node_collections_; - std::vector<nest::NodeCollectionPTR> node_collections_to_register_; std::unordered_map<nest::index, MultimeterInfo> multimeter_infos_; double latest_simulation_time_ = 0; };