Skip to content

Commit ceb3903

Browse files
committed
feat: allow using user defiend ids with insert_node_with_id
1 parent 03c7834 commit ceb3903

3 files changed

Lines changed: 108 additions & 1 deletion

File tree

api/dsr_api.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,48 @@ template std::optional<uint64_t> DSRGraph::insert_node<DSR::Node &&>(DSR::Node&
225225
template std::optional<uint64_t> DSRGraph::insert_node<DSR::Node&>(DSR::Node&);
226226

227227

228+
template<typename No>
229+
std::optional<uint64_t> DSRGraph::insert_node_with_id(No &&node)
230+
requires (std::is_same_v<std::remove_reference_t<No>, DSR::Node>)
231+
{
232+
std::optional<IDL::MvregNode> delta;
233+
bool inserted = false;
234+
{
235+
std::unique_lock<std::shared_mutex> lock(_mutex);
236+
std::shared_lock<std::shared_mutex> lck_cache(_mutex_cache_maps);
237+
//Check id
238+
if (nodes.contains(node.id())) {
239+
DSR_LOG_WARNING("[INSERT_NODE_WITH_ID] Node id already exists", node.id(), node.type());
240+
return {};
241+
}
242+
if (node.name().empty() or name_map.contains(node.name()))
243+
node.name(node.type() + "_" + id_generator::hex_string(node.id()));
244+
lck_cache.unlock();
245+
std::tie(inserted, delta) = insert_node_(user_node_to_crdt(std::forward<No>(node)));
246+
}
247+
if (inserted)
248+
{
249+
if (!copy)
250+
{
251+
if (delta.has_value())
252+
{
253+
dsrpub_node.write(&delta.value());
254+
DSR_LOG_DEBUG("[INSERT_NODE_WITH_ID] emitting update_node_signal", node.id(), node.type());
255+
emitter.update_node_signal(node.id(), node.type(), SignalInfo{agent_id});
256+
for (const auto &[k, v]: node.fano())
257+
{
258+
emitter.update_edge_signal(node.id(), k.first, k.second, SignalInfo{agent_id});
259+
}
260+
}
261+
}
262+
return node.id();
263+
}
264+
return {};
265+
}
266+
267+
template std::optional<uint64_t> DSRGraph::insert_node_with_id<DSR::Node &&>(DSR::Node&&);
268+
template std::optional<uint64_t> DSRGraph::insert_node_with_id<DSR::Node&>(DSR::Node&);
269+
228270
std::tuple<bool, std::optional<std::vector<IDL::MvregNodeAttr>>> DSRGraph::update_node_(CRDTNode &&node)
229271
{
230272

api/include/dsr/api/dsr_api.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ namespace DSR
9191
template<typename No>
9292
std::optional<uint64_t> insert_node(No &&node) requires (std::is_same_v<std::remove_reference_t<No>, DSR::Node>);
9393
template<typename No>
94+
std::optional<uint64_t> insert_node_with_id(No &&node) requires (std::is_same_v<std::remove_reference_t<No>, DSR::Node>);
95+
template<typename No>
9496
bool update_node(No &&node) requires (std::is_same_v<std::remove_cvref_t<No>, DSR::Node>);
9597
bool delete_node(const DSR::Node& node);
9698
bool delete_node(const std::string &name);

tests/graph/node_operations.cpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,70 @@ TEST_CASE("Graph node operations", "[NODE]") {
133133
}
134134

135135

136-
TEST_CASE("Node creation",
136+
TEST_CASE("Insert node with specific id", "[NODE]") {
137+
138+
auto filename = make_empty_config_file();
139+
DSRGraph G(random_string(10), rand() % 1200, filename);
140+
141+
SECTION("Insert a node with a specific id") {
142+
auto node_name = random_string();
143+
uint64_t specific_id = 5000;
144+
auto n = Node::create<testtype_node_type>(node_name);
145+
n.id(specific_id);
146+
std::optional<uint64_t> r = G.insert_node_with_id(n);
147+
REQUIRE(r.has_value());
148+
REQUIRE(r.value() == specific_id);
149+
std::optional<Node> retrieved = G.get_node(specific_id);
150+
REQUIRE(retrieved.has_value());
151+
REQUIRE(retrieved->name() == node_name);
152+
}
153+
154+
SECTION("Insert a node with a duplicate id fails") {
155+
auto n1 = Node::create<testtype_node_type>(random_string());
156+
uint64_t specific_id = 6000;
157+
n1.id(specific_id);
158+
std::optional<uint64_t> r1 = G.insert_node_with_id(n1);
159+
REQUIRE(r1.has_value());
160+
161+
auto n2 = Node::create<testtype_node_type>(random_string());
162+
n2.id(specific_id);
163+
std::optional<uint64_t> r2 = G.insert_node_with_id(n2);
164+
REQUIRE_FALSE(r2.has_value());
165+
}
166+
167+
SECTION("Insert a node with empty name generates a name") {
168+
uint64_t specific_id = 7000;
169+
auto n = Node::create<testtype_node_type>("");
170+
n.id(specific_id);
171+
std::optional<uint64_t> r = G.insert_node_with_id(n);
172+
REQUIRE(r.has_value());
173+
std::optional<Node> retrieved = G.get_node(specific_id);
174+
REQUIRE(retrieved.has_value());
175+
REQUIRE_FALSE(retrieved->name().empty());
176+
}
177+
178+
SECTION("Insert a node with a duplicate name generates a new name") {
179+
auto shared_name = random_string();
180+
uint64_t id1 = 8000, id2 = 8001;
181+
182+
auto n1 = Node::create<testtype_node_type>(shared_name);
183+
n1.id(id1);
184+
std::optional<uint64_t> r1 = G.insert_node_with_id(n1);
185+
REQUIRE(r1.has_value());
186+
187+
auto n2 = Node::create<testtype_node_type>(shared_name);
188+
n2.id(id2);
189+
std::optional<uint64_t> r2 = G.insert_node_with_id(n2);
190+
REQUIRE(r2.has_value());
191+
192+
std::optional<Node> retrieved = G.get_node(id2);
193+
REQUIRE(retrieved.has_value());
194+
REQUIRE(retrieved->name() != shared_name);
195+
}
196+
}
197+
198+
199+
TEST_CASE("Node creation",
137200
"[Node]") {
138201

139202

0 commit comments

Comments
 (0)