dressipi usecase hardcoded

This commit is contained in:
Marko Budiselic 2016-09-14 12:19:56 +01:00
parent 266d8ed055
commit c67742e3fa
23 changed files with 311 additions and 10 deletions

3
build/.gitignore vendored
View File

@ -1,2 +1,3 @@
*
/*
!.gitignore
!/compiled

3
build/compiled/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/*
!.gitignore
!/cpu

3
build/compiled/cpu/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/*
!.gitignore
!/hardcode

View File

@ -0,0 +1,149 @@
#include <iostream>
#include <queue>
#include <string>
#include <vector>
#include "query_engine/i_code_cpu.hpp"
#include "storage/model/properties/all.hpp"
using std::cout;
using std::endl;
// Dressipi astar query of 4 clicks.
// BARRIER!
namespace barrier
{
// using STREAM = std::ostream;
using STREAM = RecordStream<::io::Socket>;
constexpr size_t max_depth = 3;
constexpr size_t limit = 10;
class Node
{
public:
Node *parent = {nullptr};
VertexPropertyType<Double> tkey;
double cost;
int depth = {0};
VertexAccessor vacc;
Node(VertexAccessor vacc, double cost,
VertexPropertyType<Double> const &tkey)
: cost(cost), vacc(vacc), tkey(tkey)
{
}
Node(VertexAccessor vacc, double cost, Node *parent,
VertexPropertyType<Double> const &tkey)
: cost(cost), vacc(vacc), parent(parent), depth(parent->depth + 1),
tkey(tkey)
{
}
double sum_vertex_score()
{
auto now = this;
double sum = 0;
do {
sum += (now->vacc.at(tkey).get())->value();
now = now->parent;
} while (now != nullptr);
return sum;
}
};
bool vertex_filter_contained(DbAccessor &t, VertexAccessor &v, Node *before)
{
if (v.fill()) {
bool found;
do {
found = false;
before = before->parent;
if (before == nullptr) {
return true;
}
} while (v.in_contains(before->vacc));
}
return false;
}
void astar(DbAccessor &t, code_args_t &args, STREAM &stream)
{
VertexPropertyType<Double> tkey = t.vertex_property_key<Double>("score");
auto cmp = [](Node *left, Node *right) { return left->cost > right->cost; };
std::priority_queue<Node *, std::vector<Node *>, decltype(cmp)> queue(cmp);
std::vector<Node *> all_nodes;
auto start_vr = t.vertex_find(Id(args[0].as<Int64>().value()));
if (!start_vr.is_present()) {
stream.write_failure({{}});
return;
}
start_vr.get().fill();
Node *start = new Node(start_vr.take(), 0, tkey);
queue.push(start);
all_nodes.push_back(start);
int count = 0;
do {
auto now = queue.top();
queue.pop();
if (max_depth <= now->depth) {
// best.push_back(now);
count++;
if (count >= limit) {
break;
}
continue;
}
iter::for_all(now->vacc.out(), [&](auto edge) {
VertexAccessor va = edge.to();
if (vertex_filter_contained(t, va, now)) {
auto cost = 1 - va.at(tkey).get()->value();
Node *n = new Node(va, now->cost + cost, now, tkey);
queue.push(n);
all_nodes.push_back(n);
}
});
} while (!queue.empty());
stream.write_field("n");
stream.write_record();
stream.write_list_header(0);
stream.chunk();
stream.write_meta("r");
for (auto n : all_nodes) {
delete n;
}
}
class CodeCPU : public ICodeCPU<STREAM>
{
public:
bool run(Db &db, code_args_t &args, STREAM &stream) override
{
DbAccessor t(db);
astar(t, args, stream);
return t.commit();
}
~CodeCPU() {}
};
}
extern "C" ICodeCPU<barrier::STREAM> *produce()
{
// BARRIER!
return new barrier::CodeCPU();
}
extern "C" void destruct(ICodeCPU<barrier::STREAM> *p) { delete p; }

View File

@ -493,6 +493,7 @@ public:
void write_list_header(size_t size);
void write_record();
void write_meta(const std::string &type);
void write_failure(const std::map<std::string, std::string> &data);
void send();
void chunk();
};

View File

@ -4,6 +4,7 @@
#include <type_traits>
#include <utility>
#include <vector>
#include <map>
// THis shoul be the only place to include code from memgraph other than
// barrier.cpp

View File

@ -16,5 +16,6 @@ enum class ClauseAction : uint32_t
ReturnNode,
ReturnRelationship,
ReturnPack,
ReturnProjection
ReturnProjection,
ReturnCount
};

View File

@ -69,5 +69,18 @@ auto return_query_action =
}
}
// return functions
for (auto const &kv : action_data.actions)
{
auto name = kv.first;
if (kv.second == ClauseAction::ReturnCount)
{
if (cypher_data.source(name) == EntitySource::MainStorage)
{
code += code_line(code::count, name);
}
}
}
return code;
};

View File

@ -12,6 +12,7 @@
#include "query_engine/query_stripper.hpp"
#include "utils/hashing/fnv.hpp"
#include "logging/default.hpp"
#include "utils/file.hpp"
using std::string;
@ -46,16 +47,32 @@ public:
return query_program_t(code, std::move(stripped));
}
// code has to be generated, compiled and loaded
// TODO load output path from config
auto base_path = CONFIG(config::COMPILE_CPU_PATH);
auto path_cpp = base_path + hash_string + ".cpp";
auto hard_code_cpp = base_path + "hardcode/" + hash_string + ".cpp";
auto stripped_space = stripper.strip_space(query);
code_generator.generate_cpp(stripped_space.query, stripped.hash,
path_cpp);
// cpp files in the hardcode folder have bigger priority then
// other cpp files
if (!utils::fexists(hard_code_cpp))
{
code_generator.generate_cpp(stripped_space.query, stripped.hash,
path_cpp);
}
// compile the code
auto path_so = base_path + hash_string + ".so";
code_compiler.compile(path_cpp, path_so);
// hardcoded queries are compiled to the same folder as generated
// queries (all .so files are in the same folder)
if (utils::fexists(hard_code_cpp))
{
code_compiler.compile(hard_code_cpp, path_so);
}
else
{
code_compiler.compile(path_cpp, path_so);
}
// loads dynamic lib and store it
auto code_lib = load_code_lib(path_so);

View File

@ -105,6 +105,18 @@ const std::string find_and_write_edges_by_type =
" }});\n"
" stream.write_meta(\"rw\");\n";
// TODO: vertices and edges
const std::string count =
"size_t count = 0;\n"
" t.vertex_access().fill().for_all(\n"
" [&](auto vertex) {{ ++count; }});\n"
" stream.write_field(\"count({0})\");\n"
" stream.write_record();\n"
" stream.write_list_header(1);\n"
" stream.write(Int64(count));\n"
" stream.chunk();\n"
" stream.write_meta(\"r\");\n";
const std::string return_true = "return true;";
const std::string todo = "// TODO: {}";

View File

@ -519,4 +519,15 @@ public:
code += generator.generate();
}
void visit(ast::CountFunction& ast_count) override
{
auto &action_data = generator.action_data();
auto &cypher_data = generator.cypher_data();
if (state == CypherState::Return)
{
action_data.actions[ast_count.argument] = ClauseAction::ReturnCount;
}
}
};

9
include/utils/align.hpp Normal file
View File

@ -0,0 +1,9 @@
#pragma once
// FROM: A Malloc Tutorial, Marwan Burelle, 2009
// align address x to 4 bytes
#define align_4(x) (((((x) - 1)>>2)<<2)+4)
// align address x to 8 bytes
#define align_8(x) (((((x) - 1)>>3)<<3)+8)

20
include/utils/file.hpp Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <fstream>
namespace utils
{
inline bool fexists(const char *filename)
{
std::ifstream ifile(filename);
return (bool)ifile;
}
inline bool fexists(const std::string& filename)
{
std::ifstream ifile(filename.c_str());
return (bool)ifile;
}
}

View File

@ -15,7 +15,8 @@ using std::endl;
namespace barrier
{
using STREAM = std::ostream; // RecordStream<::io::Socket>;
// using STREAM = std::ostream;
using STREAM = RecordStream<::io::Socket>;
constexpr size_t max_depth = 3;
constexpr size_t limit = 10;
@ -78,7 +79,7 @@ void astar(DbAccessor &t, code_args_t &args, STREAM &stream)
auto start_vr = t.vertex_find(Id(args[0].as<Int64>().value()));
if (!start_vr.is_present()) {
// stream.write_failure({{}});
stream.write_failure({{}});
return;
}
@ -93,7 +94,7 @@ void astar(DbAccessor &t, code_args_t &args, STREAM &stream)
queue.pop();
if (max_depth <= now->depth) {
// stream.write_success_empty();
stream.write_success_empty();
// best.push_back(now);
count++;
if (count >= limit) {

View File

@ -674,6 +674,12 @@ void RecordStream<Stream>::write_meta(const std::string &type)
HALF_CALL(write_meta(type));
}
template <class Stream>
void RecordStream<Stream>::write_failure(const std::map<std::string, std::string> &data)
{
HALF_CALL(write_failure(data));
}
template <class Stream>
void RecordStream<Stream>::send()
{

View File

@ -19,3 +19,4 @@
#include "set.hpp"
#include "expr.hpp"
#include "with.hpp"
#include "functions.hpp"

View File

@ -36,6 +36,9 @@ struct Star;
struct Slash;
struct Rem;
// functions
struct CountFunction;
struct RelationshipSpecs;
struct RelationshipTypeList;
struct Relationship;
@ -83,6 +86,7 @@ struct AstVisitor
PatternList, Match, ReadQuery, Start, Where, WriteQuery, Create,
Return, Distinct, Delete, DeleteQuery, UpdateQuery, Set, SetKey,
ReadWriteQuery, IdentifierList, WithList, WithClause, WithQuery, Long,
CountFunction,
InternalIdExpr, SetValue, SetElement, SetList>
{
};

View File

@ -24,6 +24,16 @@ struct LeafExpr : public ValueExpr<Derived>
T value;
};
// T is argument type
template <class T, class Derived>
struct FunctionExpr : public ValueExpr<Derived>
{
FunctionExpr(const std::string& name, T argument) : name(name), argument(argument) {}
std::string name;
T argument;
};
template <class Derived>
struct BinaryExpr : public ValueExpr<Derived>
{
@ -43,4 +53,5 @@ struct PatternExpr : public Expr
Pattern *pattern;
};
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "expr.hpp"
namespace ast
{
struct CountFunction : public FunctionExpr<std::string, CountFunction>
{
CountFunction(const std::string &argument) : FunctionExpr("count", argument)
{
}
};
}

View File

@ -495,6 +495,12 @@ pattern_expr(E) ::= pattern(P). {
E = ast->create<ast::PatternExpr>(P);
}
%type function_expr {ast::Expr*}
function_expr(E) ::= COUNT LP IDN(A) RP. {
E = ast->create<ast::CountFunction>(A->value);
}
%type expr {ast::Expr*}
expr(E) ::= value_expr(V). {
@ -505,6 +511,10 @@ expr(E) ::= pattern_expr(P). {
E = P;
}
expr(E) ::= function_expr(F). {
E = F;
}
//%type alias {ast::Alias*}
//
//alias(A) ::= IDN(X) AS IDN(Y). {

View File

@ -294,6 +294,12 @@ public:
Traverser::visit(rem);
}
void visit(ast::CountFunction& count) override
{
auto entry = printer.advance("Count ");
entry << count.name << "(" << count.argument << ")";
}
void visit(ast::PropertyList& prop_list) override
{
auto entry = printer.advance("Property List");

View File

@ -58,6 +58,9 @@ public:
rule("(?i:AND)", TK_AND);
rule("(?i:OR)", TK_OR);
// functions
rule("(?i:COUNT)", TK_COUNT);
// string literal TODO single quote escape
rule("'(.*?)'", TK_STR);

View File

@ -154,6 +154,10 @@ public:
accept(rem.right);
}
void visit(ast::CountFunction& count) override
{
}
void visit(ast::PropertyList& prop_list) override
{
accept(prop_list.value);