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)  

apiHandler.hpp
Go to the documentation of this file.
1 
4 /* apiHandler.h - header file for apiHandler.h */
5 
6 #ifndef API_HANDLER_HPP
7 #define API_HANDLER_HPP
8 
9 // =-=-=-=-=-=-=-
10 // boost includes
11 
12 #include "rods.h"
13 #include "packStruct.h"
14 #include "irods_lookup_table.hpp"
15 #include "irods_plugin_base.hpp"
17 #include "irods_stacktrace.hpp"
18 #include "boost/shared_ptr.hpp"
19 #include "boost/any.hpp"
20 #include "irods_pack_table.hpp"
21 #include "irods_at_scope_exit.hpp"
22 
24 #include "irods_re_plugin.hpp"
26 
27 #include <functional>
28 #include <utility>
29 #include <type_traits>
30 #include <vector>
31 #include <string>
32 #include <string_view>
33 
34 namespace irods
35 {
36 // NOOP function for clearInStruct
37  void clearInStruct_noop( void* );
38 
39  struct apidef_t {
40  // =-=-=-=-=-=-=-
41  // attributes
42  int apiNumber; /* the API number */
43  char* apiVersion; /* The API version of this call */
44  int clientUserAuth; /* Client user authentication level.
45  * NO_USER_AUTH, REMOTE_USER_AUTH,
46  * LOCAL_USER_AUTH, REMOTE_PRIV_USER_AUTH or
47  * LOCAL_PRIV_USER_AUTH */
48  int proxyUserAuth; /* same for proxyUser */
49  const char* inPackInstruct; /* the packing instruct for the input
50  * struct */
51  int inBsFlag; /* input bytes stream flag. 0 ==> no input
52  * byte stream. 1 ==> we have an input byte
53  * stream */
54  const char* outPackInstruct;/* the packing instruction for the
55  * output struct */
56  int outBsFlag; /* output bytes stream. 0 ==> no output byte
57  * stream. 1 ==> we have an output byte stream
58  */
59  boost::any svrHandler; /* the server handler. should be defined NULL for
60  * client */
61 
62  const char * operation_name;
63 
64  std::function<void( void* )> clearInStruct; // free input struct function
65 
66  int(*call_wrapper)(...); // wraps the api call for type casting
67  }; // struct apidef_t
68 
69  template <typename Integer,
71  bool is_acceptable_error(Integer error_code) {
72  static const std::vector<Integer> acceptable_errors {
73  SYS_NO_HANDLER_REPLY_MSG //... others as necessary
74  };
75  return std::any_of( acceptable_errors.begin(), acceptable_errors.end(),
76  [error_code](auto listed)->bool { return listed == error_code; }
77  );
78  }
79 
80  template <typename... types_t>
82  private:
83  std::function<int(rsComm_t*, types_t...)> fcn_;
84 
85  public:
86  api_call_adaptor( std::function<int(rsComm_t*, types_t...)> _fcn )
87  : fcn_(_fcn)
88  {
89  }
90 
92  int ret = fcn_( _comm, _t... );
93  if( ret >= 0 ) {
94  return CODE( ret );
95  }
96  else {
97  return ERROR( ret, "fail" );
98  }
99  }
100 
101  }; // class api_call_adaptor
102 
104  {
105  private:
107 
108  public:
111  template<typename... types_t>
112  error add_operation(const std::string& _op, std::function<int(types_t...)> _f)
113  {
114  if ( _op.empty() ) {
115  std::stringstream msg;
116  msg << "empty operation key [" << _op << "]";
117  return ERROR(SYS_INVALID_INPUT_PARAM, msg.str());
118  }
119 
120  operation_name = _op;
122 
123  return SUCCESS();
124  } // add_operation
125 
126  template<typename... types_t>
127  int call_handler(rsComm_t* _comm, types_t... _t)
128  {
129  using namespace std;
130 
132  rodsLog(LOG_ERROR, "missing api operation [%s]", operation_name.c_str());
134  }
135 
136  try {
137  using fcn_t = std::function<int(rsComm_t*, types_t...)>;
138  fcn_t fcn = boost::any_cast<fcn_t>( operations_[ operation_name ] );
139 #ifdef ENABLE_RE
141  irods::plugin_context ctx(_comm,prop_map);
142  ruleExecInfo_t rei;
143  memset( &rei, 0, sizeof( rei ) );
144  if (_comm) {
145  rei.rsComm = _comm;
146  rei.uoic = &_comm->clientUser;
147  rei.uoip = &_comm->proxyUser;
148  }
149 
150  rule_engine_context_manager_type re_ctx_mgr(re_plugin_globals->global_re_mgr, &rei);
151 
152  // Always run the finally-PEP at scope exit.
153  at_scope_exit invoke_finally_pep{[&] {
154  error finally_err = invoke_policy_enforcement_point(re_ctx_mgr,
155  ctx,
157  "finally",
158  forward<types_t>(_t)...);
159 
160  if (!finally_err.ok()) {
161  irods::log(PASS(finally_err));
162  }
163  }};
164 
165  error op_err = SUCCESS();
166 
167  // invoke the pre-pep for this operation
168  error pre_err = invoke_policy_enforcement_point(
169  re_ctx_mgr,
170  ctx,
172  "pre",
173  std::forward<types_t>(_t)...);
174 
175  if (pre_err.code() != RULE_ENGINE_SKIP_OPERATION) {
176  if (!pre_err.ok()) {
177  // if the pre-pep fails, invoke the exception pep
178  error except_err = invoke_policy_enforcement_point(
179  re_ctx_mgr,
180  ctx,
182  "except",
183  std::forward<types_t>(_t)...);
184 
185  if (!except_err.ok()) {
186  irods::log(PASS(except_err));
187  }
188 
189  return pre_err.code();
190  }
191 
192  using adapted_func_type = std::function<error(irods::plugin_context&, rsComm_t*, types_t...)>;
193  adapted_func_type adapted_fcn{api_call_adaptor<types_t...>(fcn)};
194  op_err = adapted_fcn(ctx, _comm, forward<types_t>(_t)...);
195 
196  if (!op_err.ok() && !is_acceptable_error(op_err.code())) {
197  // if the operation fails, invoke the exception pep
198  error except_err = invoke_policy_enforcement_point(
199  re_ctx_mgr,
200  ctx,
202  "except",
203  forward<types_t>(_t)...);
204 
205  if (!except_err.ok()) {
206  irods::log(PASS(except_err));
207  }
208 
209  return op_err.code();
210  }
211 
212  // invoke the post-pep for this operation
213  error post_err = invoke_policy_enforcement_point(
214  re_ctx_mgr,
215  ctx,
217  "post",
218  forward<types_t>(_t)...);
219  if (!post_err.ok()) {
220  // if the post-pep fails, invoke the exception pep
221  error except_err = invoke_policy_enforcement_point(
222  re_ctx_mgr,
223  ctx,
225  "except",
226  forward<types_t>(_t)...);
227 
228  if (!except_err.ok()) {
229  irods::log(PASS(except_err));
230  }
231 
232  return post_err.code();
233  }
234 
235  return op_err.code();
236  }
237 
238  return op_err.code();
239 #else // ENABLE_RE
240  return fcn(_comm, _t...);
241 #endif // ENABLE_RE
242  }
243  catch (const boost::bad_any_cast&) {
244  std::string msg( "failed for call - " );
245  msg += operation_name;
247  return INVALID_ANY_CAST;
248  }
249 
250  return 0;
251  } // call_handler
252 
253  // =-=-=-=-=-=-=-
254  // ctors
255  api_entry( apidef_t& );
256 
257  api_entry( const api_entry& );
258 
259  // =-=-=-=-=-=-=-
260  // operators
261  api_entry& operator=( const api_entry& );
262 
263  // =-=-=-=-=-=-=-
264  // attributes
265  int apiNumber; /* the API number */
266  char* apiVersion; /* The API version of this call */
267  int clientUserAuth; /* Client user authentication level.
268  * NO_USER_AUTH, REMOTE_USER_AUTH,
269  * LOCAL_USER_AUTH, REMOTE_PRIV_USER_AUTH or
270  * LOCAL_PRIV_USER_AUTH */
271  int proxyUserAuth; /* same for proxyUser */
272  const char* inPackInstruct; /* the packing instruct for the input
273  * struct */
274  int inBsFlag; /* input bytes stream flag. 0 ==> no input
275  * byte stream. 1 ==> we have an input byte
276  * stream */
277  const char* outPackInstruct;/* the packing instruction for the
278  * output struct */
279  int outBsFlag; /* output bytes stream. 0 ==> no output byte
280  * stream. 1 ==> we have an output byte stream
281  */
282  funcPtr call_wrapper; // wraps the api call for type casting
283  std::string in_pack_key;
284  std::string out_pack_key;
285  std::string in_pack_value;
286  std::string out_pack_value;
287  std::string operation_name;
288 
290 
291  std::function<void( void* )> clearInStruct; //free input struct function
292 
293  private:
294 #ifdef ENABLE_RE
295  template<typename... types_t>
296  error invoke_policy_enforcement_point(
298  plugin_context _ctx,
299  const std::string& _operation_name,
300  const std::string& _class,
301  types_t... _t)
302  {
303  bool ret = false;
304  error saved_op_err = SUCCESS();
305  error skip_op_err = SUCCESS();
306 
307  for (auto& ns : NamespacesHelper::Instance()->getNamespaces()) {
308  std::string rule_name = ns + "pep_" + _operation_name + "_" + _class;
309 
310  if (RuleExistsHelper::Instance()->checkOperation( rule_name ) ) {
311  if (_re_ctx_mgr.rule_exists(rule_name, ret).ok() && ret) {
312  error op_err = _re_ctx_mgr.exec_rule(rule_name, instance_name_, _ctx, std::forward<types_t>(_t)...);
313 
314  if (!op_err.ok()) {
315  rodsLog(LOG_DEBUG, "%s-pep rule [%s] failed with error code [%d]", _class.c_str(), rule_name.c_str(), op_err.code());
316  saved_op_err = op_err;
317  }
318  else if (op_err.code() == RULE_ENGINE_SKIP_OPERATION) {
319  skip_op_err = op_err;
320 
321  if (_class != "pre") {
322  rodsLog(LOG_WARNING, "RULE_ENGINE_SKIP_OPERATION (%d) incorrectly returned from PEP [%s]! "
323  "RULE_ENGINE_SKIP_OPERATION should only be returned from pre-PEPs!",
324  RULE_ENGINE_SKIP_OPERATION, rule_name.c_str());
325  }
326  }
327  }
328  else {
329  rodsLog(LOG_DEBUG10, "Rule [%s] passes regex test, but does not exist", rule_name.c_str());
330  }
331  }
332  }
333 
334  if (!saved_op_err.ok()) {
335  return saved_op_err;
336  }
337 
338  if (skip_op_err.code() == RULE_ENGINE_SKIP_OPERATION) {
339  return skip_op_err;
340  }
341 
342  return saved_op_err;
343  } // invoke_policy_enforcement_point
344 #endif // ENABLE_RE
345  }; // class api_entry
346 
347  typedef boost::shared_ptr< api_entry > api_entry_ptr;
348 
352  : public lookup_table<api_entry_ptr, size_t, boost::hash<size_t>>
353  {
354  public:
355  api_entry_table(apidef_t defs[], size_t size);
356 
357  auto is_plugin_loaded(std::string_view plugin_name) -> bool;
358  auto mark_plugin_as_loaded(std::string_view plugin_name) -> void;
359 
360  private:
361  std::vector<std::string> loaded_plugins_;
362  }; // class api_entry_table
363 
367  api_entry_table& _api_tbl, // table holding api entries
368  pack_entry_table& _pack_tbl, // table for pack struct ref
369  bool _cli_flg = true ); // default to client
370 }; // namespace irods
371 
372 #endif /* API_HANDLER_H */
irods::apidef_t::apiNumber
int apiNumber
Definition: apiHandler.hpp:42
rodsLog
void rodsLog(int level, const char *formatStr,...)
Definition: rodsLog.cpp:86
irods::apidef_t::svrHandler
boost::any svrHandler
Definition: apiHandler.hpp:59
irods::at_scope_exit
Definition: irods_at_scope_exit.hpp:10
irods::apidef_t::outBsFlag
int outBsFlag
Definition: apiHandler.hpp:56
rsComm_t
Definition: rcConnect.h:145
irods::lookup_table< boost::any >
irods::api_call_adaptor::fcn_
std::function< int(rsComm_t *, types_t...)> fcn_
Definition: apiHandler.hpp:83
RuleExistsHelper::Instance
static RuleExistsHelper * Instance()
Definition: irods_re_ruleexistshelper.cpp:6
irods::apidef_t::call_wrapper
int(* call_wrapper)(...)
Definition: apiHandler.hpp:66
irods::api_entry::outPackInstruct
const char * outPackInstruct
Definition: apiHandler.hpp:277
irods::api_entry::out_pack_key
std::string out_pack_key
Definition: apiHandler.hpp:284
irods::api_entry::out_pack_value
std::string out_pack_value
Definition: apiHandler.hpp:286
RULE_ENGINE_SKIP_OPERATION
@ RULE_ENGINE_SKIP_OPERATION
Definition: irods_state_table.h:29
irods_plugin_base.hpp
irods::rule_engine_context_manager
Definition: irods_re_plugin.hpp:522
irods_stacktrace.hpp
PASS
#define PASS(prev_error_)
Definition: irods_error.hpp:118
irods::api_entry::add_operation
error add_operation(const std::string &_op, std::function< int(types_t...)> _f)
Definition: apiHandler.hpp:112
LOG_WARNING
#define LOG_WARNING
Definition: rodsLog.h:38
irods::api_entry::outBsFlag
int outBsFlag
Definition: apiHandler.hpp:279
irods::api_entry_table::loaded_plugins_
std::vector< std::string > loaded_plugins_
Definition: apiHandler.hpp:361
irods::init_api_table
error init_api_table(api_entry_table &_api_tbl, pack_entry_table &_pack_tbl, bool _cli_flg=true)
Definition: apiHandler.cpp:103
irods::api_entry::in_pack_key
std::string in_pack_key
Definition: apiHandler.hpp:283
irods::api_entry::apiNumber
int apiNumber
Definition: apiHandler.hpp:265
irods::api_entry::proxyUserAuth
int proxyUserAuth
Definition: apiHandler.hpp:271
irods::api_entry::api_entry
api_entry(apidef_t &)
Definition: apiHandler.cpp:17
irods::apidef_t
Definition: apiHandler.hpp:39
NamespacesHelper::Instance
static NamespacesHelper * Instance()
Definition: irods_re_namespaceshelper.cpp:6
irods::apidef_t::proxyUserAuth
int proxyUserAuth
Definition: apiHandler.hpp:48
irods_re_ruleexistshelper.hpp
irods::api_call_adaptor
Definition: apiHandler.hpp:81
irods::plugin_context
Definition: irods_plugin_context.hpp:18
LOG_ERROR
#define LOG_ERROR
Definition: rodsLog.h:43
SYS_INVALID_INPUT_PARAM
@ SYS_INVALID_INPUT_PARAM
Definition: rodsErrorTable.h:195
irods_pack_table.hpp
irods_re_plugin.hpp
irods::api_entry_ptr
boost::shared_ptr< api_entry > api_entry_ptr
Definition: apiHandler.hpp:347
RuleExecInfo::rsComm
rsComm_t * rsComm
Definition: irods_re_structs.hpp:22
SUCCESS
#define SUCCESS()
Definition: irods_error.hpp:121
irods::apidef_t::operation_name
const char * operation_name
Definition: apiHandler.hpp:62
irods::error::code
long long code() const
Definition: irods_error.cpp:194
irods::api_entry::call_wrapper
funcPtr call_wrapper
Definition: apiHandler.hpp:282
irods::api_call_adaptor::api_call_adaptor
api_call_adaptor(std::function< int(rsComm_t *, types_t...)> _fcn)
Definition: apiHandler.hpp:86
RuleExecInfo::uoip
userInfo_t * uoip
Definition: irods_re_structs.hpp:31
LOG_DEBUG
#define LOG_DEBUG
Definition: rodsLog.h:23
irods::api_entry::inBsFlag
int inBsFlag
Definition: apiHandler.hpp:274
rsComm_t::proxyUser
userInfo_t proxyUser
Definition: rcConnect.h:152
irods
Definition: apiHandler.hpp:35
irods::api_entry::call_handler
int call_handler(rsComm_t *_comm, types_t... _t)
Definition: apiHandler.hpp:127
irods::plugin_base
Definition: irods_plugin_base.hpp:48
irods::is_acceptable_error
bool is_acceptable_error(Integer error_code)
Definition: apiHandler.hpp:71
irods::api_entry::operation_name
std::string operation_name
Definition: apiHandler.hpp:287
irods::apidef_t::clearInStruct
std::function< void(void *)> clearInStruct
Definition: apiHandler.hpp:64
INVALID_ANY_CAST
@ INVALID_ANY_CAST
Definition: rodsErrorTable.h:771
irods::api_entry::extra_pack_struct
lookup_table< std::string > extra_pack_struct
Definition: apiHandler.hpp:289
get_irods_version.value
dictionary value
Definition: get_irods_version.py:27
irods::lookup_table::has_entry
bool has_entry(KeyType _k) const
Definition: irods_lookup_table.hpp:41
packStruct.h
irods::apidef_t::inPackInstruct
const char * inPackInstruct
Definition: apiHandler.hpp:49
irods::log
void log(const error &)
Definition: irods_log.cpp:13
SYS_NO_HANDLER_REPLY_MSG
@ SYS_NO_HANDLER_REPLY_MSG
Definition: rodsErrorTable.h:879
rsComm_t::clientUser
userInfo_t clientUser
Definition: rcConnect.h:153
ERROR
#define ERROR(code_, message_)
Definition: irods_error.hpp:117
irods::error
Definition: irods_error.hpp:23
int
typedef int((*funcPtr)())
irods::plugin_base::instance_name_
std::string instance_name_
Definition: irods_plugin_base.hpp:327
irods::api_entry_table
Definition: apiHandler.hpp:353
RuleExecInfo::uoic
userInfo_t * uoic
Definition: irods_re_structs.hpp:30
irods::api_entry::inPackInstruct
const char * inPackInstruct
Definition: apiHandler.hpp:272
irods::apidef_t::inBsFlag
int inBsFlag
Definition: apiHandler.hpp:51
irods_re_namespaceshelper.hpp
error
int error
Definition: filesystem.cpp:101
RuleExecInfo
Definition: irods_re_structs.hpp:18
irods::apidef_t::outPackInstruct
const char * outPackInstruct
Definition: apiHandler.hpp:54
irods::api_entry::apiVersion
char * apiVersion
Definition: apiHandler.hpp:266
irods::api_call_adaptor::operator()
irods::error operator()(irods::plugin_context &, rsComm_t *_comm, types_t... _t)
Definition: apiHandler.hpp:91
irods_at_scope_exit.hpp
irods::apidef_t::clientUserAuth
int clientUserAuth
Definition: apiHandler.hpp:44
irods::api_entry::operator=
api_entry & operator=(const api_entry &)
Definition: apiHandler.cpp:59
irods::pack_entry_table
Definition: irods_pack_table.hpp:13
LOG_DEBUG10
#define LOG_DEBUG10
Definition: rodsLog.h:19
size
long long size
Definition: filesystem.cpp:102
irods::api_entry::clientUserAuth
int clientUserAuth
Definition: apiHandler.hpp:267
CODE
#define CODE(code_)
Definition: irods_error.hpp:120
irods::error::ok
bool ok()
Definition: irods_error.cpp:258
irods::apidef_t::apiVersion
char * apiVersion
Definition: apiHandler.hpp:43
irods::clearInStruct_noop
void clearInStruct_noop(void *)
Definition: irods_pack_table.cpp:20
irods::api_entry
Definition: apiHandler.hpp:104
irods::re_plugin_globals
std::unique_ptr< struct irods::global_re_plugin_mgr > re_plugin_globals
Definition: irods_re_plugin.cpp:16
rods.h
irods_lookup_table.hpp
irods::plugin_base::operations_
lookup_table< boost::any > operations_
Definition: irods_plugin_base.hpp:340
irods::api_entry::clearInStruct
std::function< void(void *)> clearInStruct
Definition: apiHandler.hpp:291
irods::api_entry::in_pack_value
std::string in_pack_value
Definition: apiHandler.hpp:285