Architecture¶
Extending¶
TxnBox is intended to be easily extendible with regard to adding new directives, comparisons, and extractors. For each such extension there are two major phases that must be supported, loading and invoking.
Loading is parsing data in the configuration file. Invoking happens during transaction processing.
Extractor¶
An extractor gathers data and provides it to the plugin. While this is usually data in a transaction that is not required. The gathered data is called a feature. Every extractor must be able to provide its feature in string format. It can also provide the feature in one of a few predefined feature types -
INTEGER
, a signed integral value.BOOL
, a boolean value that is the equivalent oftrue
andfalse
.IP_ADDR
, an IP address.
Other feature types may be supported in the future.
An extractor must inherit from Extractor.
Comparison¶
A comparison compares fixed data to a feature and potentially provides some side effects on a successful match. At a minimum, the comparison class implementation must provide a function operator overload which performs the run time comparison with the feature. This can will be one or more of several overloads. The precise methods depend on which feature types are supported.
String - feature argument type is
swoc::TextView
.Boolean - feature argument type is
bool
.Number - feature argument type is
intmax_t
.IP Address - feature argument type is
swoc::IPAddr
.
This is the only required elements, but there are several others which are very convienient and should be added unless there is a reason to not do so.
A
static
const
std::string
which contains the name of the comparison.A
static
const
FeatureMask which contains the valid feature types for the comparison.A
static
load
method which constructs an instance from YAML configuration.Storage for the comparison fixed data.
The former could be hardwired wherever it is used, but having a single copy is better. The
load
method could be done with a free function or a lambda but again it is better to
consolidate this in the class itself.
To illustrate, consider the suffix
comparison. The bare minimum class definition is:
class Cmp_Suffix : public Comparison {
public:
bool operator() (Context& ctx, TextView& text) const override;
};
Because Cmp_Suffix
class is only valid for string features, it provides only the
TextView
overload. The more complete declaration would be:
class Cmp_Suffix : public Comparison {
public:
static const std::string KEY;
static const FeatureMask TYPES;
bool operator() (Context& ctx, TextView& text) const override;
static Rv<Handle> load(Config& cfg, YAML::Node cmp_node, YAML::Node key_node);
protected:
Extractor::Expr _value; ///< Suffix value to compare.
};
The is_valid_for
method is defined to return true
only for the VIEW
feature
type, which is consistent with providing only the swoc::TextView
function operator
overload. That method calls TextView::ends_with
to do the check.
In order to be available to the configuration, the comparison must be passed, along with its name, to the Comparison::define method. There are various initialization mechanism, the one used inside TxnBox looks like this:
namespace {
[[maybe_unused]] bool INITIALIZED = [] () -> bool {
Comparison::define(Cmp_Suffix::KEY, Cmp_Suffix::TYPES, &Cmp_Suffix::load);
return true;
} ();
More detail is available at Cmp_Suffix.