irods  4.2.8
About: iRODS (the integrated Rule Oriented Data System) is a distributed data-management system for creating data grids, digital libraries, persistent archives, and real-time data systems.
  Fossies Dox: irods-4.2.8.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

irods_re_plugin.hpp
Go to the documentation of this file.
1 #ifndef IRODS_RE_PLUGIN_HPP
2 #define IRODS_RE_PLUGIN_HPP
3 
4 #include "irods_error.hpp"
5 #include "irods_load_plugin.hpp"
6 #include "irods_lookup_table.hpp"
7 #include "irods_re_structs.hpp"
8 #include "irods_state_table.h"
9 #include "rodsLog.h"
10 
11 #include <iostream>
12 #include <list>
13 #include <vector>
14 #include <utility>
15 #include <functional>
16 #include <map>
17 #include <memory>
18 #include <initializer_list>
19 
20 #include <boost/any.hpp>
21 #include <boost/algorithm/string.hpp>
22 #include <boost/optional.hpp>
23 
24 namespace irods {
25 
26 // Notes about the exec_rule_* family of functions:
27 // - exec_rule: Executes dynamic PEPs and user-defined rules.
28 // - exec_rule_text: Used by irule exclusively.
29 // - exec_rule_expression: Used to execute delay() and remote() code.
30 
31 /* How to use
32  * Get rei and set necessary fields
33  ruleExecInfo_t rei;
34  memset( ( char* )&rei, 0, sizeof( ruleExecInfo_t ) );
35  rei.rsComm = _comm;
36 
37  * Create rule_engine_context_manager
38  rule_engine_context_manager<unit, ruleExecInfo_t*, AUDIT_RULE> re_ctx_mgr = rule_engine_context_manager<unit, ruleExecInfo_t*, AUDIT_RULE>(global_re_mgr, &rei);
39 
40  * to call any operation with dynamic pep
41  dynamic_operation_execution_manager<T,C,DONT_AUDIT_RULE> rex_mgr (std::shared_ptr<rule_engine_context_manager<unit,ruleExecInfo_t*,DONT_AUDIT_RULE> > (new rule_engine_context_manager<unit,ruleExecInfo_t*,DONT_AUDIT_RULE >(global_re_mgr, &rei)));
42  rex_mgr.call("instance", "op", op, args...);
43 
44  * If you want to determine if rule exists (not microservices)
45  bool ret;
46  error err;
47  if ( !(err = re_ctx_mgr.rule_exists(_rn, ret)).ok() ) {
48  return err;
49  } else if( !ret ) {
50  return ERROR( SYS_RULE_NOT_FOUND, "no rule found" );
51  }
52 
53  * If you want to execute a rule, pass input parameter using rvalue or reference, output parameter using pointer
54  std::string out;
55  err = re_ctx_mgr.exec_rule(_rn, &out, args...);
56 
57 */
58  template<typename T>
59  T clone(T& a) {
60 
61  return a;
62  }
63 
64  // the unpack constructor tell pluggable rule engine interface that the intention is to unpack the packed parameter list and call another rule
65  // when the rule engine interface tries to pack the parameters again, it will instead pass them on to the plugin
66  class unpack {
67  public:
68  unpack(std::list<boost::any> &_l);
69  std::list<boost::any> &l_;
70  };
71 
72  void var_arg_to_list(std::list<boost::any>& _l);
73 
74  template<typename... As>
75  void var_arg_to_list(std::list<boost::any>& _l, unpack &&_p, As &&... _ps) {
76  var_arg_to_list(_l, _p, std::forward<As>(_ps)...);
77  }
78 
79  template<typename... As>
80  void var_arg_to_list(std::list<boost::any>& _l, unpack &_p, As &&... _ps) {
81  for (auto itr = begin (_p.l_) ; itr != end(_p.l_);++itr) {
82  _l.push_back(boost::any(*itr));
83  }
84  var_arg_to_list(_l, std::forward<As>(_ps)...);
85 
86  }
87 
88  template<typename A, typename... As>
89  void var_arg_to_list(std::list<boost::any>& _l,A&& _p, As&&... _ps) {
90  _l.push_back(boost::any(_p));
91  var_arg_to_list(_l, std::forward<As>(_ps)...);
92  }
93 
94  error list_to_var_arg(std::list<boost::any>& _l);
95 
96  template<typename A, typename... As>
97  error list_to_var_arg(std::list<boost::any>& _l, A&& _p, As&&... _ps) {
98  if(_l.empty()) {
99  return ERROR(RE_TYPE_ERROR, "arg list mismatch");
100  } else {
101  _p = boost::any_cast<A>(_l.front());
102  _l.pop_front();
103  return list_to_var_arg(_l, std::forward<As>(_ps)...);
104 
105  }
106  }
107 
108  template<typename... As>
109  std::list<boost::any> pack(As &&... _ps) {
110  std::list<boost::any> l;
111  var_arg_to_list(l, std::forward<As>(_ps)...);
112  return l;
113  }
114 
115  // microservice manager
116  template<typename C>
118  };
119 
120  template<typename C>
122 
126  };
127 
128  template<typename T, typename C, rule_execution_manager_pack Audit>
129  class rule_engine_context_manager;
130 
131  // callback
132  // before we have concepts, we need to tightly couple this with rule_engine_context_manager to ensure typechecking
133  class callback final {
134  public:
135  template<typename T, typename C, rule_execution_manager_pack Audit>
136  callback(rule_engine_context_manager<T,C,Audit>& _callback_hdlr) : callback_hdlr_(&_callback_hdlr) {}
137 
138  template<typename... As>
139  error operator()(const std::string& _rn, As&&... _ps);
140  protected:
141  boost::any callback_hdlr_;
142  };
143 
144  // serialize wraps a function so that it can be called at runtime wihtout prior knowledge of original parameter types
145  // only when the parameter type matches the oringal does the call succeed
146  class serialize final {
147  public:
148  template<typename... As>
149  serialize(std::function<error(As ...)> _op, std::string _op_name = "<unknown>") : op_(_op), op_name_(_op_name) { }
150 
151  template<typename... Bs>
152  error operator()(Bs&&... _ps) {
153  if(typeid(std::function<error(Bs...)>) == op_.type()) {
154  return boost::any_cast<std::function<error(Bs...)> >(op_)(std::forward<Bs>(_ps)...);
155  } else {
156  return ERROR(RE_TYPE_ERROR, std::string("operation ") + op_name_ + " called with wrong types of arguments");
157  }
158  }
159  protected:
160  boost::any op_;
161  std::string op_name_;
162  };
163 
164  template <typename T>
165  using re_plugin_operation = error(*) (T&, ...);
166 
167 
168  template<typename T>
169  class pluggable_rule_engine final {
170  public:
171 
172  pluggable_rule_engine(const std::string &_in, const std::string &_context) : instance_name_(_in) {
173  }
174 
175  template<typename... types_t>
177  const std::string& _op,
178  std::function<error(types_t...)> _f ) {
179  if ( _op.empty() ) {
180  std::stringstream msg;
181  msg << "empty operation [" << _op << "]";
182  return ERROR( SYS_INVALID_INPUT_PARAM, msg.str() );
183  }
184  operations_[_op] = _f;
185  return SUCCESS();
186 
187  }
188 
190  try {
191  auto fcn = boost::any_cast<std::function<error(T&,const std::string&)>>( operations_["start"] );
192  return fcn(_in, instance_name_);
193  } catch (const boost::bad_any_cast& e) {
194  return ERROR(INVALID_ANY_CAST, boost::format("failed to extract start operation from instance [%s] exception message [%s]") % instance_name_ % e.what());
195  }
196  }
197 
199  try {
200  auto fcn = boost::any_cast<std::function<error(T&,const std::string&)>>( operations_["stop"] );
201  return fcn(_in,instance_name_);
202  } catch (const boost::bad_any_cast& e) {
203  return ERROR(INVALID_ANY_CAST, boost::format("failed to extract stop operation from instance [%s] exception message [%s]") % instance_name_ % e.what());
204  }
205  }
206 
207  error rule_exists(const std::string& _rn, T& _re_ctx, bool& _out) {
208  try {
209  auto fcn = boost::any_cast<std::function<error(T&,const std::string&,bool&)>>( operations_["rule_exists"] );
210  return fcn(_re_ctx, _rn, _out);
211  } catch (const boost::bad_any_cast& e) {
212  return ERROR(INVALID_ANY_CAST, boost::format("failed to extract rule_exists operation from instance [%s] exception message [%s]") % instance_name_ % e.what());
213  }
214  }
215 
216  error list_rules(T& _re_ctx, std::vector<std::string>& _rule_vec) {
217  try {
218  auto fcn = boost::any_cast<std::function<error(T&,std::vector<std::string>&)>>( operations_["list_rules"] );
219  return fcn(_re_ctx, _rule_vec);
220  } catch ( const boost::bad_any_cast& e ) {
221  return ERROR( INVALID_ANY_CAST, boost::format( "failed to extract list_rules operation from instance [%s] exception message [%s]") % instance_name_ % e.what() );
222  }
223  }
224 
225  template<typename ...As>
226  error exec_rule(const std::string& _rn, T& _re_ctx, As&&... _ps, callback _callback) {
227  try {
228  auto l = pack(std::forward<As>(_ps)...);
229  auto fcn = boost::any_cast<std::function<error(T&, const std::string&, std::list<boost::any> &, callback)>>( operations_["exec_rule"] );
230  return fcn(_re_ctx, _rn, l, _callback);
231  } catch (const boost::bad_any_cast& e) {
232  return ERROR(INVALID_ANY_CAST, boost::format("failed to extract exec_rule operation from instance [%s] exception message [%s]") % instance_name_ % e.what());
233  }
234  }
235 
237  T& _re_ctx,
238  const std::string& _rt,
239  msParamArray_t* _ms_params,
240  const std::string& _out_desc,
241  callback _callback) {
242  try {
243  auto fcn = boost::any_cast<
244  std::function<error(T&, const std::string&, msParamArray_t*, const std::string&, callback)>>(
245  operations_["exec_rule_text"] );
246  return fcn(_re_ctx, _rt, _ms_params, _out_desc, _callback);
247  } catch (const boost::bad_any_cast& e) {
248  return ERROR(INVALID_ANY_CAST, boost::format("failed to extract exec_rule_text operation from instance [%s] exception message [%s]") % instance_name_ % e.what());
249  }
250  }
251 
253  T& _re_ctx,
254  const std::string& _rt,
255  msParamArray_t* _ms_params,
256  callback _callback) {
257  try {
258  auto fcn = boost::any_cast<
259  std::function<error(T&, const std::string&, msParamArray_t*, callback)>>(
260  operations_["exec_rule_expression"] );
261  return fcn(_re_ctx, _rt, _ms_params, _callback);
262  } catch (const boost::bad_any_cast& e) {
263  return ERROR(INVALID_ANY_CAST, boost::format("failed to extract exec_rule_expression operation from instance [%s] exception message [%s]") % instance_name_ % e.what());
264  }
265  }
266 
267  private:
268  error load_operation(void *handle, std::string _fcn, std::string _key);
270  std::string instance_name_;
271  };
272 
273  template<typename T, typename C, rule_execution_manager_pack Audit>
275 
276  template<typename T, typename C, rule_execution_manager_pack Audit>
278  public:
279 
281  std::shared_ptr<rule_engine_context_manager<T,C,Audit> > _re_mgr // rule engine manager
282  ) : re_mgr_{_re_mgr} { }
283 
285  const std::string& _instance_name,
286  const std::string& _rule_text,
287  msParamArray_t* _ms_params,
288  const std::string& _out_desc)
289  {
290  return re_mgr_->exec_rule_text(_instance_name, _rule_text, _ms_params, _out_desc);
291  }
292 
294  const std::string& _instance_name,
295  const std::string& _rule_text,
296  msParamArray_t* _ms_params)
297  {
298  return re_mgr_->exec_rule_expression(_instance_name, _rule_text, _ms_params);
299  }
300 
301  template<typename OP, typename... As >
303  std::string _instance_name,
304  std::string _operation_name,
305  OP _operation,
306  As&& ... _ps) {
307  // =-=-=-=-=-=-=-
308  // debug message for creating dynPEP rules
309  rodsLog(
310  LOG_DEBUG,
311  "exec_op [%s]",
312  _operation_name.c_str() );
313 
314  bool execOnce = false;
315  std::function<error()> op = [&execOnce, &_ps..., &_operation] () {
316  if(execOnce) {
317  return ERROR(RE_TYPE_ERROR, "cannot execute operation more than once with client supplied arguments");
318  } else {
319  execOnce = true;
320  return _operation(std::forward<As>(_ps)...);
321  }
322  };
323 
324  auto err = op();
325 
326  return !err.ok() ? PASS(err) : err;
327  }
328 
329  protected:
330 
331  std::shared_ptr<rule_engine_context_manager<T,C,Audit> >re_mgr_;
332 
333  }; // class dynamic_operation_execution_manager
334 
335 
336  // DONE
337  template<typename T>
338  struct re_pack_inp final {
339  std::string instance_name_;
340  std::string plugin_name_;
343  re_pack_inp(std::string _instance_name, std::string _plugin_name, T _re_ctx) : instance_name_(_instance_name), plugin_name_(_plugin_name), re_ctx_(_re_ctx) { }
344  };
345 
346  // load rule engines from plugins DONE
347  template<typename T>
349  public:
350  double interface_version() { return 1.0; }
351  rule_engine_plugin_manager(std::string _dir) : dir_(_dir) { }
352 
354  for (auto itr = begin(re_plugin_map_);itr != end(re_plugin_map_); ++itr) delete itr->second;
355  }
356 
357  error resolve(std::string& _plugin_name, const std::string& _inst_name, pluggable_rule_engine<T> *& _re_ptr) {
358  auto itr = re_plugin_map_.find(_inst_name);
359  if(itr == end(re_plugin_map_)) {
360  error err = load_plugin <pluggable_rule_engine<T> > (_re_ptr, _plugin_name, dir_, _inst_name, std::string("empty_context"));
361  if (!err.ok()) {
362  irods::log( PASS( err ) );
363  return err;
364  }
365  re_plugin_map_[_inst_name] = _re_ptr;
366  } else {
367  _re_ptr = itr->second;
368  }
369  return SUCCESS();
370  }
371 
372  std::map<std::string, pluggable_rule_engine<T> *> re_plugin_map_;
373 
374  protected:
375  std::string dir_;
376 
377  };
378 
379  // load rule engines from plugins DONE
380  template<typename T, typename C>
381  class rule_engine_manager final {
382  public:
383  rule_engine_manager(rule_engine_plugin_manager <T>& _re_plugin_mgr, std::vector<re_pack_inp<T> > &_re_packs, microservice_manager<C> &_ms_mgr) : ms_mgr_(_ms_mgr), re_plugin_mgr_(_re_plugin_mgr) {
384  std::for_each(begin(_re_packs), end(_re_packs), [this](re_pack_inp<T> &_inp) {
385  error err = this->init_rule_engine(_inp);
386  if( !err.ok() ) {
387  irods::log( PASS( err ) );
388  }
389  });
390  }
391 
393  }
394 
397  error err;
398 
399  err = re_plugin_mgr_.resolve(_inp.plugin_name_, _inp.instance_name_, pre);
400  if(!err.ok()) {
401  return PASS( err );
402  }
403 
404  _inp.re_ = pre;
405  re_packs_.push_back(_inp);
406 
407  return SUCCESS();
408  }
409 
411  std::for_each(begin(re_packs_), end(re_packs_), [](re_pack_inp<T> &_inp) {
412  _inp.re_->start_operation(_inp.re_ctx_);
413  });
414  }
415 
417  std::for_each(begin(re_packs_), end(re_packs_), [](re_pack_inp<T> &_inp) {
418  _inp.re_->stop_operation(_inp.re_ctx_);
419  });
420  }
421 
423  std::list<re_pack_inp<T> > re_packs_;
424  protected:
426 
427  };
428 
429  inline bool is_continuation_code(int _error_code)
430  {
431  // Continue to the next rule engine plugin if the current REP
432  // returns either of the following:
433  // - SYS_NOT_SUPPORTED : Signals to the REPF that the REP did nothing.
434  // - RULE_ENGINE_CONTINUE: Signals to the REPF to continue with the next REP.
435  const std::initializer_list<int> continuation_codes = {SYS_NOT_SUPPORTED, RULE_ENGINE_CONTINUE};
436 
437  return std::any_of(std::begin(continuation_codes),
438  std::end(continuation_codes),
439  [_error_code](auto _ec) { return _ec == _error_code; });
440  }
441 
442  inline void log_error_code(const error& e)
443  {
444  if (e.code() == RE_PARSER_ERROR || e.code() == RULE_ENGINE_ERROR || is_continuation_code(e.code())) {
445  rodsLog(LOG_DEBUG, "Rule Engine Plugin returned [%i].", e.code());
446  }
447  else {
448  rodsLog(LOG_ERROR, "Rule Engine Plugin returned [%i].", e.code());
449  }
450  }
451 
452  template <typename ER, typename EM, typename T, typename ...As>
453  inline error control(std::list<re_pack_inp<T> >& _re_packs, ER _er, EM _em, const std::string& _rn, As &&... _ps) {
454  // "unsafe_ms_ctx" is a special keyword that must be processed by the microservice
455  // handler, "_em". If this keyword is seen, the REPs should be skipped.
456  if ("unsafe_ms_ctx" != _rn) {
457  // Holds the error code of the last REP that processed the rule "_rn".
458  // If the rule was NOT processed by any REP, then "last_error_code" will
459  // be empty and "_rn" MIGHT reference a microservice. It is VERY important that
460  // "last_error_code" be instantiated in the empty state.
461  boost::optional<int> last_error_code;
462 
463  // Iterate over the list of REPs. If the rule exists in one of the REPs,
464  // then execute that REP's rule code.
465  for (auto itr = begin(_re_packs); itr != end(_re_packs); ++itr) {
466  bool rule_exists = false;
467 
468  error err = itr->re_->rule_exists(_rn, itr->re_ctx_, rule_exists);
469 
470  if (!err.ok()) {
471  return err;
472  }
473 
474  if (rule_exists) {
475  err = _er(*itr, _rn, std::forward<As>(_ps)...);
476  last_error_code = err.code();
477 
478  if (!is_continuation_code(*last_error_code)) {
479  return err;
480  }
481  }
482  }
483 
484  // If the rule was processed by a REP and the last error code is zero or a continuation
485  // code, then return the last error code. Checking for zero is equivalent to a REP returning
486  // SUCCESS(). This keeps the REPF from trying to execute rules as microservices.
487  if (last_error_code && (*last_error_code == 0 || is_continuation_code(*last_error_code))) {
488  return CODE(*last_error_code);
489  }
490  }
491 
492  return _em(_rn, std::forward<As>(_ps)...);
493  }
494 
495  template<typename T, typename C>
497  public:
499  re_mgr_{_re_mgr} {}
500 
501  virtual ~rule_exists_manager() {}
502 
503  error rule_exists(const std::string& _rn, bool& ret) {
504  auto er = [&ret] (re_pack_inp<T>&, const std::string&) {
505  ret = true;
506  return SUCCESS();
507  };
508 
509  auto em = [&ret] (const std::string&) {
510  ret = false;
511  return SUCCESS();
512  };
513 
514  return control(re_mgr_.re_packs_, er, em, _rn);
515  }
516  protected:
518  };
519 
520  // rule_engine_manager + ctx DONE
521  template<typename T, typename C, rule_execution_manager_pack Audit>
523 
524  template<typename T, typename C>
526  {
527  public:
529  : rule_exists_manager<T,C>{_re_mgr}
530  , ctx_{_ctx}
531  , rex_mgr_{std::make_shared<rule_engine_context_manager<T,C,DONT_AUDIT_RULE>>(_re_mgr, _ctx)}
532  {
533  }
534 
535  template <typename ...As>
536  error exec_rule(const std::string& _rn, As &&... _ps) {
537  auto er = [this](re_pack_inp<T>& _itr, const std::string& _rn, decltype(_ps)... _ps) {
538  using func_t = std::function<error(const std::string&, re_pack_inp<T>&, decltype(_ps)...)>;
539 
540  func_t fun = [this](const std::string& _rn, re_pack_inp<T>& _itr, decltype(_ps)... _ps) {
541  return _itr.re_->template exec_rule<As...>(_rn, _itr.re_ctx_, std::forward<As >(_ps)..., callback(*this));
542  };
543 
544  return this->rex_mgr_.call(_itr.instance_name_,
545  std::string("exec_rule"),
546  fun,
547  _rn,
548  _itr,
549  std::forward<As>(_ps)...);
550  };
551 
552  auto em = [this](const std::string& _rn, decltype(_ps)... _ps) {
553  using func_t = std::function<error(const std::string&, C&, decltype(_ps)...)>;
554 
555  func_t fun = [this](const std::string& _rn, C& _ctx, decltype(_ps)... _ps) {
556  return this->re_mgr_.ms_mgr_.exec_microservice(_rn, _ctx, std::forward<As>(_ps)...);
557  };
558 
559  return this->rex_mgr_.call(std::string("microservice_manager"),
560  std::string("exec_microservice"),
561  fun,
562  _rn,
563  this->ctx_,
564  std::forward<As>(_ps)...);
565  };
566 
567  return control(this->re_mgr_.re_packs_, er, em, _rn, std::forward<As>(_ps)...);
568  }
569 
570  //TODO: Add auditing via rex_mgr_ call
572  const std::string& _instance_name,
573  const std::string& _rt,
574  msParamArray_t* _ms_params,
575  const std::string& _out_desc)
576  {
577  if (_instance_name.empty()) {
578  for (auto&& re_pack : this->re_mgr_.re_packs_) {
579  log_error_code(re_pack.re_->exec_rule_text(re_pack.re_ctx_, _rt, _ms_params, _out_desc, callback(*this)));
580  }
581 
582  return SUCCESS();
583  }
584 
585  for (auto&& re_pack : this->re_mgr_.re_packs_) {
586  if (_instance_name == re_pack.instance_name_) {
587  return re_pack.re_->exec_rule_text(re_pack.re_ctx_, _rt, _ms_params, _out_desc, callback(*this));
588  }
589  }
590 
591  std::string msg = "instance not found [";
592  msg += _instance_name;
593  msg += ']';
594 
595  return ERROR(SYS_INVALID_INPUT_PARAM, msg);
596  }
597 
599  const std::string& _instance_name,
600  const std::string& _rt,
601  msParamArray_t* _ms_params)
602  {
603  if (_instance_name.empty()) {
604  for (auto&& re_pack : this->re_mgr_.re_packs_) {
605  log_error_code(re_pack.re_->exec_rule_expression(re_pack.re_ctx_, _rt, _ms_params, callback(*this)));
606  }
607 
608  return SUCCESS();
609  }
610 
611  for (auto&& re_pack : this->re_mgr_.re_packs_) {
612  if (_instance_name == re_pack.instance_name_) {
613  return re_pack.re_->exec_rule_expression(re_pack.re_ctx_, _rt, _ms_params, callback(*this));
614  }
615  }
616 
617  std::string msg = "instance not found [";
618  msg += _instance_name;
619  msg += ']';
620 
621  return ERROR(SYS_INVALID_INPUT_PARAM, msg);
622  }
623 
624  error list_rules(std::vector< std::string >& rule_vec) {
625  return this->rex_mgr_.list_rules( rule_vec );
626  }
627 
628  protected:
629  C ctx_;
631  };
632 
633  template<typename T, typename C>
635  {
636  public:
638  rule_exists_manager<T,C>{_re_mgr},
639  ctx_{_ctx} {}
640 
641  template <typename ...As>
642  error exec_rule(const std::string& _rn, As &&... _ps) {
643  auto er = [this](re_pack_inp<T>& _itr, const std::string& _rn, decltype(_ps)... _ps) {
644  return _itr.re_->template exec_rule<As...>( _rn, _itr.re_ctx_, std::forward<As>(_ps)..., callback(*this));
645  };
646 
647  auto em = [this](const std::string& _rn, decltype(_ps)... _ps) {
648  return this->re_mgr_.ms_mgr_.exec_microservice(_rn, this->ctx_, std::forward<As>(_ps)...);
649  };
650 
651  return control(this->re_mgr_.re_packs_, er, em, _rn, std::forward<As>(_ps)...);
652  }
653 
655  const std::string& _instance_name,
656  const std::string& _rt,
657  msParamArray_t* _ms_params,
658  const std::string& _out_desc)
659  {
660  if (_instance_name.empty()) {
661  for (auto&& re_pack : this->re_mgr_.re_packs_) {
662  log_error_code(re_pack.re_->exec_rule_text(re_pack.re_ctx_, _rt, _ms_params, _out_desc, callback(*this)));
663  }
664 
665  return SUCCESS();
666  }
667 
668  for (auto&& re_pack : this->re_mgr_.re_packs_) {
669  if (_instance_name == re_pack.instance_name_) {
670  return re_pack.re_->exec_rule_text(re_pack.re_ctx_, _rt, _ms_params, _out_desc, callback(*this));
671  }
672  }
673 
674  std::string msg = "instance not found [";
675  msg += _instance_name;
676  msg += ']';
677 
678  return ERROR(SYS_INVALID_INPUT_PARAM, msg);
679  }
680 
682  const std::string& _instance_name,
683  const std::string& _rt,
684  msParamArray_t* _ms_params)
685  {
686  if (_instance_name.empty()) {
687  for (auto&& re_pack : this->re_mgr_.re_packs_) {
688  log_error_code(re_pack.re_->exec_rule_expression(re_pack.re_ctx_, _rt, _ms_params, callback(*this)));
689  }
690 
691  return SUCCESS();
692  }
693 
694  for (auto&& re_pack : this->re_mgr_.re_packs_) {
695  if (_instance_name == re_pack.instance_name_) {
696  return re_pack.re_->exec_rule_expression(re_pack.re_ctx_, _rt, _ms_params, callback(*this));
697  }
698  }
699 
700  std::string msg = "instance not found [";
701  msg += _instance_name;
702  msg += ']';
703 
704  return ERROR(SYS_INVALID_INPUT_PARAM, msg);
705  }
706 
707  error list_rules(std::vector< std::string >& rule_vec) {
708  for( auto itr = begin(this->re_mgr_.re_packs_);
709  itr != end(this->re_mgr_.re_packs_);
710  ++itr ) {
711  error ret = itr->re_->list_rules( itr->re_ctx_, rule_vec );
712  if ( !ret.ok() ) {
713  rodsLog( LOG_ERROR, "Error in list_rules for instance [%s]", itr->instance_name_.c_str() );
714  return ret;
715  }
716  }
717 
718  return SUCCESS();
719  }
720 
721  protected:
722  C ctx_;
723  };
724 
725  template<typename T>
726  error pluggable_rule_engine<T>::load_operation(void *_handle, std::string _fcn, std::string _key) {
727  dlerror();
728  re_plugin_operation<T> plugin_op_ptr = reinterpret_cast< re_plugin_operation<T> > (dlsym(_handle, _fcn.c_str()));
729  if (!plugin_op_ptr) {
730  return ERROR(-1, "cannot load plugin operation " + _key + " " + _fcn);
731  }
732  operations_[_key] = plugin_op_ptr;
733  return SUCCESS();
734  }
735 
736  using unit = std::tuple<>;
737 #define UNIT unit()
738 
741 
742  template<>
744  public:
745  error exec_microservice_adapter(std::string _msn, default_ms_ctx _ctx, std::list<boost::any>&);
746 
747  template<typename... As>
748  error exec_microservice(std::string _msn, default_ms_ctx _ctx, As&&... _ps) {
749  // =-=-=-=-=-=-=-
750  // debug message for creating dynPEP rules
751  rodsLog(
752  LOG_DEBUG,
753  "microservice_manager::exec_microservice_no_audit [%s]",
754  _msn.c_str() );
755 
756  // =-=-=-=-=-=-=-
757  // add the output parameter
758 
759  auto l = pack(std::forward<As>(_ps)...);
760  error err = exec_microservice_adapter(_msn, _ctx, l);
761 
762  return err;
763 
764  }
765 
766  };
767 
768  template<typename... As>
769  error callback::operator()(const std::string& _rn, As&& ... _ps) {
771  auto cb = boost::any_cast<rule_engine_context_manager<default_re_ctx, default_ms_ctx, AUDIT_RULE> *>(callback_hdlr_);
772  return cb->exec_rule(_rn, std::forward<As> (_ps)...);
774  auto cb = boost::any_cast<rule_engine_context_manager<default_re_ctx, default_ms_ctx, DONT_AUDIT_RULE> *>(callback_hdlr_);
775  return cb->exec_rule(_rn, std::forward<As> (_ps)...);
776  } else {
777  rodsLog(
778  LOG_ERROR,
779  "rule engine callback: unsupported effect handler type. encountered:\n%s\nexpected:\n%s\n%s\n",
780  callback_hdlr_.type().name(),
783  );
784  return ERROR(RE_TYPE_ERROR, "unsupported effect handler type");
785  }
786  }
787 
788  error convertToMsParam(boost::any &itr, msParam_t *t);
789  error convertFromMsParam(boost::any& itr, msParam_t *t);
790 
791  template <typename T>
792  T any_extract(boost::any _p, std::function<T()> f) {
793  if(_p.type() == typeid(T*)) {
794  return *boost::any_cast<T*>(_p);
795 
796  } else if(_p.type() == typeid(T)){
797  return boost::any_cast<T>(_p);
798 
799  } else {
800  // rodsLog(LOG_ERROR, (std::string("cannot convert type ") + _p.type().name() + " to " + typeid(T).name()).c_str());
801  return f();
802  }
803  }
804 
805  template <typename T>
806  void any_update(boost::any& _p, T _p2) {
807  if(_p.type() == typeid(T*)) {
808  *boost::any_cast<T*>(_p) = _p2;
809  }
810  }
811 
812  template<typename S, typename T, typename F>
813  void foreach2(S&& a, T&& b, F&& f) {
814  typename std::remove_reference<S>::type::iterator itr = a.begin();
815  typename std::remove_reference<T>::type::iterator itr2 = b.begin();
816  for(;itr!=a.end() && itr2!=b.end();++itr, ++itr2) {
817  f(*itr, *itr2);
818  }
819  }
820 
821  template< typename InputC, typename OutputC, typename UnaryOperation >
822  void transform(const InputC &ic, OutputC &oc, UnaryOperation func) {
823  std::transform(ic.begin(), ic.end(), oc.begin(), func);
824  }
825 
826  template< typename InputC, typename OutputC, typename UnaryOperation >
827  OutputC transform(const InputC &ic, UnaryOperation func) {
828  OutputC oc;
829  std::transform(ic.begin(), ic.end(), oc.begin(), func);
830  return oc;
831  }
832 
833  std::vector<re_pack_inp<default_re_ctx> > init_global_re_packs();
836  std::vector<re_pack_inp<default_re_ctx> > global_re_packs = init_global_re_packs();
839  };
840 
841  extern std::unique_ptr<struct irods::global_re_plugin_mgr> re_plugin_globals;
842 }
843 #define DEFINE_FACTORY \
844  irods::pluggable_rule_engine<irods::default_re_ctx>* plugin_factory(const std::string& _inst_name, const std::string& _context) { \
845  return new irods::pluggable_rule_engine<irods::default_re_ctx>( _inst_name , _context); \
846  } \
847  double get_plugin_interface_version() { \
848  static const double PLUGIN_INTERFACE_VERSION = 1.0; \
849  return PLUGIN_INTERFACE_VERSION; \
850  }
851 
852 #endif
rodsLog
void rodsLog(int level, const char *formatStr,...)
Definition: rodsLog.cpp:86
NULL
#define NULL
Definition: rodsDef.h:70
irods::transform
OutputC transform(const InputC &ic, UnaryOperation func)
Definition: irods_re_plugin.hpp:827
irods::unit
std::tuple<> unit
Definition: irods_re_plugin.hpp:736
irods::callback::callback
callback(rule_engine_context_manager< T, C, Audit > &_callback_hdlr)
Definition: irods_re_plugin.hpp:136
irods::lookup_table< boost::any >
irods::default_microservice_manager< default_ms_ctx >::exec_microservice
error exec_microservice(std::string _msn, default_ms_ctx _ctx, As &&... _ps)
Definition: irods_re_plugin.hpp:748
irods::rule_engine_plugin_manager::interface_version
double interface_version()
Definition: irods_re_plugin.hpp:350
irods::transform
void transform(const InputC &ic, OutputC &oc, UnaryOperation func)
Definition: irods_re_plugin.hpp:822
irods::callback::callback_hdlr_
boost::any callback_hdlr_
Definition: irods_re_plugin.hpp:141
irods::global_re_plugin_mgr::global_ms_mgr
microservice_manager< default_ms_ctx > global_ms_mgr
Definition: irods_re_plugin.hpp:835
irods::callback::operator()
error operator()(const std::string &_rn, As &&... _ps)
Definition: irods_re_plugin.hpp:769
irods::rule_engine_context_manager
Definition: irods_re_plugin.hpp:522
irods::default_microservice_manager
Definition: irods_re_plugin.hpp:117
irods::control
error control(std::list< re_pack_inp< T > > &_re_packs, ER _er, EM _em, const std::string &_rn, As &&... _ps)
Definition: irods_re_plugin.hpp:453
irods::serialize::serialize
serialize(std::function< error(As ...)> _op, std::string _op_name="<unknown>")
Definition: irods_re_plugin.hpp:149
irods::serialize::operator()
error operator()(Bs &&... _ps)
Definition: irods_re_plugin.hpp:152
PASS
#define PASS(prev_error_)
Definition: irods_error.hpp:118
irods::convertFromMsParam
error convertFromMsParam(boost::any &itr, msParam_t *t)
Definition: irods_re_plugin.cpp:62
irods::rule_exists_manager::~rule_exists_manager
virtual ~rule_exists_manager()
Definition: irods_re_plugin.hpp:501
irods::var_arg_to_list
void var_arg_to_list(std::list< boost::any > &_l)
Definition: irods_re_plugin.cpp:18
irods::re_pack_inp::plugin_name_
std::string plugin_name_
Definition: irods_re_plugin.hpp:340
irods::rule_exists_manager::rule_exists_manager
rule_exists_manager(rule_engine_manager< T, C > &_re_mgr)
Definition: irods_re_plugin.hpp:498
irods::unpack
Definition: irods_re_plugin.hpp:66
irods::clone
T clone(T &a)
Definition: irods_re_plugin.hpp:59
irods::pluggable_rule_engine::start_operation
error start_operation(T &_in)
Definition: irods_re_plugin.hpp:189
irods::PLUGIN_TYPE_RULE_ENGINE
const std::string PLUGIN_TYPE_RULE_ENGINE("rule_engines")
irods::rule_engine_manager::call_start_operations
void call_start_operations()
Definition: irods_re_plugin.hpp:410
irods::init_global_re_packs
std::vector< re_pack_inp< default_re_ctx > > init_global_re_packs()
Definition: irods_re_plugin.cpp:32
irods::re_pack_inp::instance_name_
std::string instance_name_
Definition: irods_re_plugin.hpp:339
irods::pluggable_rule_engine::load_operation
error load_operation(void *handle, std::string _fcn, std::string _key)
Definition: irods_re_plugin.hpp:726
irods::convertToMsParam
error convertToMsParam(boost::any &itr, msParam_t *t)
Definition: irods_re_plugin.cpp:47
irods::pluggable_rule_engine
Definition: irods_re_plugin.hpp:169
RULE_ENGINE_ERROR
@ RULE_ENGINE_ERROR
Definition: rodsErrorTable.h:777
irods::pluggable_rule_engine::exec_rule_text
error exec_rule_text(T &_re_ctx, const std::string &_rt, msParamArray_t *_ms_params, const std::string &_out_desc, callback _callback)
Definition: irods_re_plugin.hpp:236
LOG_ERROR
#define LOG_ERROR
Definition: rodsLog.h:43
SYS_INVALID_INPUT_PARAM
@ SYS_INVALID_INPUT_PARAM
Definition: rodsErrorTable.h:195
irods::rule_engine_manager::re_plugin_mgr_
rule_engine_plugin_manager< T > & re_plugin_mgr_
Definition: irods_re_plugin.hpp:425
irods::pluggable_rule_engine::exec_rule_expression
error exec_rule_expression(T &_re_ctx, const std::string &_rt, msParamArray_t *_ms_params, callback _callback)
Definition: irods_re_plugin.hpp:252
irods::rule_engine_plugin_manager::re_plugin_map_
std::map< std::string, pluggable_rule_engine< T > * > re_plugin_map_
Definition: irods_re_plugin.hpp:372
irods::rule_execution_manager_pack
rule_execution_manager_pack
Definition: irods_re_plugin.hpp:123
irods::experimental::filesystem::client::end
auto end(const collection_iterator &) noexcept -> const collection_iterator
Definition: collection_iterator.hpp:88
irods::dynamic_operation_execution_manager::exec_rule_expression
error exec_rule_expression(const std::string &_instance_name, const std::string &_rule_text, msParamArray_t *_ms_params)
Definition: irods_re_plugin.hpp:293
SYS_NOT_SUPPORTED
@ SYS_NOT_SUPPORTED
Definition: rodsErrorTable.h:133
SUCCESS
#define SUCCESS()
Definition: irods_error.hpp:121
irods::experimental::filesystem::client::begin
auto begin(collection_iterator _iter) noexcept -> collection_iterator
Definition: collection_iterator.hpp:83
rule_exists
irods::error rule_exists(irods::default_re_ctx &, const std::string &_rn, bool &_ret)
Definition: libirods_rule_engine_plugin-cpp_default_policy.cpp:896
irods::rule_engine_context_manager< T, C, AUDIT_RULE >::exec_rule_expression
error exec_rule_expression(const std::string &_instance_name, const std::string &_rt, msParamArray_t *_ms_params)
Definition: irods_re_plugin.hpp:598
irods::error::code
long long code() const
Definition: irods_error.cpp:194
irods::rule_engine_plugin_manager
Definition: irods_re_plugin.hpp:348
irods::rule_engine_context_manager< T, C, AUDIT_RULE >::list_rules
error list_rules(std::vector< std::string > &rule_vec)
Definition: irods_re_plugin.hpp:624
irods::pluggable_rule_engine::rule_exists
error rule_exists(const std::string &_rn, T &_re_ctx, bool &_out)
Definition: irods_re_plugin.hpp:207
irods::pluggable_rule_engine::stop_operation
error stop_operation(T &_in)
Definition: irods_re_plugin.hpp:198
irods::rule_engine_plugin_manager::resolve
error resolve(std::string &_plugin_name, const std::string &_inst_name, pluggable_rule_engine< T > *&_re_ptr)
Definition: irods_re_plugin.hpp:357
LOG_DEBUG
#define LOG_DEBUG
Definition: rodsLog.h:23
irods::pluggable_rule_engine::pluggable_rule_engine
pluggable_rule_engine(const std::string &_in, const std::string &_context)
Definition: irods_re_plugin.hpp:172
irods::dynamic_operation_execution_manager
Definition: irods_re_plugin.hpp:277
irods
Definition: apiHandler.hpp:35
irods::pluggable_rule_engine::exec_rule
error exec_rule(const std::string &_rn, T &_re_ctx, As &&... _ps, callback _callback)
Definition: irods_re_plugin.hpp:226
RE_TYPE_ERROR
@ RE_TYPE_ERROR
Definition: rodsErrorTable.h:720
irods::rule_engine_context_manager< T, C, DONT_AUDIT_RULE >::exec_rule_text
error exec_rule_text(const std::string &_instance_name, const std::string &_rt, msParamArray_t *_ms_params, const std::string &_out_desc)
Definition: irods_re_plugin.hpp:654
irods::re_pack_inp
Definition: irods_re_plugin.hpp:338
exec_rule
irods::error exec_rule(irods::default_re_ctx &, const std::string &_rn, std::list< boost::any > &_ps, irods::callback _eff_hdlr)
Definition: libirods_rule_engine_plugin-cpp_default_policy.cpp:910
irods::rule_engine_context_manager< T, C, AUDIT_RULE >::exec_rule
error exec_rule(const std::string &_rn, As &&... _ps)
Definition: irods_re_plugin.hpp:536
irods_load_plugin.hpp
irods::rule_engine_manager::call_stop_operations
void call_stop_operations()
Definition: irods_re_plugin.hpp:416
irods::pluggable_rule_engine::operations_
irods::lookup_table< boost::any > operations_
Definition: irods_re_plugin.hpp:269
terminate_irods_processes.e
e
Definition: terminate_irods_processes.py:19
irods::AUDIT_RULE
@ AUDIT_RULE
Definition: irods_re_plugin.hpp:124
INVALID_ANY_CAST
@ INVALID_ANY_CAST
Definition: rodsErrorTable.h:771
irods::rule_engine_plugin_manager::~rule_engine_plugin_manager
~rule_engine_plugin_manager()
Definition: irods_re_plugin.hpp:353
irods::rule_engine_plugin_manager::rule_engine_plugin_manager
rule_engine_plugin_manager(std::string _dir)
Definition: irods_re_plugin.hpp:351
irods::callback
Definition: irods_re_plugin.hpp:133
irods::dynamic_operation_execution_manager::dynamic_operation_execution_manager
dynamic_operation_execution_manager(std::shared_ptr< rule_engine_context_manager< T, C, Audit > > _re_mgr)
Definition: irods_re_plugin.hpp:280
irods::pluggable_rule_engine::add_operation
error add_operation(const std::string &_op, std::function< error(types_t...)> _f)
Definition: irods_re_plugin.hpp:176
irods::default_re_ctx
unit default_re_ctx
Definition: irods_re_plugin.hpp:739
MsParam
Definition: msParam.h:76
irods::pack
std::list< boost::any > pack(As &&... _ps)
Definition: irods_re_plugin.hpp:109
rodsLog.h
irods::log
void log(const error &)
Definition: irods_log.cpp:13
irods::rule_engine_context_manager< T, C, DONT_AUDIT_RULE >::exec_rule_expression
error exec_rule_expression(const std::string &_instance_name, const std::string &_rt, msParamArray_t *_ms_params)
Definition: irods_re_plugin.hpp:681
irods::rule_engine_context_manager< T, C, AUDIT_RULE >::rule_engine_context_manager
rule_engine_context_manager(rule_engine_manager< T, C > &_re_mgr, C _ctx)
Definition: irods_re_plugin.hpp:528
irods::rule_exists_manager
Definition: irods_re_plugin.hpp:496
irods::re_plugin_operation
error(*)(T &,...) re_plugin_operation
Definition: irods_re_plugin.hpp:165
ERROR
#define ERROR(code_, message_)
Definition: irods_error.hpp:117
irods::rule_engine_manager::~rule_engine_manager
~rule_engine_manager()
Definition: irods_re_plugin.hpp:392
irods::error
Definition: irods_error.hpp:23
irods::global_re_plugin_mgr
Definition: irods_re_plugin.hpp:834
irods::rule_engine_manager::init_rule_engine
error init_rule_engine(re_pack_inp< T > &_inp)
Definition: irods_re_plugin.hpp:395
irods::rule_engine_context_manager< T, C, AUDIT_RULE >::ctx_
C ctx_
Definition: irods_re_plugin.hpp:629
get_db_schema_version.l
l
Definition: get_db_schema_version.py:19
irods::list_to_var_arg
error list_to_var_arg(std::list< boost::any > &_l)
Definition: irods_re_plugin.cpp:22
irods::rule_engine_context_manager< T, C, AUDIT_RULE >::rex_mgr_
dynamic_operation_execution_manager< T, C, DONT_AUDIT_RULE > rex_mgr_
Definition: irods_re_plugin.hpp:630
irods::unpack::unpack
unpack(std::list< boost::any > &_l)
Definition: irods_re_plugin.cpp:30
irods::rule_exists_manager::re_mgr_
rule_engine_manager< T, C > & re_mgr_
Definition: irods_re_plugin.hpp:517
irods::rule_engine_manager::re_packs_
std::list< re_pack_inp< T > > re_packs_
Definition: irods_re_plugin.hpp:423
run_tests.callback
callback
Definition: run_tests.py:119
irods::dynamic_operation_execution_manager::exec_rule_text
error exec_rule_text(const std::string &_instance_name, const std::string &_rule_text, msParamArray_t *_ms_params, const std::string &_out_desc)
Definition: irods_re_plugin.hpp:284
irods::log_error_code
void log_error_code(const error &e)
Definition: irods_re_plugin.hpp:442
irods::rule_engine_manager
Definition: irods_re_plugin.hpp:381
op
Definition: parser.hpp:25
irods::dynamic_operation_execution_manager::call
error call(std::string _instance_name, std::string _operation_name, OP _operation, As &&... _ps)
Definition: irods_re_plugin.hpp:302
irods.six.b
def b(s)
Definition: six.py:606
error
int error
Definition: filesystem.cpp:101
RuleExecInfo
Definition: irods_re_structs.hpp:18
irods_re_structs.hpp
irods::global_re_plugin_mgr::global_re_packs
std::vector< re_pack_inp< default_re_ctx > > global_re_packs
Definition: irods_re_plugin.hpp:836
irods::rule_engine_context_manager< T, C, DONT_AUDIT_RULE >::list_rules
error list_rules(std::vector< std::string > &rule_vec)
Definition: irods_re_plugin.hpp:707
irods::serialize::op_
boost::any op_
Definition: irods_re_plugin.hpp:160
irods::DONT_AUDIT_RULE
@ DONT_AUDIT_RULE
Definition: irods_re_plugin.hpp:125
irods::re_pack_inp::re_ctx_
T re_ctx_
Definition: irods_re_plugin.hpp:341
irods::re_pack_inp::re_pack_inp
re_pack_inp(std::string _instance_name, std::string _plugin_name, T _re_ctx)
Definition: irods_re_plugin.hpp:343
irods::rule_engine_manager::rule_engine_manager
rule_engine_manager(rule_engine_plugin_manager< T > &_re_plugin_mgr, std::vector< re_pack_inp< T > > &_re_packs, microservice_manager< C > &_ms_mgr)
Definition: irods_re_plugin.hpp:383
irods::rule_engine_context_manager< T, C, DONT_AUDIT_RULE >::ctx_
C ctx_
Definition: irods_re_plugin.hpp:722
irods::rule_engine_context_manager< T, C, DONT_AUDIT_RULE >::rule_engine_context_manager
rule_engine_context_manager(rule_engine_manager< T, C > &_re_mgr, C _ctx)
Definition: irods_re_plugin.hpp:637
irods::unpack::l_
std::list< boost::any > & l_
Definition: irods_re_plugin.hpp:69
irods::foreach2
void foreach2(S &&a, T &&b, F &&f)
Definition: irods_re_plugin.hpp:813
irods_error.hpp
RE_PARSER_ERROR
@ RE_PARSER_ERROR
Definition: rodsErrorTable.h:695
irods::pluggable_rule_engine::list_rules
error list_rules(T &_re_ctx, std::vector< std::string > &_rule_vec)
Definition: irods_re_plugin.hpp:216
irods::serialize::op_name_
std::string op_name_
Definition: irods_re_plugin.hpp:161
irods::any_update
void any_update(boost::any &_p, T _p2)
Definition: irods_re_plugin.hpp:806
irods::re_pack_inp::re_
pluggable_rule_engine< T > * re_
Definition: irods_re_plugin.hpp:342
irods::is_continuation_code
bool is_continuation_code(int _error_code)
Definition: irods_re_plugin.hpp:429
MsParamArray
Definition: msParam.h:84
irods::pluggable_rule_engine::instance_name_
std::string instance_name_
Definition: irods_re_plugin.hpp:270
irods::rule_engine_plugin_manager::dir_
std::string dir_
Definition: irods_re_plugin.hpp:375
CODE
#define CODE(code_)
Definition: irods_error.hpp:120
irods::error::ok
bool ok()
Definition: irods_error.cpp:258
RULE_ENGINE_CONTINUE
@ RULE_ENGINE_CONTINUE
Definition: irods_state_table.h:28
irods::rule_engine_manager::ms_mgr_
microservice_manager< C > & ms_mgr_
Definition: irods_re_plugin.hpp:422
irods::any_extract
T any_extract(boost::any _p, std::function< T()> f)
Definition: irods_re_plugin.hpp:792
irods::rule_engine_context_manager< T, C, DONT_AUDIT_RULE >::exec_rule
error exec_rule(const std::string &_rn, As &&... _ps)
Definition: irods_re_plugin.hpp:642
irods::re_plugin_globals
std::unique_ptr< struct irods::global_re_plugin_mgr > re_plugin_globals
Definition: irods_re_plugin.cpp:16
irods::rule_engine_context_manager< T, C, AUDIT_RULE >::exec_rule_text
error exec_rule_text(const std::string &_instance_name, const std::string &_rt, msParamArray_t *_ms_params, const std::string &_out_desc)
Definition: irods_re_plugin.hpp:571
irods_lookup_table.hpp
irods::rule_exists_manager::rule_exists
error rule_exists(const std::string &_rn, bool &ret)
Definition: irods_re_plugin.hpp:503
irods::serialize
Definition: irods_re_plugin.hpp:146
irods_state_table.h
irods::dynamic_operation_execution_manager::re_mgr_
std::shared_ptr< rule_engine_context_manager< T, C, Audit > > re_mgr_
Definition: irods_re_plugin.hpp:331
irods::global_re_plugin_mgr::global_re_mgr
rule_engine_manager< default_re_ctx, default_ms_ctx > global_re_mgr
Definition: irods_re_plugin.hpp:838