Created EdgeRecord as class and changed in edge vector for map.

EdgeRecord now contains from,to fields as immutables.
Vertex in place of in vector of edges has in RbHashMultimap of edges.
Astar exepriment now uses real filters based on before mentioned map.
This commit is contained in:
Kruno Tomola Fabro 2016-08-09 20:29:03 +01:00
parent c3c8fb6620
commit 61eccc28ce
13 changed files with 193 additions and 157 deletions

View File

@ -1,11 +1,33 @@
#pragma once
#include "mvcc/version_list.hpp"
#include "storage/edge.hpp"
// class EdgeRecord: public mvcc::VersionList<Edge>{
// public:
// using mvcc::VersionList<Edge>;
//
// VertexRecord* get_key(){
// //TODO
// }
// };
class EdgeRecord : public mvcc::VersionList<Edge>
{
public:
EdgeRecord(Id id, VertexRecord *from, VertexRecord *to)
: from_v(from), to_v(to), VersionList(id)
{
}
EdgeRecord(const VersionList &) = delete;
/* @brief Move constructs the version list
* Note: use only at the beginning of the "other's" lifecycle since this
* constructor doesn't move the RecordLock, but only the head pointer
*/
EdgeRecord(EdgeRecord &&other)
: from_v(other.from_v), to_v(other.to_v), VersionList(std::move(other))
{
}
VertexRecord *&get_key() { return from_v; }
auto from() const { return this->from_v; }
auto to() const { return this->to_v; }
private:
VertexRecord *from_v;
VertexRecord *to_v;
};

View File

@ -24,6 +24,8 @@ public:
throw std::bad_function_call::bad_function_call();
}
bool contains(VertexRecord *vr) { return edges.contains(vr); }
void clear() { edges.clear(); }
private:

View File

@ -1,3 +1,5 @@
#include <chrono>
#include <ctime>
#include <fstream>
#include <iostream>
#include <queue>
@ -20,10 +22,15 @@ public:
double cost;
int depth = {0};
Vertex *vertex;
VertexRecord *record;
Node(Vertex *va, double cost) : cost(cost), vertex(va) {}
Node(Vertex *va, double cost, Node *parent)
: cost(cost), vertex(va), parent(parent), depth(parent->depth + 1)
Node(Vertex *va, VertexRecord *record, double cost)
: cost(cost), vertex(va), record(record)
{
}
Node(Vertex *va, VertexRecord *record, double cost, Node *parent)
: cost(cost), vertex(va), parent(parent), depth(parent->depth + 1),
record(record)
{
}
};
@ -82,10 +89,10 @@ double calc_heuristic_cost_dummy(Edge *edge, Vertex *vertex)
return 1 - vertex->data.props.at("score").as<Double>().value;
}
typedef bool (*EdgeFilter)(tx::Transaction &t, Edge *, Node *before);
typedef bool (*EdgeFilter)(tx::Transaction &t, EdgeRecord *, Node *before);
typedef bool (*VertexFilter)(tx::Transaction &t, Vertex *, Node *before);
bool edge_filter_dummy(tx::Transaction &t, Edge *e, Node *before)
bool edge_filter_dummy(tx::Transaction &t, EdgeRecord *e, Node *before)
{
return true;
}
@ -104,9 +111,8 @@ bool vertex_filter_contained_dummy(tx::Transaction &t, Vertex *v, Node *before)
if (before == nullptr) {
return true;
}
for (auto e : before->vertex->data.out) {
Edge *edge = e->find(t);
Vertex *e_v = edge->data.to->find(t);
for (auto edge : before->vertex->data.out) {
Vertex *e_v = edge->to()->find(t);
if (e_v == v) {
found = true;
break;
@ -116,6 +122,19 @@ bool vertex_filter_contained_dummy(tx::Transaction &t, Vertex *v, Node *before)
return false;
}
bool vertex_filter_contained(tx::Transaction &t, Vertex *v, Node *before)
{
bool found;
do {
found = false;
before = before->parent;
if (before == nullptr) {
return true;
}
} while (v->data.in.contains(before->record));
return false;
}
// Vertex filter ima max_depth funkcija te edge filter ima max_depth funkcija.
// Jedan za svaku dubinu.
// Filtri vracaju true ako element zadovoljava uvjete.
@ -129,8 +148,8 @@ void a_star(Db &db, int64_t sys_id_start, uint max_depth, EdgeFilter e_filter[],
auto cmp = [](Node *left, Node *right) { return left->cost > right->cost; };
std::priority_queue<Node *, std::vector<Node *>, decltype(cmp)> queue(cmp);
Node *start =
new Node(db.graph.vertices.find(t, sys_id_start).vlist->find(t), 0);
auto start_vr = db.graph.vertices.find(t, sys_id_start).vlist;
Node *start = new Node(start_vr->find(t), start_vr, 0);
queue.push(start);
int count = 0;
do {
@ -145,13 +164,13 @@ void a_star(Db &db, int64_t sys_id_start, uint max_depth, EdgeFilter e_filter[],
continue;
}
for (auto e : now->vertex->data.out) {
Edge *edge = e->find(t);
for (auto edge : now->vertex->data.out) {
if (e_filter[now->depth](t, edge, now)) {
Vertex *v = edge->data.to->find(t);
Vertex *v = edge->to()->find(t);
if (v_filter[now->depth](t, v, now)) {
Node *n = new Node(
v, now->cost + calc_heuristic_cost(edge, v), now);
v, edge->to(),
now->cost + calc_heuristic_cost(edge->find(t), v), now);
queue.push(n);
}
}
@ -172,9 +191,14 @@ int main()
//
EdgeFilter e_filters[] = {&edge_filter_dummy, &edge_filter_dummy,
&edge_filter_dummy, &edge_filter_dummy};
VertexFilter f_filters[] = {&vertex_filter_dummy, &vertex_filter_dummy,
&vertex_filter_dummy, &vertex_filter_dummy};
VertexFilter f_filters[] = {
&vertex_filter_contained, &vertex_filter_contained,
&vertex_filter_contained, &vertex_filter_contained};
auto begin = clock();
a_star(db, 0, 3, e_filters, f_filters, &calc_heuristic_cost_dummy, 10);
clock_t end = clock();
double elapsed_ms = (double(end - begin) / CLOCKS_PER_SEC) * 1000;
std::cout << "A-star: " << elapsed_ms << " [ms]\n";
return 0;
}
@ -254,14 +278,11 @@ void load_csv(Db &db, char *file_path, char *edge_file_path)
auto v2 = va[to - start_vertex_id];
auto edge_accessor = db.graph.edges.insert(t);
auto edge_accessor = db.graph.edges.insert(t, v1.vlist, v2.vlist);
v1.vlist->update(t)->data.out.add(edge_accessor.vlist);
v2.vlist->update(t)->data.in.add(edge_accessor.vlist);
edge_accessor.from(v1.vlist);
edge_accessor.to(v2.vlist);
auto &edge_type = db.graph.edge_type_store.find_or_create(type);
edge_accessor.edge_type(edge_type);
};
@ -299,14 +320,10 @@ void load_graph_dummy(Db &db)
auto v2 = db.graph.vertices.find(t, va[to]);
auto edge_accessor = db.graph.edges.insert(t);
auto edge_accessor = db.graph.edges.insert(t, v1.vlist, v2.vlist);
v1.vlist->update(t)->data.out.add(edge_accessor.vlist);
v2.vlist->update(t)->data.in.add(edge_accessor.vlist);
edge_accessor.from(v1.vlist);
edge_accessor.to(v2.vlist);
auto &edge_type = db.graph.edge_type_store.find_or_create(type);
edge_accessor.edge_type(edge_type);
};

View File

@ -130,6 +130,22 @@ public:
RhHashMap() {}
RhHashMap(const RhHashMap &other)
{
capacity = other.capacity;
count = other.count;
if (capacity > 0) {
size_t bytes = sizeof(Combined) * capacity;
array = (Combined *)malloc(bytes);
memcpy(array, other.array, bytes);
} else {
array = nullptr;
}
}
~RhHashMap() { this->clear(); }
Iterator begin() { return Iterator(this); }
ConstIterator begin() const { return ConstIterator(this); }

View File

@ -1,5 +1,6 @@
#include "utils/crtp.hpp"
#include "utils/option_ptr.hpp"
#include <cstring>
// HashMultiMap with RobinHood collision resolution policy.
// Single threaded.
@ -165,16 +166,18 @@ public:
}
}
RhHashMultiMap(RhHashMultiMap &&other)
{
capacity = other.capacity;
count = other.count;
array = other.array;
// RhHashMultiMap(RhHashMultiMap &&other)
// {
// capacity = other.capacity;
// count = other.count;
// array = other.array;
//
// other.array = nullptr;
// other.capacity = 0;
// other.count = 0;
// }
other.array = nullptr;
other.capacity = 0;
other.count = 0;
}
~RhHashMultiMap() { this->clear(); }
Iterator begin() { return Iterator(this); }
@ -192,7 +195,7 @@ public:
{
size_t bytes = sizeof(Combined) * size;
array = (Combined *)malloc(bytes);
memset(array, 0, bytes);
std::memset(array, 0, bytes);
capacity = size;
}
@ -219,6 +222,8 @@ public:
free(a);
}
bool contains(const K &key) { return find(key) != end(); }
Iterator find(const K &key)
{
size_t mask = this->mask();
@ -227,7 +232,7 @@ public:
bool bef_init = false;
size_t before_off;
K before_key = key;
auto before_key = key;
size_t border = 8 <= capacity ? 8 : capacity;
while (off < border) {
@ -270,7 +275,7 @@ public:
}
// Inserts element with the given key.
void add(K key, D *data)
void add(K &key, D *data)
{
assert(key == data->get_key());
@ -280,7 +285,7 @@ public:
bool bef_init = false;
size_t before_off;
K before_key = key;
auto before_key = key;
size_t border = 8 <= capacity ? 8 : capacity;
while (off < border) {

View File

@ -172,4 +172,4 @@ class Vertex;
class Edge;
using VertexRecord = mvcc::VersionList<Vertex>;
using EdgeRecord = mvcc::VersionList<Edge>;
// using EdgeRecord = mvcc::VersionList<Edge>;

View File

@ -2,11 +2,11 @@
#include "database/db.hpp"
#include "query_engine/query_stripper.hpp"
#include "query_engine/util.hpp"
#include "storage/model/properties/property.hpp"
#include "utils/command_line/arguments.hpp"
#include "query_engine/util.hpp"
auto load_queries(Db& db)
auto load_queries(Db &db)
{
std::map<uint64_t, std::function<bool(const properties_t &)>> queries;
@ -72,14 +72,11 @@ auto load_queries(Db& db)
auto v2 = db.graph.vertices.find(t, args[1]->as<Int32>().value);
if (!v2) return t.commit(), false;
auto edge_accessor = db.graph.edges.insert(t);
auto edge_accessor = db.graph.edges.insert(t, v1.vlist, v2.vlist);
v1.vlist->update(t)->data.out.add(edge_accessor.vlist);
v2.vlist->update(t)->data.in.add(edge_accessor.vlist);
edge_accessor.from(v1.vlist);
edge_accessor.to(v2.vlist);
auto &edge_type = db.graph.edge_type_store.find_or_create("IS");
edge_accessor.edge_type(edge_type);
@ -127,31 +124,28 @@ auto load_queries(Db& db)
return true;
};
// MATCH (n1), (n2) WHERE ID(n1)=0 AND ID(n2)=1 CREATE (n1)<-[r:IS {age: 25, weight: 70}]-(n2) RETURN r
auto create_edge_v2 = [&db](const properties_t &args)
{
auto& t = db.tx_engine.begin();
// MATCH (n1), (n2) WHERE ID(n1)=0 AND ID(n2)=1 CREATE (n1)<-[r:IS {age: 25,
// weight: 70}]-(n2) RETURN r
auto create_edge_v2 = [&db](const properties_t &args) {
auto &t = db.tx_engine.begin();
auto n1 = db.graph.vertices.find(t, args[0]->as<Int64>().value);
if (!n1) return t.commit(), false;
auto n2 = db.graph.vertices.find(t, args[1]->as<Int64>().value);
if (!n2) return t.commit(), false;
auto r = db.graph.edges.insert(t);
auto r = db.graph.edges.insert(t, n2.vlist, n1.vlist);
r.property("age", args[2]);
r.property("weight", args[3]);
auto &IS = db.graph.edge_type_store.find_or_create("IS");
r.edge_type(IS);
n2.vlist->update(t)->data.out.add(r.vlist);
n1.vlist->update(t)->data.in.add(r.vlist);
r.from(n2.vlist);
r.to(n1.vlist);
t.commit();
return true;
};
queries[15648836733456301916u] = create_edge_v2;
// MATCH (n) RETURN n
auto match_all_nodes = [&db](const properties_t &args)
{
auto match_all_nodes = [&db](const properties_t &args) {
auto &t = db.tx_engine.begin();
auto vertices_accessor = db.graph.vertices.access();
@ -171,8 +165,7 @@ auto load_queries(Db& db)
queries[15284086425088081497u] = match_all_nodes;
// MATCH (n:LABEL) RETURN n
auto find_by_label = [&db](const properties_t &args)
{
auto find_by_label = [&db](const properties_t &args) {
auto &t = db.tx_engine.begin();
auto &label = db.graph.label_store.find_or_create("LABEL");
@ -181,7 +174,7 @@ auto load_queries(Db& db)
db.graph.vertices.find_label_index(label);
auto accessor = index_record_collection.access();
cout << "VERTICES" << endl;
for (auto& v : accessor) {
for (auto &v : accessor) {
cout << v.record->data.props.at("name").as<String>().value << endl;
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "mvcc/edge_record.hpp"
#include "storage/edge.hpp"
#include "storage/record_accessor.hpp"
#include "utils/assert.hpp"
@ -8,7 +9,8 @@
class Edges;
// TODO: Edge, Db, Edge::Accessor
class Edge::Accessor : public RecordAccessor<Edge, Edges, Edge::Accessor>
class Edge::Accessor
: public RecordAccessor<Edge, Edges, Edge::Accessor, EdgeRecord>
{
public:
using RecordAccessor::RecordAccessor;
@ -26,17 +28,17 @@ public:
}
// TODO: VertexAccessor
void from(VertexRecord *vertex_record)
{
this->record->data.from = vertex_record;
}
// void from(VertexRecord *vertex_record)
// {
// this->record->data.from = vertex_record;
// }
//
// void to(VertexRecord *vertex_record)
// {
// this->record->data.to = vertex_record;
// }
void to(VertexRecord *vertex_record)
{
this->record->data.to = vertex_record;
}
auto from() const { return this->vlist->from(); }
auto from() const { return this->record->data.from; }
auto to() const { return this->record->data.to; }
auto to() const { return this->vlist->to(); }
};

View File

@ -6,7 +6,7 @@
class Edges
{
public:
public:
Edge::Accessor find(tx::Transaction &t, const Id &id)
{
auto edges_accessor = edges.access();
@ -22,13 +22,14 @@ class Edges
return Edge::Accessor(edge, &edges_iterator->second, this);
}
Edge::Accessor insert(tx::Transaction &t)
Edge::Accessor insert(tx::Transaction &t, VertexRecord *from,
VertexRecord *to)
{
// get next vertex id
auto next = counter.next(std::memory_order_acquire);
// create new vertex record
EdgeRecord edge_record(next);
EdgeRecord edge_record(next, from, to);
// insert the new vertex record into the vertex store
auto edges_accessor = edges.access();
@ -41,7 +42,7 @@ class Edges
return Edge::Accessor(edge, &inserted_edge_record->second, this);
}
private:
private:
ConcurrentMap<uint64_t, EdgeRecord> edges;
AtomicCounter<uint64_t> counter;
};

View File

@ -1,7 +1,8 @@
#pragma once
#include <vector>
#include "mvcc/edge_record.hpp"
#include "mvcc/version_list.hpp"
#include <vector>
class EdgeList
{
@ -14,26 +15,17 @@ public:
auto end() const { return edges.end(); }
auto cend() const { return edges.end(); }
void add(EdgeRecord* edge)
{
edges.push_back(edge);
}
void add(EdgeRecord *edge) { edges.push_back(edge); }
size_t degree() const
{
return edges.size();
}
size_t degree() const { return edges.size(); }
void remove(EdgeRecord* edge)
void remove(EdgeRecord *edge)
{
edges.erase(std::remove(edges.begin(), edges.end(), edge), edges.end());
}
void clear()
{
edges.clear();
}
void clear() { edges.clear(); }
private:
std::vector<EdgeRecord*> edges;
std::vector<EdgeRecord *> edges;
};

View File

@ -7,11 +7,8 @@
class EdgeModel : public PropertyModel
{
public:
VertexRecord *from;
VertexRecord *to;
// TODO: here should be the reference
// but something that is copyable
// because this model is copied all the time (mvcc)
const EdgeType *edge_type {nullptr};
const EdgeType *edge_type{nullptr};
};

View File

@ -3,12 +3,12 @@
#include "edge_list.hpp"
#include "property_model.hpp"
#include "storage/label/label_collection.hpp"
// #include "storage/model/edge_map.hpp"
#include "storage/model/edge_map.hpp"
class VertexModel : public PropertyModel
{
public:
EdgeList out;
EdgeList in;
EdgeMap in;
LabelCollection labels;
};

View File

@ -1,20 +1,18 @@
#pragma once
#include "transactions/transaction.hpp"
#include "mvcc/version_list.hpp"
#include "storage/model/properties/property.hpp"
#include "storage/model/properties/properties.hpp"
#include "storage/model/properties/property.hpp"
#include "transactions/transaction.hpp"
template <class T, class Store, class Derived>
template <class T, class Store, class Derived,
class vlist_t = mvcc::VersionList<T>>
class RecordAccessor
{
protected:
using vlist_t = mvcc::VersionList<T>;
public:
RecordAccessor() = default;
RecordAccessor(T* record, vlist_t* vlist, Store* store)
RecordAccessor(T *record, vlist_t *vlist, Store *store)
: record(record), vlist(vlist), store(store)
{
assert(record != nullptr);
@ -22,59 +20,50 @@ public:
assert(store != nullptr);
}
bool empty() const
{
return record == nullptr;
}
bool empty() const { return record == nullptr; }
const Id& id() const
const Id &id() const
{
assert(!empty());
return vlist->id;
}
Derived update(tx::Transaction& t) const
Derived update(tx::Transaction &t) const
{
assert(!empty());
return Derived(vlist->update(t), vlist, store);
}
bool remove(tx::Transaction& t) const
bool remove(tx::Transaction &t) const
{
assert(!empty());
return vlist->remove(record, t);
}
const Property& property(const std::string& key) const
const Property &property(const std::string &key) const
{
return record->data.props.at(key);
}
template <class V, class... Args>
void property(const std::string& key, Args&&... args)
void property(const std::string &key, Args &&... args)
{
record->data.props.template set<V>(key, std::forward<Args>(args)...);
}
void property(const std::string& key, Property::sptr value)
void property(const std::string &key, Property::sptr value)
{
record->data.props.set(key, std::move(value));
}
Properties& properties() const
{
return record->data.props;
}
Properties &properties() const { return record->data.props; }
explicit operator bool() const
{
return record != nullptr;
}
explicit operator bool() const { return record != nullptr; }
// protected:
T* const record {nullptr};
vlist_t* const vlist {nullptr};
Store* const store {nullptr};
// protected:
T *const record{nullptr};
vlist_t *const vlist{nullptr};
Store *const store{nullptr};
};