Commits

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

developing http server

Comments (0)

Files changed (6)

docs/src/api/http-server.png

Old
Old image
New
New image

ginsfsm/gaplic.py

             'register_unique_gobj': self.register_unique_gobj,
             'deregister_unique_gobj': self.deregister_unique_gobj,
             'find_unique_gobj': self.find_unique_gobj,
+            'delete_all_references': self.delete_all_references,
             '_increase_inside': self._increase_inside,
             '_decrease_inside': self._decrease_inside,
             '_tab': self._tab,
         named_gobj = self._unique_named_gobjs.get(gobj_name, None)
         return named_gobj
 
+    def delete_all_references(self, gobj):
+        """ Delete all references of gobj in timer and event queues.
+        """
+        # TODO: by the moment, be care with your event generation
+
     def _loop(self):
         """ process event queue, timer queue, and epoll.
         Return True if there is some remain event for be proccessed.
         return False
 
     def _process_timer(self):
-        # dont use iteritems() items(),
-        # some xtimer can remove during processing timers
+        # don't use iteritems() items(),
+        # some xtimer can be removed during processing timers
         some_event = False
         try:
             for xtimer in iterkeys_(self._gotter_timers):
     'register_unique_gobj': [None, None, 0, None, ''],
     'deregister_unique_gobj': [None, None, 0, None, ''],
     'find_unique_gobj': [None, None, 0, None, ''],
+    'delete_all_references': [None, None, 0, None, ''],
     '_increase_inside': [None, None, 0, None, ''],
     '_decrease_inside': [None, None, 0, None, ''],
     '_tab': [None, None, 0, None, ''],
 
         self._dl_subscriptions = set()      # uauuu, how many fans!!
         self._some_subscriptions = False
-        self._gobj_destroyed = False  # mark as destroyed when destroy_gobj()
+        self._destroyed = False  # mark as destroyed when destroy_gobj()
 
         gconfig = add_gconfig(gconfig, GOBJ_GCONFIG)
         GConfig.__init__(self, gconfig)
     def destroy_gobj(self, gobj):
         """ Destroy a gobj
         """
-        gobj.deregister_unique_gobj(gobj)
+        self.deregister_unique_gobj(gobj)
         if gobj.parent is not None:
             gobj.parent._remove_child(gobj)
 
             except RuntimeError:
                 pass  # "Set changed size during iteration" is OK
 
+        self.delete_all_references(gobj)
         gobj.delete_all_subscriptions()
-        gobj._gobj_destroyed = True
-        SMachine._machine_destroyed = True
+        gobj._destroyed = True
         del gobj
 
     def start_up(self):
             You must consult the attributes supported by each machine's event.
         """
         destination = self._resolv_destination(destination)
-        if destination._gobj_destroyed:
+        event = self._event_factory(destination, event, **kw)
+        if destination._destroyed:
             logging.error("GObj ERROR internal: "
-                "sending an event to a destroyed gobj",
+                "sending event %s to a destroyed gobj", event.event_name
             )
             return -1
 
-        event = self._event_factory(destination, event, **kw)
-
         if self.gaplic:
             cur_ident = threading.current_thread().ident
             cur_name = threading.current_thread().name
         """
         return None
 
+    def delete_all_references(self, gobj):
+        """ Delete all references of gobj in upper levels (ex: queues).
+        Call when the gobj is destroyed.
+        To be overriden by :term:`gaplic` or similar.
+        """
+
     def _add_child(self, gobj):
         """ Add a child ``gobj``.
 

ginsfsm/protocols/http/server/c_http_clisrv.py

 def ac_disconnected(self, event):
     """ Gsock closed.
     """
+    self.gsock = None
     self.broadcast_event('EV_HTTP_CHANNEL_CLOSED')
 
 
 
 
 def ac_inactivity_timeout(self, event):
-    # Close the channel by inactivity.
-    self.send_event(self.gsock, 'EV_DROP')
+    """ Close the channel by inactivity.
+    """
+    if self.gsock:
+        self.send_event(self.gsock, 'EV_DROP')
 
 
 def ac_responseless_timeout(self, event):
-    # Close the channel by responseless of top level.
+    """ Close the channel by responseless of top level.
+    """
+    if not self.gsock:
+        return
+
     body = ('The server is busy. '
             'Please re-try your request in a few moments.'
     )

ginsfsm/protocols/http/server/c_http_server.py

     self._n_connected_clisrv += 1
     gsock = event.source[-1]
     gsock.delete_all_subscriptions()
-    gsock.subscribe_event('EV_DISCONNECTED', self)  # to destroy the gobj.
 
     if self.name:
         prefix_name = self.name
     else:
         prefix_name = None
     channel = '.http.%s' % gsock.name
-    self.create_gobj(
+    clisrv = self.create_gobj(
         prefix_name + channel if prefix_name else None,
         GHttpCliSrv,
         self,
         max_request_header_size=self.max_request_header_size,
         max_request_body_size=self.max_request_body_size,
     )
+    clisrv.subscribe_event('EV_HTTP_CHANNEL_CLOSED', self)
 
 
 def ac_disconnected(self, event):
     """ **Some** clisvr gsock closed, drop it.
     """
-    gsock = event.source[-1]
-    self.post_event(self, 'EV_DESTROY_CLISRV', gsock=gsock)
+    gobj = event.source[-1]
+    self.post_event(self, 'EV_DESTROY_CLISRV', gobj=gobj)
 
 
 def ac_drop_httpchannel(self, event):
     """ It's better receive this event by post_event().
     """
-    gsock = event.gsock
+    gobj = event.gobj
     self._n_connected_clisrv -= 1
-    self.destroy_gobj(gsock)
+    self.destroy_gobj(gobj)
 
 
 def ac_timeout(self, event):
 GHTTPSERVER_FSM = {
     'event_list': (
         'EV_CONNECTED: bottom input',
-        'EV_DISCONNECTED: bottom input',
+        'EV_HTTP_CHANNEL_CLOSED: bottom input',
         'EV_TIMEOUT',
         'EV_DESTROY_CLISRV',
     ),
     'machine': {
         'ST_IDLE':
         (
-            ('EV_TIMEOUT',          ac_timeout,             None),
-            ('EV_CONNECTED',        ac_connected,           None),
-            ('EV_DISCONNECTED',     ac_disconnected,        None),
-            ('EV_DESTROY_CLISRV',   ac_drop_httpchannel,    None),
+            ('EV_TIMEOUT',              ac_timeout,             None),
+            ('EV_CONNECTED',            ac_connected,           None),
+            ('EV_HTTP_CHANNEL_CLOSED',  ac_disconnected,        None),
+            ('EV_DESTROY_CLISRV',       ac_drop_httpchannel,    None),
         ),
     }
 }
           :class:`ginsfsm.protocols.http.server.c_http_clisrv.GHttpCliSrv` gobj
           is created, to process all the events of the GSock gobj.
 
-          This class will remain subscribing to the ``'EV_DISCONNECTED'`` event
-          in order to destroy the GSock gobj.
+          This class will be subscred to the ``'EV_HTTP_CHANNEL_CLOSED'`` event
+          in order to destroy the GHttpCliSrv gobj.
 
           Event attributes:
 
             * ``sockname``: the socket’s own address.
 
 
-        * :attr:`'EV_DISCONNECTED'`: socket disconnected.
+        * :attr:`'EV_HTTP_CHANNEL_CLOSED'`: http channel disconnected.
 
           The clisrv `gobj` will be destroyed.
 

ginsfsm/smachine.py

         self._current_state = 1
         self.__trace_mach = False
         self.logger = None
-        self._machine_destroyed = False  # mark as destroyed when destroy_gobj()
 
         # check state names
         state_names = list(self._state_list)
         the executed :term:`action`.
         """
 
-        if self._machine_destroyed:
-            logging.error("SMachine ERROR internal: "
-                "sending an event to a destroyed gobj",
-            )
-            return -1
-
         result = None
         logger = self.logger
         trace_mach = self.trace_mach