On Fri, Feb 22, 2013 at 08:38:50PM +0900, Isaku Yamahata wrote:
> On Fri, Feb 22, 2013 at 07:14:19PM +0900, YAMADA Hideki wrote:
> > Now, direct method calling is used for app-to-app communication,
> > via _CONTEXTS parameters.
> > This patch is more loose coupling way than direct way.
> >
> > Signed-off-by: YAMADA Hideki <[email protected]>
> > ---
> > ryu/base/app_manager.py | 29 +++++++++++++++++++++++++++++
> > ryu/controller/event.py | 17 +++++++++++++++++
> > 2 files changed, 46 insertions(+), 0 deletions(-)
> >
> > diff --git a/ryu/base/app_manager.py b/ryu/base/app_manager.py
> > index 1a2567e..922130a 100644
> > --- a/ryu/base/app_manager.py
> > +++ b/ryu/base/app_manager.py
> > @@ -24,6 +24,7 @@ from gevent.queue import Queue
> > from ryu import utils
> > from ryu.controller.handler import register_instance
> > from ryu.controller.controller import Datapath
> > +from ryu.controller.event import EventRequestBase, EventReplyBase
> >
> > LOG = logging.getLogger('ryu.base.app_manager')
> >
> > @@ -62,6 +63,7 @@ class RyuApp(object):
> > self.observers = {}
> > self.threads = []
> > self.events = Queue()
> > + self.replys = Queue()
> > self.threads.append(gevent.spawn(self._event_loop))
> >
> > def register_handler(self, ev_cls, handler):
> > @@ -82,6 +84,10 @@ class RyuApp(object):
> > def _event_loop(self):
> > while True:
> > ev = self.events.get()
> > +
> > + if isinstance(ev, EventReplyBase):
> > + self.replys.put(ev)
> > +
> > handlers = self.get_handlers(ev)
> > for handler in handlers:
> > handler(ev)
> > @@ -102,6 +108,29 @@ class RyuApp(object):
> > for observer in self.get_observers(ev):
> > self.send_event(observer, ev)
> >
> > + def send_request(self, dst, ev):
> > + assert isinstance(ev, EventRequestBase)
> > + ev.src = self.name
> > + self.send_event(dst, ev)
> > +
> > + def send_reply(self, request, ev):
> > + assert isinstance(request, EventRequestBase)
> > + assert isinstance(ev, EventReplyBase)
> > + ev.src = self.name
> > + ev.xid = request.xid
> > + self.send_event(request.src, ev)
> > +
> > + def recv_reply(self, xid):
> > + # waiting for reply
> > + while True:
> > + reply = self.replys.get() # blocking when empty
> > + if reply.xid == xid:
> > + #LOG.debug('receive reply(xid=%s)', reply.xid)
> > + return reply
> > + else:
> > + #LOG.debug('put off reply(xid=%s)', reply.xid)
> > + self.replys.put(reply)
> > +
> > def close(self):
> > """
> > teardown method.
>
> requeuing result seems ugly. How about something like this?
> (totally untested. Just for showing intention.)
>
> diff --git a/ryu/base/app_manager.py b/ryu/base/app_manager.py
> index a9895a2..5c5d240 100644
> --- a/ryu/base/app_manager.py
> +++ b/ryu/base/app_manager.py
> @@ -61,6 +61,7 @@ class RyuApp(object):
> self.observers = {}
> self.threads = []
> self.events = Queue()
> + self.replys = {}
> self.threads.append(gevent.spawn(self._event_loop))
>
> def register_handler(self, ev_cls, handler):
> @@ -101,6 +102,47 @@ class RyuApp(object):
> for observer in self.get_observers(ev):
> self.send_event(observer, ev)
>
> + def send_request(self, dst, ev):
> + assert isinstance(ev, EventRequestBase)
> + ev.src = self.name
> + self.send_event(dst, ev)
> +
> + def send_reply(self, request, ev):
> + assert isinstance(request, EventRequestBase)
> + assert isinstance(ev, EventReplyBase)
> + ev.src = self.name
> + ev.xid = request.xid
> + # self.send_event_to_observers(ev)
> + self.send_event(request.src, ev)
> +
> + def send_requst_block(self, dst, ev):
> + assert ev.xid not in self.replys
> + async_result = gevent.event.AsyncResult()
> + self.replys[ev.xid] = async_result
> + self.send_request(dst, ev)
> + return async_result.get()
> +
> + def reply_handler(self, ev):
> + """ This handler is called by handler.
> + e.g.
> + class MyRequestEvent(EventRequetBase):
> + ...
> +
> + class MyReplyEvent(EventReplayBase):
> + ...
> +
> + class MyRequester(RyuApp):
> + def request(self):
> + ...
> + reply = self.send_request_block(dst, ev)
> +
> + @handler.set_ev_cls(MyReplyEvent)
> + def my_reply_handler(self, ev):
> + self.reply_handler(ev)
> + """
> + async_result = self.replys.pop(ev.xid)
> + async_result.set(ev)
> +
This causes deadlock if send_request_block is called by event handler thread.
So approach would be
- frame work
- wake up is done out side of event handler.
- Probably RyuApp._send_event?
- framework does nothing.
require RyuApp to create its own thread to handle it
RyuApp may
- create dedicated thread to sleep
- create dedicated thread to wake up
- don't call it from event handler
split up the routine into more, which will be called on next event.
- other ideas?
--
yamahata
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel