Reimplement copy().

The old implementation used the serialization framework, which is
going away. This is a new standalone implementation that should also
be quite a bit faster.

WIP: Not fully implemented and tested yet.
This commit is contained in:
Robin Sommer 2017-06-14 07:23:37 -07:00
parent 49908ac865
commit b9dad02615
3 changed files with 244 additions and 24 deletions

View file

@ -72,31 +72,59 @@ Val::~Val()
#endif
}
Val* Val::Clone() const
Val* Val::Clone()
{
SerializationFormat* form = new BinarySerializationFormat();
form->StartWrite();
CloneSerializer ss(form);
SerialInfo sinfo(&ss);
sinfo.cache = false;
sinfo.include_locations = false;
if ( ! this->Serialize(&sinfo) )
return 0;
char* data;
uint32 len = form->EndWrite(&data);
form->StartRead(data, len);
UnserialInfo uinfo(&ss);
uinfo.cache = false;
Val* clone = Unserialize(&uinfo, type);
free(data);
return clone;
Val::CloneState state;
return Clone(&state);
}
Val* Val::Clone(CloneState* state)
{
auto i = state->clones.find(this);
if ( i != state->clones.end() )
return i->second->Ref();
auto c = DoClone(state);
assert(c);
state->clones.insert(std::make_pair(this, c));
return c;
}
Val* Val::DoClone(CloneState* state)
{
switch ( type->InternalType() ) {
case TYPE_INTERNAL_INT:
case TYPE_INTERNAL_UNSIGNED:
case TYPE_INTERNAL_DOUBLE:
// Immutable.
return Ref();
case TYPE_INTERNAL_OTHER:
// Derived classes are responsible for this. Exception:
// Functions and files. There aren't any derived classes.
if ( type->Tag() == TYPE_FUNC )
// Immutable.
return Ref();
if ( type->Tag() == TYPE_FILE )
{
auto f = AsFile();
::Ref(f);
return new Val(f);
}
// Fall-through.
default:
reporter->InternalError("cloning illegal base type");
}
reporter->InternalError("cannot be reached");
return nullptr;
}
bool Val::Serialize(SerialInfo* info) const
{
return SerialObj::Serialize(info);
@ -862,6 +890,12 @@ void PortVal::ValDescribe(ODesc* d) const
d->Add("/unknown");
}
Val* PortVal::DoClone(CloneState* state)
{
// Immutable.
return Ref();
}
IMPLEMENT_SERIAL(PortVal, SER_PORT_VAL);
bool PortVal::DoSerialize(SerialInfo* info) const
@ -920,6 +954,12 @@ Val* AddrVal::SizeVal() const
return val_mgr->GetCount(128);
}
Val* AddrVal::DoClone(CloneState* state)
{
// Immutable.
return Ref();
}
IMPLEMENT_SERIAL(AddrVal, SER_ADDR_VAL);
bool AddrVal::DoSerialize(SerialInfo* info) const
@ -1044,6 +1084,12 @@ bool SubNetVal::Contains(const IPAddr& addr) const
return val.subnet_val->Contains(a);
}
Val* SubNetVal::DoClone(CloneState* state)
{
// Immutable.
return Ref();
}
IMPLEMENT_SERIAL(SubNetVal, SER_SUBNET_VAL);
bool SubNetVal::DoSerialize(SerialInfo* info) const
@ -1100,6 +1146,11 @@ unsigned int StringVal::MemoryAllocation() const
return padded_sizeof(*this) + val.string_val->MemoryAllocation();
}
Val* StringVal::DoClone(CloneState* state)
{
return new StringVal(new BroString((u_char*) val.string_val->Bytes(), val.string_val->Len(), 1));
}
IMPLEMENT_SERIAL(StringVal, SER_STRING_VAL);
bool StringVal::DoSerialize(SerialInfo* info) const
@ -1162,6 +1213,13 @@ unsigned int PatternVal::MemoryAllocation() const
return padded_sizeof(*this) + val.re_val->MemoryAllocation();
}
Val* PatternVal::DoClone(CloneState* state)
{
// TODO: Double-check
auto re = new RE_Matcher(val.re_val->PatternText(), val.re_val->AnywherePatternText());
return new PatternVal(re);
}
IMPLEMENT_SERIAL(PatternVal, SER_PATTERN_VAL);
bool PatternVal::DoSerialize(SerialInfo* info) const
@ -1260,6 +1318,16 @@ void ListVal::Describe(ODesc* d) const
}
}
Val* ListVal::DoClone(CloneState* state)
{
auto lv = new ListVal(tag);
loop_over_list(vals, i)
lv->Append(vals[i]->Clone(state));
return lv;
}
IMPLEMENT_SERIAL(ListVal, SER_LIST_VAL);
bool ListVal::DoSerialize(SerialInfo* info) const
@ -2498,6 +2566,55 @@ void TableVal::ReadOperation(Val* index, TableEntryVal* v)
}
}
Val* TableVal::DoClone(CloneState* state)
{
auto tv = new TableVal(table_type);
const PDict(TableEntryVal)* tbl = AsTable();
IterCookie* cookie = tbl->InitForIteration();
HashKey* key;
TableEntryVal* val;
while ( (val = tbl->NextEntry(key, cookie)) )
{
Val* idx = RecoverIndex(key);
TableEntryVal* nval = val ? new TableEntryVal(*val) : nullptr;
tv->AsNonConstTable()->Insert(key, nval);
if ( subnets )
{
tv->subnets->Insert(idx, nval);
Unref(idx);
}
delete key;
}
if ( attrs )
{
::Ref(attrs);
tv->attrs = attrs;
}
if ( expire_time )
{
tv->expire_time = expire_time->Ref();
// As network_time is not necessarily initialized yet, we set
// a timer which fires immediately.
timer = new TableValTimer(this, 1);
timer_mgr->Add(timer);
}
if ( expire_func )
tv->expire_func = expire_func->Ref();
if ( def_val )
tv->def_val = def_val->Ref();
return tv;
}
IMPLEMENT_SERIAL(TableVal, SER_TABLE_VAL);
// This is getting rather complex due to the ability to suspend even within
@ -3052,7 +3169,7 @@ void RecordVal::Describe(ODesc* d) const
void RecordVal::DescribeReST(ODesc* d) const
{
const val_list* vl = AsRecord();
int n = vl->length();
int n = vl->length();
d->Add("{");
d->PushIndent();
@ -3077,6 +3194,21 @@ void RecordVal::DescribeReST(ODesc* d) const
d->Add("}");
}
Val* RecordVal::DoClone(CloneState* state)
{
// TODO: We leave origin unset, ok?
::Ref(record_type);
auto rv = new RecordVal(record_type);
loop_over_list(*val.val_list_val, i)
{
Val* v = (*val.val_list_val)[i]->Clone(state);
rv->val.val_list_val->append(v);
}
return nullptr;
}
IMPLEMENT_SERIAL(RecordVal, SER_RECORD_VAL);
bool RecordVal::DoSerialize(SerialInfo* info) const
@ -3193,6 +3325,12 @@ void EnumVal::ValDescribe(ODesc* d) const
d->Add(ename);
}
Val* EnumVal::DoClone(CloneState* state)
{
// Immutable.
return Ref();
}
IMPLEMENT_SERIAL(EnumVal, SER_ENUM_VAL);
bool EnumVal::DoSerialize(SerialInfo* info) const
@ -3378,6 +3516,19 @@ bool VectorVal::RemoveProperties(Properties arg_props)
return true;
}
Val* VectorVal::DoClone(CloneState* state)
{
auto vv = new VectorVal(vector_type);
for ( unsigned int i = 0; i < val.vector_val->size(); ++i )
{
auto v = (*val.vector_val)[i]->Clone(state);
vv->val.vector_val->push_back(v);
}
return vv;
}
IMPLEMENT_SERIAL(VectorVal, SER_VECTOR_VAL);
bool VectorVal::DoSerialize(SerialInfo* info) const
@ -3450,6 +3601,12 @@ OpaqueVal::~OpaqueVal()
{
}
Val* OpaqueVal::DoClone(CloneState* state)
{
// TODO
return nullptr;
}
IMPLEMENT_SERIAL(OpaqueVal, SER_OPAQUE_VAL);
bool OpaqueVal::DoSerialize(SerialInfo* info) const