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

Reply via email to