Add support for multiple evaluators per operation type

This commit adds the ability to register multiple evaluator types for a
given operation type. This will be used to allow plug-ins to define their
own evaluators for various operation types (most notably, custom
operations) so that they may be used to carry app-specific data which can
be parsed by a plug-in.
This commit is contained in:
Nathan Hourt 2020-09-01 17:46:52 -05:00 committed by Michel Santos
parent 4d836dacb9
commit ab113b2fc4
2 changed files with 30 additions and 3 deletions

View file

@ -344,11 +344,27 @@ namespace graphene { namespace chain {
void initialize_indexes();
void init_genesis(const genesis_state_type& genesis_state = genesis_state_type());
/**
* @brief Register a new evaluator to the evaluator chain for its operation type
* @tparam EvaluatorType An evaluator type which will be used to evaluate its declared operation type
*
* This method registers a new evaluator type with tthe database. The evaluator specifies an operation type
* which it should be used to evaluate. The evaluator will be instantiated each time an operaton of the
* appropriate type is processed and used to evaluate the operation.
*
* This method may be called more than once with multiple evaluator types for a given operation type. When
* multiple evaluator types are registered for a given operation type, they will all execute in the order of
* registration; however, only the return value of the first registered evaluator will be returned; return
* values of subsequently registered evaluators will be silently dropped.
*/
template<typename EvaluatorType>
void register_evaluator()
{
_operation_evaluators[
operation::tag<typename EvaluatorType::operation_type>::value].reset( new op_evaluator_impl<EvaluatorType>() );
auto& eval_ptr = _operation_evaluators[operation::tag<typename EvaluatorType::operation_type>::value];
if (eval_ptr == nullptr)
eval_ptr = std::make_unique<op_evaluator_impl<EvaluatorType>>();
else
eval_ptr->append_evaluator(std::make_unique<op_evaluator_impl<EvaluatorType>>());
}
//////////////////// db_balance.cpp ////////////////////

View file

@ -124,17 +124,28 @@ namespace graphene { namespace chain {
{
public:
virtual ~op_evaluator(){}
virtual void append_evaluator(unique_ptr<op_evaluator> next_evaluator) = 0;
virtual operation_result evaluate(transaction_evaluation_state& eval_state, const operation& op, bool apply) = 0;
};
template<typename T>
class op_evaluator_impl : public op_evaluator
{
unique_ptr<op_evaluator> next_evaluator;
public:
virtual void append_evaluator(unique_ptr<op_evaluator> next_evaluator) override {
if (this->next_evaluator == nullptr)
this->next_evaluator = std::move(next_evaluator);
else
this->next_evaluator->append_evaluator(std::move(next_evaluator));
}
virtual operation_result evaluate(transaction_evaluation_state& eval_state, const operation& op, bool apply = true) override
{
T eval;
return eval.start_evaluate(eval_state, op, apply);
auto result = eval.start_evaluate(eval_state, op, apply);
if (next_evaluator != nullptr)
next_evaluator->evaluate(eval_state, op, apply);
return result;
}
};