Looks like a bug.
Can you please test this patch?

>From 34a3c034c3d67b73c0a806195e9984f95a381bf3 Mon Sep 17 00:00:00 2001
Message-Id: 
<34a3c034c3d67b73c0a806195e9984f95a381bf3.1372911748.git.yamah...@valinux.co.jp>
In-Reply-To: <[email protected]>
References: <[email protected]>
From: Isaku Yamahata <[email protected]>
Date: Thu, 4 Jul 2013 13:07:15 +0900
Subject: [PATCH] ryu/base/app_manager.py: teach state

Signed-off-by: Isaku Yamahata <[email protected]>
---
 ryu/base/app_manager.py |   32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/ryu/base/app_manager.py b/ryu/base/app_manager.py
index 173e35c..c666f2c 100644
--- a/ryu/base/app_manager.py
+++ b/ryu/base/app_manager.py
@@ -57,8 +57,8 @@ class RyuApp(object):
     def __init__(self, *_args, **_kwargs):
         super(RyuApp, self).__init__()
         self.name = self.__class__.__name__
-        self.event_handlers = {}
-        self.observers = {}
+        self.event_handlers = {}        # ev_cls -> handlers:list
+        self.observers = {}     # ev_cls -> observer-name -> states:set
         self.threads = []
         self.events = hub.Queue(128)
         self.replies = hub.Queue()
@@ -71,11 +71,17 @@ class RyuApp(object):
         self.event_handlers[ev_cls].append(handler)
 
     def register_observer(self, ev_cls, name, states=None):
-        states = states or []
-        self.observers.setdefault(ev_cls, {})[name] = states
+        states = states or set()
+        ev_cls_observers = self.observers.setdefault(ev_cls, {})
+        ev_cls_observers.setdefault(name, set()).update(states)
 
-    def get_handlers(self, ev):
-        return self.event_handlers.get(ev.__class__, [])
+    def get_handlers(self, ev, state=None):
+        handlers = self.event_handlers.get(ev.__class__, [])
+        if state is None:
+            return handlers
+
+        return [handler for handler in handlers
+                if not handler.dispatchers or state in handler.dispatchers]
 
     def get_observers(self, ev, state):
         observers = []
@@ -98,28 +104,28 @@ class RyuApp(object):
 
     def _event_loop(self):
         while True:
-            ev = self.events.get()
-            handlers = self.get_handlers(ev)
+            ev, state = self.events.get()
+            handlers = self.get_handlers(ev, state)
             for handler in handlers:
                 handler(ev)
 
-    def _send_event(self, ev):
-        self.events.put(ev)
+    def _send_event(self, ev, state):
+        self.events.put((ev, state))
 
-    def send_event(self, name, ev):
+    def send_event(self, name, ev, state=None):
         if name in SERVICE_BRICKS:
             if isinstance(ev, EventRequestBase):
                 ev.src = self.name
             LOG.debug("EVENT %s->%s %s" %
                       (self.name, name, ev.__class__.__name__))
-            SERVICE_BRICKS[name]._send_event(ev)
+            SERVICE_BRICKS[name]._send_event(ev, state)
         else:
             LOG.debug("EVENT LOST %s->%s %s" %
                       (self.name, name, ev.__class__.__name__))
 
     def send_event_to_observers(self, ev, state=None):
         for observer in self.get_observers(ev, state):
-            self.send_event(observer, ev)
+            self.send_event(observer, ev, state)
 
     def reply_to_request(self, req, rep):
         rep.dst = req.src
-- 
1.7.10.4



On Wed, Jul 03, 2013 at 09:50:50AM +0100, Alan Barr wrote:
> Thanks for your reply, please find code and output below.
> 
>  
> 
> I have done some minimal debugging, and know that register_observer is over
> writing the states for the app class each time it is called. It expects one
> method with multiple states instead of multiple methods each registered for 
> one
> state.
> 
> Granted, I don?t fully understand this process yet as I?m not sure why the
> method along with the class is not being stored - though I feel this may be
> part of the problem. I haven?t looked at where the events are being picked up
> by the observers yet ? which must be responsible for calling all of the
> registered methods for this event, regardless of their registered dispatcher.
> 
>  
> 
>  
> 
> ##### CODE #####
> 
> import logging
> 
> import struct
> 
>  
> 
> from ryu.base import app_manager
> 
> from ryu.controller import mac_to_port
> 
> from ryu.controller import ofp_event
> 
> from ryu.controller.handler import set_ev_cls
> 
> from ryu.ofproto import ofproto_v1_3
> 
> from ryu.ofproto import ofproto_v1_3_parser
> 
> from ryu.lib.mac import haddr_to_str
> 
>  
> 
> from ryu.controller.controller import Datapath
> 
> from ryu.controller.handler import HANDSHAKE_DISPATCHER
> 
> from ryu.controller.handler import CONFIG_DISPATCHER
> 
> from ryu.controller.handler import DEAD_DISPATCHER
> 
> from ryu.controller.handler import MAIN_DISPATCHER
> 
>  
> 
> class PacketTesting(app_manager.RyuApp):
> 
>     OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
> 
>  
> 
>     def __init__(self, *args, **kwargs):
> 
>         super(PacketTesting, self).__init__(*args, **kwargs)
> 
>    
> 
>     @set_ev_cls(ofp_event.EventOFPEchoRequest, MAIN_DISPATCHER)
> 
>     def _echo_rep_main(self, ev):
> 
>         print "DEBUG: In Handler for Echo Request (Main)"
> 
>  
> 
>     @set_ev_cls(ofp_event.EventOFPEchoRequest, CONFIG_DISPATCHER)
> 
>     def _echo_rep_conf(self, ev):
> 
>         print "DEBUG: In Handler for Echo Request (Config)"
> 
>  
> 
>     @set_ev_cls(ofp_event.EventOFPEchoRequest, HANDSHAKE_DISPATCHER)
> 
>     def _echo_rep_hand(self, ev):
> 
>         print "DEBUG: In Handler for Echo Request (Handshake)"
> 
>  
> 
>     @set_ev_cls(ofp_event.EventOFPEchoRequest, DEAD_DISPATCHER)
> 
>     def _echo_rep_dead(self, ev):
> 
>         print "DEBUG: In Handler for Echo Request (Dead)"
> 
>  
> 
>  
> 
> ##### OUTPUT #####
> 
>  
> 
> loading app ../ryu_echo_req_ex.py
> 
> loading app ryu.controller.ofp_handler
> 
> instantiating app ../ryu_echo_req_ex.py
> 
> instantiating app ryu.controller.ofp_handler
> 
> BRICK PacketTesting
> 
>   CONSUMES EventOFPEchoRequest
> 
> BRICK ofp_event
> 
>   PROVIDES EventOFPEchoRequest TO {'PacketTesting': ['main']}
> 
>   CONSUMES EventOFPErrorMsg
> 
>   CONSUMES EventOFPEchoRequest
> 
>   CONSUMES EventOFPSwitchFeatures
> 
>   CONSUMES EventOFPHello
> 
> connected socket:<eventlet.greenio.GreenSocket object at 0xa0fb84c> address:
> ('127.0.0.1', 60098)
> 
> hello ev <ryu.controller.ofp_event.EventOFPHello object at 0xa0fbb6c>
> 
> move onto config mode
> 
> switch features ev version: 0x4 msg_type 0x6 xid 0xf8480126 OFPSwitchFeatures
> (auxiliary_id=0,capabilities=71,datapath_id=153,n_buffers=256,n_tables=
> 254,reserved=0)
> 
> move onto main mode
> 
> EVENT ofp_event->PacketTesting EventOFPEchoRequest
> 
> DEBUG: In Handler for Echo Request (Config)
> 
> DEBUG: In Handler for Echo Request (Dead)
> 
> DEBUG: In Handler for Echo Request (Handshake)
> 
> DEBUG: In Handler for Echo Request (Main)
> 
> EVENT ofp_event->PacketTesting EventOFPEchoRequest
> 
> DEBUG: In Handler for Echo Request (Config)
> 
> DEBUG: In Handler for Echo Request (Dead)
> 
> DEBUG: In Handler for Echo Request (Handshake)
> 
> DEBUG: In Handler for Echo Request (Main)
> 
> On 3 Jul 2013 07:41, "Isaku Yamahata" <[email protected]> wrote:
> 
>     Your expectation sounds correct. Posting your code would help.
> 
>     thanks,
> 
>     On Tue, Jul 02, 2013 at 01:54:20PM +0100, Alan Barr wrote:
>     > Hello all,
>     >
>     >
>     >
>     > I was wondering if someone could clarify if what I am seeing is expected
>     > behaviour.
>     >
>     > I am new to Ryu and currently trying to familiarise myself with it.
>     >
>     > In one of my test applications I have registered four different methods
>     for
>     > EventOFPEchoRequest, one method for each of HANDSHAKE, CONFIG, MAIN and
>     DEAD
>     > dispatchers.
>     >
>     > When this event is triggered, all of these methods are called, not just
>     the one
>     > registered for the appropriate state.
>     >
>     >
>     >
>     > Is this the correct behaviour? I don't have a valid use case of this, 
> I'm
>     just
>     > trying to better understand Ryu and this was my first test setup. I 
> wasn?
>     t
>     > expecting this behaviour.
>     >
>     >
>     >
>     > I was basing this off:
>     >
>     >
>     >
>     > ?A decorator for Ryu application to declare an event handler. Decorated
>     method
>     > will become an event handler. ev_cls is an event class whose instances
>     this
>     > RyuApp wants to receive. dispatchers argument specifies one of the
>     following
>     > negotiation phases (or a list of them) for which events should be
>     generated for
>     > this handler. Note that, in case an event changes the phase, the phase
>     before
>     > the change is used to check the interest.? https://github.com/osrg/ryu/
>     wiki/API
>     >
>     >
>     >
>     > I'm on commit a66bcf031d782c25b987431feb76251970158573.
>     >
>     >
>     >
>     > Kind Regards,
>     >
>     > Alan Barr
>     >
>     >
>     >
> 
>     >
>     
> ------------------------------------------------------------------------------
>     > This SF.net email is sponsored by Windows:
>     >
>     > Build for Windows Store.
>     >
>     > http://p.sf.net/sfu/windows-dev2dev
>     > _______________________________________________
>     > Ryu-devel mailing list
>     > [email protected]
>     > https://lists.sourceforge.net/lists/listinfo/ryu-devel
> 
> 
>     --
>     yamahata
> 
>     
> ------------------------------------------------------------------------------
>     This SF.net email is sponsored by Windows:
> 
>     Build for Windows Store.
> 
>     http://p.sf.net/sfu/windows-dev2dev
>     _______________________________________________
>     Ryu-devel mailing list
>     [email protected]
>     https://lists.sourceforge.net/lists/listinfo/ryu-devel
> 

> ------------------------------------------------------------------------------
> This SF.net email is sponsored by Windows:
> 
> Build for Windows Store.
> 
> http://p.sf.net/sfu/windows-dev2dev
> _______________________________________________
> Ryu-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/ryu-devel


-- 
yamahata

------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:

Build for Windows Store.

http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to