mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Remove StateAccess class.
This commit is contained in:
parent
02214dafc4
commit
31ddca863c
8 changed files with 14 additions and 744 deletions
|
@ -12,7 +12,7 @@ DebugLogger debug_logger;
|
|||
// Same order here as in DebugStream.
|
||||
DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = {
|
||||
{ "serial", 0, false }, { "rules", 0, false },
|
||||
{ "state", 0, false }, {"string", 0, false },
|
||||
{ "string", 0, false },
|
||||
{ "notifiers", 0, false }, { "main-loop", 0, false },
|
||||
{ "dpd", 0, false }, { "tm", 0, false },
|
||||
{ "logging", 0, false }, {"input", 0, false },
|
||||
|
|
|
@ -16,9 +16,8 @@
|
|||
enum DebugStream {
|
||||
DBG_SERIAL, // Serialization
|
||||
DBG_RULES, // Signature matching
|
||||
DBG_STATE, // StateAccess logging
|
||||
DBG_STRING, // String code
|
||||
DBG_NOTIFIERS, // Notifiers (see StateAccess.h)
|
||||
DBG_NOTIFIERS, // Notifiers
|
||||
DBG_MAINLOOP, // Main IOSource loop
|
||||
DBG_ANALYZER, // Analyzer framework
|
||||
DBG_TM, // Time-machine packet input via Brocolli
|
||||
|
|
|
@ -79,7 +79,7 @@ void ID::SetVal(Val* v, Opcode op, bool arg_weak_ref)
|
|||
#else
|
||||
if ( debug_logger.IsVerbose() || props )
|
||||
#endif
|
||||
StateAccess::Log(new StateAccess(op, this, v, val));
|
||||
notifiers.Modified(this);
|
||||
}
|
||||
|
||||
if ( ! weak_ref )
|
||||
|
|
|
@ -4,538 +4,6 @@
|
|||
#include "NetVar.h"
|
||||
#include "DebugLogger.h"
|
||||
|
||||
int StateAccess::replaying = 0;
|
||||
|
||||
StateAccess::StateAccess(Opcode arg_opcode,
|
||||
const MutableVal* arg_target, const Val* arg_op1,
|
||||
const Val* arg_op2, const Val* arg_op3)
|
||||
{
|
||||
opcode = arg_opcode;
|
||||
target.val = const_cast<MutableVal*>(arg_target);
|
||||
target_type = TYPE_MVAL;
|
||||
op1.val = const_cast<Val*>(arg_op1);
|
||||
op1_type = TYPE_VAL;
|
||||
op2 = const_cast<Val*>(arg_op2);
|
||||
op3 = const_cast<Val*>(arg_op3);
|
||||
delete_op1_key = false;
|
||||
|
||||
RefThem();
|
||||
}
|
||||
|
||||
StateAccess::StateAccess(Opcode arg_opcode,
|
||||
const ID* arg_target, const Val* arg_op1,
|
||||
const Val* arg_op2, const Val* arg_op3)
|
||||
{
|
||||
opcode = arg_opcode;
|
||||
target.id = const_cast<ID*>(arg_target);
|
||||
target_type = TYPE_ID;
|
||||
op1.val = const_cast<Val*>(arg_op1);
|
||||
op1_type = TYPE_VAL;
|
||||
op2 = const_cast<Val*>(arg_op2);
|
||||
op3 = const_cast<Val*>(arg_op3);
|
||||
delete_op1_key = false;
|
||||
|
||||
RefThem();
|
||||
}
|
||||
|
||||
StateAccess::StateAccess(Opcode arg_opcode,
|
||||
const ID* arg_target, const HashKey* arg_op1,
|
||||
const Val* arg_op2, const Val* arg_op3)
|
||||
{
|
||||
opcode = arg_opcode;
|
||||
target.id = const_cast<ID*>(arg_target);
|
||||
target_type = TYPE_ID;
|
||||
op1.key = new HashKey(arg_op1->Key(), arg_op1->Size(), arg_op1->Hash());
|
||||
op1_type = TYPE_KEY;
|
||||
op2 = const_cast<Val*>(arg_op2);
|
||||
op3 = const_cast<Val*>(arg_op3);
|
||||
delete_op1_key = true;
|
||||
|
||||
RefThem();
|
||||
}
|
||||
|
||||
StateAccess::StateAccess(Opcode arg_opcode,
|
||||
const MutableVal* arg_target, const HashKey* arg_op1,
|
||||
const Val* arg_op2, const Val* arg_op3)
|
||||
{
|
||||
opcode = arg_opcode;
|
||||
target.val = const_cast<MutableVal*>(arg_target);
|
||||
target_type = TYPE_MVAL;
|
||||
op1.key = new HashKey(arg_op1->Key(), arg_op1->Size(), arg_op1->Hash());
|
||||
op1_type = TYPE_KEY;
|
||||
op2 = const_cast<Val*>(arg_op2);
|
||||
op3 = const_cast<Val*>(arg_op3);
|
||||
delete_op1_key = true;
|
||||
|
||||
RefThem();
|
||||
}
|
||||
|
||||
StateAccess::StateAccess(const StateAccess& sa)
|
||||
{
|
||||
opcode = sa.opcode;
|
||||
target_type = sa.target_type;
|
||||
op1_type = sa.op1_type;
|
||||
delete_op1_key = false;
|
||||
|
||||
if ( target_type == TYPE_ID )
|
||||
target.id = sa.target.id;
|
||||
else
|
||||
target.val = sa.target.val;
|
||||
|
||||
if ( op1_type == TYPE_VAL )
|
||||
op1.val = sa.op1.val;
|
||||
else
|
||||
{
|
||||
// We need to copy the key as the pointer may not be
|
||||
// valid anymore later.
|
||||
op1.key = new HashKey(sa.op1.key->Key(), sa.op1.key->Size(),
|
||||
sa.op1.key->Hash());
|
||||
delete_op1_key = true;
|
||||
}
|
||||
|
||||
op2 = sa.op2;
|
||||
op3 = sa.op3;
|
||||
|
||||
RefThem();
|
||||
}
|
||||
|
||||
StateAccess::~StateAccess()
|
||||
{
|
||||
if ( target_type == TYPE_ID )
|
||||
Unref(target.id);
|
||||
else
|
||||
Unref(target.val);
|
||||
|
||||
if ( op1_type == TYPE_VAL )
|
||||
Unref(op1.val);
|
||||
else if ( delete_op1_key )
|
||||
delete op1.key;
|
||||
|
||||
Unref(op2);
|
||||
Unref(op3);
|
||||
}
|
||||
|
||||
void StateAccess::RefThem()
|
||||
{
|
||||
if ( target_type == TYPE_ID )
|
||||
Ref(target.id);
|
||||
else
|
||||
Ref(target.val);
|
||||
|
||||
if ( op1_type == TYPE_VAL && op1.val )
|
||||
Ref(op1.val);
|
||||
|
||||
if ( op2 )
|
||||
Ref(op2);
|
||||
if ( op3 )
|
||||
Ref(op3);
|
||||
}
|
||||
|
||||
static Val* GetInteger(bro_int_t n, TypeTag t)
|
||||
{
|
||||
if ( t == TYPE_INT )
|
||||
return val_mgr->GetInt(n);
|
||||
|
||||
return val_mgr->GetCount(n);
|
||||
}
|
||||
|
||||
void StateAccess::Replay()
|
||||
{
|
||||
// For simplicity we assume that we only replay unserialized accesses.
|
||||
assert(target_type == TYPE_ID && op1_type == TYPE_VAL);
|
||||
|
||||
if ( ! target.id )
|
||||
return;
|
||||
|
||||
Val* v = target.id->ID_Val();
|
||||
TypeTag t = v ? v->Type()->Tag() : TYPE_VOID;
|
||||
|
||||
if ( opcode != OP_ASSIGN && ! v )
|
||||
{
|
||||
// FIXME: I think this warrants an internal error,
|
||||
// but let's check that first ...
|
||||
// reporter->InternalError("replay id lacking a value");
|
||||
reporter->Error("replay id lacks a value");
|
||||
return;
|
||||
}
|
||||
|
||||
++replaying;
|
||||
|
||||
switch ( opcode ) {
|
||||
case OP_ASSIGN:
|
||||
assert(op1.val);
|
||||
// There mustn't be a direct assignment to a unique ID.
|
||||
assert(target.id->Name()[0] != '#');
|
||||
|
||||
target.id->SetVal(op1.val->Ref());
|
||||
break;
|
||||
|
||||
case OP_INCR:
|
||||
if ( IsIntegral(t) )
|
||||
{
|
||||
assert(op1.val && op2);
|
||||
// We derive the amount as difference between old
|
||||
// and new value.
|
||||
bro_int_t amount =
|
||||
op1.val->CoerceToInt() - op2->CoerceToInt();
|
||||
|
||||
target.id->SetVal(GetInteger(v->CoerceToInt() + amount, t),
|
||||
OP_INCR);
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_ASSIGN_IDX:
|
||||
assert(op1.val);
|
||||
|
||||
if ( t == TYPE_TABLE )
|
||||
{
|
||||
assert(op2);
|
||||
v->AsTableVal()->Assign(op1.val, op2 ? op2->Ref() : 0);
|
||||
}
|
||||
|
||||
else if ( t == TYPE_RECORD )
|
||||
{
|
||||
const char* field = op1.val->AsString()->CheckString();
|
||||
int idx = v->Type()->AsRecordType()->FieldOffset(field);
|
||||
|
||||
if ( idx >= 0 )
|
||||
v->AsRecordVal()->Assign(idx, op2 ? op2->Ref() : 0);
|
||||
else
|
||||
reporter->Error("access replay: unknown record field %s for assign", field);
|
||||
}
|
||||
|
||||
else if ( t == TYPE_VECTOR )
|
||||
{
|
||||
assert(op2);
|
||||
bro_uint_t index = op1.val->AsCount();
|
||||
v->AsVectorVal()->Assign(index, op2 ? op2->Ref() : 0);
|
||||
}
|
||||
|
||||
else
|
||||
reporter->InternalError("unknown type in replaying index assign");
|
||||
|
||||
break;
|
||||
|
||||
case OP_INCR_IDX:
|
||||
{
|
||||
assert(op1.val && op2 && op3);
|
||||
|
||||
// We derive the amount as the difference between old
|
||||
// and new value.
|
||||
bro_int_t amount = op2->CoerceToInt() - op3->CoerceToInt();
|
||||
|
||||
if ( t == TYPE_TABLE )
|
||||
{
|
||||
t = v->Type()->AsTableType()->YieldType()->Tag();
|
||||
Val* lookup_op1 = v->AsTableVal()->Lookup(op1.val);
|
||||
int delta = lookup_op1->CoerceToInt() + amount;
|
||||
Val* new_val = GetInteger(delta, t);
|
||||
v->AsTableVal()->Assign(op1.val, new_val, OP_INCR );
|
||||
}
|
||||
|
||||
else if ( t == TYPE_RECORD )
|
||||
{
|
||||
const char* field = op1.val->AsString()->CheckString();
|
||||
int idx = v->Type()->AsRecordType()->FieldOffset(field);
|
||||
if ( idx >= 0 )
|
||||
{
|
||||
t = v->Type()->AsRecordType()->FieldType(idx)->Tag();
|
||||
Val* lookup_field =
|
||||
v->AsRecordVal()->Lookup(idx);
|
||||
bro_int_t delta =
|
||||
lookup_field->CoerceToInt() + amount;
|
||||
Val* new_val = GetInteger(delta, t);
|
||||
v->AsRecordVal()->Assign(idx, new_val, OP_INCR);
|
||||
}
|
||||
else
|
||||
reporter->Error("access replay: unknown record field %s for assign", field);
|
||||
}
|
||||
|
||||
else if ( t == TYPE_VECTOR )
|
||||
{
|
||||
bro_uint_t index = op1.val->AsCount();
|
||||
t = v->Type()->AsVectorType()->YieldType()->Tag();
|
||||
Val* lookup_op1 = v->AsVectorVal()->Lookup(index);
|
||||
int delta = lookup_op1->CoerceToInt() + amount;
|
||||
Val* new_val = GetInteger(delta, t);
|
||||
v->AsVectorVal()->Assign(index, new_val);
|
||||
}
|
||||
|
||||
else
|
||||
reporter->InternalError("unknown type in replaying index increment");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case OP_ADD:
|
||||
assert(op1.val);
|
||||
if ( t == TYPE_TABLE )
|
||||
{
|
||||
v->AsTableVal()->Assign(op1.val, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_DEL:
|
||||
assert(op1.val);
|
||||
if ( t == TYPE_TABLE )
|
||||
{
|
||||
Unref(v->AsTableVal()->Delete(op1.val));
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_EXPIRE:
|
||||
assert(op1.val);
|
||||
if ( t == TYPE_TABLE )
|
||||
{
|
||||
// No old check for expire. It may have already
|
||||
// been deleted by ourselves. Furthermore, we
|
||||
// ignore the expire_func's return value.
|
||||
TableVal* tv = v->AsTableVal();
|
||||
if ( tv->Lookup(op1.val, false) )
|
||||
{
|
||||
// We want to propagate state updates which
|
||||
// are performed in the expire_func.
|
||||
StateAccess::ResumeReplay();
|
||||
|
||||
tv->CallExpireFunc(op1.val->Ref());
|
||||
|
||||
StateAccess::SuspendReplay();
|
||||
|
||||
Unref(tv->AsTableVal()->Delete(op1.val));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case OP_PRINT:
|
||||
assert(op1.val);
|
||||
reporter->InternalError("access replay for print not implemented");
|
||||
break;
|
||||
|
||||
case OP_READ_IDX:
|
||||
if ( t == TYPE_TABLE )
|
||||
{
|
||||
assert(op1.val);
|
||||
TableVal* tv = v->AsTableVal();
|
||||
|
||||
// Update the timestamp if we have a read_expire.
|
||||
if ( tv->FindAttr(ATTR_EXPIRE_READ) )
|
||||
{
|
||||
tv->UpdateTimestamp(op1.val);
|
||||
}
|
||||
}
|
||||
else
|
||||
reporter->Error("read for non-table");
|
||||
break;
|
||||
|
||||
default:
|
||||
reporter->InternalError("access replay: unknown opcode for StateAccess");
|
||||
break;
|
||||
}
|
||||
|
||||
--replaying;
|
||||
}
|
||||
|
||||
ID* StateAccess::Target() const
|
||||
{
|
||||
return target_type == TYPE_ID ? target.id : target.val->UniqueID();
|
||||
}
|
||||
|
||||
void StateAccess::Describe(ODesc* d) const
|
||||
{
|
||||
const ID* id;
|
||||
const char* id_str = "";
|
||||
const char* unique_str = "";
|
||||
|
||||
d->SetShort();
|
||||
|
||||
if ( target_type == TYPE_ID )
|
||||
{
|
||||
id = target.id;
|
||||
|
||||
if ( ! id )
|
||||
{
|
||||
d->Add("(unknown id)");
|
||||
return;
|
||||
}
|
||||
|
||||
id_str = id->Name();
|
||||
|
||||
if ( id->ID_Val() && id->ID_Val()->IsMutableVal() &&
|
||||
id->Name()[0] != '#' )
|
||||
unique_str = fmt(" [id] (%s)", id->ID_Val()->AsMutableVal()->UniqueID()->Name());
|
||||
}
|
||||
else
|
||||
{
|
||||
id = target.val->UniqueID();
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( target.val->GetID() )
|
||||
{
|
||||
id_str = target.val->GetID()->Name();
|
||||
unique_str = fmt(" [val] (%s)", id->Name());
|
||||
}
|
||||
else
|
||||
#endif
|
||||
id_str = id->Name();
|
||||
}
|
||||
|
||||
const Val* op1 = op1_type == TYPE_VAL ?
|
||||
this->op1.val :
|
||||
id->ID_Val()->AsTableVal()->RecoverIndex(this->op1.key);
|
||||
|
||||
switch ( opcode ) {
|
||||
case OP_ASSIGN:
|
||||
assert(op1);
|
||||
d->Add(id_str);
|
||||
d->Add(" = ");
|
||||
op1->Describe(d);
|
||||
if ( op2 )
|
||||
{
|
||||
d->Add(" (");
|
||||
op2->Describe(d);
|
||||
d->Add(")");
|
||||
}
|
||||
d->Add(unique_str);
|
||||
break;
|
||||
|
||||
case OP_INCR:
|
||||
assert(op1 && op2);
|
||||
d->Add(id_str);
|
||||
d->Add(" += ");
|
||||
d->Add(op1->CoerceToInt() - op2->CoerceToInt());
|
||||
d->Add(unique_str);
|
||||
break;
|
||||
|
||||
case OP_ASSIGN_IDX:
|
||||
assert(op1);
|
||||
d->Add(id_str);
|
||||
d->Add("[");
|
||||
op1->Describe(d);
|
||||
d->Add("]");
|
||||
d->Add(" = ");
|
||||
if ( op2 )
|
||||
op2->Describe(d);
|
||||
else
|
||||
d->Add("(null)");
|
||||
if ( op3 )
|
||||
{
|
||||
d->Add(" (");
|
||||
op3->Describe(d);
|
||||
d->Add(")");
|
||||
}
|
||||
d->Add(unique_str);
|
||||
break;
|
||||
|
||||
case OP_INCR_IDX:
|
||||
assert(op1 && op2 && op3);
|
||||
d->Add(id_str);
|
||||
d->Add("[");
|
||||
op1->Describe(d);
|
||||
d->Add("]");
|
||||
d->Add(" += ");
|
||||
d->Add(op2->CoerceToInt() - op3->CoerceToInt());
|
||||
d->Add(unique_str);
|
||||
break;
|
||||
|
||||
case OP_ADD:
|
||||
assert(op1);
|
||||
d->Add("add ");
|
||||
d->Add(id_str);
|
||||
d->Add("[");
|
||||
op1->Describe(d);
|
||||
d->Add("]");
|
||||
if ( op2 )
|
||||
{
|
||||
d->Add(" (");
|
||||
op2->Describe(d);
|
||||
d->Add(")");
|
||||
}
|
||||
d->Add(unique_str);
|
||||
break;
|
||||
|
||||
case OP_DEL:
|
||||
assert(op1);
|
||||
d->Add("del ");
|
||||
d->Add(id_str);
|
||||
d->Add("[");
|
||||
op1->Describe(d);
|
||||
d->Add("]");
|
||||
if ( op2 )
|
||||
{
|
||||
d->Add(" (");
|
||||
op2->Describe(d);
|
||||
d->Add(")");
|
||||
}
|
||||
d->Add(unique_str);
|
||||
break;
|
||||
|
||||
case OP_EXPIRE:
|
||||
assert(op1);
|
||||
d->Add("expire ");
|
||||
d->Add(id_str);
|
||||
d->Add("[");
|
||||
op1->Describe(d);
|
||||
d->Add("]");
|
||||
if ( op2 )
|
||||
{
|
||||
d->Add(" (");
|
||||
op2->Describe(d);
|
||||
d->Add(")");
|
||||
}
|
||||
d->Add(unique_str);
|
||||
break;
|
||||
|
||||
case OP_PRINT:
|
||||
assert(op1);
|
||||
d->Add("print ");
|
||||
d->Add(id_str);
|
||||
op1->Describe(d);
|
||||
d->Add(unique_str);
|
||||
break;
|
||||
|
||||
case OP_READ_IDX:
|
||||
assert(op1);
|
||||
d->Add("read ");
|
||||
d->Add(id_str);
|
||||
d->Add("[");
|
||||
op1->Describe(d);
|
||||
d->Add("]");
|
||||
break;
|
||||
|
||||
default:
|
||||
reporter->InternalError("unknown opcode for StateAccess");
|
||||
break;
|
||||
}
|
||||
|
||||
if ( op1_type != TYPE_VAL )
|
||||
Unref(const_cast<Val*>(op1));
|
||||
}
|
||||
|
||||
void StateAccess::Log(StateAccess* access)
|
||||
{
|
||||
if ( access->target_type == TYPE_ID )
|
||||
{
|
||||
if ( access->target.id->FindAttr(ATTR_TRACKED) )
|
||||
notifiers.Modified(access->target.id);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( access->target.val->GetProperties() & MutableVal::TRACKED )
|
||||
notifiers.Modified(access->target.val);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
ODesc desc;
|
||||
access->Describe(&desc);
|
||||
DBG_LOG(DBG_STATE, "operation: %s%s",
|
||||
desc.Description(), replaying > 0 ? " (replay)" : "");
|
||||
#endif
|
||||
|
||||
delete access;
|
||||
|
||||
}
|
||||
|
||||
NotifierRegistry notifiers;
|
||||
|
||||
NotifierRegistry::~NotifierRegistry()
|
||||
|
|
|
@ -27,69 +27,6 @@ enum Opcode { // Op1 Op2 Op3 (Vals)
|
|||
OP_READ_IDX, // idx
|
||||
};
|
||||
|
||||
class StateAccess {
|
||||
public:
|
||||
StateAccess(Opcode opcode, const ID* target, const Val* op1,
|
||||
const Val* op2 = 0, const Val* op3 = 0);
|
||||
StateAccess(Opcode opcode, const MutableVal* target, const Val* op1,
|
||||
const Val* op2 = 0, const Val* op3 = 0);
|
||||
|
||||
// For tables, the idx operand may be given as an index HashKey.
|
||||
// This is for efficiency. While we need to reconstruct the index
|
||||
// if we are actually going to serialize the access, we can at
|
||||
// least skip it if we don't.
|
||||
StateAccess(Opcode opcode, const ID* target, const HashKey* op1,
|
||||
const Val* op2 = 0, const Val* op3 = 0);
|
||||
StateAccess(Opcode opcode, const MutableVal* target, const HashKey* op1,
|
||||
const Val* op2 = 0, const Val* op3 = 0);
|
||||
|
||||
StateAccess(const StateAccess& sa);
|
||||
|
||||
virtual ~StateAccess();
|
||||
|
||||
// Replays this access in the our environment.
|
||||
void Replay();
|
||||
|
||||
// Returns target ID which may be an internal one for unbound vals.
|
||||
ID* Target() const;
|
||||
|
||||
void Describe(ODesc* d) const;
|
||||
|
||||
// Main entry point when StateAcesses are performed.
|
||||
// For every state-changing operation, this has to be called.
|
||||
static void Log(StateAccess* access);
|
||||
|
||||
// If we're going to make additional non-replaying accesses during a
|
||||
// Replay(), we have to call these.
|
||||
static void SuspendReplay() { --replaying; }
|
||||
static void ResumeReplay() { ++replaying; }
|
||||
|
||||
private:
|
||||
StateAccess() { target.id = 0; op1.val = op2 = op3 = 0; }
|
||||
void RefThem();
|
||||
|
||||
Opcode opcode;
|
||||
union {
|
||||
ID* id;
|
||||
MutableVal* val;
|
||||
} target;
|
||||
|
||||
union {
|
||||
Val* val;
|
||||
const HashKey* key;
|
||||
} op1;
|
||||
|
||||
Val* op2;
|
||||
Val* op3;
|
||||
|
||||
enum Type { TYPE_ID, TYPE_VAL, TYPE_MVAL, TYPE_KEY };
|
||||
Type target_type;
|
||||
Type op1_type;
|
||||
bool delete_op1_key;
|
||||
|
||||
static int replaying;
|
||||
};
|
||||
|
||||
// We provide a notifier framework to inform interested parties of
|
||||
// modifications to selected global IDs/Vals. To get notified about a change,
|
||||
// derive a class from Notifier and register the interesting IDs/Vals with
|
||||
|
|
130
src/Val.cc
130
src/Val.cc
|
@ -438,8 +438,6 @@ ID* MutableVal::Bind() const
|
|||
"%u", ++id_counter);
|
||||
name[MAX_NAME_SIZE-1] = '\0';
|
||||
|
||||
// DBG_LOG(DBG_STATE, "new unique ID %s", name);
|
||||
|
||||
id = new ID(name, SCOPE_GLOBAL, true);
|
||||
id->SetType(const_cast<MutableVal*>(this)->Type()->Ref());
|
||||
|
||||
|
@ -457,8 +455,6 @@ void MutableVal::TransferUniqueID(MutableVal* mv)
|
|||
if ( ! id )
|
||||
Bind();
|
||||
|
||||
DBG_LOG(DBG_STATE, "transfering ID (new %s, old/alias %s)", new_name, id->Name());
|
||||
|
||||
// Keep old name as alias.
|
||||
aliases.push_back(id);
|
||||
|
||||
|
@ -1178,55 +1174,6 @@ int TableVal::Assign(Val* index, HashKey* k, Val* new_val, Opcode op)
|
|||
subnets->Insert(index, new_entry_val);
|
||||
}
|
||||
|
||||
if ( LoggingAccess() && op != OP_NONE )
|
||||
{
|
||||
Val* rec_index = 0;
|
||||
if ( ! index )
|
||||
index = rec_index = RecoverIndex(&k_copy);
|
||||
|
||||
if ( new_val )
|
||||
{
|
||||
// A table.
|
||||
if ( new_val->IsMutableVal() )
|
||||
new_val->AsMutableVal()->AddProperties(GetProperties());
|
||||
|
||||
bool unref_old_val = false;
|
||||
Val* old_val = old_entry_val ?
|
||||
old_entry_val->Value() : 0;
|
||||
if ( op == OP_INCR && ! old_val )
|
||||
// If it's an increment, somebody has already
|
||||
// checked that the index is there. If it's
|
||||
// not, that can only be due to using the
|
||||
// default.
|
||||
{
|
||||
old_val = Default(index);
|
||||
unref_old_val = true;
|
||||
}
|
||||
|
||||
assert(op != OP_INCR || old_val);
|
||||
|
||||
StateAccess::Log(
|
||||
new StateAccess(
|
||||
op == OP_INCR ?
|
||||
OP_INCR_IDX : OP_ASSIGN_IDX,
|
||||
this, index, new_val, old_val));
|
||||
|
||||
if ( unref_old_val )
|
||||
Unref(old_val);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// A set.
|
||||
StateAccess::Log(
|
||||
new StateAccess(OP_ADD, this,
|
||||
index, 0, 0));
|
||||
}
|
||||
|
||||
if ( rec_index )
|
||||
Unref(rec_index);
|
||||
}
|
||||
|
||||
// Keep old expiration time if necessary.
|
||||
if ( old_entry_val && attrs && attrs->FindAttr(ATTR_EXPIRE_CREATE) )
|
||||
new_entry_val->SetExpireAccess(old_entry_val->ExpireAccessTime());
|
||||
|
@ -1237,6 +1184,7 @@ int TableVal::Assign(Val* index, HashKey* k, Val* new_val, Opcode op)
|
|||
delete old_entry_val;
|
||||
}
|
||||
|
||||
Modified();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1556,11 +1504,7 @@ Val* TableVal::Lookup(Val* index, bool use_default_val)
|
|||
if ( v )
|
||||
{
|
||||
if ( attrs && attrs->FindAttr(ATTR_EXPIRE_READ) )
|
||||
{
|
||||
v->SetExpireAccess(network_time);
|
||||
if ( LoggingAccess() && ExpirationEnabled() )
|
||||
ReadOperation(index, v);
|
||||
}
|
||||
|
||||
return v->Value() ? v->Value() : this;
|
||||
}
|
||||
|
@ -1587,11 +1531,7 @@ Val* TableVal::Lookup(Val* index, bool use_default_val)
|
|||
if ( v )
|
||||
{
|
||||
if ( attrs && attrs->FindAttr(ATTR_EXPIRE_READ) )
|
||||
{
|
||||
v->SetExpireAccess(network_time);
|
||||
if ( LoggingAccess() && ExpirationEnabled() )
|
||||
ReadOperation(index, v);
|
||||
}
|
||||
|
||||
return v->Value() ? v->Value() : this;
|
||||
}
|
||||
|
@ -1645,11 +1585,7 @@ TableVal* TableVal::LookupSubnetValues(const SubNetVal* search)
|
|||
if ( entry )
|
||||
{
|
||||
if ( attrs && attrs->FindAttr(ATTR_EXPIRE_READ) )
|
||||
{
|
||||
entry->SetExpireAccess(network_time);
|
||||
if ( LoggingAccess() && ExpirationEnabled() )
|
||||
ReadOperation(s, entry);
|
||||
}
|
||||
}
|
||||
|
||||
Unref(s); // assign does not consume index
|
||||
|
@ -1679,8 +1615,6 @@ bool TableVal::UpdateTimestamp(Val* index)
|
|||
return false;
|
||||
|
||||
v->SetExpireAccess(network_time);
|
||||
if ( LoggingAccess() && attrs->FindAttr(ATTR_EXPIRE_READ) )
|
||||
ReadOperation(index, v);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1699,25 +1633,10 @@ Val* TableVal::Delete(const Val* index)
|
|||
if ( subnets && ! subnets->Remove(index) )
|
||||
reporter->InternalWarning("index not in prefix table");
|
||||
|
||||
if ( LoggingAccess() )
|
||||
{
|
||||
if ( v )
|
||||
{
|
||||
// A set.
|
||||
Val* has_old_val = val_mgr->GetInt(1);
|
||||
StateAccess::Log(
|
||||
new StateAccess(OP_DEL, this, index,
|
||||
has_old_val));
|
||||
Unref(has_old_val);
|
||||
}
|
||||
else
|
||||
StateAccess::Log(
|
||||
new StateAccess(OP_DEL, this, index, 0));
|
||||
}
|
||||
|
||||
delete k;
|
||||
delete v;
|
||||
|
||||
Modified();
|
||||
return va;
|
||||
}
|
||||
|
||||
|
@ -1736,9 +1655,7 @@ Val* TableVal::Delete(const HashKey* k)
|
|||
|
||||
delete v;
|
||||
|
||||
if ( LoggingAccess() )
|
||||
StateAccess::Log(new StateAccess(OP_DEL, this, k));
|
||||
|
||||
Modified();
|
||||
return va;
|
||||
}
|
||||
|
||||
|
@ -1949,6 +1866,7 @@ void TableVal::DoExpire(double t)
|
|||
HashKey* k = 0;
|
||||
TableEntryVal* v = 0;
|
||||
TableEntryVal* v_saved = 0;
|
||||
bool modified = false;
|
||||
|
||||
for ( int i = 0; i < table_incremental_step &&
|
||||
(v = tbl->NextEntry(k, expire_cookie)); ++i )
|
||||
|
@ -2001,18 +1919,18 @@ void TableVal::DoExpire(double t)
|
|||
Unref(index);
|
||||
}
|
||||
|
||||
if ( LoggingAccess() )
|
||||
StateAccess::Log(
|
||||
new StateAccess(OP_EXPIRE, this, k));
|
||||
|
||||
tbl->RemoveEntry(k);
|
||||
Unref(v->Value());
|
||||
delete v;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
delete k;
|
||||
}
|
||||
|
||||
if ( modified )
|
||||
Modified();
|
||||
|
||||
if ( ! v )
|
||||
{
|
||||
expire_cookie = 0;
|
||||
|
@ -2124,11 +2042,8 @@ void TableVal::ReadOperation(Val* index, TableEntryVal* v)
|
|||
// practical issues such as latency, we send one update every half
|
||||
// &read_expire.
|
||||
if ( network_time - v->LastReadUpdate() > timeout / 2 )
|
||||
{
|
||||
StateAccess::Log(new StateAccess(OP_READ_IDX, this, index));
|
||||
v->SetLastReadUpdate(network_time);
|
||||
}
|
||||
}
|
||||
|
||||
Val* TableVal::DoClone(CloneState* state)
|
||||
{
|
||||
|
@ -2307,21 +2222,8 @@ RecordVal::~RecordVal()
|
|||
void RecordVal::Assign(int field, Val* new_val, Opcode op)
|
||||
{
|
||||
Val* old_val = AsNonConstRecord()->replace(field, new_val);
|
||||
|
||||
if ( LoggingAccess() && op != OP_NONE )
|
||||
{
|
||||
if ( new_val && new_val->IsMutableVal() )
|
||||
new_val->AsMutableVal()->AddProperties(GetProperties());
|
||||
|
||||
StringVal* index = new StringVal(Type()->AsRecordType()->FieldName(field));
|
||||
StateAccess::Log(
|
||||
new StateAccess(
|
||||
op == OP_INCR ? OP_INCR_IDX : OP_ASSIGN_IDX,
|
||||
this, index, new_val, old_val));
|
||||
Unref(index); // The logging may keep a cached copy.
|
||||
}
|
||||
|
||||
Unref(old_val);
|
||||
Modified();
|
||||
}
|
||||
|
||||
Val* RecordVal::Lookup(int field) const
|
||||
|
@ -2627,19 +2529,6 @@ bool VectorVal::Assign(unsigned int index, Val* element, Opcode op)
|
|||
else
|
||||
val.vector_val->resize(index + 1);
|
||||
|
||||
if ( LoggingAccess() && op != OP_NONE )
|
||||
{
|
||||
if ( element->IsMutableVal() )
|
||||
element->AsMutableVal()->AddProperties(GetProperties());
|
||||
|
||||
Val* ival = val_mgr->GetCount(index);
|
||||
|
||||
StateAccess::Log(new StateAccess(op == OP_INCR ?
|
||||
OP_INCR_IDX : OP_ASSIGN_IDX,
|
||||
this, ival, element, val_at_index));
|
||||
Unref(ival);
|
||||
}
|
||||
|
||||
Unref(val_at_index);
|
||||
|
||||
// Note: we do *not* Ref() the element, if any, at this point.
|
||||
|
@ -2647,6 +2536,7 @@ bool VectorVal::Assign(unsigned int index, Val* element, Opcode op)
|
|||
// to do it similarly.
|
||||
(*val.vector_val)[index] = element;
|
||||
|
||||
Modified();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
15
src/Val.h
15
src/Val.h
|
@ -51,8 +51,6 @@ class StringVal;
|
|||
class EnumVal;
|
||||
class MutableVal;
|
||||
|
||||
class StateAccess;
|
||||
|
||||
class VectorVal;
|
||||
|
||||
class TableEntryVal;
|
||||
|
@ -532,17 +530,6 @@ public:
|
|||
virtual bool AddProperties(Properties state);
|
||||
virtual bool RemoveProperties(Properties state);
|
||||
|
||||
// Whether StateAccess:LogAccess needs to be called.
|
||||
bool LoggingAccess() const
|
||||
{
|
||||
#ifndef DEBUG
|
||||
return props & TRACKED;
|
||||
#else
|
||||
return debug_logger.IsVerbose() ||
|
||||
(props & TRACKED);
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit MutableVal(BroType* t) : Val(t)
|
||||
{ props = 0; id = 0; }
|
||||
|
@ -553,6 +540,7 @@ protected:
|
|||
friend class Val;
|
||||
|
||||
void SetID(ID* arg_id) { Unref(id); id = arg_id; }
|
||||
void Modified() { notifiers.Modified(this); }
|
||||
|
||||
private:
|
||||
ID* Bind() const;
|
||||
|
@ -957,7 +945,6 @@ public:
|
|||
|
||||
protected:
|
||||
friend class Val;
|
||||
friend class StateAccess;
|
||||
TableVal() {}
|
||||
|
||||
void Init(TableType* t);
|
||||
|
|
11
src/bro.bif
11
src/bro.bif
|
@ -1843,17 +1843,6 @@ function global_ids%(%): id_table
|
|||
TableVal* ids = new TableVal(id_table);
|
||||
PDict(ID)* globals = global_scope()->Vars();
|
||||
IterCookie* c = globals->InitForIteration();
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* Explanation time: c needs to be a robust cookie when one is in debug mode,
|
||||
* otherwise the Zeek process will crash in ~80% of cases when -B all is specified.
|
||||
* The reason for this are the RecordVals that we create. RecordVal::Assign triggers
|
||||
* a StateAccess::Log, which in turn (only in debug mode) triggers StateAccess::Describe,
|
||||
* which creates a UniqueID for the variable, which triggers an insert into global_scope.
|
||||
* Which invalidates the iteration cookie if it is not robust.
|
||||
**/
|
||||
globals->MakeRobustCookie(c);
|
||||
#endif
|
||||
|
||||
ID* id;
|
||||
while ( (id = globals->NextEntry(c)) )
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue