dressipi usecase hardcoded
This commit is contained in:
parent
266d8ed055
commit
c67742e3fa
3
build/.gitignore
vendored
3
build/.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
*
|
||||
/*
|
||||
!.gitignore
|
||||
!/compiled
|
||||
|
3
build/compiled/.gitignore
vendored
Normal file
3
build/compiled/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/*
|
||||
!.gitignore
|
||||
!/cpu
|
3
build/compiled/cpu/.gitignore
vendored
Normal file
3
build/compiled/cpu/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/*
|
||||
!.gitignore
|
||||
!/hardcode
|
149
build/compiled/cpu/hardcode/9470552549410791677.cpp
Normal file
149
build/compiled/cpu/hardcode/9470552549410791677.cpp
Normal 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; }
|
@ -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();
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -16,5 +16,6 @@ enum class ClauseAction : uint32_t
|
||||
ReturnNode,
|
||||
ReturnRelationship,
|
||||
ReturnPack,
|
||||
ReturnProjection
|
||||
ReturnProjection,
|
||||
ReturnCount
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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: {}";
|
||||
|
@ -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
9
include/utils/align.hpp
Normal 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
20
include/utils/file.hpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
@ -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) {
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -19,3 +19,4 @@
|
||||
#include "set.hpp"
|
||||
#include "expr.hpp"
|
||||
#include "with.hpp"
|
||||
#include "functions.hpp"
|
||||
|
@ -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>
|
||||
{
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
14
src/cypher/ast/functions.hpp
Normal file
14
src/cypher/ast/functions.hpp
Normal 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)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
@ -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). {
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user