From: Steven Simpson <[email protected]> * 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 <[email protected]> --- xorp/SConstruct | 13 ++ xorp/libxipc/finder_client.cc | 33 +++++- 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 | 37 ++++++- xorp/libxipc/xrl_dispatcher.cc | 34 +++++- xorp/libxipc/xrl_dispatcher.hh | 44 +++++++- xorp/libxipc/xrl_pf_stcp.cc | 64 ++++++++--- xorp/libxipc/xrl_pf_stcp.hh | 6 +- xorp/libxipc/xrl_router.cc | 9 +- xorp/libxipc/xrl_router.hh | 6 +- xorp/xrl/scripts/tgt-gen | 179 +++++++++++++++++++++++++++--- 15 files changed, 442 insertions(+), 62 deletions(-) diff --git a/xorp/SConstruct b/xorp/SConstruct index 56d36da..a53aee8 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'] @@ -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"): @@ -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..95b484f 100644 --- a/xorp/libxipc/finder_client.cc +++ b/xorp/libxipc/finder_client.cc @@ -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; @@ -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")); } } diff --git a/xorp/libxipc/finder_client.hh b/xorp/libxipc/finder_client.hh index 21e1f11..a601484 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 + XRL_CMD_OPT_CALLBACK(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 + 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(); 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..2892b99 100644 --- a/xorp/libxipc/xrl_cmd_map.hh +++ b/xorp/libxipc/xrl_cmd_map.hh @@ -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) : @@ -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); } diff --git a/xorp/libxipc/xrl_dispatcher.cc b/xorp/libxipc/xrl_dispatcher.cc index ead5e09..173b579 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(); + 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* @@ -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..64e7791 100644 --- a/xorp/libxipc/xrl_dispatcher.hh +++ b/xorp/libxipc/xrl_dispatcher.hh @@ -25,6 +25,35 @@ #include "xrl_cmd_map.hh" +#ifdef XORP_ENABLE_ASYNC_SERVER + +#define XRL_DISPATCHER_RETURN_ERROR(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 XRL_DISPATCHER_RETURN_ERROR(OUT, ERR) \ + do { \ + return (ERR); \ + } while (0) + + +typedef XrlError XrlDispatcherRT; +typedef XrlArgs& XrlDispatcherOT; + +#endif + class XrlDispatcher : public XrlCmdMap { public: struct XI { @@ -41,10 +70,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_pf_stcp.cc b/xorp/libxipc/xrl_pf_stcp.cc index e441809..1108423 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; + XRL_DISPATCHER_RETURN_ERROR(response, e); XrlDispatcher::XI* xi = d->lookup_xrl(command); if (!xi) - return e; + XRL_DISPATCHER_RETURN_ERROR(response, e); Xrl& xrl = xi->_xrl; try { if (xi->_new) { if (xrl.unpack(packed_xrl, packed_xrl_bytes) != packed_xrl_bytes) - return e; + XRL_DISPATCHER_RETURN_ERROR(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; + XRL_DISPATCHER_RETURN_ERROR(response, e); } } catch (...) { - return e; + XRL_DISPATCHER_RETURN_ERROR(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(); @@ -798,7 +822,10 @@ XrlPFSTCPSender::die(const char* reason, bool verbose) // the lists of callbacks. list<ref_ptr<RequestState> > tmp; tmp.splice(tmp.begin(), _requests_waiting); - tmp.splice(tmp.begin(), _requests_sent); + for (RequestMap::iterator iter = _requests_sent.begin(); + iter != _requests_sent.end(); iter++) + tmp.push_back(iter->second); + _requests_sent.clear(); _active_requests = 0; _active_bytes = 0; @@ -877,13 +904,13 @@ XrlPFSTCPSender::send_request(RequestState* rs) } void -XrlPFSTCPSender::dispose_request() +XrlPFSTCPSender::dispose_request(RequestMap::iterator ptr) { assert(_requests_sent.empty() == false); xassert(_requests_sent.size() + _requests_waiting.size() == _active_requests); - _active_bytes -= _requests_sent.front()->size(); + _active_bytes -= ptr->second->size(); _active_requests -= 1; - _requests_sent.pop_front(); + _requests_sent.erase(ptr); xassert(_requests_waiting.size() == _writer->buffers_remaining()); } @@ -914,7 +941,7 @@ XrlPFSTCPSender::update_writer(AsyncFileWriter::Event e, } ref_ptr<RequestState> rrp = _requests_waiting.front(); - _requests_sent.push_back(rrp); + _requests_sent[rrp->seqno()] = rrp; _requests_waiting.pop_front(); } @@ -955,7 +982,8 @@ XrlPFSTCPSender::read_event(BufferedAsyncReader* /* reader */, return; } - if (sph.seqno() != _requests_sent.front()->seqno()) { + RequestMap::iterator stptr = _requests_sent.find(sph.seqno()); + if (stptr == _requests_sent.end()) { die("Bad sequence number"); return; } @@ -963,7 +991,7 @@ XrlPFSTCPSender::read_event(BufferedAsyncReader* /* reader */, if (sph.type() == STCP_PT_HELO_ACK) { debug_msg("Got keep alive ack\n"); _keepalive_sent = false; - dispose_request(); + dispose_request(stptr); _reader->dispose(sph.frame_bytes()); _reader->set_trigger_bytes(sph.header_size()); return; @@ -996,8 +1024,8 @@ XrlPFSTCPSender::read_event(BufferedAsyncReader* /* reader */, } // Get ref_ptr to callback from request state and discard the rest - XrlPFSender::SendCallback cb = _requests_sent.front()->cb(); - dispose_request(); + XrlPFSender::SendCallback cb = stptr->second->cb(); + dispose_request(stptr); xassert(_active_requests == _requests_waiting.size() + _requests_sent.size()); diff --git a/xorp/libxipc/xrl_pf_stcp.hh b/xorp/libxipc/xrl_pf_stcp.hh index 1482719..78f3967 100644 --- a/xorp/libxipc/xrl_pf_stcp.hh +++ b/xorp/libxipc/xrl_pf_stcp.hh @@ -111,8 +111,9 @@ private: uint8_t* buffer, size_t buffer_bytes); + typedef map<uint32_t, ref_ptr<RequestState> > RequestMap; void send_request(RequestState*); - void dispose_request(); + void dispose_request(RequestMap::iterator ptr); void start_keepalives(); void stop_keepalives(); @@ -129,7 +130,8 @@ private: AsyncFileWriter* _writer; list<ref_ptr<RequestState> > _requests_waiting; // All requests pending - list<ref_ptr<RequestState> > _requests_sent; // All requests pending + + RequestMap _requests_sent; // All requests pending uint32_t _current_seqno; size_t _active_bytes; diff --git a/xorp/libxipc/xrl_router.cc b/xorp/libxipc/xrl_router.cc index e547cbf..d457e40 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(); + XRL_DISPATCHER_RETURN_ERROR(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..3c2fc87 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(); + XRL_CMD_RETURN_ERROR(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 _______________________________________________ Xorp-hackers mailing list [email protected] http://mailman.ICSI.Berkeley.EDU/mailman/listinfo/xorp-hackers
