228 lines
6.5 KiB
C++
Executable File
228 lines
6.5 KiB
C++
Executable File
/*=============================================================================
|
|
# Filename: QueryCache.cpp
|
|
# Author: Hao, Cui
|
|
# Mail: prospace@bupt.edu.cn
|
|
# Last Modified: 2017-06-01
|
|
# Description: implement functions in QueryCache.h
|
|
=============================================================================*/
|
|
|
|
#include"QueryCache.h"
|
|
|
|
using namespace std;
|
|
|
|
bool QueryCache::getMinimalRepresentation(const Patterns &triple_pattern, Patterns &minimal_repre, map<string, string> &minimal_mapping)
|
|
{
|
|
if ((int)triple_pattern.size() > TRIPLE_NUM_LIMIT) return false;
|
|
|
|
set<string> varset;
|
|
for (int i = 0; i < (int)triple_pattern.size(); i++)
|
|
{
|
|
if (triple_pattern[i].subject.value[0] == '?') varset.insert(triple_pattern[i].subject.value);
|
|
if (triple_pattern[i].predicate.value[0] == '?') varset.insert(triple_pattern[i].predicate.value);
|
|
if (triple_pattern[i].object.value[0] == '?') varset.insert(triple_pattern[i].object.value);
|
|
}
|
|
|
|
int var_count = varset.size();
|
|
if (var_count > VAR_NUM_LIMIT) return false;
|
|
|
|
string permutation;
|
|
int n_permutation = 1;
|
|
for (int i = 0; i < var_count; i++)
|
|
{
|
|
permutation.push_back(char('a' + i));
|
|
n_permutation *= (i + 1);
|
|
}
|
|
|
|
vector<QueryTree::GroupPattern::Pattern> temp_repre;
|
|
map<string, string> temp_mapping;
|
|
|
|
for (int i = 0; i < n_permutation; i++)
|
|
{
|
|
temp_repre = triple_pattern;
|
|
temp_mapping.clear();
|
|
|
|
for (int j = 0; j < (int)temp_repre.size(); j++)
|
|
{
|
|
string &subject = temp_repre[j].subject.value;
|
|
string &predicate = temp_repre[j].predicate.value;
|
|
string &object = temp_repre[j].object.value;
|
|
|
|
if (subject[0] == '?')
|
|
{
|
|
if (temp_mapping.count(subject) == 0)
|
|
temp_mapping[subject] = "?" + permutation.substr((int)temp_mapping.size(), 1);
|
|
|
|
subject = temp_mapping[subject];
|
|
}
|
|
if (predicate[0] == '?')
|
|
{
|
|
if (temp_mapping.count(predicate) == 0)
|
|
temp_mapping[predicate] = "?" + permutation.substr((int)temp_mapping.size(), 1);
|
|
|
|
predicate = temp_mapping[predicate];
|
|
}
|
|
if (object[0] == '?')
|
|
{
|
|
if (temp_mapping.count(object) == 0)
|
|
temp_mapping[object] = "?" + permutation.substr((int)temp_mapping.size(), 1);
|
|
|
|
object = temp_mapping[object];
|
|
}
|
|
}
|
|
|
|
sort(temp_repre.begin(), temp_repre.end());
|
|
|
|
if (i == 0)
|
|
{
|
|
minimal_repre = temp_repre;
|
|
minimal_mapping = temp_mapping;
|
|
}
|
|
else if (temp_repre < minimal_repre)
|
|
{
|
|
minimal_repre = temp_repre;
|
|
minimal_mapping = temp_mapping;
|
|
}
|
|
|
|
next_permutation(permutation.begin(), permutation.end());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool QueryCache::tryCaching(const Patterns &triple_pattern, const TempResult &temp_result, int eva_time)
|
|
{
|
|
Patterns minimal_repre;
|
|
map<string, string> minimal_mapping;
|
|
|
|
if (!this->getMinimalRepresentation(triple_pattern, minimal_repre, minimal_mapping))
|
|
return false;
|
|
|
|
if (eva_time < MINIMAL_EVA_TIME_LIMIT) return false;
|
|
|
|
long long temp_result_memory_used = (long long)temp_result.id_varset.getVarsetSize() * (long long)temp_result.result.size();
|
|
if (temp_result_memory_used > ITEM_MEMORY_LIMIT) return false;
|
|
|
|
while (temp_result_memory_used + total_memory_used > TOTAL_MEMORY_LIMIT)
|
|
{
|
|
LRUStruct x = lru.top();
|
|
lru.pop();
|
|
|
|
pair<vector<unsigned>, int> &cached_element = cache[x.second.first][x.second.second];
|
|
if (x.first != cached_element.second)
|
|
{
|
|
x.first = cached_element.second;
|
|
lru.push(x);
|
|
}
|
|
else
|
|
{
|
|
total_memory_used -= (long long)cached_element.first.size();
|
|
|
|
cache[x.second.first].erase(x.second.second);
|
|
if (cache[x.second.first].empty())
|
|
cache.erase(x.second.first);
|
|
}
|
|
}
|
|
|
|
int varnum = temp_result.id_varset.getVarsetSize();
|
|
|
|
Varset unordered_varset;
|
|
for (int i = 0; i < varnum; i++)
|
|
unordered_varset.addVar(minimal_mapping[temp_result.id_varset.vars[i]]);
|
|
|
|
Varset ordered_varset = unordered_varset;
|
|
sort(ordered_varset.vars.begin(), ordered_varset.vars.end());
|
|
|
|
vector<int> unordered2ordered = unordered_varset.mapTo(ordered_varset);
|
|
|
|
if (cache.count(minimal_repre) == 0)
|
|
{
|
|
cache[minimal_repre] = map<vector<string>, pair<vector<unsigned>, int> >();
|
|
}
|
|
|
|
if (cache[minimal_repre].count(ordered_varset.vars) == 0)
|
|
{
|
|
cache[minimal_repre][ordered_varset.vars] = pair<vector<unsigned>, int>();
|
|
}
|
|
|
|
vector<unsigned> &cache_result = cache[minimal_repre][ordered_varset.vars].first;
|
|
|
|
cache_result.resize(varnum * (int)temp_result.result.size());
|
|
|
|
for (int i = 0; i < (int)temp_result.result.size(); i++)
|
|
for (int j = 0; j < varnum; j++)
|
|
cache_result[i * varnum + unordered2ordered[j]] = temp_result.result[i].id[j];
|
|
|
|
cache[minimal_repre][ordered_varset.vars].second = ++time_now;
|
|
lru.push(make_pair(time_now, make_pair(minimal_repre, ordered_varset.vars)));
|
|
total_memory_used += temp_result_memory_used;
|
|
|
|
if (time_now >= (int)1e9)
|
|
{
|
|
time_now = 0;
|
|
|
|
for (map<Patterns, map<vector<string>, pair<vector<unsigned>, int> > >::iterator i = cache.begin(); i != cache.end(); i++)
|
|
for (map<vector<string>, pair<vector<unsigned>, int> >::iterator j = i->second.begin(); j != i->second.end(); j++)
|
|
j->second.second = time_now;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool QueryCache::checkCached(const Patterns &triple_pattern, const Varset &varset, TempResult &temp_result)
|
|
{
|
|
Patterns minimal_repre;
|
|
map<string, string> minimal_mapping;
|
|
|
|
if (!this->getMinimalRepresentation(triple_pattern, minimal_repre, minimal_mapping))
|
|
return false;
|
|
|
|
int varnum = varset.getVarsetSize();
|
|
|
|
Varset unordered_varset;
|
|
for (int i = 0; i < varnum; i++)
|
|
unordered_varset.addVar(minimal_mapping[varset.vars[i]]);
|
|
|
|
Varset ordered_varset = unordered_varset;
|
|
sort(ordered_varset.vars.begin(), ordered_varset.vars.end());
|
|
|
|
vector<int> unordered2ordered = unordered_varset.mapTo(ordered_varset);
|
|
|
|
if (cache.count(minimal_repre) != 0)
|
|
{
|
|
if (cache[minimal_repre].count(ordered_varset.vars) != 0)
|
|
{
|
|
vector<unsigned> &cache_result = cache[minimal_repre][ordered_varset.vars].first;
|
|
|
|
temp_result.id_varset = varset;
|
|
|
|
temp_result.result.resize((int)cache_result.size() / varnum);
|
|
for (int i = 0; i < (int)temp_result.result.size(); i++)
|
|
{
|
|
unsigned *v = new unsigned [varnum];
|
|
|
|
for (int j = 0; j < varnum; j++)
|
|
v[j] = cache_result[i * varnum + unordered2ordered[j]];
|
|
|
|
temp_result.result[i].id = v;
|
|
}
|
|
|
|
time_now = min(time_now + 1, (int)1e9);
|
|
cache[minimal_repre][ordered_varset.vars].second = time_now;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void QueryCache::clear()
|
|
{
|
|
time_now = 0;
|
|
total_memory_used = 0;
|
|
|
|
cache.clear();
|
|
while (!lru.empty())
|
|
lru.pop();
|
|
}
|