[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