zeek/src/StateAccess.h
Johanna Amann 474efe9e69 Remove value serialization.
Note - this compiles, but you cannot run Bro anymore - it crashes
immediately with a 0-pointer access. The reason behind it is that the
required clone functionality does not work anymore.
2019-05-09 11:54:38 -07:00

140 lines
3.6 KiB
C++

// A class describing a state-modyfing access to a Value or an ID.
#ifndef STATEACESSS_H
#define STATEACESSS_H
#include <set>
#include <map>
#include <string>
class Val;
class ID;
class MutableVal;
class HashKey;
class ODesc;
class TableVal;
enum Opcode { // Op1 Op2 Op3 (Vals)
OP_NONE,
OP_ASSIGN, // new old
OP_ASSIGN_IDX, // idx new old
OP_ADD, // idx old
OP_INCR, // idx new old
OP_INCR_IDX, // idx new old
OP_DEL, // idx old
OP_PRINT, // args
OP_EXPIRE, // idx
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();
bool MergeTables(TableVal* dst, Val* src);
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
// the NotifierRegistry.
//
// Note: For containers (e.g., tables), notifications are only issued if the
// container itself is modified, *not* for changes to the values contained
// therein.
class NotifierRegistry {
public:
class Notifier {
public:
virtual ~Notifier() { }
// Called when a change is being performed. Note that when these
// methods are called, it is undefined whether the change has
// already been done or is just going to be performed soon.
virtual void Access(ID* id, const StateAccess& sa) = 0;
virtual void Access(Val* val, const StateAccess& sa) = 0;
virtual const char* Name() const; // for debugging
};
NotifierRegistry() { }
~NotifierRegistry() { }
// Inform the given notifier if ID/Val changes.
void Register(ID* id, Notifier* notifier);
void Register(Val* val, Notifier* notifier);
// Cancel notification for this ID/Val.
void Unregister(ID* id, Notifier* notifier);
void Unregister(Val* val, Notifier* notifier);
private:
friend class StateAccess;
void AccessPerformed(const StateAccess& sa);
typedef std::set<Notifier*> NotifierSet;
typedef std::map<std::string, NotifierSet*> NotifierMap;
NotifierMap ids;
};
extern NotifierRegistry notifiers;
#endif