memgraph/tests/manual/card_fraud_local.cpp
florijan 95f1b6fe56 Fix remote plan invalidation
Summary:
Ensures that query plans are invalidated on the remote only when it's
guaranteed they will never be used on the master. This is done by
invalidating remote caches in the `CachedPlan` destructor.

There are two unplesant side-effects. First, an RPC call is made in an
object destructor. This is somewhat ugly, but not that different then
making an RPC call that must succeed in any other function. Note that
this does NOT slow down any query execution because the relevant
destructor is called by the skiplist garbage collector. The second ugly
side-effect is that in the unit test now we need to sleep to ensure the
skiplist GC destructs a cached plan before checking that it's
invalidated on the remote worker.

We might want to redesign this at some point.

Reviewers: teon.banek

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1302
2018-03-16 11:18:16 +01:00

78 lines
2.6 KiB
C++

#include <atomic>
#include <random>
#include <thread>
#include <vector>
#include "gflags/gflags.h"
#include "distributed_common.hpp"
DEFINE_int32(num_tx_creators, 3, "Number of threads creating transactions");
DEFINE_int32(tx_per_thread, 1000, "Number of transactions each thread creates");
int main(int argc, char *argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
Cluster cluster(5);
cluster.Execute("CREATE INDEX ON :Card(id)");
cluster.Execute("CREATE INDEX ON :Transaction(id)");
cluster.Execute("CREATE INDEX ON :Pos(id)");
int kCardCount = 20000;
int kPosCount = 20000;
cluster.Execute("UNWIND range(0, $card_count) AS id CREATE (:Card {id:id})",
{{"card_count", kCardCount - 1}});
cluster.Execute("UNWIND range(0, $pos_count) AS id CREATE (:Pos {id:id})",
{{"pos_count", kPosCount - 1}});
CheckResults(cluster.Execute("MATCH (:Pos) RETURN count(1)"), {{kPosCount}},
"Failed to create POS");
CheckResults(cluster.Execute("MATCH (:Card) RETURN count(1)"), {{kCardCount}},
"Failed to create Cards");
std::atomic<int> tx_counter{0};
auto create_tx = [&cluster, kCardCount, kPosCount, &tx_counter](int count) {
std::mt19937 rand_dev{std::random_device{}()};
std::uniform_int_distribution<> int_dist;
auto rint = [&rand_dev, &int_dist](int upper) {
return int_dist(rand_dev) % upper;
};
for (int i = 0; i < count; ++i) {
try {
auto res = cluster.Execute(
"MATCH (p:Pos {id: $pos}), (c:Card {id: $card}) "
"CREATE (p)<-[:At]-(:Transaction {id : $tx})-[:Using]->(c) "
"RETURN count(1)",
{{"pos", rint(kPosCount)},
{"card", rint(kCardCount)},
{"tx", tx_counter++}});
CheckResults(res, {{1}}, "Transaction creation");
} catch (LockTimeoutException &) {
--i;
} catch (mvcc::SerializationError &) {
--i;
}
if (i > 0 && i % 200 == 0)
LOG(INFO) << "Created " << i << " transactions";
}
};
LOG(INFO) << "Creating " << FLAGS_num_tx_creators * FLAGS_tx_per_thread
<< " transactions in " << FLAGS_num_tx_creators << " threads";
std::vector<std::thread> tx_creators;
for (int i = 0; i < FLAGS_num_tx_creators; ++i)
tx_creators.emplace_back(create_tx, FLAGS_tx_per_thread);
for (auto &t : tx_creators) t.join();
CheckResults(cluster.Execute("MATCH (:Transaction) RETURN count(1)"),
{{FLAGS_num_tx_creators * FLAGS_tx_per_thread}},
"Failed to create Transactions");
LOG(INFO) << "Test terminated successfully";
return 0;
}