1. artgins
  2. ginsfsm

Commits

Ginés Martínez Sánchez  committed ce79af0 Draft

testing and cleaning

  • Participants
  • Parent commits c07a63b
  • Branches default

Comments (0)

Files changed (11)

File ginsfsm/c_sock.py

View file
     'ports': [tuple, (), 0, None, "multi ports"],
     'use_multi_ports': [bool, False, 0, None, "use multi ports"],
     'ssl_options': [dict, {}, 0, None, "ssl options"],
-    'use_named_clisrv': [bool, False, 0, None, "True if clisrv must be named"],
     'tx_buffer_size': [int, 4096, 0, None, ""],
     'connected_event_name': [
         str, 'EV_CONNECTED', 0, None,

File ginsfsm/c_srv_sock.py

View file
     'ports': [tuple, (), 0, None, "multi ports"],
     'use_multi_ports': [bool, False, 0, None, "use multi ports"],
     'ssl_options': [dict, {}, 0, None, "ssl options"],
-    'use_named_clisrv': [bool, False, 0, None, "True if clisrv must be named"],
 }
 
 
                 else:
                     raise
 
-        self._n_clisrv += 1
-        if self.name or self.use_named_clisrv:
-            channel_name = self.name + '-clisrv_%x' % self._n_clisrv
-        else:
-            channel_name = None
-
         if self.config.ssl_options:
             gsock_class = GSSLSock
         else:
             gsock_class = GSock
+
+        self._n_clisrv += 1
         clisrv = self.create_gobj(
-            channel_name if channel_name else None,
+            'clisrv_%x' % self._n_clisrv,
             gsock_class,
-            self.config.subscriber,
+            self,
+            subscriber=self.config.subscriber,
         )
         clisrv.set_clisrv_socket(sock)
         clisrv.handle_connect()

File ginsfsm/examples/sockjs/test_sockjs_server.ini

View file
 
 [app:wsgi-server]
 use = call:ginsfsm.examples.sockjs.test_sockjs_server:main
-wsgi-server.host = 0.0.0.0
-wsgi-server.port = 8080
+GWsgiServer.host = 0.0.0.0
+GWsgiServer.port = 8080
 application = wsgi-application
-GSock.trace_dump = true
-# GObj: super-global setter.
-#GObj.trace_mach = true
-GObj.trace_traverse = true
-GWebSocket.trace_mach = true
+GSock.trace_dump = false
+GObj.trace_mach = false
+GObj.trace_traverse = false
+GWebSocket.trace_mach = false
 
 [app:wsgi-application]
 use = call:ginsfsm.examples.sockjs.test_sockjs_server:paste_app_factory
 handlers = console
 
 [logger_ginsfsm]
-level = DEBUG
+level = INFO
 handlers =
 qualname = ginsfsm
 

File ginsfsm/examples/sockjs/test_sockjs_server.py

View file
     ga = GAplic('ga', **local_conf)
     set_global_main_gaplic(ga)
     ga.create_gobj(
-        'wsgi-server',
+        'test-sockjs',
         GWsgiServer,
         ga,
         application=application,
         'GObj.trace_mach': False,
         'GObj.logger': logging,
         'GSock.trace_dump': True,
-        'wsgi-server.host': '0.0.0.0',
-        'wsgi-server.port': 8080,
+        'GWsgiServer.host': '0.0.0.0',
+        'GWsgiServer.port': 8080,
         'application': 'wsgi-application',
     }
 

File ginsfsm/gobj.py

View file
     `subscriber_gobj`: subcriber gobj to sending event.
     `kw`: event parameters
     """
-    def __init__(self, event_name, subscriber_gobj, **kw):
+    def __init__(self, me, event_name, subscriber_gobj, **kw):
+        self.me = me
         self.event_name = event_name
         self.subscriber_gobj = subscriber_gobj
         self.kw = kw
         self.__dict__.update(**kw)
 
+    def __repr__(self):
+        resp = "Subscription:\n  me : %r\n  ev : %r\n  sub: %r\n" % (
+            self.me,
+            self.event_name,
+            self.subscriber_gobj)
+        return resp
+
 
 GOBJ_GCONFIG = {
     'trace_traverse': [bool, False, 0, None, 'Display traverse search'],
         gconfig = add_gconfig(gconfig, GOBJ_GCONFIG)
         GConfig.__init__(self, gconfig)
 
+    def __del__(self):
+        if self.logger:
+            self.logger.debug("Destroyed! <-- %r" % (self))
+
     def __str__(self):
         name = "%s" % (self.name)
         parent = self.parent
             name = self.get_random_name(name)
 
         if self.logger:
-            self.logger.info("Creating --> '%s:%s'" % (
+            self.logger.debug("Creating --> '%s:%s'" % (
                 gclass.__name__, name))
 
         gobj = gclass()
         """ Destroy a gobj
         """
         if gobj.logger:
-            gobj.logger.info("Destroying <-- %r" % (gobj))
+            gobj.logger.debug("Destroying --> %r" % (gobj))
 
         if gobj._destroyed:
             logging.error("ERROR reentering in destroy_gobj: %r" % gobj)
             except RuntimeError:
                 pass  # "Set changed size during iteration" is OK
 
-        gobj.delete_all_subscriptions()
+        gobj.delete_all_subscriptions(force=True)
         gobj.go_out()
         del gobj
 
             )
         self.gaplic.enqueue_event(event)
 
-    def subscribe_event(self, event_name, subscriber_gobj, **kw):
-        """ Subscribe to an event.
-
-        :param event_name: string event name or tuple/list of string
-            event names.  If ``event_name`` is ``None`` then it subscribes
-            to all events. If it's not ``None`` then it must be a valid event
-            name from the :term:`output-event` list,
-            otherwise a :exc:`EventError` will be raised.
-
-        :param subscriber_gobj: subscriber obj that wants receive the event.
-
-            ``subscriber_gobj`` must be:
-                * `None`: the subscriber is the parent.
-                * `string`: the subscriber is a :term:`unique-named-gobj`.
-                * type :class:`GObj` instance.
-                * Deferred callback.
-
-            otherwise otherwise a :exc:`GObjError` will be raised.
-
-        :param kw: keyword arguments.
-
-        Possible values for **kw** arguments:
-            * `__use_post_event__`: ``bool``
-
-              You must set it to `True` in order to broadcast the events
-              using `post-event` instead of `send-event`.
-
-            * `__rename_event_name__`: `'new event name'`
-
-              You can rename the output original event name.
-              The :attr:`original_event_name` attribute is added to
-              the sent event with the value of the original event name.
-        """
-        #if subscriber_gobj is not None:
-        if not (isinstance(subscriber_gobj, string_types) or
-                isinstance(subscriber_gobj, Deferred) or
-                isinstance(subscriber_gobj, GObj)
-                ):
-            raise GObjError('Bad type of subscriber_gobj %r' % (
-                subscriber_gobj,))
-
-        output_events = self.get_output_event_list()
-
-        if not isinstance(event_name, (list, tuple)):
-            event_name = (event_name,)
-
-        for name in event_name:
-            if name is None:
-                continue
-            if not isinstance(name, string_types):
-                raise EventError(
-                    'subscribe_event(): event %r is not string in %r'
-                    % (name, self))
-
-            if name not in output_events:
-                raise EventError(
-                    'subscribe_event(): output-event %r not defined in'
-                    ' %r' % (event_name, self))
-
-        existing_subs = self._find_subscription(event_name, subscriber_gobj)
-        if existing_subs:
-            # avoid duplication subscriptions
-            self.delete_subscription(event_name, subscriber_gobj)
-        subscription = _Subscription(event_name, subscriber_gobj, **kw)
-        self._dl_subscriptions.add(subscription)
-        self._some_subscriptions = True
-
     def broadcast_event(self, event, **kw):
         """ Broadcast the ``event`` to all subscribers.
 
                                 return  # propietary event
                 sended_gobj.add(sub.subscriber_gobj)
 
+    def subscribe_event(self, event_name, subscriber_gobj, **kw):
+        """ Subscribe to an event.
+
+        :param event_name: string event name or tuple/list of string
+            event names.  If ``event_name`` is ``None`` then it subscribes
+            to all events. If it's not ``None`` then it must be a valid event
+            name from the :term:`output-event` list,
+            otherwise a :exc:`EventError` will be raised.
+
+        :param subscriber_gobj: subscriber obj that wants receive the event.
+
+            ``subscriber_gobj`` must be:
+                * `None`: the subscriber is the parent.
+                * `string`: the subscriber is a :term:`unique-named-gobj`.
+                * type :class:`GObj` instance.
+                * Deferred callback.
+
+            otherwise otherwise a :exc:`GObjError` will be raised.
+
+        :param kw: keyword arguments.
+
+        Possible values for **kw** arguments:
+            * `__use_post_event__`: ``bool``
+
+              You must set it to `True` in order to broadcast the events
+              using `post-event` instead of `send-event`.
+
+            * `__rename_event_name__`: `'new event name'`
+
+              You can rename the output original event name.
+              The :attr:`original_event_name` attribute is added to
+              the sent event with the value of the original event name.
+
+
+            * `__hard_subscription__`: permanent subscription.
+
+              This subscription cannot be remove,
+              neither with delete_all_subscriptions().
+
+        """
+        #if subscriber_gobj is not None:
+        if not (isinstance(subscriber_gobj, string_types) or
+                isinstance(subscriber_gobj, Deferred) or
+                isinstance(subscriber_gobj, GObj)
+                ):
+            raise GObjError('Bad type of subscriber_gobj %r' % (
+                subscriber_gobj,))
+
+        output_events = self.get_output_event_list()
+
+        if not isinstance(event_name, (list, tuple)):
+            event_name = (event_name,)
+
+        for name in event_name:
+            if name is None:
+                continue
+            if not isinstance(name, string_types):
+                raise EventError(
+                    'subscribe_event(): event %r is not string in %r'
+                    % (name, self))
+
+            if name not in output_events:
+                raise EventError(
+                    'subscribe_event(): output-event %r not defined in'
+                    ' %r' % (event_name, self))
+
+        existing_subs = self._find_subscription(event_name, subscriber_gobj)
+        if existing_subs:
+            # avoid duplication subscriptions
+            self.logger.warning(
+                "WARNING duplicate subscription:\n"
+                "  me : %r\n"
+                "  ev : %r\n"
+                "  sub: %r\n" %
+                (self, event_name, subscriber_gobj))
+            self.delete_subscription(event_name, subscriber_gobj)
+        subscription = _Subscription(self, event_name, subscriber_gobj, **kw)
+        self.logger.debug('NEW %r' % subscription)
+        self._dl_subscriptions.add(subscription)
+        self._some_subscriptions = True
+
     def _find_subscription(self, event_name, subscriber_gobj):
         """ Find a subscription by event_name and subscriber gobj.
         Internal use to avoid duplicates subscriptions.
         if not isinstance(event_name, (list, tuple)):
             event_name = (event_name,)
         for sub in self._dl_subscriptions:
-            if list(sub.event_name).sort() == list(event_name).sort() and \
-                    sub.subscriber_gobj == subscriber_gobj:
-                return sub
+            if sorted(list(sub.event_name)) == sorted(list(event_name)):
+                if sub.subscriber_gobj == subscriber_gobj:
+                    return sub
+        return None
 
     def delete_subscription(self, event_name, subscriber_gobj):
         """ Remove `subscription`.
             event names.
         :param subscriber_gobj: subscriber gobj.
         """
-        existing_subs = self._find_subscription(event_name, subscriber_gobj)
-        if existing_subs:
-            self._dl_subscriptions.remove(existing_subs)
-            if len(self._dl_subscriptions) == 0:
-                self._some_subscriptions = False
-            return True
-        logging.error("ERROR delete_subscription(): '%s' NOT FOUND " % (
-            event_name))
+        sub = self._find_subscription(event_name, subscriber_gobj)
+        self.logger.debug('DEL %r' % sub)
+        if sub:
+            if sub.kw.get('__hard_subscription__', None):
+                self.logger.error(
+                    "WARNING cannot delete a hard subscription(): '%s'" % (
+                        event_name))
+                return False
+            else:
+                self._dl_subscriptions.remove(sub)
+                if len(self._dl_subscriptions) == 0:
+                    self._some_subscriptions = False
+                return True
+
+        self.logger.error(
+            "ERROR delete_subscription(): '%s' NOT FOUND " % (event_name))
 
         return False
 
-    def delete_all_subscriptions(self):
+    def delete_all_subscriptions(self, force=False):
         """ Remove all subscriptions.
         """
-        while len(self._dl_subscriptions):
-            try:
-                for subs in self._dl_subscriptions:
-                    self._dl_subscriptions.remove(subs)
-            except RuntimeError:
-                pass  # "Set changed size during iteration" is OK
+        subscriptions = self._dl_subscriptions.copy()
+        for sub in subscriptions:
+            if not force:
+                if sub.kw.get('__hard_subscription__'):
+                    continue
+            self.logger.debug('DEL %r' % sub)
+            self._dl_subscriptions.remove(sub)
+
+        if len(self._dl_subscriptions) == 0:
+            self._some_subscriptions = False
 
     def set_owned_event_filter(self, filter):
         """ Set a filter function to be used
         trace_traverse = self.config.trace_traverse
         if trace_traverse:
             logger = self.logger
-            logger.info("==> TRAVERSING('%s') -> %s" % (
+            logger.debug("==> TRAVERSING('%s') -> %s" % (
                 name, self.resource_path()))
 
         if name is None:
             else:
                 if gobj.name == name:
                     if trace_traverse:
-                        logger.info("    TRAVERSING FOUND!")
+                        logger.debug("    TRAVERSING FOUND!")
                     return gobj
 
         # Secondly search re_name
                     # this gobj has been got as re_matched_name.
                     gobj.re_matched_name = name
                     if trace_traverse:
-                        logger.info("    TRAVERSING %s FOUND RE!" % name)
+                        logger.debug("    TRAVERSING %s FOUND RE!" % name)
                     return gobj
             else:
                 continue
         if trace_traverse:
-            logger.info("<== TRAVERSING('%s') -> %s END!" % (
+            logger.debug("<== TRAVERSING('%s') -> %s END!" % (
                 name, self.resource_path()))
         raise KeyError('No such child named %s' % name)
 

File ginsfsm/protocols/http/server/c_http_clisrv.py

View file
     if self.gsock:
         gsock = self.gsock
         self.gsock = None
-        self.destroy_gobj(gsock)
+        GObj.destroy_gobj(gsock)
     self.broadcast_event('EV_HTTP_CHANNEL_CLOSED', channel=self)
 
 
         self.dl_requests = deque()  # requests queue
         self.sent_continue = False  # used as a latch after sending 100continue
 
+    def go_out(self):
+        """ Finish zone.
+        """
+        if self.gsock:
+            gsock = self.gsock
+            self.gsock = None
+            GObj.destroy_gobj(gsock)
+
     def start_up(self):
         if self.config.subscriber is None:
             self.config.subscriber = self.parent
         # gsock MUST be passed at creating gobj
 
         # Canalize the flow of messages
-        self.gsock.subscribe_event(None, self)  # bottom events for me
-        self.subscribe_event(None, self.config.subscriber)  # top events for subscrib.
+        # bottom events for me
+        self.gsock.subscribe_event(None, self)
+        # we need to know disconnected event for deleting gobjs
+        self.gsock.subscribe_event(
+            'EV_DISCONNECTED',
+            self,
+            __hard_subscription__=True,
+        )
+
+        # top events for subscriber
+        self.subscribe_event(None, self.config.subscriber)
         self.broadcast_event('EV_HTTP_CHANNEL_OPENED', channel=self)
 
         # Setup the timers

File ginsfsm/protocols/http/server/c_http_server.py

View file
     A new client http has been acepted.
     The new clisrv GSock, created by GServerSock is sending this event.
     """
-    self._n_connected_clisrv += 1
     gsock = event.source[-1]
     gsock.delete_all_subscriptions()
 
+    self._n_channel += 1
     clisrv = self.create_gobj(
-        'channel',
+        'channel_%x' % self._n_channel,
         GHttpCliSrv,
         self,
         gsock=gsock,
         max_request_header_size=self.config.max_request_header_size,
         max_request_body_size=self.config.max_request_body_size,
     )
-    clisrv.subscribe_event('EV_HTTP_CHANNEL_CLOSED', self)
+    clisrv.subscribe_event(
+        'EV_HTTP_CHANNEL_CLOSED',
+        self,
+        __hard_subscription__=True,
+    )
 
 
 def ac_channel_closed(self, event):
     """ It's better receive this event by post_event().
     """
     channel = event.channel
-    self._n_connected_clisrv -= 1
+    self._n_channel -= 1
     # the gsock is destroy in channel.ac_disconnected (GHttpCliSrv)
-    self.destroy_gobj(channel)
+    GObj.destroy_gobj(channel)
 
 
 def ac_timeout(self, event):
     self.set_timeout(10)
     print "Server's clients: %d, connected %d" % (
-        len(self.dl_childs), self._n_connected_clisrv)
+        len(self.dl_childs), self._n_channel)
 
 
 GHTTPSERVER_FSM = {
 
     def __init__(self):
         GObj.__init__(self, GHTTPSERVER_FSM, GHTTPSERVER_GCONFIG)
-        self._n_connected_clisrv = 0
+        self._n_channel = 0
 
     def start_up(self):
         self.gserversock = self.create_gobj(
-            'server-sock' if self.name else None,
+            self.name if self.name else 'sock-server',
             GServerSock,
             self,
             subscriber=self,  # Iniatially capture all events from new clisrv.

File ginsfsm/protocols/sockjs/server/c_transport_websocket.py

View file
         #   Accept the connection
         #
         self.ws_connection = self.context.gaplic.create_gobj(
-            None,
+            'websocket',
             GWebSocket,
-            None,           # No parent, Iam a Mixin!
+            self.channel,     # child of parent, to be delete when channel was
             request=self.request,
             gsock=self.gsock,
         )

File ginsfsm/protocols/sockjs/server/c_websocket.py

View file
         In own handshake, if iam a client, we initiate the request http.
 
         """
-        if self.config.subscriber is None:
-            self.config.subscriber = self.parent
         if self.config.subscriber:
             self.subscribe_event(None, self.config.subscriber)
 

File ginsfsm/protocols/wsgi/server/c_wsgi_server.py

View file
 
     def start_up(self):
         self.ghttpserver = self.create_gobj(
-            'http-server',
+            self.name if self.name else 'http-server',
             GHttpServer,
             self,
             subscriber=self,

File ginsfsm/router.py

View file
                 this_route.gaplic_name,
                 this_route.roles,
                 gsock.addr))
-            self.logger.info("%d dynamic routes" % (
-                len(registry.dynamic_routes)))
 
         if session:
             session.route = this_route