2018-02-05 23:28:22 +08:00
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
#include "database/graph_db_accessor.hpp"
|
|
|
|
#include "storage/edge_accessor.hpp"
|
|
|
|
#include "storage/vertex_accessor.hpp"
|
|
|
|
|
|
|
|
#include "distributed_common.hpp"
|
|
|
|
|
|
|
|
using namespace database;
|
2018-06-15 03:15:01 +08:00
|
|
|
using namespace std::literals::chrono_literals;
|
2018-02-05 23:28:22 +08:00
|
|
|
|
2018-07-05 16:55:00 +08:00
|
|
|
class DistributedDataExchangeTest : public DistributedGraphDbTest {
|
|
|
|
public:
|
|
|
|
DistributedDataExchangeTest() : DistributedGraphDbTest("data_exchange") {}
|
|
|
|
};
|
|
|
|
|
|
|
|
TEST_F(DistributedDataExchangeTest, RemoteDataGetting) {
|
2018-02-05 23:28:22 +08:00
|
|
|
// Only old data is visible remotely, so create and commit some data.
|
|
|
|
gid::Gid v1_id, v2_id, e1_id;
|
|
|
|
|
|
|
|
{
|
2018-07-26 15:08:21 +08:00
|
|
|
auto dba = master().Access();
|
|
|
|
auto v1 = dba->InsertVertex();
|
|
|
|
auto v2 = dba->InsertVertex();
|
|
|
|
auto e1 = dba->InsertEdge(v1, v2, dba->EdgeType("et"));
|
2018-02-05 23:28:22 +08:00
|
|
|
|
|
|
|
// Set some data so we see we're getting the right stuff.
|
2018-07-26 15:08:21 +08:00
|
|
|
v1.PropsSet(dba->Property("p1"), 42);
|
|
|
|
v1.add_label(dba->Label("label"));
|
|
|
|
v2.PropsSet(dba->Property("p2"), "value");
|
|
|
|
e1.PropsSet(dba->Property("p3"), true);
|
2018-02-05 23:28:22 +08:00
|
|
|
|
|
|
|
v1_id = v1.gid();
|
|
|
|
v2_id = v2.gid();
|
|
|
|
e1_id = e1.gid();
|
|
|
|
|
2018-07-26 15:08:21 +08:00
|
|
|
dba->Commit();
|
2018-02-05 23:28:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// The master must start a transaction before workers can work in it.
|
2018-07-26 15:08:21 +08:00
|
|
|
auto master_dba = master().Access();
|
2018-02-05 23:28:22 +08:00
|
|
|
|
|
|
|
{
|
2018-07-26 15:08:21 +08:00
|
|
|
auto w1_dba = worker(1).Access(master_dba->transaction_id());
|
|
|
|
VertexAccessor v1_in_w1{{v1_id, 0}, *w1_dba};
|
2019-02-15 18:18:44 +08:00
|
|
|
auto guard = storage::GetDataLock(v1_in_w1);
|
2018-02-05 23:28:22 +08:00
|
|
|
EXPECT_NE(v1_in_w1.GetOld(), nullptr);
|
|
|
|
EXPECT_EQ(v1_in_w1.GetNew(), nullptr);
|
2018-07-26 15:08:21 +08:00
|
|
|
EXPECT_EQ(v1_in_w1.PropsAt(w1_dba->Property("p1")).Value<int64_t>(), 42);
|
|
|
|
EXPECT_TRUE(v1_in_w1.has_label(w1_dba->Label("label")));
|
2018-02-05 23:28:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2018-07-26 15:08:21 +08:00
|
|
|
auto w2_dba = worker(2).Access(master_dba->transaction_id());
|
|
|
|
VertexAccessor v2_in_w2{{v2_id, 0}, *w2_dba};
|
2019-02-15 18:18:44 +08:00
|
|
|
auto guard = storage::GetDataLock(v2_in_w2);
|
2018-02-05 23:28:22 +08:00
|
|
|
EXPECT_NE(v2_in_w2.GetOld(), nullptr);
|
|
|
|
EXPECT_EQ(v2_in_w2.GetNew(), nullptr);
|
2018-07-26 15:08:21 +08:00
|
|
|
EXPECT_EQ(v2_in_w2.PropsAt(w2_dba->Property("p2")).Value<std::string>(),
|
2018-02-05 23:28:22 +08:00
|
|
|
"value");
|
2018-07-26 15:08:21 +08:00
|
|
|
EXPECT_FALSE(v2_in_w2.has_label(w2_dba->Label("label")));
|
2018-02-05 23:28:22 +08:00
|
|
|
|
2018-07-26 15:08:21 +08:00
|
|
|
VertexAccessor v1_in_w2{{v1_id, 0}, *w2_dba};
|
|
|
|
EdgeAccessor e1_in_w2{{e1_id, 0}, *w2_dba};
|
2018-02-05 23:28:22 +08:00
|
|
|
EXPECT_EQ(e1_in_w2.from(), v1_in_w2);
|
|
|
|
EXPECT_EQ(e1_in_w2.to(), v2_in_w2);
|
2018-07-26 15:08:21 +08:00
|
|
|
EXPECT_EQ(e1_in_w2.EdgeType(), w2_dba->EdgeType("et"));
|
|
|
|
EXPECT_EQ(e1_in_w2.PropsAt(w2_dba->Property("p3")).Value<bool>(), true);
|
2018-02-05 23:28:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-05 16:55:00 +08:00
|
|
|
TEST_F(DistributedDataExchangeTest, RemoteExpansion) {
|
2018-02-05 23:28:22 +08:00
|
|
|
// Model (v1)-->(v2), where each vertex is on one worker.
|
2018-02-14 16:44:48 +08:00
|
|
|
auto from = InsertVertex(worker(1));
|
|
|
|
auto to = InsertVertex(worker(2));
|
|
|
|
InsertEdge(from, to, "et");
|
2018-02-05 23:28:22 +08:00
|
|
|
{
|
|
|
|
// Expand on the master for three hops. Collect vertex gids.
|
2018-07-26 15:08:21 +08:00
|
|
|
auto dba = master().Access();
|
2018-02-05 23:28:22 +08:00
|
|
|
std::vector<VertexAccessor> visited;
|
|
|
|
|
2018-02-08 19:57:12 +08:00
|
|
|
auto expand = [](auto &v) {
|
2018-02-05 23:28:22 +08:00
|
|
|
for (auto e : v.out()) return e.to();
|
|
|
|
for (auto e : v.in()) return e.from();
|
|
|
|
CHECK(false) << "No edge in vertex";
|
|
|
|
};
|
|
|
|
|
|
|
|
// Do a few hops back and forth, all on the master.
|
2018-07-26 15:08:21 +08:00
|
|
|
VertexAccessor v{from, *dba};
|
2018-02-05 23:28:22 +08:00
|
|
|
for (int i = 0; i < 5; ++i) {
|
|
|
|
v = expand(v);
|
|
|
|
EXPECT_FALSE(v.address().is_local());
|
2018-02-14 16:44:48 +08:00
|
|
|
EXPECT_EQ(v.address(), i % 2 ? from : to);
|
2018-02-05 23:28:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-05-29 17:32:21 +08:00
|
|
|
|
2018-07-05 16:55:00 +08:00
|
|
|
TEST_F(DistributedDataExchangeTest, VertexCountsEqual) {
|
2018-05-29 17:32:21 +08:00
|
|
|
for (int i = 0; i < 5; ++i) InsertVertex(master());
|
|
|
|
for (int i = 0; i < 7; ++i) InsertVertex(worker(1));
|
|
|
|
for (int i = 0; i < 9; ++i) InsertVertex(worker(2));
|
|
|
|
|
|
|
|
{
|
2018-07-26 15:08:21 +08:00
|
|
|
auto accessor = master().Access();
|
2018-05-29 17:32:21 +08:00
|
|
|
auto m_cnt =
|
2018-07-26 15:08:21 +08:00
|
|
|
master().data_clients().VertexCounts(accessor->transaction().id_);
|
2018-05-29 17:32:21 +08:00
|
|
|
auto w1_cnt =
|
2018-07-26 15:08:21 +08:00
|
|
|
worker(1).data_clients().VertexCounts(accessor->transaction().id_);
|
2018-05-29 17:32:21 +08:00
|
|
|
auto w2_cnt =
|
2018-07-26 15:08:21 +08:00
|
|
|
worker(2).data_clients().VertexCounts(accessor->transaction().id_);
|
2018-05-29 17:32:21 +08:00
|
|
|
|
|
|
|
auto check = [&m_cnt, &w1_cnt, &w2_cnt](int key, int value) {
|
|
|
|
return m_cnt[key] == w1_cnt[key] && w1_cnt[key] == w2_cnt[key] &&
|
|
|
|
m_cnt[key] == value;
|
|
|
|
};
|
|
|
|
|
|
|
|
EXPECT_TRUE(check(master().WorkerId(), 5));
|
|
|
|
EXPECT_TRUE(check(worker(1).WorkerId(), 7));
|
|
|
|
EXPECT_TRUE(check(worker(2).WorkerId(), 9));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-05 16:55:00 +08:00
|
|
|
TEST_F(DistributedDataExchangeTest, VertexCountsTransactional) {
|
2018-05-29 17:32:21 +08:00
|
|
|
{
|
2018-07-26 15:08:21 +08:00
|
|
|
auto accessor = master().Access();
|
2018-05-29 17:32:21 +08:00
|
|
|
InsertVertex(master());
|
|
|
|
EXPECT_EQ(master().data_clients().VertexCounts(
|
2018-07-26 15:08:21 +08:00
|
|
|
accessor->transaction().id_)[master().WorkerId()],
|
2018-05-29 17:32:21 +08:00
|
|
|
0);
|
|
|
|
}
|
|
|
|
// Transaction after insert which should now see the insertion
|
|
|
|
{
|
2018-07-26 15:08:21 +08:00
|
|
|
auto accessor = master().Access();
|
2018-05-29 17:32:21 +08:00
|
|
|
EXPECT_EQ(master().data_clients().VertexCounts(
|
2018-07-26 15:08:21 +08:00
|
|
|
accessor->transaction().id_)[master().WorkerId()],
|
2018-05-29 17:32:21 +08:00
|
|
|
1);
|
|
|
|
}
|
|
|
|
}
|