Improve TableVal HashKey management

* Deprecated ComputeHash() methods and replaced with MakeHashKey()
  which returns std::unique_ptr<HashKey>

* Deprecated RecoverIndex() and replaced with RecreateIndex()
  which takes HashKey& and returns IntrusivePtr.

* Updated the new TableVal Assign()/Remove() methods to take either
  std::unique_ptr<HashKey> or HashKey& as appropriate for clarity of
  ownership expectations.
This commit is contained in:
Jon Siwek 2020-05-20 22:16:47 -07:00
parent 8a6a92c348
commit 3f92df51b7
18 changed files with 137 additions and 114 deletions

View file

@ -229,7 +229,7 @@ char* CompositeHash::SingleValHash(bool type_check, char* kp0,
while ( tbl->NextEntry(k, it) ) while ( tbl->NextEntry(k, it) )
{ {
hashkeys[k] = idx++; hashkeys[k] = idx++;
lv->Append(tv->RecoverIndex(k)); lv->Append(tv->RecreateIndex(*k));
} }
for ( auto& kv : hashkeys ) for ( auto& kv : hashkeys )
@ -333,7 +333,7 @@ char* CompositeHash::SingleValHash(bool type_check, char* kp0,
} }
HashKey* CompositeHash::ComputeHash(const Val& argv, bool type_check) const std::unique_ptr<HashKey> CompositeHash::MakeHashKey(const Val& argv, bool type_check) const
{ {
auto v = &argv; auto v = &argv;
@ -349,8 +349,7 @@ HashKey* CompositeHash::ComputeHash(const Val& argv, bool type_check) const
// be okay; the only thing is that the ListVal unref's it. // be okay; the only thing is that the ListVal unref's it.
Val* ncv = (Val*) v; Val* ncv = (Val*) v;
lv.Append({NewRef{}, ncv}); lv.Append({NewRef{}, ncv});
HashKey* hk = ComputeHash(lv, type_check); return MakeHashKey(lv, type_check);
return hk;
} }
char* k = key; char* k = key;
@ -383,10 +382,10 @@ HashKey* CompositeHash::ComputeHash(const Val& argv, bool type_check) const
return nullptr; return nullptr;
} }
return new HashKey((k == key), (void*) k, kp - k); return std::make_unique<HashKey>((k == key), (void*) k, kp - k);
} }
HashKey* CompositeHash::ComputeSingletonHash(const Val* v, bool type_check) const std::unique_ptr<HashKey> CompositeHash::ComputeSingletonHash(const Val* v, bool type_check) const
{ {
if ( v->GetType()->Tag() == TYPE_LIST ) if ( v->GetType()->Tag() == TYPE_LIST )
{ {
@ -404,21 +403,21 @@ HashKey* CompositeHash::ComputeSingletonHash(const Val* v, bool type_check) cons
switch ( singleton_tag ) { switch ( singleton_tag ) {
case TYPE_INTERNAL_INT: case TYPE_INTERNAL_INT:
case TYPE_INTERNAL_UNSIGNED: case TYPE_INTERNAL_UNSIGNED:
return new HashKey(v->ForceAsInt()); return std::make_unique<HashKey>(v->ForceAsInt());
case TYPE_INTERNAL_ADDR: case TYPE_INTERNAL_ADDR:
return v->AsAddr().GetHashKey(); return v->AsAddr().MakeHashKey();
case TYPE_INTERNAL_SUBNET: case TYPE_INTERNAL_SUBNET:
return v->AsSubNet().GetHashKey(); return v->AsSubNet().MakeHashKey();
case TYPE_INTERNAL_DOUBLE: case TYPE_INTERNAL_DOUBLE:
return new HashKey(v->InternalDouble()); return std::make_unique<HashKey>(v->InternalDouble());
case TYPE_INTERNAL_VOID: case TYPE_INTERNAL_VOID:
case TYPE_INTERNAL_OTHER: case TYPE_INTERNAL_OTHER:
if ( v->GetType()->Tag() == TYPE_FUNC ) if ( v->GetType()->Tag() == TYPE_FUNC )
return new HashKey(v->AsFunc()->GetUniqueFuncID()); return std::make_unique<HashKey>(v->AsFunc()->GetUniqueFuncID());
if ( v->GetType()->Tag() == TYPE_PATTERN ) if ( v->GetType()->Tag() == TYPE_PATTERN )
{ {
@ -430,14 +429,14 @@ HashKey* CompositeHash::ComputeSingletonHash(const Val* v, bool type_check) cons
char* key = new char[n]; char* key = new char[n];
std::memcpy(key, texts[0], strlen(texts[0]) + 1); std::memcpy(key, texts[0], strlen(texts[0]) + 1);
std::memcpy(key + strlen(texts[0]) + 1, texts[1], strlen(texts[1]) + 1); std::memcpy(key + strlen(texts[0]) + 1, texts[1], strlen(texts[1]) + 1);
return new HashKey(false, key, n); return std::make_unique<HashKey>(false, key, n);
} }
reporter->InternalError("bad index type in CompositeHash::ComputeSingletonHash"); reporter->InternalError("bad index type in CompositeHash::ComputeSingletonHash");
return nullptr; return nullptr;
case TYPE_INTERNAL_STRING: case TYPE_INTERNAL_STRING:
return new HashKey(v->AsString()); return std::make_unique<HashKey>(v->AsString());
case TYPE_INTERNAL_ERROR: case TYPE_INTERNAL_ERROR:
return nullptr; return nullptr;
@ -707,12 +706,12 @@ int CompositeHash::SizeAlign(int offset, unsigned int size) const
return offset; return offset;
} }
IntrusivePtr<ListVal> CompositeHash::RecoverVals(const HashKey* k) const IntrusivePtr<ListVal> CompositeHash::RecoverVals(const HashKey& k) const
{ {
auto l = make_intrusive<ListVal>(TYPE_ANY); auto l = make_intrusive<ListVal>(TYPE_ANY);
const auto& tl = type->Types(); const auto& tl = type->Types();
const char* kp = (const char*) k->Key(); const char* kp = (const char*) k.Key();
const char* const k_end = kp + k->Size(); const char* const k_end = kp + k.Size();
for ( const auto& type : tl ) for ( const auto& type : tl )
{ {
@ -728,12 +727,12 @@ IntrusivePtr<ListVal> CompositeHash::RecoverVals(const HashKey* k) const
return l; return l;
} }
const char* CompositeHash::RecoverOneVal(const HashKey* k, const char* kp0, const char* CompositeHash::RecoverOneVal(const HashKey& k, const char* kp0,
const char* const k_end, BroType* t, const char* const k_end, BroType* t,
IntrusivePtr<Val>* pval, bool optional) const IntrusivePtr<Val>* pval, bool optional) const
{ {
// k->Size() == 0 for a single empty string. // k->Size() == 0 for a single empty string.
if ( kp0 >= k_end && k->Size() > 0 ) if ( kp0 >= k_end && k.Size() > 0 )
reporter->InternalError("over-ran key in CompositeHash::RecoverVals"); reporter->InternalError("over-ran key in CompositeHash::RecoverVals");
TypeTag tag = t->Tag(); TypeTag tag = t->Tag();
@ -874,7 +873,7 @@ const char* CompositeHash::RecoverOneVal(const HashKey* k, const char* kp0,
kp1 = kp0; kp1 = kp0;
int divider = strlen(kp0) + 1; int divider = strlen(kp0) + 1;
re = new RE_Matcher(kp1, kp1 + divider); re = new RE_Matcher(kp1, kp1 + divider);
kp1 += k->Size(); kp1 += k.Size();
} }
else else
{ {
@ -1033,7 +1032,7 @@ const char* CompositeHash::RecoverOneVal(const HashKey* k, const char* kp0,
if ( is_singleton ) if ( is_singleton )
{ {
kp1 = kp0; kp1 = kp0;
n = k->Size(); n = k.Size();
} }
else else
{ {

View file

@ -2,6 +2,8 @@
#pragma once #pragma once
#include <memory>
#include "Type.h" #include "Type.h"
#include "IntrusivePtr.h" #include "IntrusivePtr.h"
@ -15,19 +17,23 @@ public:
// Compute the hash corresponding to the given index val, // Compute the hash corresponding to the given index val,
// or nullptr if it fails to typecheck. // or nullptr if it fails to typecheck.
HashKey* ComputeHash(const Val& v, bool type_check) const; std::unique_ptr<HashKey> MakeHashKey(const Val& v, bool type_check) const;
[[deprecated("Remove in v4.1. Pass a Val& instead.")]] [[deprecated("Remove in v4.1. Use MakeHashKey().")]]
HashKey* ComputeHash(const Val* v, bool type_check) const HashKey* ComputeHash(const Val* v, bool type_check) const
{ return ComputeHash(*v, type_check); } { return MakeHashKey(*v, type_check).release(); }
// Given a hash key, recover the values used to create it. // Given a hash key, recover the values used to create it.
IntrusivePtr<ListVal> RecoverVals(const HashKey* k) const; IntrusivePtr<ListVal> RecoverVals(const HashKey& k) const;
[[deprecated("Remove in v4.1. Pass in HashKey& instead.")]]
IntrusivePtr<ListVal> RecoverVals(const HashKey* k) const
{ return RecoverVals(*k); }
unsigned int MemoryAllocation() const { return padded_sizeof(*this) + pad_size(size); } unsigned int MemoryAllocation() const { return padded_sizeof(*this) + pad_size(size); }
protected: protected:
HashKey* ComputeSingletonHash(const Val* v, bool type_check) const; std::unique_ptr<HashKey> ComputeSingletonHash(const Val* v, bool type_check) const;
// Computes the piece of the hash for Val*, returning the new kp. // Computes the piece of the hash for Val*, returning the new kp.
// Used as a helper for ComputeHash in the non-singleton case. // Used as a helper for ComputeHash in the non-singleton case.
@ -38,7 +44,7 @@ protected:
// Upon return, pval will point to the recovered Val of type t. // Upon return, pval will point to the recovered Val of type t.
// Returns and updated kp for the next Val. Calls reporter->InternalError() // Returns and updated kp for the next Val. Calls reporter->InternalError()
// upon errors, so there is no return value for invalid input. // upon errors, so there is no return value for invalid input.
const char* RecoverOneVal(const HashKey* k, const char* RecoverOneVal(const HashKey& k,
const char* kp, const char* const k_end, const char* kp, const char* const k_end,
BroType* t, IntrusivePtr<Val>* pval, bool optional) const; BroType* t, IntrusivePtr<Val>* pval, bool optional) const;

View file

@ -218,4 +218,6 @@ public:
{ return (T*) Dictionary::NextEntry(h, cookie, 1); } { return (T*) Dictionary::NextEntry(h, cookie, 1); }
T* RemoveEntry(const HashKey* key) T* RemoveEntry(const HashKey* key)
{ return (T*) Remove(key->Key(), key->Size(), key->Hash()); } { return (T*) Remove(key->Key(), key->Size(), key->Hash()); }
T* RemoveEntry(const HashKey& key)
{ return (T*) Remove(key.Key(), key.Size(), key.Hash()); }
}; };

View file

@ -53,8 +53,11 @@ IPAddr::IPAddr(const BroString& s)
} }
HashKey* IPAddr::GetHashKey() const HashKey* IPAddr::GetHashKey() const
{ return MakeHashKey().release(); }
std::unique_ptr<HashKey> IPAddr::MakeHashKey() const
{ {
return new HashKey((void*)in6.s6_addr, sizeof(in6.s6_addr)); return std::make_unique<HashKey>((void*)in6.s6_addr, sizeof(in6.s6_addr));
} }
static inline uint32_t bit_mask32(int bottom_bits) static inline uint32_t bit_mask32(int bottom_bits)
@ -303,6 +306,9 @@ std::string IPPrefix::AsString() const
} }
HashKey* IPPrefix::GetHashKey() const HashKey* IPPrefix::GetHashKey() const
{ return MakeHashKey().release(); }
std::unique_ptr<HashKey> IPPrefix::MakeHashKey() const
{ {
struct { struct {
in6_addr ip; in6_addr ip;
@ -312,7 +318,7 @@ HashKey* IPPrefix::GetHashKey() const
key.ip = prefix.in6; key.ip = prefix.in6;
key.len = Length(); key.len = Length();
return new HashKey(&key, sizeof(key)); return std::make_unique<HashKey>(&key, sizeof(key));
} }
bool IPPrefix::ConvertString(const char* text, IPPrefix* result) bool IPPrefix::ConvertString(const char* text, IPPrefix* result)

View file

@ -6,6 +6,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <string.h> #include <string.h>
#include <string> #include <string>
#include <memory>
#include "threading/SerialTypes.h" #include "threading/SerialTypes.h"
@ -247,9 +248,11 @@ public:
} }
/** /**
* Returns a key that can be used to lookup the IP Address in a hash * Returns a key that can be used to lookup the IP Address in a hash table.
* table. Passes ownership to caller.
*/ */
std::unique_ptr<HashKey> MakeHashKey() const;
[[deprecated("Remove in v4.1. Use MakeHashKey().")]]
HashKey* GetHashKey() const; HashKey* GetHashKey() const;
/** /**
@ -629,9 +632,11 @@ public:
operator std::string() const { return AsString(); } operator std::string() const { return AsString(); }
/** /**
* Returns a key that can be used to lookup the IP Prefix in a hash * Returns a key that can be used to lookup the IP Prefix in a hash table.
* table. Passes ownership to caller.
*/ */
std::unique_ptr<HashKey> MakeHashKey() const;
[[deprecated("Remove in v4.1. Use MakeHashKey().")]]
HashKey* GetHashKey() const; HashKey* GetHashKey() const;
/** Converts the prefix into the type used internally by the /** Converts the prefix into the type used internally by the

View file

@ -739,16 +739,14 @@ bool BloomFilterVal::Typify(IntrusivePtr<BroType> arg_type)
void BloomFilterVal::Add(const Val* val) void BloomFilterVal::Add(const Val* val)
{ {
HashKey* key = hash->ComputeHash(*val, true); auto key = hash->MakeHashKey(*val, true);
bloom_filter->Add(key); bloom_filter->Add(key.get());
delete key;
} }
size_t BloomFilterVal::Count(const Val* val) const size_t BloomFilterVal::Count(const Val* val) const
{ {
HashKey* key = hash->ComputeHash(*val, true); auto key = hash->MakeHashKey(*val, true);
size_t cnt = bloom_filter->Count(key); size_t cnt = bloom_filter->Count(key.get());
delete key;
return cnt; return cnt;
} }
@ -900,9 +898,8 @@ bool CardinalityVal::Typify(IntrusivePtr<BroType> arg_type)
void CardinalityVal::Add(const Val* val) void CardinalityVal::Add(const Val* val)
{ {
HashKey* key = hash->ComputeHash(*val, true); auto key = hash->MakeHashKey(*val, true);
c->AddElement(key->Hash()); c->AddElement(key->Hash());
delete key;
} }
IMPLEMENT_OPAQUE_VALUE(CardinalityVal) IMPLEMENT_OPAQUE_VALUE(CardinalityVal)

View file

@ -78,7 +78,7 @@ void Reporter::InitOptions()
while ( (v = wl_table->NextEntry(k, c)) ) while ( (v = wl_table->NextEntry(k, c)) )
{ {
auto index = wl_val->RecoverIndex(k); auto index = wl_val->RecreateIndex(*k);
std::string key = index->Idx(0)->AsString()->CheckString(); std::string key = index->Idx(0)->AsString()->CheckString();
weird_sampling_whitelist.emplace(move(key)); weird_sampling_whitelist.emplace(move(key));
delete k; delete k;

View file

@ -719,7 +719,7 @@ SwitchStmt::~SwitchStmt()
bool SwitchStmt::AddCaseLabelValueMapping(const Val* v, int idx) bool SwitchStmt::AddCaseLabelValueMapping(const Val* v, int idx)
{ {
HashKey* hk = comp_hash->ComputeHash(*v, true); auto hk = comp_hash->MakeHashKey(*v, true);
if ( ! hk ) if ( ! hk )
{ {
@ -728,16 +728,12 @@ bool SwitchStmt::AddCaseLabelValueMapping(const Val* v, int idx)
type_name(v->GetType()->Tag()), type_name(e->GetType()->Tag())); type_name(v->GetType()->Tag()), type_name(e->GetType()->Tag()));
} }
int* label_idx = case_label_value_map.Lookup(hk); int* label_idx = case_label_value_map.Lookup(hk.get());
if ( label_idx ) if ( label_idx )
{
delete hk;
return false; return false;
}
case_label_value_map.Insert(hk, new int(idx)); case_label_value_map.Insert(hk.get(), new int(idx));
delete hk;
return true; return true;
} }
@ -763,7 +759,7 @@ std::pair<int, ID*> SwitchStmt::FindCaseLabelMatch(const Val* v) const
// Find matching expression cases. // Find matching expression cases.
if ( case_label_value_map.Length() ) if ( case_label_value_map.Length() )
{ {
HashKey* hk = comp_hash->ComputeHash(*v, true); auto hk = comp_hash->MakeHashKey(*v, true);
if ( ! hk ) if ( ! hk )
{ {
@ -773,10 +769,8 @@ std::pair<int, ID*> SwitchStmt::FindCaseLabelMatch(const Val* v) const
return std::make_pair(-1, nullptr); return std::make_pair(-1, nullptr);
} }
if ( auto i = case_label_value_map.Lookup(hk) ) if ( auto i = case_label_value_map.Lookup(hk.get()) )
label_idx = *i; label_idx = *i;
delete hk;
} }
// Find matching type cases. // Find matching type cases.
@ -1193,7 +1187,7 @@ IntrusivePtr<Val> ForStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const
IterCookie* c = loop_vals->InitForIteration(); IterCookie* c = loop_vals->InitForIteration();
while ( (current_tev = loop_vals->NextEntry(k, c)) ) while ( (current_tev = loop_vals->NextEntry(k, c)) )
{ {
auto ind_lv = tv->RecoverIndex(k); auto ind_lv = tv->RecreateIndex(*k);
delete k; delete k;
if ( value_var ) if ( value_var )

View file

@ -540,7 +540,7 @@ static void BuildJSON(threading::formatter::JSON::NullDoubleWriter& writer, Val*
auto c = table->InitForIteration(); auto c = table->InitForIteration();
while ( (entry = table->NextEntry(k, c)) ) while ( (entry = table->NextEntry(k, c)) )
{ {
auto lv = tval->RecoverIndex(k); auto lv = tval->RecreateIndex(*k);
delete k; delete k;
Val* entry_key = lv->Length() == 1 ? lv->Idx(0).get() : lv.get(); Val* entry_key = lv->Length() == 1 ? lv->Idx(0).get() : lv.get();
@ -1508,14 +1508,15 @@ void TableVal::CheckExpireAttr(attr_tag at)
bool TableVal::Assign(IntrusivePtr<Val> index, IntrusivePtr<Val> new_val) bool TableVal::Assign(IntrusivePtr<Val> index, IntrusivePtr<Val> new_val)
{ {
HashKey* k = ComputeHash(*index); auto k = MakeHashKey(*index);
if ( ! k ) if ( ! k )
{ {
index->Error("index type doesn't match table", table_type->Indices()); index->Error("index type doesn't match table", table_type->Indices());
return false; return false;
} }
return Assign(std::move(index), k, std::move(new_val)); return Assign(std::move(index), std::move(k), std::move(new_val));
} }
bool TableVal::Assign(Val* index, Val* new_val) bool TableVal::Assign(Val* index, Val* new_val)
@ -1523,7 +1524,8 @@ bool TableVal::Assign(Val* index, Val* new_val)
return Assign({NewRef{}, index}, {AdoptRef{}, new_val}); return Assign({NewRef{}, index}, {AdoptRef{}, new_val});
} }
bool TableVal::Assign(IntrusivePtr<Val> index, HashKey* k, IntrusivePtr<Val> new_val) bool TableVal::Assign(IntrusivePtr<Val> index, std::unique_ptr<HashKey> k,
IntrusivePtr<Val> new_val)
{ {
bool is_set = table_type->IsSet(); bool is_set = table_type->IsSet();
@ -1532,19 +1534,18 @@ bool TableVal::Assign(IntrusivePtr<Val> index, HashKey* k, IntrusivePtr<Val> new
TableEntryVal* new_entry_val = new TableEntryVal(new_val); TableEntryVal* new_entry_val = new TableEntryVal(new_val);
HashKey k_copy(k->Key(), k->Size(), k->Hash()); HashKey k_copy(k->Key(), k->Size(), k->Hash());
TableEntryVal* old_entry_val = AsNonConstTable()->Insert(k, new_entry_val); TableEntryVal* old_entry_val = AsNonConstTable()->Insert(k.get(), new_entry_val);
// If the dictionary index already existed, the insert may free up the // If the dictionary index already existed, the insert may free up the
// memory allocated to the key bytes, so have to assume k is invalid // memory allocated to the key bytes, so have to assume k is invalid
// from here on out. // from here on out.
delete k;
k = nullptr; k = nullptr;
if ( subnets ) if ( subnets )
{ {
if ( ! index ) if ( ! index )
{ {
auto v = RecoverIndex(&k_copy); auto v = RecreateIndex(k_copy);
subnets->Insert(v.get(), new_entry_val); subnets->Insert(v.get(), new_entry_val);
} }
else else
@ -1559,7 +1560,7 @@ bool TableVal::Assign(IntrusivePtr<Val> index, HashKey* k, IntrusivePtr<Val> new
if ( change_func ) if ( change_func )
{ {
auto change_index = index ? std::move(index) : RecoverIndex(&k_copy); auto change_index = index ? std::move(index) : RecreateIndex(k_copy);
auto v = old_entry_val ? old_entry_val->GetVal() : new_val; auto v = old_entry_val ? old_entry_val->GetVal() : new_val;
CallChangeFunc(change_index.get(), v.get(), old_entry_val ? ELEMENT_CHANGED : ELEMENT_NEW); CallChangeFunc(change_index.get(), v.get(), old_entry_val ? ELEMENT_CHANGED : ELEMENT_NEW);
} }
@ -1571,7 +1572,7 @@ bool TableVal::Assign(IntrusivePtr<Val> index, HashKey* k, IntrusivePtr<Val> new
bool TableVal::Assign(Val* index, HashKey* k, Val* new_val) bool TableVal::Assign(Val* index, HashKey* k, Val* new_val)
{ {
return Assign({NewRef{}, index}, k, {AdoptRef{}, new_val}); return Assign({NewRef{}, index}, std::unique_ptr<HashKey>{k}, {AdoptRef{}, new_val});
} }
IntrusivePtr<Val> TableVal::SizeVal() const IntrusivePtr<Val> TableVal::SizeVal() const
@ -1607,9 +1608,11 @@ bool TableVal::AddTo(Val* val, bool is_first_init, bool propagate_ops) const
TableEntryVal* v; TableEntryVal* v;
while ( (v = tbl->NextEntry(k, c)) ) while ( (v = tbl->NextEntry(k, c)) )
{ {
std::unique_ptr<HashKey> hk{k};
if ( is_first_init && t->AsTable()->Lookup(k) ) if ( is_first_init && t->AsTable()->Lookup(k) )
{ {
auto key = table_hash->RecoverVals(k); auto key = table_hash->RecoverVals(*k);
// ### Shouldn't complain if their values are equal. // ### Shouldn't complain if their values are equal.
key->Warn("multiple initializations for index"); key->Warn("multiple initializations for index");
continue; continue;
@ -1617,12 +1620,12 @@ bool TableVal::AddTo(Val* val, bool is_first_init, bool propagate_ops) const
if ( type->IsSet() ) if ( type->IsSet() )
{ {
if ( ! t->Assign(v->GetVal(), k, nullptr) ) if ( ! t->Assign(v->GetVal(), std::move(hk), nullptr) )
return false; return false;
} }
else else
{ {
if ( ! t->Assign(nullptr, k, v->GetVal()) ) if ( ! t->Assign(nullptr, std::move(hk), v->GetVal()) )
return false; return false;
} }
} }
@ -1657,7 +1660,7 @@ bool TableVal::RemoveFrom(Val* val) const
// OTOH, they are both the same type, so as long as // OTOH, they are both the same type, so as long as
// we don't have hash keys that are keyed per dictionary, // we don't have hash keys that are keyed per dictionary,
// it should work ... // it should work ...
t->Remove(k); t->Remove(*k);
delete k; delete k;
} }
@ -1910,11 +1913,11 @@ const IntrusivePtr<Val>& TableVal::Find(const IntrusivePtr<Val>& index)
if ( tbl->Length() > 0 ) if ( tbl->Length() > 0 )
{ {
HashKey* k = ComputeHash(*index); auto k = MakeHashKey(*index);
if ( k ) if ( k )
{ {
TableEntryVal* v = AsTable()->Lookup(k); TableEntryVal* v = AsTable()->Lookup(k.get());
delete k;
if ( v ) if ( v )
{ {
@ -2006,13 +2009,12 @@ bool TableVal::UpdateTimestamp(Val* index)
v = (TableEntryVal*) subnets->Lookup(index); v = (TableEntryVal*) subnets->Lookup(index);
else else
{ {
HashKey* k = ComputeHash(*index); auto k = MakeHashKey(*index);
if ( ! k ) if ( ! k )
return false; return false;
v = AsTable()->Lookup(k); v = AsTable()->Lookup(k.get());
delete k;
} }
if ( ! v ) if ( ! v )
@ -2023,7 +2025,7 @@ bool TableVal::UpdateTimestamp(Val* index)
return true; return true;
} }
IntrusivePtr<ListVal> TableVal::RecoverIndex(const HashKey* k) const IntrusivePtr<ListVal> TableVal::RecreateIndex(const HashKey& k) const
{ {
return table_hash->RecoverVals(k); return table_hash->RecoverVals(k);
} }
@ -2091,8 +2093,8 @@ void TableVal::CallChangeFunc(const Val* index, Val* old_value, OnChangeType tpe
IntrusivePtr<Val> TableVal::Remove(const Val& index) IntrusivePtr<Val> TableVal::Remove(const Val& index)
{ {
HashKey* k = ComputeHash(index); auto k = MakeHashKey(index);
TableEntryVal* v = k ? AsNonConstTable()->RemoveEntry(k) : nullptr; TableEntryVal* v = k ? AsNonConstTable()->RemoveEntry(k.get()) : nullptr;
IntrusivePtr<Val> va; IntrusivePtr<Val> va;
if ( v ) if ( v )
@ -2101,7 +2103,6 @@ IntrusivePtr<Val> TableVal::Remove(const Val& index)
if ( subnets && ! subnets->Remove(&index) ) if ( subnets && ! subnets->Remove(&index) )
reporter->InternalWarning("index not in prefix table"); reporter->InternalWarning("index not in prefix table");
delete k;
delete v; delete v;
Modified(); Modified();
@ -2112,7 +2113,7 @@ IntrusivePtr<Val> TableVal::Remove(const Val& index)
return va; return va;
} }
IntrusivePtr<Val> TableVal::Remove(const HashKey* k) IntrusivePtr<Val> TableVal::Remove(const HashKey& k)
{ {
TableEntryVal* v = AsNonConstTable()->RemoveEntry(k); TableEntryVal* v = AsNonConstTable()->RemoveEntry(k);
IntrusivePtr<Val> va; IntrusivePtr<Val> va;
@ -2151,7 +2152,7 @@ IntrusivePtr<ListVal> TableVal::ToListVal(TypeTag t) const
HashKey* k; HashKey* k;
while ( tbl->NextEntry(k, c) ) while ( tbl->NextEntry(k, c) )
{ {
auto index = table_hash->RecoverVals(k); auto index = table_hash->RecoverVals(*k);
if ( t == TYPE_ANY ) if ( t == TYPE_ANY )
l->Append(std::move(index)); l->Append(std::move(index));
@ -2226,7 +2227,7 @@ void TableVal::Describe(ODesc* d) const
if ( ! v ) if ( ! v )
reporter->InternalError("hash table underflow in TableVal::Describe"); reporter->InternalError("hash table underflow in TableVal::Describe");
auto vl = table_hash->RecoverVals(k); auto vl = table_hash->RecoverVals(*k);
int dim = vl->Length(); int dim = vl->Length();
if ( i > 0 ) if ( i > 0 )
@ -2398,7 +2399,7 @@ void TableVal::DoExpire(double t)
if ( expire_func ) if ( expire_func )
{ {
idx = RecoverIndex(k); idx = RecreateIndex(*k);
double secs = CallExpireFunc(idx); double secs = CallExpireFunc(idx);
// It's possible that the user-provided // It's possible that the user-provided
@ -2428,7 +2429,7 @@ void TableVal::DoExpire(double t)
if ( subnets ) if ( subnets )
{ {
if ( ! idx ) if ( ! idx )
idx = RecoverIndex(k); idx = RecreateIndex(*k);
if ( ! subnets->Remove(idx.get()) ) if ( ! subnets->Remove(idx.get()) )
reporter->InternalWarning("index not in prefix table"); reporter->InternalWarning("index not in prefix table");
} }
@ -2437,7 +2438,7 @@ void TableVal::DoExpire(double t)
if ( change_func ) if ( change_func )
{ {
if ( ! idx ) if ( ! idx )
idx = RecoverIndex(k); idx = RecreateIndex(*k);
CallChangeFunc(idx.get(), v->GetVal().get(), ELEMENT_EXPIRED); CallChangeFunc(idx.get(), v->GetVal().get(), ELEMENT_EXPIRED);
} }
@ -2568,7 +2569,7 @@ IntrusivePtr<Val> TableVal::DoClone(CloneState* state)
if ( subnets ) if ( subnets )
{ {
auto idx = RecoverIndex(key); auto idx = RecreateIndex(*key);
tv->subnets->Insert(idx.get(), nval); tv->subnets->Insert(idx.get(), nval);
} }
@ -2615,9 +2616,12 @@ unsigned int TableVal::MemoryAllocation() const
+ table_hash->MemoryAllocation(); + table_hash->MemoryAllocation();
} }
HashKey* TableVal::ComputeHash(const Val& index) const HashKey* TableVal::ComputeHash(const Val* index) const
{ return MakeHashKey(*index).release(); }
std::unique_ptr<HashKey> TableVal::MakeHashKey(const Val& index) const
{ {
return table_hash->ComputeHash(index, true); return table_hash->MakeHashKey(index, true);
} }
void TableVal::SaveParseTimeTableState(RecordType* rt) void TableVal::SaveParseTimeTableState(RecordType* rt)
@ -2658,7 +2662,7 @@ TableVal::ParseTimeTableState TableVal::DumpTableState()
while ( (val = tbl->NextEntry(key, cookie)) ) while ( (val = tbl->NextEntry(key, cookie)) )
{ {
rval.emplace_back(RecoverIndex(key), val->GetVal()); rval.emplace_back(RecreateIndex(*key), val->GetVal());
delete key; delete key;
} }

View file

@ -761,13 +761,13 @@ public:
* case of a set, just adds the index). * case of a set, just adds the index).
* @param index The key to assign. For tables, this is allowed to be null * @param index The key to assign. For tables, this is allowed to be null
* (if needed, the index val can be recovered from the hash key). * (if needed, the index val can be recovered from the hash key).
* @param k A precomputed hash key to use (this method takes ownership * @param k A precomputed hash key to use.
* of deleting it).
* @param new_val The value to assign at the index. For a set, this * @param new_val The value to assign at the index. For a set, this
* must be nullptr. * must be nullptr.
* @return True if the assignment type-checked. * @return True if the assignment type-checked.
*/ */
bool Assign(IntrusivePtr<Val> index, HashKey* k, IntrusivePtr<Val> new_val); bool Assign(IntrusivePtr<Val> index, std::unique_ptr<HashKey> k,
IntrusivePtr<Val> new_val);
// Returns true if the assignment typechecked, false if not. The // Returns true if the assignment typechecked, false if not. The
// methods take ownership of new_val, but not of the index. If we're // methods take ownership of new_val, but not of the index. If we're
@ -877,8 +877,14 @@ public:
// Returns false if index does not exist. // Returns false if index does not exist.
bool UpdateTimestamp(Val* index); bool UpdateTimestamp(Val* index);
// Returns the index corresponding to the given HashKey. /**
IntrusivePtr<ListVal> RecoverIndex(const HashKey* k) const; * @return The index corresponding to the given HashKey.
*/
IntrusivePtr<ListVal> RecreateIndex(const HashKey& k) const;
[[deprecated("Remove in v4.1. Use RecreateIndex().")]]
ListVal* RecoverIndex(const HashKey* k) const
{ return RecreateIndex(*k).release(); }
/** /**
* Remove an element from the table and return it. * Remove an element from the table and return it.
@ -892,11 +898,10 @@ public:
/** /**
* Same as Remove(const Val&), but uses a precomputed hash key. * Same as Remove(const Val&), but uses a precomputed hash key.
* @param k The hash key to lookup. This method takes ownership of * @param k The hash key to lookup.
* deleting it.
* @return Same as Remove(const Val&). * @return Same as Remove(const Val&).
*/ */
IntrusivePtr<Val> Remove(const HashKey* k); IntrusivePtr<Val> Remove(const HashKey& k);
[[deprecated("Remove in v4.1. Use Remove().")]] [[deprecated("Remove in v4.1. Use Remove().")]]
Val* Delete(const Val* index) Val* Delete(const Val* index)
@ -904,7 +909,7 @@ public:
[[deprecated("Remove in v4.1. Use Remove().")]] [[deprecated("Remove in v4.1. Use Remove().")]]
Val* Delete(const HashKey* k) Val* Delete(const HashKey* k)
{ return Remove(k).release(); } { return Remove(*k).release(); }
// Returns a ListVal representation of the table (which must be a set). // Returns a ListVal representation of the table (which must be a set).
IntrusivePtr<ListVal> ToListVal(TypeTag t = TYPE_ANY) const; IntrusivePtr<ListVal> ToListVal(TypeTag t = TYPE_ANY) const;
@ -954,11 +959,15 @@ public:
timer = nullptr; timer = nullptr;
} }
HashKey* ComputeHash(const Val& index) const; /**
* @param The index value to hash.
* @return The hash of the index value or nullptr if
* type-checking failed.
*/
std::unique_ptr<HashKey> MakeHashKey(const Val& index) const;
[[deprecated("Remove in v4.1. Pass a Val& instead.")]] [[deprecated("Remove in v4.1. Use MakeHashKey().")]]
HashKey* ComputeHash(const Val* index) const HashKey* ComputeHash(const Val* index) const;
{ return ComputeHash(*index); }
notifier::Modifiable* Modifiable() override { return this; } notifier::Modifiable* Modifiable() override { return this; }

View file

@ -901,7 +901,7 @@ broker::expected<broker::data> bro_broker::val_to_data(const Val* v)
while ( (entry = table->NextEntry(hk, c)) ) while ( (entry = table->NextEntry(hk, c)) )
{ {
auto vl = table_val->RecoverIndex(hk); auto vl = table_val->RecreateIndex(*hk);
delete hk; delete hk;
broker::vector composite_key; broker::vector composite_key;

View file

@ -38,7 +38,7 @@ std::set<std::string> val_to_topic_set(Val* val)
while ( tbl->NextEntry(k, c) ) while ( tbl->NextEntry(k, c) )
{ {
auto index = val->AsTableVal()->RecoverIndex(k); auto index = val->AsTableVal()->RecreateIndex(*k);
rval.emplace(index->Idx(0)->AsString()->CheckString()); rval.emplace(index->Idx(0)->AsString()->CheckString());
delete k; delete k;
} }

View file

@ -166,12 +166,12 @@ HashKey* AnalyzerSet::GetKey(const file_analysis::Tag& t, RecordVal* args) const
auto lv = make_intrusive<ListVal>(TYPE_ANY); auto lv = make_intrusive<ListVal>(TYPE_ANY);
lv->Append(t.AsVal()); lv->Append(t.AsVal());
lv->Append({NewRef{}, args}); lv->Append({NewRef{}, args});
HashKey* key = analyzer_hash->ComputeHash(*lv, true); auto key = analyzer_hash->MakeHashKey(*lv, true);
if ( ! key ) if ( ! key )
reporter->InternalError("AnalyzerArgs type mismatch"); reporter->InternalError("AnalyzerArgs type mismatch");
return key; return key.release();
} }
file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(const Tag& tag, file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(const Tag& tag,

View file

@ -285,7 +285,7 @@ bool Manager::CreateStream(Stream* info, RecordVal* description)
TableEntryVal* v; TableEntryVal* v;
while ( (v = info->config->AsTable()->NextEntry(k, c)) ) while ( (v = info->config->AsTable()->NextEntry(k, c)) )
{ {
auto index = info->config->RecoverIndex(k); auto index = info->config->RecreateIndex(*k);
string key = index->Idx(0)->AsString()->CheckString(); string key = index->Idx(0)->AsString()->CheckString();
string value = v->GetVal()->AsString()->CheckString(); string value = v->GetVal()->AsString()->CheckString();
rinfo.config.insert(std::make_pair(copy_string(key.c_str()), copy_string(value.c_str()))); rinfo.config.insert(std::make_pair(copy_string(key.c_str()), copy_string(value.c_str())));
@ -1248,7 +1248,8 @@ int Manager::SendEntryTable(Stream* i, const Value* const *vals)
oldval = stream->tab->Find({NewRef{}, idxval}); oldval = stream->tab->Find({NewRef{}, idxval});
} }
HashKey* k = stream->tab->ComputeHash(*idxval); auto k = stream->tab->MakeHashKey(*idxval);
if ( ! k ) if ( ! k )
reporter->InternalError("could not hash"); reporter->InternalError("could not hash");
@ -1256,7 +1257,7 @@ int Manager::SendEntryTable(Stream* i, const Value* const *vals)
ih->idxkey = new HashKey(k->Key(), k->Size(), k->Hash()); ih->idxkey = new HashKey(k->Key(), k->Size(), k->Hash());
ih->valhash = valhash; ih->valhash = valhash;
stream->tab->Assign({AdoptRef{}, idxval}, k, {AdoptRef{}, valval}); stream->tab->Assign({AdoptRef{}, idxval}, std::move(k), {AdoptRef{}, valval});
if ( predidx != nullptr ) if ( predidx != nullptr )
Unref(predidx); Unref(predidx);
@ -1342,7 +1343,7 @@ void Manager::EndCurrentSend(ReaderFrontend* reader)
if ( stream->pred || stream->event ) if ( stream->pred || stream->event )
{ {
auto idx = stream->tab->RecoverIndex(ih->idxkey); auto idx = stream->tab->RecreateIndex(*ih->idxkey);
assert(idx != nullptr); assert(idx != nullptr);
val = stream->tab->FindOrDefault(idx); val = stream->tab->FindOrDefault(idx);
assert(val != nullptr); assert(val != nullptr);
@ -1371,7 +1372,7 @@ void Manager::EndCurrentSend(ReaderFrontend* reader)
SendEvent(stream->event, 4, stream->description->Ref(), ev->Ref(), SendEvent(stream->event, 4, stream->description->Ref(), ev->Ref(),
predidx->Ref(), val->Ref()); predidx->Ref(), val->Ref());
stream->tab->Remove(ih->idxkey); stream->tab->Remove(*ih->idxkey);
stream->lastDict->Remove(lastDictIdxKey); // delete in next line stream->lastDict->Remove(lastDictIdxKey); // delete in next line
delete lastDictIdxKey; delete lastDictIdxKey;
delete(ih); delete(ih);

View file

@ -865,7 +865,7 @@ bool Manager::Write(EnumVal* id, RecordVal* columns_arg)
TableEntryVal* v; TableEntryVal* v;
while ( (v = filter->config->AsTable()->NextEntry(k, c)) ) while ( (v = filter->config->AsTable()->NextEntry(k, c)) )
{ {
auto index = filter->config->RecoverIndex(k); auto index = filter->config->RecreateIndex(*k);
string key = index->Idx(0)->AsString()->CheckString(); string key = index->Idx(0)->AsString()->CheckString();
string value = v->GetVal()->AsString()->CheckString(); string value = v->GetVal()->AsString()->CheckString();
info->config.insert(std::make_pair(copy_string(key.c_str()), copy_string(value.c_str()))); info->config.insert(std::make_pair(copy_string(key.c_str()), copy_string(value.c_str())));

View file

@ -29,9 +29,9 @@ void TopkVal::Typify(IntrusivePtr<BroType> t)
HashKey* TopkVal::GetHash(Val* v) const HashKey* TopkVal::GetHash(Val* v) const
{ {
HashKey* key = hash->ComputeHash(*v, true); auto key = hash->MakeHashKey(*v, true);
assert(key); assert(key);
return key; return key.release();
} }
TopkVal::TopkVal(uint64_t arg_size) : OpaqueVal(topk_type) TopkVal::TopkVal(uint64_t arg_size) : OpaqueVal(topk_type)

View file

@ -179,7 +179,7 @@ function Reporter::set_weird_sampling_whitelist%(weird_sampling_whitelist: strin
while ( (v = wl_table->NextEntry(k, c)) ) while ( (v = wl_table->NextEntry(k, c)) )
{ {
auto index = wl_val->RecoverIndex(k); auto index = wl_val->RecreateIndex(*k);
string key = index->Idx(0)->AsString()->CheckString(); string key = index->Idx(0)->AsString()->CheckString();
whitelist_set.emplace(move(key)); whitelist_set.emplace(move(key));
delete k; delete k;

View file

@ -1024,7 +1024,7 @@ Supervisor::NodeConfig Supervisor::NodeConfig::FromRecord(const RecordVal* node)
while ( (v = cluster_table->NextEntry(k, c)) ) while ( (v = cluster_table->NextEntry(k, c)) )
{ {
auto key = cluster_table_val->RecoverIndex(k); auto key = cluster_table_val->RecreateIndex(*k);
delete k; delete k;
auto name = key->Idx(0)->AsStringVal()->ToStdString(); auto name = key->Idx(0)->AsStringVal()->ToStdString();
auto rv = v->GetVal()->AsRecordVal(); auto rv = v->GetVal()->AsRecordVal();