Commits

Yoshifumi YAMAGUCHI committed bfb1b8e

reading sock.rst

  • Participants
  • Parent commits fd86816

Comments (0)

Files changed (6)

File notes/source/gunicorn/__init__.rst

+.. -*- coding: utf-8 -*-
+
+============================
+ __init__ -- gunicorn初期化
+============================
+
+.. module:: gunicorn
+
+.. attribute:: version_info
+
+   ``(0, 12, 0)`` というタプル
+
+.. attribute:: __version__
+   
+   ``0.12.0`` という文字列
+
+.. attribute:: SERVER_SOFTWARE
+
+   ``gunicorn/0.12.0`` という文字列
+
+   **呼び出し**
+
+   - :meth:`Arbiter.__init__`
+

File notes/source/gunicorn/app.rst

 
    ベースとなるApplicationクラス。
 
+   .. attribute:: cfg
+
+      
+
+   .. method:: __init__(usage)
+
+      **概要**
+
+      :param usage: 特定フォーマットの使用方法の文字列
+
+      - 各パラメータを設定
+      - :meth:`do_load_config` を呼び出し
+
+      **実装**
+
+      .. code-block:: python
+
+         def __init__(self, usage=None):
+             self.usage = usage
+             self.cfg = None
+             self.callable = None
+             self.logger = None
+             self.do_load_config()
+
+
+   .. method:: do_load_config()
+
+      **概要**
+
+      - :meth:`load_config` を呼び出し
+
+      **実装**
+
+      .. code-block:: python
+
+         def do_load_config(self):
+             try:
+                 self.load_config()
+             except Exception, e:
+                 sys.stderr.write("\nError: %s\n" % str(e))
+                 sys.stderr.flush()
+
+
+      **呼び出し**
+
+      - :meth:`__init__`
+
+
+   .. method:: load_config()
+
+      **概要**
+
+      - :attr:`cfg` に :class:`Config` のインスタンスを設定
+      - :meth:`Config.parser` でオプションのパーサを作成
+      - :meth:`init` で :attr:`cfg` 由来の追加の設定を行う
+
+      **実装**
+
+      .. code-block:: python
+
+         def load_config(self):
+             # init configuration
+             self.cfg = Config(self.usage)
+             
+             # parse console args
+             parser = self.cfg.parser()
+             opts, args = parser.parse_args()
+             
+             # optional settings from apps
+             cfg = self.init(parser, opts, args)
+             
+             # Load up the any app specific configuration
+             if cfg:
+                 for k, v in list(cfg.items()):
+                     self.cfg.set(k.lower(), v)
+                     
+             # Load up the config file if its found.
+             if opts.config and os.path.exists(opts.config):
+                 cfg = {
+                     "__builtins__": __builtins__,
+                     "__name__": "__config__",
+                     "__file__": opts.config,
+                     "__doc__": None,
+                     "__package__": None
+                 }
+                 try:
+                     execfile(opts.config, cfg, cfg)
+                 except Exception:
+                     print "Failed to read config file: %s" % opts.config
+                     traceback.print_exc()
+                     sys.exit(1)
+             
+                 for k, v in list(cfg.items()):
+                     # Ignore unknown names
+                     if k not in self.cfg.settings:
+                         continue
+                     try:
+                         self.cfg.set(k.lower(), v)
+                     except:
+                         sys.stderr.write("Invalid value for %s: %s\n\n" % (k, v))
+                         raise
+                 
+             # Lastly, update the configuration with any command line
+             # settings.
+             for k, v in list(opts.__dict__.items()):
+                 if v is None:
+                     continue
+
+
+      **呼び出し**
+
+      - :meth:`do_load_config`
+
+
+   .. method:: init(parser, opts, args)
+
+      **概要**
+      
+      :param parser: 
+      :param opts:
+      :param args:
+
+      サブクラスで実装するべき初期化。サブクラス毎の設定の初期化を行う。
+
+      **実装**
+
+      .. code-block:: python
+
+         def init(self, parser, opts, args):
+             raise NotImplementedError
+
+      **呼び出し**
+
+      - :meth:`load_config`
+         
+
    .. method:: run()
 
       :meth:`Arbiter.run` を呼び出している

File notes/source/gunicorn/arbiter.rst

 
    .. attribute:: PIPE
 
+      **呼び出し**
+
       - :meth:`init_signals`
 
    .. attribute:: LISTENER
 
+      **呼び出し**
+
       - :meth:`start`
 
    .. attribute:: SIGNALS
 
+      **呼び出し**
+
       - :meth:`init_signals`
 
    .. attribute:: SIG_QUEUE
 
+      **呼び出し**
+
       - :meth:`signal`
 
+   .. attribute:: SERVER_SOFTWARE
+
+      **呼び出し**
+
+      - :meth:`__init__`
+
+
+   .. attribute:: app
+
+      呼び出し元の :class:`Application` インスタンス
+
+   .. attribute:: cfg
+
+      呼び出し元の :class:`Application` に設定されている :class:`Config` のインスタンス
+
+   .. method:: __init__(app)
+
+      **概要**
+
+      :param app: :class:`Application` のインスタンス
+
+      - `logging.getLogger()`_ でログファイルを用意
+      - INFOレベルでgunicornのバージョンをログで採取
+      - :attr:`__init__.SERVER_SOFTWARE` を環境変数に設定
+      - :meth:`setup` を呼び出し
+
+      .. _`logging.getLogger()`: file:///Users/ymotongpoo/docs/python26jp/build/html/library/logging.html#logging.getLogger
+
+      **実装**
+
+      .. code-block:: python
+
+         def __init__(self, app):
+             self.log = logging.getLogger(__name__)
+             self.log.info("Starting gunicorn %s" % __version__)
+            
+             os.environ["SERVER_SOFTWARE"] = SERVER_SOFTWARE
+     
+             self.setup(app)
+             
+             self.pidfile = None
+             self.worker_age = 0
+             self.reexec_pid = 0
+             self.master_name = "Master"
+             
+             # get current path, try to use PWD env first
+             try:
+                 a = os.stat(os.environ['PWD'])
+                 b = os.stat(os.getcwd())
+                 if a.ino == b.ino and a.dev == b.dev:
+                     cwd = os.environ['PWD']
+                 else:
+                     cwd = os.getcwd()
+             except:
+                 cwd = os.getcwd()
+                 
+             args = sys.argv[:]
+             args.insert(0, sys.executable)
+     
+             # init start context
+             self.START_CTX = {
+                 "args": args,
+                 "cwd": cwd,
+                 0: sys.executable
+             }
+
+
+   .. method:: setup(app)
+
+      **概要**
+
+      :param app: :class:`Application` のインスタンス
+
+      **実装**
+
+      .. code-block:: python
+
+         def setup(self, app):
+             self.app = app
+             self.cfg = app.cfg
+             self.address = self.cfg.address
+             self.num_workers = self.cfg.workers
+             self.debug = self.cfg.debug
+             self.timeout = self.cfg.timeout
+             self.proc_name = self.cfg.proc_name
+             self.worker_class = self.cfg.worker_class
+             
+             if self.cfg.debug:
+                 self.log.debug("Current configuration:")
+                 for config, value in sorted(self.cfg.settings.iteritems()):
+                     self.log.debug("  %s: %s" % (config, value.value))
+             
+             if self.cfg.preload_app:
+                 if not self.cfg.debug:
+                     self.app.wsgi()
+                 else:
+                     self.log.warning("debug mode: app isn't preloaded.")
+
+
+      **呼び出し**
+
+      - :meth:`__init__`
 
    .. method:: run()
 
 
    .. method:: start()
 
-      **実装**
+      **概要**
 
       - pidを取得する
       - :meth:`init_signals` 呼ぶ
       - :attr:`LISTENER` がなければ :meth:`gunicorn.sock.create_socket` 呼ぶ
 
+      **実装**
+
       .. code-block:: python
 
          def start(self):
              self.cfg.when_ready(self)
 
 
+      **呼び出し**
+      
+      - :meth:`run`
+
    .. method:: init_signals()
 
       **概要**
       - :func:`util.set_non_blocking` を呼び出して、いま作成したパイプをノンブロッキングにする。
       - :func:`util.close_on_exec` を呼び出して、パイプが他のプロセスから呼ばれていた場合に `exec()` 時にクローズするようにする。
       - :attr:`SIGNALS` の各非同期イベントシグナルを `signal.signal()`_ に渡して、それぞれに対するハンドラを :meth:`signal` にする。
+      - 子プロセスの刈り取り処理の為に `SIGCHLD`_ だけは別途実装する。
 
       .. _`signal.signal()`: http://www.python.jp/doc/2.6/library/signal.html#signal.signal
+      .. _`SIGCHLD`: http://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9
 
       **実装**
    
 
       **概要**
 
-      
+      `os.write()`_ でパイプに ``'.'`` を書きこむ。
+
+      .. _`os.write()`: http://www.python.jp/doc/2.6/library/os.html#os.write
 
       **実装**
 

File notes/source/gunicorn/config.rst

+.. -*- coding: utf-8 -*-
+
+==========================
+ config -- 設定モジュール
+==========================
+
+.. module:: config
+
+.. attribute:: KNOWN_SETTINGS
+
+   デフォルト設定用関数を入れておくリスト
+
+.. function:: make_settings(ignore)
+
+   **概要**
+
+   :param ignore: 無視する設定名を入れておくタプル
+
+   **実装**
+
+   .. code-block:: python
+
+      def make_settings(ignore=None):
+          settings = {}
+          ignore = ignore or ()
+          for s in KNOWN_SETTINGS:
+              setting = s()
+              if setting.name in ignore:
+                  continue
+              settings[setting.name] = setting.copy()
+          return settings
+
+   **呼び出し**
+
+   - :meth:`Config.__init__`
+
+
+.. class:: Config
+
+   .. attribute:: settings
+   
+      設定用の辞書
+
+   .. attribute:: usage
+
+   .. method:: __init__(usage)
+
+      **概要**
+
+      :param usage: 特定フォーマットの使用方法の記述
+      
+      - :attr:`settings` を :meth:`make_settings` で作成
+      - :attr:`usage` に usage を代入。デフォルトは ``None``
+
+      **実装**
+
+      .. code-block:: python
+
+         def __init__(self, usage=None):
+             self.settings = make_settings()
+             self.usage = usage
+         
+
+   .. method:: parser()
+
+      **概要**
+
+      - `optparse.OptionParser()`_ でオプションパーサーを生成
+      - setting内の設定を受け取れるように設定
+
+      .. _`optparse.OptionParser(**kwargs)`: file:///Users/ymotongpoo/docs/python26jp/build/html/library/optparse.html
+
+      **実装**
+
+      .. code-block:: python
+
+         def parser(self):
+             kwargs = {
+                 "usage": self.usage,
+                 "version": __version__
+             }
+             parser = optparse.OptionParser(**kwargs)
+     
+             keys = self.settings.keys()
+             def sorter(k):
+                 return (self.settings[k].section, self.settings[k].order)
+             keys.sort(key=sorter)
+             for k in keys:
+                 self.settings[k].add_option(parser)
+
+      **呼び出し**
+
+      - :meth:`Application.load_config`

File notes/source/gunicorn/index.rst

    entry
    app
    arbiter   
+   config
+   sock
    util
 
+.. toctree::
+   :hidden:
+
+   __init__
+
+
 
 ツリー
 ======

File notes/source/gunicorn/sock.rst

+.. -*- coding: utf-8 -*-
+
+============================
+ sock -- ソケットモジュール
+============================
+
+.. module:: sock
+
+.. function:: create_socket(conf)
+
+**概要**
+
+:param conf: 設定
+
+**実装**
+
+.. code-block:: python
+
+   def create_socket(conf):
+       """
+       Create a new socket for the given address. If the
+       address is a tuple, a TCP socket is created. If it
+       is a string, a Unix socket is created. Otherwise
+       a TypeError is raised.
+       """
+       # get it only once
+       addr = conf.address
+       
+       if isinstance(addr, tuple):
+           if util.is_ipv6(addr[0]):
+               sock_type = TCP6Socket
+           else:
+               sock_type = TCPSocket
+       elif isinstance(addr, basestring):
+           sock_type = UnixSocket
+       else:
+           raise TypeError("Unable to create socket from: %r" % addr)
+   
+       if 'GUNICORN_FD' in os.environ:
+           fd = int(os.environ.pop('GUNICORN_FD'))
+           try:
+               return sock_type(conf, fd=fd)
+           except socket.error, e:
+               if e[0] == errno.ENOTCONN:
+                   log.error("GUNICORN_FD should refer to an open socket.")
+               else:
+                   raise
+   
+       # If we fail to create a socket from GUNICORN_FD
+       # we fall through and try and open the socket
+       # normally.
+       
+       for i in range(5):
+           try:
+               return sock_type(conf)
+           except socket.error, e:
+               if e[0] == errno.EADDRINUSE:
+                   log.error("Connection in use: %s" % str(addr))
+               if e[0] == errno.EADDRNOTAVAIL:
+                   log.error("Invalid address: %s" % str(addr))
+                   sys.exit(1)
+               if i < 5:
+                   log.error("Retrying in 1 second.")
+                   time.sleep(1)
+             
+       log.error("Can't connect to %s" % str(addr))
+       sys.exit(1)
+
+
+**呼び出し**
+
+- :meth:`Arbiter.start`