mirror of
https://github.com/zeek/zeek.git
synced 2025-10-03 23:28:20 +00:00
Allow serialization of closures over Broker.
anonymous-functions, their closures, can now be sent over broker. In order to send an anonymous function the receiver must have parsed a definition of the functon, but it need not to have been evaluated. See testing/btest/language/closure-sending.zeek for an example of how this can be done. This also sends their closures as well as the closures of regular functions.
This commit is contained in:
parent
f18464f1f8
commit
f0798c4b49
19 changed files with 1060 additions and 160 deletions
155
src/Frame.h
155
src/Frame.h
|
@ -4,30 +4,35 @@
|
|||
#define frame_h
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <memory> // std::shared_ptr
|
||||
#include <utility> // std::pair
|
||||
|
||||
#include <broker/data.hh>
|
||||
#include <broker/expected.hh>
|
||||
|
||||
#include "Val.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class BroFunc;
|
||||
class Trigger;
|
||||
class CallExpr;
|
||||
class Val;
|
||||
|
||||
class Frame : public BroObj {
|
||||
friend class BroFunc;
|
||||
public:
|
||||
Frame(int size, const BroFunc* func, const val_list *fn_args);
|
||||
// Constructs a copy or view of other. If a view is constructed the
|
||||
// destructor will not change other's state on deletion.
|
||||
Frame(const Frame* other, bool is_view = false);
|
||||
// Constructs a copy or view of other. If a view is constructed the
|
||||
// destructor will not change other's state on deletion.
|
||||
Frame(const Frame* other, bool is_view = false);
|
||||
~Frame() override;
|
||||
|
||||
Val* NthElement(int n) const { return frame[n]; }
|
||||
void SetElement(int n, Val* v);
|
||||
virtual void SetElement(const ID* id, Val* v);
|
||||
void SetElement(int n, Val* v);
|
||||
virtual void SetElement(const ID* id, Val* v);
|
||||
|
||||
virtual Val* GetElement(ID* id) const;
|
||||
virtual Val* GetElement(const ID* id) const;
|
||||
void AddElement(ID* id, Val* v);
|
||||
|
||||
void Reset(int startIdx);
|
||||
|
@ -56,9 +61,48 @@ public:
|
|||
|
||||
// Deep-copies values.
|
||||
virtual Frame* Clone();
|
||||
// Only deep-copies values corresponding to requested IDs.
|
||||
|
||||
/**
|
||||
* Clones this frame, only copying values corresponding to IDs in
|
||||
* *selection*. All other values are null.
|
||||
*
|
||||
* @param selection a list of IDs that will be cloned into the new
|
||||
* frame.
|
||||
* @return a new frame with the requested values and ref count +1
|
||||
*/
|
||||
virtual Frame* SelectiveClone(id_list* selection);
|
||||
|
||||
/**
|
||||
* Serializes the Frame into a Broker representation.
|
||||
*
|
||||
* @return the broker representaton, or an error if the serialization
|
||||
* failed.
|
||||
*/
|
||||
virtual broker::expected<broker::data> Serialize() const;
|
||||
|
||||
/**
|
||||
* Instantiates a Frame from a serialized one.
|
||||
*
|
||||
* @return a pair. the first item is the status of the serialization,
|
||||
* the second is the Unserialized frame with reference count +1
|
||||
*/
|
||||
static std::pair<bool, Frame*> Unserialize(const broker::vector& data);
|
||||
|
||||
/**
|
||||
* Installs *outer_ids* in this Frame's offset_map.
|
||||
*
|
||||
* Note: This needs to be done before serializing a Frame to guarantee that
|
||||
* the unserialized frame will perform lookups properly.
|
||||
*
|
||||
* @param outer_ids the ids that this frame holds
|
||||
*/
|
||||
void SetOuterIDs(std::shared_ptr<id_list> outer_ids);
|
||||
|
||||
/**
|
||||
* @return does this frame have an initialized offset_map?
|
||||
*/
|
||||
bool HasOuterIDs() const { return offset_map.size(); }
|
||||
|
||||
// If the frame is run in the context of a trigger condition evaluation,
|
||||
// the trigger needs to be registered.
|
||||
void SetTrigger(Trigger* arg_trigger);
|
||||
|
@ -75,6 +119,21 @@ public:
|
|||
protected:
|
||||
void Clear();
|
||||
|
||||
/**
|
||||
* Does offset_map contain an offset corresponding to *i*?
|
||||
*
|
||||
* @param i the ID to check for.
|
||||
* @return true of offset_map has an offset for i, false otherwise.
|
||||
*/
|
||||
bool CaptureContains(const ID* i) const;
|
||||
|
||||
/**
|
||||
* Serializes this Frame's offset map.
|
||||
*
|
||||
* @return a serialized version of the offset map.
|
||||
*/
|
||||
broker::expected<broker::data> SerializeOffsetMap() const;
|
||||
|
||||
Val** frame;
|
||||
int size;
|
||||
|
||||
|
@ -89,10 +148,23 @@ protected:
|
|||
const CallExpr* call;
|
||||
bool delayed;
|
||||
|
||||
// For ClosureFrames, we don't want a Frame as much as we want a frame that
|
||||
// is a view to another underlying one. Rather or not a Frame is a view
|
||||
// impacts how the Frame handles deleting itself.
|
||||
bool is_view;
|
||||
/**
|
||||
* Maps ID names to the offsets they had when passed into the frame.
|
||||
*
|
||||
* A frame that has been serialized maintains its own map between IDs and
|
||||
* their offsets. This is because a serialized frame is not guaranteed to
|
||||
* be unserialized somewhere where the offsets for the IDs that it contains
|
||||
* are the same.
|
||||
*/
|
||||
std::unordered_map<std::string, int> offset_map;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Rather or not this frame is a view of another one. Frames that
|
||||
* are views do not delete their underlying frame on deletion.
|
||||
*/
|
||||
bool is_view;
|
||||
};
|
||||
|
||||
|
||||
|
@ -103,28 +175,57 @@ protected:
|
|||
*/
|
||||
class ClosureFrame : public Frame {
|
||||
public:
|
||||
ClosureFrame(Frame* closure, Frame* body,
|
||||
std::shared_ptr<id_list> outer_ids);
|
||||
/**
|
||||
* Constructs a closure Frame from a closure and body frame, and a list of ids
|
||||
* that this frame should refer to its closure to for values. For non closure
|
||||
* related operations the ClosureFrame is just a view of the body frame.
|
||||
*
|
||||
* @param closure the frame that holds IDs in *outer_ids*.
|
||||
* @param body the frame to refer to for all non-closure actions.
|
||||
* @param outer_ids a list of ids that have been captured by the ClosureFrame.
|
||||
* These inform the closure on where to refer get and set operations.
|
||||
*/
|
||||
ClosureFrame(Frame* closure, Frame* body, std::shared_ptr<id_list> outer_ids);
|
||||
~ClosureFrame() override;
|
||||
Val* GetElement(ID* id) const override;
|
||||
|
||||
Val* GetElement(const ID* id) const override;
|
||||
void SetElement(const ID* id, Val* v) override;
|
||||
|
||||
Frame* Clone() override;
|
||||
Frame* SelectiveClone(id_list* selection) override;
|
||||
Frame* SelectiveClone(id_list* selection) override;
|
||||
|
||||
broker::expected<broker::data> Serialize() const override;
|
||||
static bool UnserializeIntoOffsetMap
|
||||
(const broker::vector& data, std::unordered_map<std::string, int>& target);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Finds the Value corresponding to *id* in the closure of *start*.
|
||||
*
|
||||
* @param start the frame to begin the search from
|
||||
* @param id the ID whose corresponding value is to be collected.
|
||||
* @param offset the offset at which to look for id's value when its
|
||||
* frame has been found.
|
||||
* @return the Value corresponding to *id*.
|
||||
*/
|
||||
static Val* GatherFromClosure(const Frame* start, const ID* id, const int offset);
|
||||
|
||||
/**
|
||||
* Sets the Value corresponding to *id* in the closure of *start* to *val*
|
||||
*
|
||||
* @param start the frame to begin the search from
|
||||
* @param val the Value to associate with *id* in the closure.
|
||||
* @param id the ID whose corresponding value is to be updated.
|
||||
* @param offset the offset at which to look for id's value when its
|
||||
* frame has been found.
|
||||
*/
|
||||
static void SetInClosure(Frame* start, const ID* id, Val* val, const int offset);
|
||||
|
||||
Frame* closure;
|
||||
Frame* body;
|
||||
|
||||
// Both of these assume that it has already been verified that id is
|
||||
// in the start frame.
|
||||
static Val* GatherFromClosure(const Frame* start, const ID* id);
|
||||
static void SetInClosure(Frame* start, const ID* id, Val* val);
|
||||
|
||||
bool CaptureContains(const ID* i) const;
|
||||
|
||||
std::vector<const char*> closure_elements;
|
||||
};
|
||||
|
||||
extern vector<Frame*> g_frame_stack;
|
||||
extern std::vector<Frame*> g_frame_stack;
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue