memgraph/tests/unit/mvcc_find_update_common.hpp

97 lines
3.4 KiB
C++
Raw Normal View History

2017-05-05 17:05:56 +08:00
#include <vector>
#include "gtest/gtest.h"
#include "mvcc/record.hpp"
#include "mvcc/version.hpp"
#include "mvcc/version_list.hpp"
#include "threading/sync/lock_timeout_exception.hpp"
#include "transactions/engine.hpp"
#include "transactions/transaction.cpp"
class TestClass : public mvcc::Record<TestClass> {
public:
// constructs first version, size should be 0
TestClass(int &version_list_size) : version_list_size_(version_list_size) {
++version_list_size_;
}
TestClass *CloneData() { return new TestClass(version_list_size_); }
// version constructed in version list update
TestClass(TestClass &other) : version_list_size_(other.version_list_size_) {
version_list_size_++;
}
2017-05-05 17:05:56 +08:00
friend std::ostream &operator<<(std::ostream &stream, TestClass &test_class) {
stream << test_class.tx().cre << " " << test_class.tx().exp;
2017-05-05 17:05:56 +08:00
return stream;
}
// reference to variable version_list_size in test SetUp, increases when new
// TestClass is created
int &version_list_size_;
2017-05-05 17:05:56 +08:00
};
/**
* Testing mvcc::VersionList::find behavior in
* different situations (preceeding update/remove ops
* in different transactions).
*
* The setup for each case is:
* - transaction t1 has created a new version_list v1 and commited
* - transaction t2 has strated
* - *********************
* - here the test fixture ends and custom test behavior should be added
* - *********************
* - tests should check every legal sequence of the following ops
* - creation of transaction t3
* - [commit/abort] of [t2/t3]
* - [removal/update] on version_list by [t2/t3]
* - illegal sequences (for example double commit) don't have to be checked
*/
class Mvcc : public ::testing::Test {
protected:
virtual void SetUp() {
id0 = 0;
t1 = &engine.Advance(t1->id_);
id1 = t1->id_;
2017-05-05 17:05:56 +08:00
v1 = version_list.find(*t1);
t1->Commit();
t2 = engine.Begin();
id2 = t2->id_;
2017-05-05 17:05:56 +08:00
}
// variable where number of versions is stored
int version_list_size = 0;
2017-05-05 17:05:56 +08:00
tx::Engine engine;
tx::Transaction *t1 = engine.Begin();
Write-ahead log Summary: My dear fellow Memgraphians. It's friday afternoon, and I am as ready to pop as WAL is to get reviewed... What's done: - Vertices and Edges have global IDs, stored in `VersionList`. Main storage is now a concurrent map ID->vlist_ptr. - WriteAheadLog class added. It's based around buffering WAL::Op objects (elementraly DB changes) and periodically serializing and flusing them to disk. - Snapshot recovery refactored, WAL recovery added. Snapshot format changed again to include necessary info. - Durability testing completely reworked. What's not done (and should be when we decide how): - Old WAL file purging. - Config refactor (naming and organization). Will do when we discuss what we want. - Changelog and new feature documentation (both depending on the point above). - Better error handling and recovery feedback. Currently it's all returning bools, which is not fine-grained enough (neither for errors nor partial successes, also EOF is reported as a failure at the moment). - Moving the implementation of WAL stuff to .cpp where possible. - Not sure if there are transactions being created outside of `GraphDbAccessor` and it's `BuildIndex`. Need to look into. - True write-ahead logic (flag controlled): not committing a DB transaction if the WAL has not flushed it's data. We can discuss the gain/effort ratio for this feature. Reviewers: buda, mislav.bradac, teon.banek, dgleich Reviewed By: dgleich Subscribers: mtomic, pullbot Differential Revision: https://phabricator.memgraph.io/D958
2017-11-13 16:50:49 +08:00
mvcc::VersionList<TestClass> version_list{*t1, 0, version_list_size};
2017-05-05 17:05:56 +08:00
TestClass *v1 = nullptr;
tx::Transaction *t2 = nullptr;
tx::transaction_id_t id0, id1, id2;
2017-05-05 17:05:56 +08:00
};
// helper macros. important:
// - TX_FIND and TX_UPDATE set the record variable vX
// - TX_BEGIN sets the transaction variable tX
#define T2_FIND __attribute__((unused)) auto v2 = version_list.find(*t2)
#define T3_FIND __attribute__((unused)) auto v3 = version_list.find(*t3)
#define T4_FIND __attribute__((unused)) auto v4 = version_list.find(*t4)
2017-05-05 17:05:56 +08:00
#define T2_UPDATE __attribute__((unused)) auto v2 = version_list.update(*t2)
#define T3_UPDATE __attribute__((unused)) auto v3 = version_list.update(*t3)
#define T2_COMMIT t2->Commit();
#define T3_COMMIT t3->Commit();
#define T2_ABORT t2->Abort();
#define T3_ABORT t3->Abort();
#define T3_BEGIN \
auto t3 = engine.Begin(); \
__attribute__((unused)) int id3 = t3->id_
#define T4_BEGIN auto t4 = engine.Begin();
#define T2_REMOVE version_list.remove(version_list.find(*t2), *t2)
#define T3_REMOVE version_list.remove(version_list.find(*t3), *t3)
#define EXPECT_CRE(record, expected) EXPECT_EQ(record->tx().cre, id##expected)
#define EXPECT_EXP(record, expected) EXPECT_EQ(record->tx().exp, id##expected)
#define EXPECT_NXT(v1, v2) EXPECT_EQ(v1->next(), v2)
#define EXPECT_SIZE(n) EXPECT_EQ(version_list_size, n)
2017-05-05 17:05:56 +08:00
// test the fixture
TEST_F(Mvcc, Fixture) {
EXPECT_CRE(v1, 1);
EXPECT_EXP(v1, 0);
}