mirror of
https://github.com/matrix-construct/construct
synced 2025-03-13 21:10:32 +01:00
ircd:Ⓜ️:state: Optimize DFS branches recursed based on key argument prefix.
This commit is contained in:
parent
025e1d7c78
commit
49027cc312
2 changed files with 81 additions and 33 deletions
|
@ -44,7 +44,9 @@ namespace ircd::m::state
|
|||
using iter_bool_closure = std::function<bool (const json::array &, const string_view &)>;
|
||||
|
||||
int keycmp(const json::array &a, const json::array &b);
|
||||
bool prefix_eq(const json::array &a, const json::array &b);
|
||||
json::array make_key(const mutable_buffer &out, const string_view &type, const string_view &state_key);
|
||||
json::array make_key(const mutable_buffer &out, const string_view &type);
|
||||
|
||||
string_view set_node(db::txn &txn, const mutable_buffer &id, const json::object &node);
|
||||
void get_node(const string_view &id, const node_closure &);
|
||||
|
@ -56,7 +58,9 @@ namespace ircd::m::state
|
|||
string_view insert(db::txn &, const mutable_buffer &head, const id::room &, const string_view &type, const string_view &state_key, const id::event &);
|
||||
string_view insert(db::txn &, const mutable_buffer &head, const event &);
|
||||
|
||||
bool dfs(const string_view &head, const json::array &key, const search_closure &);
|
||||
bool dfs(const string_view &head, const search_closure &);
|
||||
|
||||
bool each(const string_view &head, const iter_bool_closure &);
|
||||
bool each(const string_view &head, const string_view &type, const iter_bool_closure &);
|
||||
size_t count(const string_view &head, const iter_bool_closure &);
|
||||
|
|
110
ircd/m/state.cc
110
ircd/m/state.cc
|
@ -112,27 +112,25 @@ ircd::m::state::count(const string_view &head,
|
|||
return ret;
|
||||
}
|
||||
|
||||
///TODO: optimize
|
||||
bool
|
||||
ircd::m::state::each(const string_view &head,
|
||||
const iter_bool_closure &closure)
|
||||
{
|
||||
return each(head, string_view{}, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::state::each(const string_view &head,
|
||||
const string_view &type,
|
||||
const iter_bool_closure &closure)
|
||||
{
|
||||
return each(head, [&type, &closure]
|
||||
(const json::array &key, const string_view &val)
|
||||
char buf[KEY_MAX_SZ];
|
||||
const json::array key
|
||||
{
|
||||
if(unquote(key.at(0)) != type)
|
||||
return true;
|
||||
make_key(buf, type)
|
||||
};
|
||||
|
||||
return closure(key, val);
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::state::each(const string_view &head,
|
||||
const iter_bool_closure &closure)
|
||||
{
|
||||
return dfs(head, [&closure]
|
||||
return dfs(head, key, [&closure]
|
||||
(const json::array &key, const string_view &val, const uint &, const uint &)
|
||||
{
|
||||
return closure(key, val);
|
||||
|
@ -141,19 +139,27 @@ ircd::m::state::each(const string_view &head,
|
|||
|
||||
namespace ircd::m::state
|
||||
{
|
||||
bool _dfs_recurse(const search_closure &, const node &, int &);
|
||||
bool _dfs_recurse(const search_closure &, const node &, const json::array &key, int &);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::state::dfs(const string_view &head,
|
||||
const search_closure &closure)
|
||||
{
|
||||
return dfs(head, json::array{}, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::state::dfs(const string_view &head,
|
||||
const json::array &key,
|
||||
const search_closure &closure)
|
||||
{
|
||||
bool ret{true};
|
||||
get_node(head, [&closure, &ret]
|
||||
get_node(head, [&closure, &key, &ret]
|
||||
(const auto &node)
|
||||
{
|
||||
int depth(-1);
|
||||
ret = _dfs_recurse(closure, node, depth);
|
||||
ret = _dfs_recurse(closure, node, key, depth);
|
||||
});
|
||||
|
||||
return ret;
|
||||
|
@ -162,6 +168,7 @@ ircd::m::state::dfs(const string_view &head,
|
|||
bool
|
||||
ircd::m::state::_dfs_recurse(const search_closure &closure,
|
||||
const node &node,
|
||||
const json::array &key,
|
||||
int &depth)
|
||||
{
|
||||
++depth;
|
||||
|
@ -171,33 +178,30 @@ ircd::m::state::_dfs_recurse(const search_closure &closure,
|
|||
}};
|
||||
|
||||
const node::rep rep{node};
|
||||
for(uint pos(0); pos < rep.kn || pos < rep.cn; ++pos)
|
||||
const auto kpos{rep.find(key)};
|
||||
for(uint pos(kpos); pos < rep.kn || pos < rep.cn; ++pos)
|
||||
{
|
||||
const auto child
|
||||
{
|
||||
unquote(rep.chld[pos])
|
||||
};
|
||||
|
||||
if(!empty(child))
|
||||
if(!empty(rep.chld[pos]))
|
||||
{
|
||||
bool ret{true};
|
||||
get_node(child, [&closure, &depth, &ret]
|
||||
get_node(rep.chld[pos], [&closure, &key, &depth, &ret]
|
||||
(const auto &node)
|
||||
{
|
||||
ret = _dfs_recurse(closure, node, depth);
|
||||
ret = _dfs_recurse(closure, node, key, depth);
|
||||
});
|
||||
|
||||
if(!ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(rep.kn > pos)
|
||||
{
|
||||
const auto &key{rep.keys[pos]};
|
||||
const auto &val{unquote(rep.vals[pos])};
|
||||
if(!closure(key, val, depth, pos))
|
||||
return false;
|
||||
}
|
||||
if(rep.kn <= pos)
|
||||
continue;
|
||||
|
||||
if(!empty(key) && !prefix_eq(key, rep.keys[pos]))
|
||||
break;
|
||||
|
||||
if(!closure(rep.keys[pos], rep.vals[pos], depth, pos))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -629,6 +633,46 @@ ircd::m::state::make_key(const mutable_buffer &out,
|
|||
return { data(out), json::print(out, key) };
|
||||
}
|
||||
|
||||
ircd::json::array
|
||||
ircd::m::state::make_key(const mutable_buffer &out,
|
||||
const string_view &type)
|
||||
{
|
||||
const json::value key_parts[]
|
||||
{
|
||||
type
|
||||
};
|
||||
|
||||
const json::value key
|
||||
{
|
||||
key_parts, 1
|
||||
};
|
||||
|
||||
return { data(out), json::print(out, key) };
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::state::prefix_eq(const json::array &a,
|
||||
const json::array &b)
|
||||
{
|
||||
ushort i(0);
|
||||
auto ait(begin(a));
|
||||
auto bit(begin(b));
|
||||
for(; ait != end(a) && bit != end(b) && i < 2; ++ait, ++bit)
|
||||
{
|
||||
assert(surrounds(*ait, '"'));
|
||||
assert(surrounds(*bit, '"'));
|
||||
|
||||
if(*ait == *bit)
|
||||
{
|
||||
if(i)
|
||||
return false;
|
||||
}
|
||||
else ++i;
|
||||
}
|
||||
|
||||
return ait != end(a) || bit != end(b)? i == 0 : i < 2;
|
||||
}
|
||||
|
||||
/// Compares two keys. Keys are arrays of strings which become safely
|
||||
/// concatenated for a linear lexical comparison. Returns -1 if a less
|
||||
/// than b; 0 if equal; 1 if a greater than b.
|
||||
|
|
Loading…
Add table
Reference in a new issue