[Xorp-hackers] [PATCH] Supporting asynchronous method implementations
ss at comp.lancs.ac.uk
ss at comp.lancs.ac.uk
Fri Mar 11 05:36:28 PST 2011
From: Steven Simpson <ss at comp.lancs.ac.uk>
* 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.
* FinderClient made a friend of XrlCmdError so it can use the
private constructor.
* All changes compiled in only if XORP_ENABLE_ASYNC_SERVER is defined,
as set by enable_async_server=True on scons.
Signed-off-by: Steven Simpson <ss at comp.lancs.ac.uk>
---
xorp/SConstruct | 13 ++
xorp/libxipc/finder_client.cc | 28 ++++-
xorp/libxipc/finder_client.hh | 13 ++-
xorp/libxipc/finder_client_xrl_target.cc | 31 +++++
xorp/libxipc/finder_client_xrl_target.hh | 13 ++
xorp/libxipc/finder_messenger.cc | 15 +++
xorp/libxipc/finder_messenger.hh | 7 +
xorp/libxipc/xrl_cmd_map.hh | 34 ++++++-
xorp/libxipc/xrl_dispatcher.cc | 34 +++++-
xorp/libxipc/xrl_dispatcher.hh | 40 ++++++-
xorp/libxipc/xrl_error.hh | 7 +
xorp/libxipc/xrl_pf_stcp.cc | 42 ++++++--
xorp/libxipc/xrl_router.cc | 9 +-
xorp/libxipc/xrl_router.hh | 6 +-
xorp/xrl/scripts/tgt-gen | 179 +++++++++++++++++++++++++++---
15 files changed, 420 insertions(+), 51 deletions(-)
diff --git a/xorp/SConstruct b/xorp/SConstruct
index 56d36da..6ea1c3a 100644
--- a/xorp/SConstruct
+++ b/xorp/SConstruct
@@ -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'),
@@ -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']
@@ -412,6 +414,13 @@ else:
env['enable_fea_dummy'] = True
# Default to enabled
+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"):
env['enable_bgp'] = False
@@ -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')
diff --git a/xorp/libxipc/finder_client.cc b/xorp/libxipc/finder_client.cc
index 2fe7876..b39c622 100644
--- a/xorp/libxipc/finder_client.cc
+++ b/xorp/libxipc/finder_client.cc
@@ -961,8 +961,18 @@ 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
+{
+ cb->dispatch(XrlCmdError(e), a);
+}
+#endif
+
+XrlCmdRT
+FinderClient::dispatch_tunneled_xrl(const string& xrl_str
+ XrlCmdOptCallback(cb))
{
finder_trace_init("dispatch_tunneled_xrl(\"%s\")", xrl_str.c_str());
Xrl xrl;
@@ -971,16 +981,26 @@ 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");
+ XrlCmdReturnError(cb,
+ XrlCmdError::COMMAND_FAILED("target not found"));
}
XrlArgs ret_vals;
+#ifdef XORP_ENABLE_ASYNC_SERVER
+ XrlDispatcherCallback mycb =
+ callback(this, &FinderClient::dispatch_tunneled_xrl_cb, cb);
+ i->dispatcher()->dispatch_xrl(xrl.command(), xrl.args(), mycb);
+ finder_trace_result("success");
+ return;
+#else
i->dispatcher()->dispatch_xrl(xrl.command(),
xrl.args(), ret_vals);
finder_trace_result("success");
return XrlCmdError::OKAY();
+#endif
} catch (InvalidString&) {
- return XrlCmdError::COMMAND_FAILED("Bad Xrl string");
+ XrlCmdReturnError(cb,
+ XrlCmdError::COMMAND_FAILED("Bad Xrl string"));
}
}
diff --git a/xorp/libxipc/finder_client.hh b/xorp/libxipc/finder_client.hh
index 21e1f11..6e2b363 100644
--- a/xorp/libxipc/finder_client.hh
+++ b/xorp/libxipc/finder_client.hh
@@ -32,6 +32,7 @@
#include "finder_messenger.hh"
#include "xrl_pf.hh"
+#include "xrl_cmd_map.hh"
class FinderClientOp;
class FinderClientObserver;
@@ -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
+ XrlCmdOptCallback(cb)) = 0;
};
/**
@@ -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
+ XrlCmdOptCallback(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();
diff --git a/xorp/libxipc/finder_client_xrl_target.cc b/xorp/libxipc/finder_client_xrl_target.cc
index ce1ca05..eb9e01d 100644
--- a/xorp/libxipc/finder_client_xrl_target.cc
+++ b/xorp/libxipc/finder_client_xrl_target.cc
@@ -85,6 +85,30 @@ 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,
@@ -92,8 +116,15 @@ FinderClientXrlTarget::finder_client_0_2_dispatch_tunneled_xrl(
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
}
diff --git a/xorp/libxipc/finder_client_xrl_target.hh b/xorp/libxipc/finder_client_xrl_target.hh
index 59cc2b0..be6c664 100644
--- a/xorp/libxipc/finder_client_xrl_target.hh
+++ b/xorp/libxipc/finder_client_xrl_target.hh
@@ -46,12 +46,25 @@ 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__
diff --git a/xorp/libxipc/finder_messenger.cc b/xorp/libxipc/finder_messenger.cc
index 5e71386..a6aef38 100644
--- a/xorp/libxipc/finder_messenger.cc
+++ b/xorp/libxipc/finder_messenger.cc
@@ -97,6 +97,10 @@ 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) {
@@ -104,12 +108,23 @@ FinderMessengerBase::dispatch_xrl(uint32_t seqno, const Xrl& xrl)
} 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()
{
diff --git a/xorp/libxipc/finder_messenger.hh b/xorp/libxipc/finder_messenger.hh
index d80405d..d1d4c71 100644
--- a/xorp/libxipc/finder_messenger.hh
+++ b/xorp/libxipc/finder_messenger.hh
@@ -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,
diff --git a/xorp/libxipc/xrl_cmd_map.hh b/xorp/libxipc/xrl_cmd_map.hh
index 45c6bd6..e6fe00b 100644
--- a/xorp/libxipc/xrl_cmd_map.hh
+++ b/xorp/libxipc/xrl_cmd_map.hh
@@ -32,9 +32,41 @@
#include "xrl.hh"
#include "xrl_error.hh"
+#ifdef XORP_ENABLE_ASYNC_SERVER
+typedef void XrlCmdRT;
+
+#define XrlCmdReturnError(OUT, ERR) \
+ do { \
+ (OUT)->dispatch((ERR), NULL); \
+ return; \
+ } while (0)
+
+typedef
+XorpCallback2<void, const XrlCmdError &, const XrlArgs *>::RefPtr
+XrlRespCallback;
+
+typedef XrlRespCallback XrlCmdOT;
+
+#define XrlCmdOptCallback(V) , const XrlRespCallback& V
+
+typedef
+XorpCallback2<void, const XrlArgs&, XrlRespCallback>::RefPtr XrlRecvCallback;
+
+#else
+
+typedef const XrlCmdError XrlCmdRT;
+
+#define XrlCmdReturnError(OUT, ERR) return (ERR)
+
+typedef XrlArgs* XrlCmdOT;
+
+#define XrlCmdOptCallback(V)
+
typedef
XorpCallback2<const XrlCmdError, const XrlArgs&, XrlArgs*>::RefPtr XrlRecvCallback;
+#endif
+
class XrlCmdEntry {
public:
XrlCmdEntry(const string& s, XrlRecvCallback cb) :
@@ -45,7 +77,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);
}
diff --git a/xorp/libxipc/xrl_dispatcher.cc b/xorp/libxipc/xrl_dispatcher.cc
index ead5e09..493804a 100644
--- a/xorp/libxipc/xrl_dispatcher.cc
+++ b/xorp/libxipc/xrl_dispatcher.cc
@@ -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();
+ XrlDispatcherReturnError(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*
@@ -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
diff --git a/xorp/libxipc/xrl_dispatcher.hh b/xorp/libxipc/xrl_dispatcher.hh
index 6dadb8b..2a2843f 100644
--- a/xorp/libxipc/xrl_dispatcher.hh
+++ b/xorp/libxipc/xrl_dispatcher.hh
@@ -25,6 +25,31 @@
#include "xrl_cmd_map.hh"
+#ifdef XORP_ENABLE_ASYNC_SERVER
+
+#define XrlDispatcherReturnError(OUT, ERR) \
+ do { \
+ (OUT)->dispatch((ERR), NULL); \
+ return; \
+ } while (0)
+
+typedef void XrlDispatcherRT;
+
+typedef
+XorpCallback2<void, const XrlError &, const XrlArgs *>::RefPtr
+XrlDispatcherCallback;
+
+typedef XrlDispatcherCallback XrlDispatcherOT;
+
+#else
+
+#define XrlDispatcherReturnError(OUT, ERR) return (ERR)
+
+typedef XrlError XrlDispatcherRT;
+typedef XrlArgs& XrlDispatcherOT;
+
+#endif
+
class XrlDispatcher : public XrlCmdMap {
public:
struct XI {
@@ -41,10 +66,17 @@ public:
virtual ~XrlDispatcher() {}
virtual XI* lookup_xrl(const string& name) const;
- virtual XrlError dispatch_xrl(const string& method_name,
- const XrlArgs& in,
- XrlArgs& out) const;
- XrlError dispatch_xrl_fast(const XI& xi, XrlArgs& out) const;
+ virtual XrlDispatcherRT dispatch_xrl(const string& method_name,
+ const XrlArgs& in,
+ XrlDispatcherOT out) const;
+ XrlDispatcherRT dispatch_xrl_fast(const XI& xi,
+ XrlDispatcherOT out) const;
+
+#ifdef XORP_ENABLE_ASYNC_SERVER
+private:
+ void dispatch_cb(const XrlCmdError &, const XrlArgs *,
+ XrlDispatcherCallback resp) const;
+#endif
};
#endif // __LIBXIPC_XRL_DISPATCHER_HH__
diff --git a/xorp/libxipc/xrl_error.hh b/xorp/libxipc/xrl_error.hh
index 7ae7eed..127e519 100644
--- a/xorp/libxipc/xrl_error.hh
+++ b/xorp/libxipc/xrl_error.hh
@@ -163,6 +163,9 @@ protected:
string _note;
};
+#ifdef XORP_ENABLE_ASYNC_SERVER
+class FinderClient;
+#endif
/**
* Error codes for user callbacks.
@@ -221,6 +224,10 @@ private:
XrlCmdError(const XrlError& xe) : _xrl_error(xe) {}
XrlError _xrl_error;
static XrlCmdError _xce_ok;
+
+#ifdef XORP_ENABLE_ASYNC_SERVER
+ friend class FinderClient;
+#endif
};
diff --git a/xorp/libxipc/xrl_pf_stcp.cc b/xorp/libxipc/xrl_pf_stcp.cc
index e441809..514f2fb 100644
--- a/xorp/libxipc/xrl_pf_stcp.cc
+++ b/xorp/libxipc/xrl_pf_stcp.cc
@@ -130,6 +130,11 @@ public:
void dispatch_request(uint32_t seqno, bool batch, const uint8_t* buffer,
size_t bytes);
+ void transmit_response(const XrlError &e,
+ const XrlArgs *pResponse,
+ uint32_t seqno,
+ bool batch);
+
void ack_helo(uint32_t seqno);
void read_event(BufferedAsyncReader* reader,
@@ -151,8 +156,9 @@ public:
string toString() const;
private:
- XrlError do_dispatch(const uint8_t* packed_xrl, size_t packed_xrl_bytes,
- XrlArgs& response);
+ XrlDispatcherRT do_dispatch(const uint8_t* packed_xrl,
+ size_t packed_xrl_bytes,
+ XrlDispatcherOT response);
XrlPFSTCPListener& _parent;
XorpFd _sock;
@@ -251,10 +257,10 @@ STCPRequestHandler::read_event(BufferedAsyncReader* /* source */,
_reader.set_trigger_bytes(STCPPacketHeader::header_size());
}
-XrlError
+XrlDispatcherRT
STCPRequestHandler::do_dispatch(const uint8_t* packed_xrl,
size_t packed_xrl_bytes,
- XrlArgs& response)
+ XrlDispatcherOT response)
{
static XrlError e(XrlError::INTERNAL_ERROR().error_code(), "corrupt xrl");
@@ -264,18 +270,18 @@ STCPRequestHandler::do_dispatch(const uint8_t* packed_xrl,
string command;
size_t cmdsz = Xrl::unpack_command(command, packed_xrl, packed_xrl_bytes);
if (!cmdsz)
- return e;
+ XrlDispatcherReturnError(response, e);
XrlDispatcher::XI* xi = d->lookup_xrl(command);
if (!xi)
- return e;
+ XrlDispatcherReturnError(response, e);
Xrl& xrl = xi->_xrl;
try {
if (xi->_new) {
if (xrl.unpack(packed_xrl, packed_xrl_bytes) != packed_xrl_bytes)
- return e;
+ XrlDispatcherReturnError(response, e);
xi->_new = false;
} else {
@@ -283,10 +289,10 @@ STCPRequestHandler::do_dispatch(const uint8_t* packed_xrl,
packed_xrl_bytes -= cmdsz;
if (xrl.fill(packed_xrl, packed_xrl_bytes) != packed_xrl_bytes)
- return e;
+ XrlDispatcherReturnError(response, e);
}
} catch (...) {
- return e;
+ XrlDispatcherReturnError(response, e);
}
return d->dispatch_xrl_fast(*xi, response);
@@ -298,10 +304,28 @@ STCPRequestHandler::dispatch_request(uint32_t seqno,
const uint8_t* packed_xrl,
size_t packed_xrl_bytes)
{
+#ifdef XORP_ENABLE_ASYNC_SERVER
+ do_dispatch(packed_xrl, packed_xrl_bytes,
+ callback(this, &STCPRequestHandler::transmit_response,
+ seqno, batch));
+#else
XrlArgs response;
XrlError e;
e = do_dispatch(packed_xrl, packed_xrl_bytes, response);
+ transmit_response(e, &response, seqno, batch);
+#endif
+}
+
+
+void STCPRequestHandler::transmit_response(const XrlError &e,
+ const XrlArgs *pResponse,
+ uint32_t seqno,
+ bool batch)
+{
+ // Ensure we have a real arguments object to play with.
+ XrlArgs dummy;
+ const XrlArgs &response = pResponse ? *pResponse : dummy;
size_t xrl_response_bytes = response.packed_bytes();
size_t note_bytes = e.note().size();
diff --git a/xorp/libxipc/xrl_router.cc b/xorp/libxipc/xrl_router.cc
index e547cbf..f97b41a 100644
--- a/xorp/libxipc/xrl_router.cc
+++ b/xorp/libxipc/xrl_router.cc
@@ -650,17 +650,18 @@ XrlRouter::send(const Xrl& xrl, const XrlCallback& user_cb)
return true;
}
-XrlError
+XrlDispatcherRT
XrlRouter::dispatch_xrl(const string& method_name,
const XrlArgs& inputs,
- XrlArgs& outputs) const
+ XrlDispatcherOT outputs) const
{
string resolved_method;
if (_fc->query_self(method_name, resolved_method) == true) {
- return XrlDispatcher::dispatch_xrl(resolved_method, inputs, outputs);
+ return
+ XrlDispatcher::dispatch_xrl(resolved_method, inputs, outputs);
}
debug_msg("Could not find mapping for %s\n", method_name.c_str());
- return XrlError::NO_SUCH_METHOD();
+ XrlDispatcherReturnError(outputs, XrlError::NO_SUCH_METHOD());
}
XrlDispatcher::XI*
diff --git a/xorp/libxipc/xrl_router.hh b/xorp/libxipc/xrl_router.hh
index 9478f44..b16546b 100644
--- a/xorp/libxipc/xrl_router.hh
+++ b/xorp/libxipc/xrl_router.hh
@@ -176,9 +176,9 @@ protected:
*/
virtual void finder_ready_event(const string& tgt_name);
- XrlError dispatch_xrl(const string& method_name,
- const XrlArgs& inputs,
- XrlArgs& outputs) const;
+ XrlDispatcherRT dispatch_xrl(const string& method_name,
+ const XrlArgs& inputs,
+ XrlDispatcherOT outputs) const;
/**
* Resolve callback (slow path).
diff --git a/xorp/xrl/scripts/tgt-gen b/xorp/xrl/scripts/tgt-gen
index 899cf13..a9c7f0f 100755
--- a/xorp/xrl/scripts/tgt-gen
+++ b/xorp/xrl/scripts/tgt-gen
@@ -9,7 +9,8 @@ import os, sys
import Xif.util
from Xif.util import \
- joining_csv, csv, cpp_name, cpp_classname, xorp_indent_string, xorp_indent
+ joining_csv, csv, cpp_name, caps_cpp_classname, \
+ cpp_classname, xorp_indent_string, xorp_indent
from Xif.xiftypes import \
XrlArg, XrlMethod, XrlInterface, XrlTarget
@@ -69,7 +70,7 @@ def target_declare_handler_table(cls):
s = """
struct handler_table {
const char *name;
- const XrlCmdError (%s::*method)(const XrlArgs&, XrlArgs*);
+ XrlCmdRT (%s::*method)(const XrlArgs&, XrlCmdOT);
};
static const struct handler_table handlers[];
@@ -123,14 +124,47 @@ def target_virtual_fns(methods):
args.append(cpa)
r += csv(args)
- r += ") = 0;\n\n"
+ r += ") = 0;\n"
+
+
+
+ r += "#ifdef XORP_ENABLE_ASYNC_SERVER\n"
+ r += " typedef\n"
+ r += " XorpCallback%s<void, const XrlCmdError &" % (len(x.rargs()) + 1)
+ for a in x.rargs():
+ r += ",\n%sconst %s&" % (xorp_indent(2), a.cpp_type())
+ r += ">::RefPtr\n %sCB;\n" % (caps_cpp_classname(x.name()))
+
+
+
+ r += " virtual void async_%s\n (" \
+ % cpp_name(x.name())
+
+ # input args
+ for a in x.args():
+ r += "\n%sconst %s&\t%s," % \
+ (xorp_indent(2), a.cpp_type(), cpp_name(a.name()))
+
+ r += "\n%s%sCB);\n" % \
+ (xorp_indent(2), caps_cpp_classname(x.name()))
+ r += "#endif\n\n"
+
return r
def target_declare_handlers(methods):
s = ""
for x in methods:
- s += " const XrlCmdError handle_%s(const XrlArgs& in, XrlArgs* out);\n\n" \
+ s += " XrlCmdRT handle_%s(const XrlArgs& in, XrlCmdOT out);\n" \
% cpp_name(x.name())
+ s += "#ifdef XORP_ENABLE_ASYNC_SERVER\n"
+
+ s += " void callback_%s\n (const XrlCmdError &e" \
+ % cpp_name(x.name())
+ for a in x.rargs():
+ s += ",\n%sconst %s& arg_%s" \
+ % (xorp_indent(2), a.cpp_type(), cpp_name(a.name()))
+ s += ",\n XrlRespCallback);\n"
+ s += "#endif\n\n"
return s;
def target_declare_handler_hooks():
@@ -159,32 +193,139 @@ def target_handler_hooks(cls, name):
def target_handler_methods(cls, name, methods):
s = ""
for m in methods:
- s += "const XrlCmdError\n"
- if len(m.rargs()):
- argarg = "pxa_outputs"
- else:
- argarg = "/* pxa_outputs */"
- s += "%s::handle_%s(const XrlArgs& xa_inputs, XrlArgs* %s)\n" % \
- (cls, cpp_name(m.name()), argarg)
+ s += "\n#ifdef XORP_ENABLE_ASYNC_SERVER\n"
+ s += "void\n"
+ s += "%s::callback_%s\n (const XrlCmdError &e" \
+ % (cls, cpp_name(m.name()))
+ for r in m.rargs():
+ s += ",\n "
+ s += "const %s& rarg_%s" % (r.cpp_type(), cpp_name(r.name()))
+ s += ",\n XrlRespCallback c_b)\n"
+ s += "{\n"
+
+ s += \
+""" if (e != XrlCmdError::OKAY()) {
+ XLOG_WARNING(\"Handling method for %%s failed: %%s\",
+ \"%s\", e.str().c_str());
+ return c_b->dispatch(e, NULL);
+ } else {
+""" % m.name()
+
+ s += xorp_indent(2) + "XrlArgs out;\n"
+ if m.rargs():
+ s += "\n /* Marshall return values */\n try {\n"
+ for r in m.rargs():
+ s += xorp_indent(3) + "out.add(\"%s\", rarg_%s);\n" % \
+ (r.name(), cpp_name(r.name()))
+ s += \
+""" } catch (const XrlArgs::XrlAtomFound& ) {
+ XLOG_FATAL("Duplicate atom name"); /* XXX Should never happen */
+ }
+
+"""
+ s += " return c_b->dispatch(e, &out);\n }\n}\n\n"
+
+
+
+
+ s += "\nvoid\n%s::async_%s(" \
+ % (cls, cpp_name(m.name()))
+
+ # input args
+ for a in m.args():
+ s += "\n%sconst %s&\targ_%s," % \
+ (xorp_indent(2), a.cpp_type(), cpp_name(a.name()))
+
+ s += "\n%s%sCB c_b)\n{\n" % \
+ (xorp_indent(2), caps_cpp_classname(m.name()))
+
+ s += "\n /* Return value declarations */\n"
+ for r in m.rargs():
+ s += " %s rarg_%s;\n" % (r.cpp_type(), cpp_name(r.name()))
+
+ s += " XrlCmdError e = %s(" % cpp_name(m.name())
+ sep = ""
+ for r in m.args():
+ s += "%s\n arg_%s" % (sep, cpp_name(r.name()))
+ sep = ","
+ for r in m.rargs():
+ s += "%s\n rarg_%s" % (sep, cpp_name(r.name()))
+ sep = ","
+ s += ");\n"
+ s += " return c_b->dispatch(e"
+ for r in m.rargs():
+ s += ",\n rarg_%s" % (cpp_name(r.name()))
+ sep = ","
+ s += ");\n"
+ s += "}\n"
+ s += "#endif\n\n"
+
+
+
+ s += "XrlCmdRT\n"
+ s += "%s::handle_%s(const XrlArgs& xa_inputs, XrlCmdOT pxa_outputs)\n" % \
+ (cls, cpp_name(m.name()))
s += "{"
s += """
if (xa_inputs.size() != %d) {
XLOG_ERROR(\"Wrong number of arguments (%%u != %%u) handling %%s\",
XORP_UINT_CAST(%d), XORP_UINT_CAST(xa_inputs.size()), \"%s\");
- return XrlCmdError::BAD_ARGS();
+ XrlCmdReturnError(pxa_outputs, XrlCmdError::BAD_ARGS());
}
""" % (len(m.args()), len(m.args()), m.name())
if len(m.rargs()):
s += """
+#ifndef XORP_ENABLE_ASYNC_SERVER
if (pxa_outputs == 0) {
XLOG_FATAL(\"Return list empty\");
return XrlCmdError::BAD_ARGS();
}
+#endif
+
+"""
+ if len(m.rargs()) == 0:
+ s += """
+#ifndef XORP_ENABLE_ASYNC_SERVER
+ UNUSED(pxa_outputs);
+#endif
+
+"""
+
+ s += "#ifdef XORP_ENABLE_ASYNC_SERVER\n"
+
+
+ s += xorp_indent(1) + "try {\n"
+ s += xorp_indent(2) + \
+ "%sCB mycb =\n%scallback(this, &%s::callback_%s, pxa_outputs);\n" \
+ % (caps_cpp_classname(m.name()), xorp_indent(3), \
+ cls, cpp_name(m.name()))
+
+ s += xorp_indent(2) + "async_%s(" % cpp_name(m.name())
+ i = 0
+ for a in m.args():
+ s += "\n" + xorp_indent(3) + \
+ "xa_inputs.get(%d, \"%s\").%s()," \
+ % (i, a.name(), a.accessor())
+ i += 1
+ s += " mycb);\n"
+
+
+ s += \
+""" } catch (const XrlArgs::BadArgs& e) {
+ XLOG_ERROR(\"Error decoding the arguments: %s\", e.str().c_str());
+ return pxa_outputs->dispatch(XrlCmdError::BAD_ARGS(e.str()), NULL);
+ }
"""
+
+
+ s += "#else\n"
+
+
s += "\n /* Return value declarations */\n"
for r in m.rargs():
- s += " %s %s;\n" % (r.cpp_type(), cpp_name(r.name()))
+ s += " %s r_%s;\n" % (r.cpp_type(), cpp_name(r.name()))
+
s += xorp_indent(1) + "try {\n"
s += xorp_indent(2) + "XrlCmdError e = %s(" % cpp_name(m.name())
@@ -197,7 +338,7 @@ def target_handler_methods(cls, name, methods):
i += 1
ret_vals = []
for r in m.rargs():
- ret_vals.append("\n" + xorp_indent(3) + "%s" % cpp_name(r.name()))
+ ret_vals.append("\n" + xorp_indent(3) + "r_%s" % cpp_name(r.name()))
s += csv(get_reqs + ret_vals, ",") + ");\n"
s += \
@@ -218,15 +359,19 @@ def target_handler_methods(cls, name, methods):
if m.rargs():
s += "\n /* Marshall return values */\n try {\n"
for r in m.rargs():
- s += xorp_indent(2) + "%s->add(\"%s\", %s);\n" % \
- (argarg, r.name(), cpp_name(r.name()))
+ s += xorp_indent(2) + "pxa_outputs->add(\"%s\", r_%s);\n" % \
+ (r.name(), cpp_name(r.name()))
s += \
""" } catch (const XrlArgs::XrlAtomFound& ) {
XLOG_FATAL("Duplicate atom name"); /* XXX Should never happen */
}
"""
- s += " return XrlCmdError::OKAY();\n}\n\n"
+ s += " return XrlCmdError::OKAY();\n"
+
+
+ s += "#endif\n"
+ s += "}\n\n"
return s
def protect(file):
--
1.7.0.4
More information about the Xorp-hackers
mailing list