mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
334 lines
12 KiB
C++
334 lines
12 KiB
C++
// See the file "COPYING" in the main distribution directory for copyright.
|
|
|
|
#pragma once
|
|
|
|
#include "zeek/OpaqueVal.h"
|
|
#include "zeek/Val.h"
|
|
|
|
namespace zeek::detail::trigger {
|
|
class Trigger;
|
|
using TriggerPtr = IntrusivePtr<Trigger>;
|
|
} // namespace zeek::detail::trigger
|
|
|
|
namespace zeek::storage {
|
|
|
|
class Manager;
|
|
|
|
/**
|
|
* A structure mapped to the script-level Storage::OperationResult type for returning
|
|
* status from storage operations.
|
|
*/
|
|
struct OperationResult {
|
|
/**
|
|
* One of a set of return values used to return a code-based status. The default set
|
|
* of these values is automatically looked up by the `ReturnCode` class, but
|
|
* additional codes may be added by backends. See the script-level
|
|
* `Storage::ReturnCode` enum for documentation for the default available statuses.
|
|
*/
|
|
EnumValPtr code;
|
|
|
|
/**
|
|
* An optional error string that can be passed in the result in the case of failure.
|
|
*/
|
|
std::string err_str;
|
|
|
|
/**
|
|
* A generic value pointer for operations that can return values, such as `Open()` and
|
|
* `Get()`.
|
|
*/
|
|
ValPtr value;
|
|
|
|
/**
|
|
* Returns a RecordVal of the script-level type `Storage::OperationResult` from the
|
|
* values stored.
|
|
*/
|
|
RecordValPtr BuildVal();
|
|
|
|
/**
|
|
* Static version of `BuildVal()` that returns a RecordVal of the script-level type
|
|
* `Storage::OperationResult` from the values provided.
|
|
*/
|
|
static RecordValPtr MakeVal(EnumValPtr code, std::string_view err_str = "", ValPtr value = nullptr);
|
|
};
|
|
|
|
/**
|
|
* Base callback object for asynchronous operations.
|
|
*/
|
|
class ResultCallback {
|
|
public:
|
|
ResultCallback() = default;
|
|
ResultCallback(detail::trigger::TriggerPtr trigger, const void* assoc);
|
|
virtual ~ResultCallback() = default;
|
|
|
|
/**
|
|
* Called on the callback when an operation times out. Sets the resulting status to
|
|
* TIMEOUT and times out the trigger.
|
|
*/
|
|
void Timeout();
|
|
|
|
/**
|
|
* Returns whether the callback was created in an async context. This can be used to
|
|
* determine whether an operation was called synchronously or asynchronously.
|
|
*/
|
|
bool IsSyncCallback() const { return ! trigger; }
|
|
|
|
/**
|
|
* Completes a callback, releasing the trigger if it was valid or storing the result
|
|
* for later usage if needed.
|
|
*/
|
|
virtual void Complete(OperationResult res);
|
|
|
|
OperationResult Result() const { return result; }
|
|
|
|
protected:
|
|
zeek::detail::trigger::TriggerPtr trigger;
|
|
const void* assoc = nullptr;
|
|
OperationResult result;
|
|
};
|
|
|
|
class OpenResultCallback;
|
|
|
|
/**
|
|
* A list of available modes that backends can support. A combination of these is passed
|
|
* to `Backend::Backend` during plugin initialization.
|
|
*/
|
|
enum SupportedModes : uint8_t { SYNC = 0x01, ASYNC = 0x02 };
|
|
|
|
class Backend : public zeek::Obj {
|
|
public:
|
|
/**
|
|
* Returns a descriptive tag representing the source for debugging.
|
|
*/
|
|
const char* Tag() { return tag.c_str(); }
|
|
|
|
/**
|
|
* Store a new key/value pair in the backend.
|
|
*
|
|
* @param cb A callback object for returning status if being called via an async
|
|
* context.
|
|
* @param key the key for the data being inserted.
|
|
* @param value the value for the data being inserted.
|
|
* @param overwrite whether an existing value for a key should be overwritten.
|
|
* @param expiration_time the time when this entry should be automatically
|
|
* removed. Set to zero to disable expiration. This time is based on the current network
|
|
* time.
|
|
* @return A struct describing the result of the operation, containing a code, an
|
|
* optional error string, and a ValPtr for operations that return values.
|
|
*/
|
|
OperationResult Put(ResultCallback* cb, ValPtr key, ValPtr value, bool overwrite = true,
|
|
double expiration_time = 0);
|
|
|
|
/**
|
|
* Retrieve a value from the backend for a provided key.
|
|
*
|
|
* @param cb A callback object for returning status if being called via an async
|
|
* context.
|
|
* @param key the key to lookup in the backend.
|
|
* @return A struct describing the result of the operation, containing a code, an
|
|
* optional error string, and a ValPtr for operations that return values.
|
|
*/
|
|
OperationResult Get(ResultCallback* cb, ValPtr key);
|
|
|
|
/**
|
|
* Erases the value for a key from the backend.
|
|
*
|
|
* @param cb A callback object for returning status if being called via an async
|
|
* context.
|
|
* @param key the key to erase
|
|
* @return A struct describing the result of the operation, containing a code, an
|
|
* optional error string, and a ValPtr for operations that return values.
|
|
*/
|
|
OperationResult Erase(ResultCallback* cb, ValPtr key);
|
|
|
|
/**
|
|
* Returns whether the backend is opened.
|
|
*/
|
|
virtual bool IsOpen() = 0;
|
|
|
|
bool SupportsSync() const { return (modes & SupportedModes::SYNC) == SupportedModes::SYNC; }
|
|
bool SupportsAsync() const { return (modes & SupportedModes::ASYNC) == SupportedModes::ASYNC; }
|
|
|
|
/**
|
|
* Optional method to allow a backend to poll for data. This can be used to
|
|
* mimic sync mode even if the backend only supports async.
|
|
*/
|
|
void Poll() { DoPoll(); }
|
|
|
|
/**
|
|
* Returns the options record that was passed to `Manager::OpenBackend` when the
|
|
* backend was opened.
|
|
*/
|
|
const RecordValPtr& Options() const { return backend_options; }
|
|
|
|
protected:
|
|
// Allow the manager to call Open/Close.
|
|
friend class storage::Manager;
|
|
|
|
// Allow OpenResultCallback to call EnqueueConnectionEstablished.
|
|
friend class storage::OpenResultCallback;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param modes A combination of values from SupportedModes. These modes
|
|
# define whether a backend only supports sync or async or both.
|
|
* @param tag A string representation of the tag for this backend. This
|
|
* is passed from the Manager through the component factory.
|
|
*/
|
|
Backend(uint8_t modes, std::string_view tag) : tag(tag), modes(modes) {}
|
|
|
|
/**
|
|
* Called by the manager system to open the backend.
|
|
*
|
|
* @param cb A callback object for returning status if being called via an async
|
|
* context.
|
|
* @param options A record storing configuration options for the backend.
|
|
* @param kt The script-side type of the keys stored in the backend. Used for
|
|
* validation of types.
|
|
* @param vt The script-side type of the values stored in the backend. Used for
|
|
* validation of types and conversion during retrieval.
|
|
* @return A struct describing the result of the operation, containing a code, an
|
|
* optional error string, and a ValPtr for operations that return values.
|
|
*/
|
|
OperationResult Open(OpenResultCallback* cb, RecordValPtr options, TypePtr kt, TypePtr vt);
|
|
|
|
/**
|
|
* Finalizes the backend when it's being closed.
|
|
*
|
|
* @param cb A callback object for returning status if being called via an async
|
|
* context.
|
|
* @return A struct describing the result of the operation, containing a code, an
|
|
* optional error string, and a ValPtr for operations that return values.
|
|
*/
|
|
OperationResult Close(ResultCallback* cb);
|
|
|
|
/**
|
|
* Removes any entries in the backend that have expired. Can be overridden by
|
|
* derived classes.
|
|
*
|
|
* @param current_network_time The network time as of the start of the
|
|
* expiration operation.
|
|
*/
|
|
void Expire(double current_network_time) { DoExpire(current_network_time); }
|
|
|
|
/**
|
|
* Enqueues the Storage::backend_opened event. This is called automatically
|
|
* when an OpenResultCallback is completed successfully.
|
|
*/
|
|
void EnqueueBackendOpened();
|
|
|
|
/**
|
|
* Enqueues the Storage::backend_lost event with an optional reason
|
|
* string. This should be called by the backends whenever they lose their
|
|
* connection.
|
|
*/
|
|
void EnqueueBackendLost(std::string_view reason);
|
|
|
|
/**
|
|
* Completes a callback and cleans up the memory if the callback was from a sync
|
|
* context. This should be called by backends instead of calling the callback's
|
|
* \a`Complete` method directly.
|
|
*/
|
|
void CompleteCallback(ResultCallback* cb, const OperationResult& data) const;
|
|
|
|
TypePtr key_type;
|
|
TypePtr val_type;
|
|
RecordValPtr backend_options;
|
|
|
|
std::string tag;
|
|
|
|
private:
|
|
/**
|
|
* Workhorse method for calls to `Manager::OpenBackend()`. See that method for
|
|
* documentation of the arguments. This must be overridden by all backends.
|
|
*/
|
|
virtual OperationResult DoOpen(OpenResultCallback* cb, RecordValPtr options) = 0;
|
|
|
|
/**
|
|
* Workhorse method for calls to `Manager::CloseBackend()`. See that method for
|
|
* documentation of the arguments. This must be overridden by all backends.
|
|
*/
|
|
virtual OperationResult DoClose(ResultCallback* cb) = 0;
|
|
|
|
/**
|
|
* Workhorse method for calls to `Backend::Put()`. See that method for
|
|
* documentation of the arguments. This must be overridden by all backends.
|
|
*/
|
|
virtual OperationResult DoPut(ResultCallback* cb, ValPtr key, ValPtr value, bool overwrite,
|
|
double expiration_time) = 0;
|
|
|
|
/**
|
|
* Workhorse method for calls to `Backend::Get()`. See that method for
|
|
* documentation of the arguments. This must be overridden by all backends.
|
|
*/
|
|
virtual OperationResult DoGet(ResultCallback* cb, ValPtr key) = 0;
|
|
|
|
/**
|
|
* Workhorse method for calls to `Backend::Erase()`. See that method for
|
|
* documentation of the arguments. This must be overridden by all backends.
|
|
*/
|
|
virtual OperationResult DoErase(ResultCallback* cb, ValPtr key) = 0;
|
|
|
|
/**
|
|
* Optional method for backends to override to provide direct polling. This should be
|
|
* implemented to support synchronous operations on backends that only provide
|
|
* asynchronous communication. See the built-in Redis backend for an example.
|
|
*/
|
|
virtual void DoPoll() {}
|
|
|
|
/**
|
|
* Optional method for backends to override to provide non-native expiration of
|
|
* items. This is called by the manager on a timer. This can also be used to implement
|
|
* expiration when reading packet captures.
|
|
*
|
|
* @param current_network_time The current network time at which expiration is
|
|
* happening.
|
|
*/
|
|
virtual void DoExpire(double current_network_time) {}
|
|
|
|
uint8_t modes;
|
|
};
|
|
|
|
using BackendPtr = zeek::IntrusivePtr<Backend>;
|
|
|
|
namespace detail {
|
|
|
|
extern OpaqueTypePtr backend_opaque;
|
|
|
|
/**
|
|
* OpaqueVal interface for returning BackendHandle objects to script-land.
|
|
*/
|
|
class BackendHandleVal : public OpaqueVal {
|
|
public:
|
|
BackendHandleVal() : OpaqueVal(detail::backend_opaque) {}
|
|
BackendHandleVal(BackendPtr backend) : OpaqueVal(detail::backend_opaque), backend(std::move(backend)) {}
|
|
~BackendHandleVal() override = default;
|
|
|
|
BackendPtr backend;
|
|
|
|
protected:
|
|
IntrusivePtr<Val> DoClone(CloneState* state) override { return {NewRef{}, this}; }
|
|
|
|
DECLARE_OPAQUE_VALUE_DATA(BackendHandleVal)
|
|
};
|
|
|
|
} // namespace detail
|
|
|
|
/**
|
|
* A specialized version of callback for returning from `open` operations. This returns a
|
|
* `BackendHandleVal` in the `value` field of the result when successful.
|
|
*/
|
|
class OpenResultCallback : public ResultCallback {
|
|
public:
|
|
OpenResultCallback(IntrusivePtr<detail::BackendHandleVal> backend);
|
|
OpenResultCallback(zeek::detail::trigger::TriggerPtr trigger, const void* assoc,
|
|
IntrusivePtr<detail::BackendHandleVal> backend);
|
|
void Complete(OperationResult res) override;
|
|
|
|
IntrusivePtr<detail::BackendHandleVal> Backend() const { return backend; }
|
|
|
|
private:
|
|
IntrusivePtr<detail::BackendHandleVal> backend;
|
|
};
|
|
|
|
} // namespace zeek::storage
|