mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Ensure table/set HashKey buffer reservation and writes happen in same order
This takes the existing sorting for table index hashkeys we had in place during hash key writes and applies it also during buffer size reservation. It changes the approach slightly: the underlying map now points to the TableVal entry index vals directly, rather than to the numerical index into an additional list that gets built up to store those indexes. Doing so removes the need for that list.
This commit is contained in:
parent
1260f6b585
commit
5fc8d89897
1 changed files with 45 additions and 35 deletions
|
@ -18,6 +18,42 @@
|
|||
namespace zeek::detail
|
||||
{
|
||||
|
||||
// A comparison callable to assist with consistent iteration order over tables
|
||||
// during reservation & writes.
|
||||
struct HashKeyComparer
|
||||
{
|
||||
bool operator()(const std::unique_ptr<HashKey>& a, const std::unique_ptr<HashKey>& b) const
|
||||
{
|
||||
if ( a->Hash() != b->Hash() )
|
||||
return a->Hash() < b->Hash();
|
||||
if ( a->Size() != b->Size() )
|
||||
return a->Size() < b->Size();
|
||||
return memcmp(a->Key(), b->Key(), a->Size()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
using HashkeyMap = std::map<std::unique_ptr<HashKey>, ListValPtr, HashKeyComparer>;
|
||||
using HashkeyMapPtr = std::unique_ptr<HashkeyMap>;
|
||||
|
||||
// Helper that produces a table from HashKeys to the ListVal indexes into the
|
||||
// table, that we can iterate over in sorted-Hashkey order.
|
||||
const HashkeyMapPtr ordered_hashkeys(const TableVal* tv)
|
||||
{
|
||||
auto res = std::make_unique<HashkeyMap>();
|
||||
auto tbl = tv->AsTable();
|
||||
auto idx = 0;
|
||||
|
||||
for ( const auto& entry : *tbl )
|
||||
{
|
||||
auto k = entry.GetHashKey();
|
||||
// Do we have to recreate here? Could we reuse the existing key?
|
||||
auto lv = tv->RecreateIndex(*k);
|
||||
res->insert_or_assign(std::move(k), lv);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
CompositeHash::CompositeHash(TypeListPtr composite_type) : type(std::move(composite_type))
|
||||
{
|
||||
singleton_tag = TYPE_INTERNAL_ERROR;
|
||||
|
@ -209,38 +245,11 @@ char* CompositeHash::SingleValHash(bool type_check, char* kp0, Type* bt, Val* v,
|
|||
*kp = tv->Size();
|
||||
kp1 = reinterpret_cast<char*>(kp + 1);
|
||||
|
||||
auto tbl = tv->AsTable();
|
||||
auto lv = make_intrusive<ListVal>(TYPE_ANY);
|
||||
auto hashkeys = ordered_hashkeys(tv);
|
||||
|
||||
struct HashKeyComparer
|
||||
for ( auto& kv : *hashkeys )
|
||||
{
|
||||
bool operator()(const std::unique_ptr<HashKey>& a,
|
||||
const std::unique_ptr<HashKey>& b) const
|
||||
{
|
||||
if ( a->Hash() != b->Hash() )
|
||||
return a->Hash() < b->Hash();
|
||||
if ( a->Size() != b->Size() )
|
||||
return a->Size() < b->Size();
|
||||
return strncmp(static_cast<const char*>(a->Key()),
|
||||
static_cast<const char*>(b->Key()),
|
||||
a->Size()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
std::map<std::unique_ptr<HashKey>, int, HashKeyComparer> hashkeys;
|
||||
auto idx = 0;
|
||||
|
||||
for ( const auto& entry : *tbl )
|
||||
{
|
||||
auto k = entry.GetHashKey();
|
||||
lv->Append(tv->RecreateIndex(*k));
|
||||
hashkeys[std::move(k)] = idx++;
|
||||
}
|
||||
|
||||
for ( auto& kv : hashkeys )
|
||||
{
|
||||
auto idx = kv.second;
|
||||
const auto& key = lv->Idx(idx);
|
||||
auto key = kv.second;
|
||||
|
||||
if ( ! (kp1 = SingleValHash(type_check, kp1, key->GetType().get(),
|
||||
key.get(), false)) )
|
||||
|
@ -541,11 +550,12 @@ int CompositeHash::SingleTypeKeySize(Type* bt, const Val* v, bool type_check, in
|
|||
return (optional && ! calc_static_size) ? sz : 0;
|
||||
|
||||
sz = SizeAlign(sz, sizeof(int));
|
||||
TableVal* tv = const_cast<TableVal*>(v->AsTableVal());
|
||||
auto lv = tv->ToListVal();
|
||||
for ( int i = 0; i < tv->Size(); ++i )
|
||||
auto tv = v->AsTableVal();
|
||||
auto hashkeys = ordered_hashkeys(tv);
|
||||
|
||||
for ( auto& kv : *hashkeys )
|
||||
{
|
||||
const auto& key = lv->Idx(i);
|
||||
auto key = kv.second;
|
||||
sz = SingleTypeKeySize(key->GetType().get(), key.get(), type_check,
|
||||
sz, false, calc_static_size);
|
||||
if ( ! sz )
|
||||
|
@ -553,7 +563,7 @@ int CompositeHash::SingleTypeKeySize(Type* bt, const Val* v, bool type_check, in
|
|||
|
||||
if ( ! bt->IsSet() )
|
||||
{
|
||||
auto val = tv->FindOrDefault(key);
|
||||
auto val = const_cast<TableVal*>(tv)->FindOrDefault(key);
|
||||
sz = SingleTypeKeySize(val->GetType().get(), val.get(),
|
||||
type_check, sz, false, calc_static_size);
|
||||
if ( ! sz )
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue