memgraph/storage/storage_engine.hpp

109 lines
2.7 KiB
C++
Raw Normal View History

2015-07-07 22:18:26 +08:00
#ifndef MEMGRAPH_STORAGE_STORAGE_ENGINE_HPP
#define MEMGRAPH_STORAGE_STORAGE_ENGINE_HPP
#include <atomic>
#include <mutex>
#include "transaction/transaction.hpp"
#include "storage/model/record.hpp"
#include "memory/memory_engine.hpp"
2015-07-31 18:31:08 +08:00
#include "utils/counters/atomic_counter.hpp"
2015-07-07 22:18:26 +08:00
class StorageEngine
{
public:
2015-07-31 18:31:08 +08:00
StorageEngine(MemoryEngine& memory) : vertex_counter(0), edge_counter(0),
memory(memory) {}
2015-07-07 22:18:26 +08:00
template <class T>
2015-07-31 18:31:08 +08:00
bool insert(T** record, const Transaction& t)
2015-07-07 22:18:26 +08:00
{
2015-07-31 18:31:08 +08:00
auto n = next<T>();
*record = memory.create<T>(n);
// set creating transaction
(*record)->tx.min(t.id);
// set creating command of this transaction
(*record)->cmd.min(t.cid);
return true;
2015-07-07 22:18:26 +08:00
}
template <class T>
2015-07-31 18:31:08 +08:00
bool update(T* record,
T** updated,
const Transaction& t)
2015-07-07 22:18:26 +08:00
{
// put a lock on the node to prevent other writers from modifying it
auto guard = record->guard();
2015-07-31 18:31:08 +08:00
// find the record visible version of the record about to be updated
record = record->latest(t);
2015-07-07 22:18:26 +08:00
2015-07-31 18:31:08 +08:00
if(record == nullptr)
2015-07-07 22:18:26 +08:00
return false; // another transaction just deleted it!
*updated = memory.allocate<T>();
2015-07-31 18:31:08 +08:00
**updated = *record; // copy the data in the current node TODO memset?
2015-07-07 22:18:26 +08:00
2015-07-31 18:31:08 +08:00
record->newer(*updated);
2015-07-07 22:18:26 +08:00
return true;
}
template <class T>
2015-07-31 18:31:08 +08:00
bool remove(T& record,
const Transaction& t)
2015-07-07 22:18:26 +08:00
{
// put a lock on the node to prevent other writers from modifying it
2015-07-31 18:31:08 +08:00
auto guard = record->guard();
auto latest = record.latest(t);
if(record == nullptr)
return false;
2015-07-07 22:18:26 +08:00
// only mark the record as deleted if it isn't already deleted
// this prevents phantom reappearance of the deleted nodes
//
// T1 |---------- DELETE N --------| COMMIT
// T2 |----- DELETE N ---------------------------------| COMMIT
// T3 |-- SELECT N --|
//
// if xmax was overwritten by T2, T3 would see that T1 was still
// running and determined that the record hasn't been deleted yet
// even though T1 already committed before T3 even started!
2015-07-31 18:31:08 +08:00
if(record->xmax())
return false; // another transaction deleted it!
2015-07-07 22:18:26 +08:00
2015-07-31 18:31:08 +08:00
record->xmax(t.id);
2015-07-07 22:18:26 +08:00
return true;
}
private:
2015-07-31 18:31:08 +08:00
template<class T>
uint64_t next();
2015-07-07 22:18:26 +08:00
2015-07-31 18:31:08 +08:00
AtomicCounter<uint64_t> vertex_counter;
AtomicCounter<uint64_t> edge_counter;
MemoryEngine& memory;
2015-07-07 22:18:26 +08:00
};
2015-07-31 18:31:08 +08:00
template<>
uint64_t StorageEngine::next<Vertex>()
{
return vertex_counter.next();
}
template<>
uint64_t StorageEngine::next<Edge>()
{
return edge_counter.next();
}
2015-07-07 22:18:26 +08:00
#endif