mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00

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.
140 lines
3.6 KiB
C++
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
|