1. artgins
  2. ginsfsm

Commits

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

cleaning

  • Participants
  • Parent commits ce79af0
  • Branches default

Comments (0)

Files changed (8)

File ginsfsm/c_sock.py

View file
         close_all_sockets(obj._socket_map)
         raise
     except:
-        logging.error("Exception in I/O handler for fd %r", obj, exc_info=True)
+        obj.logger.error(
+            "Exception in I/O handler for fd %r", obj, exc_info=True)
 
 
 def poll_loop(socket_map, _impl, timeout):
     self.mt_flush()
 
 
+def ac_disconnected(self, event):
+    """ Used by GServerSock.
+    """
+    gsock = event.gsock
+    self.post_event(self, 'EV_DESTROY_GSOCK', gsock=gsock)
+
+
+def ac_drop_gsock(self, event):
+    """ Used by GServerSock.
+        Destroy gsock.
+    """
+    gsock = event.gsock
+    GObj.destroy_gobj(gsock)
+    self.config.n_gsocks -= 1
+
+
 GSOCK_FSM = {
     'event_list': (
         'EV_CONNECT:top input',
         'EV_DROP:top input',
         'EV_CONNECTED: top output',
-        'EV_DISCONNECTED: top output',
+        'EV_DISCONNECTED: top output: bottom input',  # used by srvsock
         'EV_RX_DATA: top output',
         'EV_SEND_DATA: top input',
         'EV_WRITE_OUTPUT_DATA: top input',
         'EV_FLUSH_OUTPUT_DATA: top input',
-        'EV_TRANSMIT_READY: top output'
+        'EV_TRANSMIT_READY: top output',
+        'EV_DESTROY_GSOCK',
     ),
     'state_list': ('ST_IDLE',),
     'machine': {
             ('EV_SEND_DATA',            ac_send_data,       None),
             ('EV_WRITE_OUTPUT_DATA',    ac_write,           None),
             ('EV_FLUSH_OUTPUT_DATA',    ac_flush,           None),
+
+            # Used by GServerSock
+            ('EV_DISCONNECTED',         ac_disconnected,    None),
+            ('EV_DESTROY_GSOCK',        ac_drop_gsock,      None),
         ),
     }
 }
         bool, False, 0, None,
         "True to close the socket when flushed"
     ],
+    'n_gsocks': [int, 0, 0, None, "Server Stats: Number of gsocks opened"],
 }
 
 
         try:
             self._impl_poll.unregister(fd)
         except (OSError, IOError):
-            logging.error("Error deleting fd from IOLoop", exc_info=True)
+            self.logger.error("Error deleting fd from IOLoop", exc_info=True)
 
     #==================================================
     #   socket object methods.
             return retattr
 
     def handle_read_event(self):
-        #logging.debug("handle_read_event    (%s %s)" % (self, self.name))
+        #self.logger.debug("handle_read_event    (%s %s)" % (self, self.name))
         if self._accepting:
             # _accepting sockets are never connected, they "spawn" new
             # sockets that are connected
             self.handle_read()
 
     def handle_connect_event(self):
-        #logging.debug("handle_connect_event (%s %s)" % (self, self.name))
+        #self.logger.debug("handle_connect_event (%s %s)" % (self, self.name))
         err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
         if err != 0:
             raise socket.error(err, _strerror(err))
         self.handle_connect()
 
     def handle_write_event(self):
-        #logging.debug("handle_write_event   (%s %s)" % (self, self.name))
+        #self.logger.debug("handle_write_event   (%s %s)" % (self, self.name))
         if self._accepting:
             # Accepting sockets shouldn't get a write event.
             # We will pretend it didn't happen.
         except:
             self_repr = '<__repr__(self) failed for object at %0x>' % id(self)
 
-        logging.error(
+        self.logger.error(
             'uncaptured python exception, closing channel %s (%s:%s %s)' % (
                 self_repr,
                 t,
             # accept. socketmodule.c:makesockaddr complains that the
             # address family is unknown. We don't want the whole server
             # to shut down because of this.
-            logging.warning(
+            self.logger.warning(
                 'server accept() threw an exception',
                 exc_info=True)
 
     def handle_accepted(self, sock, addr):
         sock.close()
-        logging.warning('unhandled accepted event')
+        self.logger.warning('unhandled accepted event')
 
     def _mt_connect(self, **kw):
         """ Try to connect to (host, port).
         self.__dict__.update(**kw)
 
         if self.connected:
-            logging.error(
+            self.logger.error(
                 "ERROR connecting to host %r, port %r. "
                 "ALREADY CONNECTED." % (self.config.host, self.config.port))
             return False
         if self.socket:
-            logging.error(
+            self.logger.error(
                 "ERROR connecting to host %r, port %r. SOCKET EXISTS." %
                 (self.config.host, self.config.port))
             self.close()  # ???
         try:
             self.config.ip = ip = socket.gethostbyname(self.config.host)
         except Exception as e:
-            logging.error('ERROR gethostbyname(%r) %s' % (self.config.host, e))
+            self.logger.error('ERROR gethostbyname(%r) %s' % (
+                self.config.host, e))
             return False
         hora = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
-        logging.info("%s * %r ==> Connecting to host %r, ip %r, port %r..." % (
+        self.logger.info(
+            "%s * %r ==> Connecting to host %r, ip %r, port %r..." % (
             hora,
             self,
             self.config.host,
         try:
             self.connect((ip, self.config.port))
         except Exception as e:
-            logging.error("_mt_connect() ERROR %r" % e)
+            self.logger.error("_mt_connect() ERROR %r" % e)
             return False
         return True
 
         self.sockname = self.socket.getsockname()
 
         hora = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
-        logging.info("%s - %r <== Connected! %s host %s" % (
+        self.logger.info("%s - %r <== Connected! %s host %s" % (
             hora,
             self,
             "FROM" if self._clisrv else "TO",
                 outbuf._close()
             except:
                 hora = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
-                logging.exception(
+                self.logger.exception(
                     '%s - ERROR in %s: Unknown exception'
                     'while trying to close outbuf' % (hora, self.name))
         self.close()
         self.remove_socket()
         if 1:
             hora = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
-            logging.info(
+            self.logger.info(
                 "%s * %r <== Disconnected! from %r %r %r" % (
                 hora,
                 self,
             sent = self._flush_some()
         except socket.error:
             hora = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
-            logging.exception('%s - ERROR in %s: Socket error' % (
+            self.logger.exception('%s - ERROR in %s: Socket error' % (
                 hora, self.name))
             self.will_close = True
         except:
                 if self.trace_dump:
                     hora = datetime.datetime.now().strftime(
                         "%Y-%m-%d %H:%M:%S")
-                    logging.info(
+                    self.logger.info(
                         "%s - Send data %r (%d bytes)\n%s" % (
                             hora,
                             self,
                     peer = self.socket.getpeername()
                 except:
                     peer = '(not connected)'
-                logging.warning("SSL Error on %d %s: %s",
-                                self.socket.fileno(), peer, err)
+                self.logger.warning(
+                    "SSL Error on %d %s: %s",
+                    self.socket.fileno(), peer, err)
                 return self.close()
             raise
         except socket.error, err:

File ginsfsm/c_srv_sock.py

View file
 import logging
 import errno
 import socket
+from ginsfsm.gobj import GObj
 from ginsfsm.c_sock import (
     GSock,
     GSSLSock
 )
 
+
+def ac_disconnected(self, event):  # ONLY for documentation (It's in GSock)
+    """ Used by GServerSock.
+    """
+    gsock = event.gsock
+    self.post_event(self, 'EV_DESTROY_GSOCK', gsock=gsock)
+
+
+def ac_drop_gsock(self, event):  # ONLY for documentation (It's in GSock)
+    """ Used by GServerSock.
+        Destroy gsock.
+    """
+    gsock = event.gsock
+    GObj.destroy_gobj(gsock)
+    self.config.n_gsocks -= 1
+
+
 GSERVERSOCK_FSM = {  # ONLY for documentation. Partial use of GSOCK_FSM.
     'event_list': (
         'EV_CONNECTED: top output',
+        'EV_DISCONNECTED: bottom input',
+        'EV_DESTROY_GSOCK',
     ),
     'state_list': ('ST_IDLE',),
     'machine': {
         'ST_IDLE':
         (
+            ('EV_DISCONNECTED',     ac_disconnected,    None),
+            ('EV_DESTROY_GSOCK',    ac_drop_gsock,      None),
         ),
     }
 }
     'ports': [tuple, (), 0, None, "multi ports"],
     'use_multi_ports': [bool, False, 0, None, "use multi ports"],
     'ssl_options': [dict, {}, 0, None, "ssl options"],
+    'n_gsocks': [int, 0, 0, None, "Server Stats: Number of gsocks opened"],
 }
 
 
         # TODO: check origins for permitted source ip.
         socket_options = [
             (socket.SOL_TCP, socket.TCP_NODELAY, 1),
-            ]
+        ]
         for (level, optname, value) in socket_options:
             sock.setsockopt(level, optname, value)
 
         )
         clisrv.set_clisrv_socket(sock)
         clisrv.handle_connect()
+
+        # we need to know disconnected event for deleting gobjs
+        clisrv.subscribe_event(
+            'EV_DISCONNECTED',
+            self,
+            __hard_subscription__=True,
+        )
+        self.config.n_gsocks += 1

File ginsfsm/examples/sockjs/test_sockjs_server.ini

View file
 use = call:ginsfsm.examples.sockjs.test_sockjs_server:paste_app_factory
 gaplic = ga
 
-pyramid.reload_templates = true
-pyramid.debug_authorization = true
-pyramid.debug_notfound = true
-pyramid.debug_routematch = true
-pyramid.debug_templates = true
+pyramid.reload_templates = false
+pyramid.debug_authorization = flase
+pyramid.debug_notfound = false
+pyramid.debug_routematch = false
+pyramid.debug_templates = false
 pyramid.default_locale_name = en
 
 # Begin logging configuration
 handlers = console
 
 [logger_ginsfsm]
-level = INFO
+level = WARN
 handlers =
 qualname = ginsfsm
 

File ginsfsm/gobj.py

View file
         GConfig.__init__(self, gconfig)
 
     def __del__(self):
-        if self.logger:
-            self.logger.debug("Destroyed! <-- %r" % (self))
+        logging.debug("Destroyed! <-- %r" % (self))
 
     def __str__(self):
         name = "%s" % (self.name)
         if self.__random_name__:
             name = self.get_random_name(name)
 
-        if self.logger:
-            self.logger.debug("Creating --> '%s:%s'" % (
-                gclass.__name__, name))
+        self.logger.debug("Creating --> '%s:%s'" % (
+            gclass.__name__, name))
 
         gobj = gclass()
 
     def destroy_gobj(gobj):
         """ Destroy a gobj
         """
-        if gobj.logger:
-            gobj.logger.debug("Destroying --> %r" % (gobj))
+        gobj.logger.debug("Destroying --> %r" % (gobj))
 
         if gobj._destroyed:
-            logging.error("ERROR reentering in destroy_gobj: %r" % gobj)
+            gobj.logger.error("ERROR reentering in destroy_gobj: %r" % gobj)
             return
+
         gobj._destroyed = True
         if gobj.parent is not None:
             gobj.parent._remove_child(gobj)
         while len(gobj.dl_childs):
             try:
                 for child in gobj.dl_childs:
-                    GObj.destroy_gobj(child)
+                    if not child._destroyed:
+                        GObj.destroy_gobj(child)
             except RuntimeError:
                 pass  # "Set changed size during iteration" is OK
 

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

View file
     """
 
 
-def ac_disconnected(self, event):
-    """ Gsock closed.
-    """
-    if self.gsock:
-        gsock = self.gsock
-        self.gsock = None
-        GObj.destroy_gobj(gsock)
-    self.broadcast_event('EV_HTTP_CHANNEL_CLOSED', channel=self)
-
-
 def ac_rx_data(self, event):
     """ Receiving data from the partner clisrv gsock.
         Can be one or more requests.
     if not self.gsock:
         return
 
-    body = ('Response Timeout. The server is busy. '
-            'Please re-try your request in a few moments.'
+    body = (
+        'Response Timeout. The server is busy. '
+        'Please re-try your request in a few moments.'
     )
     request = HTTPRequestParser(self)
     request.error = InternalServerError(body)
     self.finish(response)
 
 
+def ac_disconnected(self, event):
+    """ Gsock closed.
+    """
+    self.broadcast_event('EV_HTTP_CHANNEL_CLOSED', channel=self)
+
+
 GHTTPCLISRV_FSM = {
     'event_list': (
         'EV_SET_TIMER: bottom output',
     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:
         # Canalize the flow of messages
         # 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',

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

View file
         max_request_header_size=self.config.max_request_header_size,
         max_request_body_size=self.config.max_request_body_size,
     )
-    clisrv.subscribe_event(
+    clisrv.subscribe_event(  # to delete the channel
         'EV_HTTP_CHANNEL_CLOSED',
         self,
         __hard_subscription__=True,
     )
+    self.config.n_channels += 1
 
 
 def ac_channel_closed(self, event):
     """ **Some** clisvr gsock closed, drop it.
     """
     channel = event.channel
-    self.post_event(self, 'EV_DESTROY_CLISRV', channel=channel)
+    self.post_event(self, 'EV_DESTROY_CHANNEL', channel=channel)
 
 
 def ac_drop_httpchannel(self, event):
     self._n_channel -= 1
     # the gsock is destroy in channel.ac_disconnected (GHttpCliSrv)
     GObj.destroy_gobj(channel)
+    self.config.n_channels -= 1
 
 
 def ac_timeout(self, event):
         'EV_CONNECTED: bottom input',
         'EV_HTTP_CHANNEL_CLOSED: bottom input',
         'EV_TIMEOUT',
-        'EV_DESTROY_CLISRV',
+        'EV_DESTROY_CHANNEL',
     ),
     'state_list': ('ST_IDLE',),
     'machine': {
             ('EV_TIMEOUT',              ac_timeout,             None),
             ('EV_CONNECTED',            ac_connected,           None),
             ('EV_HTTP_CHANNEL_CLOSED',  ac_channel_closed,      None),
-            ('EV_DESTROY_CLISRV',       ac_drop_httpchannel,    None),
+            ('EV_DESTROY_CHANNEL',      ac_drop_httpchannel,    None),
         ),
     }
 }
     'max_request_header_size': [int, 262144, 0, None, ""],
     # maximum number of bytes in request body (1GB default)
     'max_request_body_size': [int, 1073741824, 0, None, ""],
+    'n_channels': [int, 0, 0, None, "Server stats, number of channels opened"],
 }
 
 

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

View file
             raise Exception('You must supply a connection application.')
         self._connection = self.config.sockjs_app_class
 
-        if self.logger:
-            self.logger.debug(
-                ">>> sockjs resource path: " + resource_path(self)
-            )
-
         #----------------------------------------------#
         #           Static handlers
         #----------------------------------------------#

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

View file
     def go_out(self):
         """ Finish zone.
         """
-        if self.gsock:
-            # delete gsock. It's not our child
-            gsock = self.gsock
-            self.gsock = None
-            GObj.destroy_gobj(gsock)
 
     def start_inactivity_timer(self, seconds):
         self.send_event(