Skip to content

Commit

Permalink
Supporting asynchronous method implementations
Browse files Browse the repository at this point in the history
* Command map and dispatcher declare types for callbacks to pass
  error code and out-arguments.

* Handlers in generated targets meet these callback signatures.

* Various dispatch methods changed so that out-arguments and
  error codes are removed from the signature, and the appropriate
  callback type is added, all to track changes to command map and
  dispatcher.

* Generated targets include default asynchronous implementations
  which call synchronous (pure virtual) methods.

* One finder method FinderClient::dispatch_tunneled_xrl is
  implemented asynchronously.

* Most changes above compiled in only if XORP_ENABLE_ASYNC_SERVER
  is defined, as set by enable_async_server=True on scons.

* STCP changed from using list of RequestStates in seqno order to
  map indexed by seqno.  This allows responses to return
  out-of-order, which is possible if a server implements a method
  asynchronously.

Signed-off-by: Steven Simpson <ss@comp.lancs.ac.uk>
  • Loading branch information
simpsonst authored and greearb committed Mar 22, 2011
1 parent 5a19f94 commit 619aad8
Show file tree
Hide file tree
Showing 15 changed files with 439 additions and 62 deletions.
13 changes: 13 additions & 0 deletions xorp/SConstruct
Expand Up @@ -92,6 +92,7 @@ vars.AddVariables(
BoolVariable('enable_tests', 'Build Test Programs', False),
BoolVariable('enable_click', 'Build CLICK support', False),
BoolVariable('enable_fea_dummy', 'Build fea-dummy target', True),
BoolVariable('enable_async_server', 'Permit asynchronous method implementations', False),
BoolVariable('debug_xrldb', 'Build with runtime XRL syntax validation in Router Manager', False),
EnumVariable('debug', 'Build with debug symbols', 'full',
allowed_values=('no', 'yes', 'full', 'override'),
Expand Down Expand Up @@ -267,6 +268,7 @@ print 'Enable xorpsh ', env['enable_xorpsh']
print 'Enable Test Programs: ', env['enable_tests']
print 'Enable CLICK: ', env['enable_click']
print 'Enable FEA Dummy: ', env['enable_fea_dummy']
print 'Enable async method impls: ', env['enable_async_server']
print 'Enable BGP: ', env['enable_bgp']
print 'Try Enable BOOST: ', env['enable_boost']
print 'Try Enable uSTL : ', env['enable_ustl']
Expand Down Expand Up @@ -411,6 +413,13 @@ if tst and (tst == "no"):
else:
env['enable_fea_dummy'] = True

# Default to disabled
tst = ARGUMENTS.get('enable_async_server', False)
if tst and (tst == "no"):
env['enable_async_server'] = False
else:
env['enable_async_server'] = True

# Default to enabled
tst = ARGUMENTS.get('enable_bgp', True)
if tst and (tst == "no"):
Expand Down Expand Up @@ -635,6 +644,10 @@ if not env.GetOption('clean') and \
if tst and not (tst == "no"):
conf.Define('XORP_USE_FEA_DUMMY')

tst = ARGUMENTS.get('enable_async_server', False)
if tst and not (tst == "no"):
conf.Define('XORP_ENABLE_ASYNC_SERVER')

if env['enable_xorpsh']:
conf.Define('XORP_USE_XORPSH')

Expand Down
33 changes: 29 additions & 4 deletions xorp/libxipc/finder_client.cc
Expand Up @@ -961,8 +961,20 @@ FinderClient::uncache_xrls_from_target(const string& target)
XORP_UINT_CAST(n), target.c_str());
}

XrlCmdError
FinderClient::dispatch_tunneled_xrl(const string& xrl_str)
#ifdef XORP_ENABLE_ASYNC_SERVER
void
FinderClient::dispatch_tunneled_xrl_cb(const XrlError &e, const XrlArgs *a,
XrlRespCallback cb) const
{
UNUSED(e);
UNUSED(a);
cb->dispatch(XrlCmdError::OKAY(), NULL);
}
#endif

XrlCmdRT
FinderClient::dispatch_tunneled_xrl(const string& xrl_str
XRL_CMD_OPT_CALLBACK(cb))
{
finder_trace_init("dispatch_tunneled_xrl(\"%s\")", xrl_str.c_str());
Xrl xrl;
Expand All @@ -971,16 +983,29 @@ FinderClient::dispatch_tunneled_xrl(const string& xrl_str)
InstanceList::iterator i = find_instance(xrl.target());
if (i == _ids.end()) {
finder_trace_result("target not found");
return XrlCmdError::COMMAND_FAILED("target not found");
XRL_CMD_RETURN_ERROR
(cb, XrlCmdError::COMMAND_FAILED("target not found"));
}

#ifdef XORP_ENABLE_ASYNC_SERVER
XrlDispatcherCallback ret_vals =
callback(this, &FinderClient::dispatch_tunneled_xrl_cb, cb);
#else
XrlArgs ret_vals;
#endif

i->dispatcher()->dispatch_xrl(xrl.command(),
xrl.args(), ret_vals);
finder_trace_result("success");

#ifdef XORP_ENABLE_ASYNC_SERVER
return;
#else
return XrlCmdError::OKAY();
#endif
} catch (InvalidString&) {
return XrlCmdError::COMMAND_FAILED("Bad Xrl string");
XRL_CMD_RETURN_ERROR
(cb, XrlCmdError::COMMAND_FAILED("Bad Xrl string"));
}
}

Expand Down
13 changes: 11 additions & 2 deletions xorp/libxipc/finder_client.hh
Expand Up @@ -32,6 +32,7 @@
#include "finder_messenger.hh"

#include "xrl_pf.hh"
#include "xrl_cmd_map.hh"

class FinderClientOp;
class FinderClientObserver;
Expand Down Expand Up @@ -76,7 +77,8 @@ public:
virtual ~FinderClientXrlCommandInterface() {}
virtual void uncache_xrl(const string& xrl) = 0;
virtual void uncache_xrls_from_target(const string& target) = 0;
virtual XrlCmdError dispatch_tunneled_xrl(const string& xrl) = 0;
virtual XrlCmdRT dispatch_tunneled_xrl(const string& xrl
XRL_CMD_OPT_CALLBACK(cb)) = 0;
};

/**
Expand Down Expand Up @@ -312,7 +314,14 @@ protected:
// FinderClientXrlCommandInterface
void uncache_xrl(const string& xrl);
void uncache_xrls_from_target(const string& target);
XrlCmdError dispatch_tunneled_xrl(const string& xrl);
XrlCmdRT dispatch_tunneled_xrl(const string& xrl
XRL_CMD_OPT_CALLBACK(cb));
#ifdef XORP_ENABLE_ASYNC_SERVER
private:
void
dispatch_tunneled_xrl_cb(const XrlError &e, const XrlArgs *a,
XrlRespCallback cb) const;
#endif

protected:
void crank();
Expand Down
30 changes: 30 additions & 0 deletions xorp/libxipc/finder_client_xrl_target.cc
Expand Up @@ -85,15 +85,45 @@ FinderClientXrlTarget::finder_client_0_2_remove_xrls_for_target_from_cache(
return XrlCmdError::OKAY();
}

#ifdef XORP_ENABLE_ASYNC_SERVER
void
FinderClientXrlTarget::async_finder_client_0_2_dispatch_tunneled_xrl(
const string& xrl,
FinderClient02DispatchTunneledXrlCB cb)
{
_client->dispatch_tunneled_xrl(xrl,
callback(this,
&FinderClientXrlTarget::dispatch_tunneled_xrl_cb,
cb));
}

void
FinderClientXrlTarget::dispatch_tunneled_xrl_cb(
const XrlCmdError &e,
const XrlArgs *out,
FinderClient02DispatchTunneledXrlCB cb) const
{
UNUSED(out);
cb->dispatch(XrlCmdError::OKAY(), e.error_code(), e.note());
}
#endif

XrlCmdError
FinderClientXrlTarget::finder_client_0_2_dispatch_tunneled_xrl(
const string& xrl,
uint32_t& xrl_errno,
string& xrl_errtxt
)
{
#ifdef XORP_ENABLE_ASYNC_SERVER
UNUSED(xrl);
UNUSED(xrl_errno);
UNUSED(xrl_errtxt);
return XrlCmdError::COMMAND_FAILED("Unreachable");
#else
XrlCmdError e = _client->dispatch_tunneled_xrl(xrl);
xrl_errno = e.error_code();
xrl_errtxt = e.note();
return XrlCmdError::OKAY();
#endif
}
11 changes: 11 additions & 0 deletions xorp/libxipc/finder_client_xrl_target.hh
Expand Up @@ -46,12 +46,23 @@ public:
XrlCmdError finder_client_0_2_remove_xrls_for_target_from_cache(
const string& target);

#ifdef XORP_ENABLE_ASYNC_SERVER
void async_finder_client_0_2_dispatch_tunneled_xrl(const string& xrl,
FinderClient02DispatchTunneledXrlCB);
#endif
XrlCmdError finder_client_0_2_dispatch_tunneled_xrl(const string& xrl,
uint32_t& xrl_errno,
string& xrl_errtxt);

protected:
FinderClientXrlCommandInterface* _client;

#ifdef XORP_ENABLE_ASYNC_SERVER
private:
void dispatch_tunneled_xrl_cb(const XrlCmdError &e,
const XrlArgs *out,
FinderClient02DispatchTunneledXrlCB cb) const;
#endif
};

#endif // __LIBXIPC_FINDER_CLIENT_XRL_TARGET_HH__
15 changes: 15 additions & 0 deletions xorp/libxipc/finder_messenger.cc
Expand Up @@ -97,19 +97,34 @@ FinderMessengerBase::dispatch_xrl(uint32_t seqno, const Xrl& xrl)
if (manager())
manager()->messenger_active_event(this);

#ifdef XORP_ENABLE_ASYNC_SERVER
ce->dispatch(xrl.args(),
callback(this, &FinderMessengerBase::dispatch_xrl_cb, seqno));
#else
XrlArgs reply_args;
XrlError e = ce->dispatch(xrl.args(), &reply_args);
if (XrlCmdError::OKAY() == e) {
reply(seqno, e, &reply_args);
} else {
reply(seqno, e, 0);
}
#endif

// Announce we've dispatched xrl
if (manager())
manager()->messenger_inactive_event(this);
}

#ifdef XORP_ENABLE_ASYNC_SERVER
void
FinderMessengerBase::dispatch_xrl_cb(const XrlCmdError &e,
const XrlArgs *reply_args,
uint32_t seqno)
{
reply(seqno, e, XrlCmdError::OKAY() == e ? reply_args : NULL);
}
#endif

void
FinderMessengerBase::unhook_manager()
{
Expand Down
7 changes: 7 additions & 0 deletions xorp/libxipc/finder_messenger.hh
Expand Up @@ -123,6 +123,13 @@ protected:
void response_timeout(uint32_t seqno);

private:
#ifdef XORP_ENABLE_ASYNC_SERVER
void
dispatch_xrl_cb(const XrlCmdError &e,
const XrlArgs *reply_args,
uint32_t seqno);
#endif

class ResponseState {
public:
ResponseState(uint32_t seqno,
Expand Down
37 changes: 36 additions & 1 deletion xorp/libxipc/xrl_cmd_map.hh
Expand Up @@ -32,9 +32,44 @@
#include "xrl.hh"
#include "xrl_error.hh"

#ifdef XORP_ENABLE_ASYNC_SERVER
typedef void XrlCmdRT;

#define XRL_CMD_RETURN_ERROR(OUT, ERR) \
do { \
(OUT)->dispatch((ERR), NULL); \
return; \
} while (0)

typedef
XorpCallback2<void, const XrlCmdError &, const XrlArgs *>::RefPtr
XrlRespCallback;

typedef XrlRespCallback XrlCmdOT;

#define XRL_CMD_OPT_CALLBACK(V) , const XrlRespCallback& V

typedef
XorpCallback2<void, const XrlArgs&, XrlRespCallback>::RefPtr XrlRecvCallback;

#else

typedef const XrlCmdError XrlCmdRT;

#define XRL_CMD_RETURN_ERROR(OUT, ERR) \
do { \
return (ERR); \
} while (0)

typedef XrlArgs* XrlCmdOT;

#define XRL_CMD_OPT_CALLBACK(V)

typedef
XorpCallback2<const XrlCmdError, const XrlArgs&, XrlArgs*>::RefPtr XrlRecvCallback;

#endif

class XrlCmdEntry {
public:
XrlCmdEntry(const string& s, XrlRecvCallback cb) :
Expand All @@ -45,7 +80,7 @@ public:

const string& name() const { return _name; }

const XrlCmdError dispatch(const XrlArgs& inputs, XrlArgs* outputs) const {
XrlCmdRT dispatch(const XrlArgs& inputs, XrlCmdOT outputs) const {
return _cb->dispatch(inputs, outputs);
}

Expand Down
34 changes: 27 additions & 7 deletions xorp/libxipc/xrl_dispatcher.cc
Expand Up @@ -51,20 +51,25 @@ do { \
// ----------------------------------------------------------------------------
// XrlDispatcher methods

XrlError
XrlDispatcherRT
XrlDispatcher::dispatch_xrl(const string& method_name,
const XrlArgs& inputs,
XrlArgs& outputs) const
XrlDispatcherOT outputs) const
{
const XrlCmdEntry* c = get_handler(method_name.c_str());
if (c == 0) {
trace_xrl_dispatch("dispatch_xrl (invalid) ", method_name);
debug_msg("No handler for %s\n", method_name.c_str());
return XrlError::NO_SUCH_METHOD();
XRL_DISPATCHER_RETURN_ERROR(outputs, XrlError::NO_SUCH_METHOD());
}

trace_xrl_dispatch("dispatch_xrl (valid) ", method_name);
return c->dispatch(inputs, &outputs);
#ifdef XORP_ENABLE_ASYNC_SERVER
XrlCmdOT resp = callback(this, &XrlDispatcher::dispatch_cb, outputs);
#else
XrlCmdOT resp = &outputs;
#endif
return c->dispatch(inputs, resp);
}

XrlDispatcher::XI*
Expand All @@ -77,8 +82,23 @@ XrlDispatcher::lookup_xrl(const string& name) const
return new XI(c);
}

XrlError
XrlDispatcher::dispatch_xrl_fast(const XI& xi, XrlArgs& outputs) const
XrlDispatcherRT
XrlDispatcher::dispatch_xrl_fast(const XI& xi, XrlDispatcherOT outputs) const
{
return xi._cmd->dispatch(xi._xrl.args(), &outputs);
#ifdef XORP_ENABLE_ASYNC_SERVER
XrlCmdOT resp = callback(this, &XrlDispatcher::dispatch_cb, outputs);
#else
XrlCmdOT resp = &outputs;
#endif
return xi._cmd->dispatch(xi._xrl.args(), resp);
}

#ifdef XORP_ENABLE_ASYNC_SERVER
void
XrlDispatcher::dispatch_cb(const XrlCmdError &err,
const XrlArgs *outputs,
XrlDispatcherCallback resp) const
{
resp->dispatch(err, outputs);
}
#endif

0 comments on commit 619aad8

Please sign in to comment.