2016-02-07 03:48:40 +08:00
|
|
|
#pragma once
|
|
|
|
|
2016-06-06 17:29:52 +08:00
|
|
|
#include <memory>
|
2016-02-07 03:48:40 +08:00
|
|
|
#include <string>
|
|
|
|
#include <unordered_map>
|
|
|
|
|
2016-02-08 05:56:52 +08:00
|
|
|
#include "config/config.hpp"
|
2016-08-11 11:47:30 +08:00
|
|
|
#include "logging/default.hpp"
|
2016-11-02 23:05:02 +08:00
|
|
|
#include "query/backend/cpp_old/cypher.hpp"
|
|
|
|
#include "query/dynamic_lib.hpp"
|
|
|
|
#include "query/frontend/cypher.hpp"
|
|
|
|
#include "query/plan/compiler.hpp"
|
|
|
|
#include "query/plan/generator.hpp"
|
|
|
|
#include "query/plan/program.hpp"
|
|
|
|
#include "query/preprocesor.hpp"
|
2016-09-14 19:19:56 +08:00
|
|
|
#include "utils/file.hpp"
|
2016-11-02 23:05:02 +08:00
|
|
|
#include "utils/hashing/fnv.hpp"
|
2016-02-07 03:48:40 +08:00
|
|
|
|
2016-08-29 01:50:54 +08:00
|
|
|
template <typename Stream>
|
2016-02-22 05:21:15 +08:00
|
|
|
class ProgramLoader
|
2016-06-06 17:29:52 +08:00
|
|
|
{
|
2016-02-07 03:48:40 +08:00
|
|
|
public:
|
2016-08-29 01:50:54 +08:00
|
|
|
using code_lib_t = CodeLib<Stream>;
|
|
|
|
using sptr_code_lib = std::shared_ptr<code_lib_t>;
|
|
|
|
using query_program_t = QueryProgram<Stream>;
|
2016-02-07 03:48:40 +08:00
|
|
|
|
2016-11-02 23:05:02 +08:00
|
|
|
ProgramLoader() : logger(logging::log->logger("PlanLoader")) {}
|
2016-02-07 03:48:40 +08:00
|
|
|
|
2016-11-02 23:05:02 +08:00
|
|
|
auto load(const std::string &query)
|
2016-02-07 03:48:40 +08:00
|
|
|
{
|
2016-11-02 23:05:02 +08:00
|
|
|
auto preprocessed = preprocessor.preprocess(query);
|
|
|
|
logger.debug("stripped_query = {}", preprocessed.query);
|
|
|
|
logger.debug("query_hash = {}", std::to_string(preprocessed.hash));
|
2016-02-22 05:21:15 +08:00
|
|
|
|
2016-11-02 23:05:02 +08:00
|
|
|
auto code_lib_iter = code_libs.find(preprocessed.hash);
|
2016-02-08 05:56:52 +08:00
|
|
|
|
|
|
|
// code is already compiled and loaded, just return runnable
|
|
|
|
// instance
|
2016-02-22 05:21:15 +08:00
|
|
|
if (code_lib_iter != code_libs.end()) {
|
|
|
|
auto code = code_lib_iter->second->instance();
|
2016-11-02 23:05:02 +08:00
|
|
|
return query_program_t(code, std::move(preprocessed));
|
2016-02-22 05:21:15 +08:00
|
|
|
}
|
2016-02-08 05:56:52 +08:00
|
|
|
|
2016-09-05 08:35:52 +08:00
|
|
|
auto base_path = CONFIG(config::COMPILE_CPU_PATH);
|
2016-11-02 23:05:02 +08:00
|
|
|
auto hash_string = std::to_string(preprocessed.hash);
|
2016-02-08 05:56:52 +08:00
|
|
|
auto path_cpp = base_path + hash_string + ".cpp";
|
2016-09-14 19:19:56 +08:00
|
|
|
auto hard_code_cpp = base_path + "hardcode/" + hash_string + ".cpp";
|
2016-11-02 23:05:02 +08:00
|
|
|
auto stripped_space = preprocessor.strip_space(query);
|
2016-06-06 17:29:52 +08:00
|
|
|
|
2016-09-14 19:19:56 +08:00
|
|
|
// cpp files in the hardcode folder have bigger priority then
|
|
|
|
// other cpp files
|
2016-11-02 23:05:02 +08:00
|
|
|
if (!utils::fexists(hard_code_cpp)) {
|
|
|
|
plan_generator.generate_plan(stripped_space.query,
|
|
|
|
preprocessed.hash, path_cpp);
|
2016-09-14 19:19:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// compile the code
|
2016-02-08 05:56:52 +08:00
|
|
|
auto path_so = base_path + hash_string + ".so";
|
2016-09-14 19:19:56 +08:00
|
|
|
|
|
|
|
// hardcoded queries are compiled to the same folder as generated
|
|
|
|
// queries (all .so files are in the same folder)
|
2016-11-02 23:05:02 +08:00
|
|
|
if (utils::fexists(hard_code_cpp)) {
|
|
|
|
plan_compiler.compile(hard_code_cpp, path_so);
|
|
|
|
} else {
|
|
|
|
plan_compiler.compile(path_cpp, path_so);
|
2016-09-14 19:19:56 +08:00
|
|
|
}
|
2016-02-08 05:56:52 +08:00
|
|
|
|
|
|
|
// loads dynamic lib and store it
|
|
|
|
auto code_lib = load_code_lib(path_so);
|
2016-11-02 23:05:02 +08:00
|
|
|
code_libs.insert({{preprocessed.hash, code_lib}});
|
2016-02-07 03:48:40 +08:00
|
|
|
|
2016-07-18 01:32:35 +08:00
|
|
|
// return an instance of runnable code (ICodeCPU)
|
2016-11-02 23:05:02 +08:00
|
|
|
return query_program_t(code_lib->instance(), std::move(preprocessed));
|
2016-02-07 03:48:40 +08:00
|
|
|
}
|
|
|
|
|
2016-08-11 11:47:30 +08:00
|
|
|
protected:
|
|
|
|
Logger logger;
|
|
|
|
|
2016-02-07 03:48:40 +08:00
|
|
|
private:
|
|
|
|
// TODO ifdef MEMGRAPH64 problem, how to use this kind
|
|
|
|
// of ifdef functions?
|
|
|
|
// uint64_t depends on fnv function
|
2016-11-29 11:08:08 +08:00
|
|
|
// TODO: faster datastructure
|
2016-02-07 03:48:40 +08:00
|
|
|
std::unordered_map<uint64_t, sptr_code_lib> code_libs;
|
|
|
|
|
2016-11-02 23:05:02 +08:00
|
|
|
QueryPreprocessor preprocessor;
|
|
|
|
|
|
|
|
// TODO: compile time switch between frontends and backends
|
|
|
|
using frontend_t = cypher::Frontend;
|
|
|
|
using backend_t = CypherBackend<Stream>;
|
|
|
|
PlanGenerator<frontend_t, backend_t> plan_generator;
|
|
|
|
|
|
|
|
PlanCompiler plan_compiler;
|
2016-02-07 03:48:40 +08:00
|
|
|
|
2016-11-02 23:05:02 +08:00
|
|
|
sptr_code_lib load_code_lib(const std::string &path)
|
2016-02-07 03:48:40 +08:00
|
|
|
{
|
2016-08-29 01:50:54 +08:00
|
|
|
sptr_code_lib code_lib = std::make_shared<CodeLib<Stream>>(path);
|
2016-02-07 03:48:40 +08:00
|
|
|
code_lib->load();
|
|
|
|
return code_lib;
|
|
|
|
}
|
|
|
|
};
|