Commits

Yann Malet committed 1349280

Continue to import existing docs from the wiki to sphinx

  • Participants
  • Parent commits 5da6b6c
  • Branches sphinx-docs

Comments (0)

Files changed (11)

docs/features/cache.rst

+.. _cache-framework:
+
+================
+cache framework
+================
+
+.. versionadded :: 0.9.7-dev
+
+Caching is one of the key component of a successful webapp. uWSGI includes an
+ultra-fast all-in-memory smp-safe constantly-auto-optimizing caching framework.
+
+The uwsgi api exposes only 4 functions:
+
+.. code-block:: python
+
+    cache_get(key[, cache_server])
+    cache_set(key, value[, expire, cache_server])
+    cache_del(key[, cache_server])
+    cache_exists(key[, cache_server])
+
+So for writing into the cache from python or lua you will use something like
+this::
+
+    uwsgi.cache_set("foo_key", "foo_value")
+
+and for reading::
+
+    uwsgi.cache_get("foo_key")
+
+The optional cache_server argument is a tcp / unix socket address. To enable
+caching you have to simply allocate slot for your items using the ``--cache``
+option::
+
+    ./uwsgi --socket 127.0.0.1:3031 --module mysimpleapp --master --processes 4 --cache 1000
+
+You now have a cache that can contains at most 1000 items
+
+The evil part
+==============
+
+To gain maximum performance caching has very strict limits (but no so strict).
+Key can be at most 2048 bytes (ok, this is not a limit, i do not think you will
+ever have so big names ;)
+
+Values are put in fixed size blocks, so whatever data you will put in the
+cache will take the same amount of space (blocksize is configurable).
+
+The good part
+==============
+
+Caching is completely thread/multiprocess/smp safe (write and del commands
+will lock). The cache can be accessed via network using the modifier 111, so
+you can access remote data with::
+
+    data = uwsgi.send_message("host", 111, 0, "foo_key")
+
+or::
+
+    data = uwsgi.send_message("host", 111, 3, {"key":"foo_key"})
+
+Or (more important) directly from your webserver::
+
+    location / {
+        uwsgi_pass 127.0.0.1:3031;
+        uwsgi_modifier1 111;
+        uwsgi_modifier2 3;
+        uwsgi_param key $request_uri;
+    }
+
+With this few lines you will instruct nginx to get data from a remote uwsgi
+compliant server. Honestly this is not very useful, as if you get a cache miss,
+you will see a blank page.
+
+A better system, that will fallback to a real uwsgi request would be::
+
+    location / {
+                    uwsgi_pass 192.168.173.3:3032;
+                    uwsgi_modifier1 111;
+                    uwsgi_modifier2 3;
+                    uwsgi_param key $request_uri;
+                    uwsgi_pass_request_headers off;
+                    error_page 502 504 = @real;
+            }
+
+        location @real {
+                uwsgi_pass 192.168.173.3:3032;
+                uwsgi_modifier1 0;
+                uwsgi_modifier2 0;
+                include uwsgi_params;
+        }
+
+
+The very good part
+===================
+
+The uWSGI master process will constantly optimize your cache in a way that most
+requested items are always on the top of the stack. This is still a working-on
+part but the current implementation is already fast as hell.
+
+The awesome part
+=================
+
+If you are running django here's a django cache backend ready to use; copy the
+code to a file named uwsgicache.py and put where your app can load it:
+
+.. code-block:: python
+    :linenos:
+
+    """uWSGI cache backend"""
+    
+    from django.core.cache.backends.base import BaseCache, InvalidCacheBackendError
+    from django.utils.encoding import smart_unicode, smart_str
+    
+    try:
+        import cPickle as pickle
+    except ImportError:
+        import pickle
+    
+    try:
+        import uwsgi
+    except:
+        raise InvalidCacheBackendError("uWSGI cache backend requires you are running under it to have the 'uwsgi' module available")
+    
+    class CacheClass(BaseCache):
+        def __init__(self, server, params):
+            BaseCache.__init__(self, params)
+            self._cache = uwsgi
+            self._server = server
+    
+        def exists(self, key):
+            return self._cache.cache_exists(smart_str(key), self._server)
+    
+        def add(self, key, value, timeout=0):
+            if self.exists(key):
+                return False
+            return self.set(key, value, timeout, self._server)
+    
+        def get(self, key, default=None):
+            val = self._cache.cache_get(smart_str(key), self._server)
+            if val is None:
+                return default
+            val = smart_str(val)
+            return pickle.loads(val)
+    
+        def set(self, key, value, timeout=0):
+            self._cache.cache_set(smart_str(key), pickle.dumps(value), timeout, self._server)
+    
+        def delete(self, key):
+            self._cache.cache_del(smart_str(key), self._server)
+    
+        def close(self, **kwargs):
+            pass
+    
+        def clear(self):
+            pass
+
+Then in settings.py add at the top of your MIDDLEWARE_CLASSES::
+
+    'django.middleware.cache.UpdateCacheMiddleware',
+
+and this at the bottom::
+
+    'django.middleware.cache.FetchFromCacheMiddleware',
+
+Finally add this and remember to rename MYPROJECTNAME::
+
+    # a unix or tcp socket address, leave empty to use local uwsgi
+    CACHE_BACKEND = "uwsgicache://"
+    CACHE_MIDDLEWARE_SECONDS = 60
+    CACHE_MIDDLEWARE_KEY_PREFIX = 'MYPROJECTNAME'
+
+Persistent store
+=================
+
+You can store cache data in a backing-store file to implement persistence.
+
+Simply add::
+
+    --cache-store <filename>
+
+Every kernel/os will commit data to disk at different rate. You can set
+how/when to force commit with::
+
+    --cache-store-sync <n>
+
+Where n is the number of master cycles to wait (a cycle is 1 second by default)
+before msync()

docs/features/clustering.rst

+.. _clustering::
+
+============
+Clustering
+============
+
+.. versionadded:: from 0.9.7-dev
+
+Clustering is one of the key feature of the uWSGI server. Starting from
+version 0.9.7-dev a simplified interface/platform has been added.
+
+Let's start with a simple WSGI app bound on a TCP socket::
+
+    ./uwsgi -w werkzeug.testapp:test_app -s 192.168.173.100:3032 -M -p 4
+
+Now we want to move the application to a second 1:1 node. The first problem is
+that the second node has (obviously) a second ip. This will not allow us to
+have a xml file in a nfs share that can be used by both node (as the options,
+at least for the ip, are different).
+
+Fortunately we will find the first clustering-related magic option::
+
+    ./uwsgi -w werkzeug.testapp:test_app -s 192.168.173.*:3032 -M -p 4
+
+If an ip address contains an * the uWSGI server will automatically search
+for the first available ip address that match the query on the local machine.
+
+So we can use the same command line on both node.
+
+Now we want to tune our uWSGI server, but every time we make a modification we
+need to do it on the second node and reload it.
+
+here comes the uWSGI clustering infrastructure.
+
+More nodes, more fun
+=====================
+
+Think about 4 nodes (yes we are growing fast :P )::
+
+    node1 192.168.173.100
+    node2 192.168.173.101
+    node3 192.168.173.102
+    node4 192.168.173.103
+
+We will do our setup on node1, but this time we will chose a "cluster name".
+A cluster name is simply a multicast address, that will be shared by all the
+nodes of a uWSGI cluster.
+
+We choose the 225.1.1.1:3333 adress, you can choose any address you
+like
+
+.. warning::
+    it must be a valid multicast address
+    
+.. code-block:: bash
+
+    ./uwsgi -w werkzeug.testapp:test_app -s 192.168.173.*:3032 -M -p 4 --cluster 225.1.1.1:3333
+
+Ok, our cluster is started, but what does it mean ?
+
+From now on all the members of a cluster will share options.
+
+On node2, node3 and node4 simply run::
+
+    ./uwsgi --cluster 225.1.1.1:3333
+
+Yes it is all here ! The various node will get configuration from one of
+the node that has already been started (node1 in this case). What about node1
+dying ? No problem, if you restart node3 (with node1 down) it will get
+configuration from node2 or node4.
+
+Ok we have removed the need to move and edit a lot of config files, but every
+time i make a code modification i have to restart all the uwsgi instances.
+
+Calm down, simply log to one of the nodes (or another server in the same
+subnet) and launch::
+
+    ./uwsgi --cluster-reload 225.1.1.1:3333
+
+...and all the nodes in the cluster will be reloaded
+
+Another useful option is clustered logging, you can send messages to the
+cluster and all the nodes will save them in their logfile.
+
+The uwsgi executable can send every data passed via stdin to the cluster
+logging subsystem:
+
+    echo "i love uWSGI" | ./uwsgi --cluster-log 225.1.1.1:3333
+
+uWSGI proxy
+============
+
+The uWSGI proxy is cluster aware, if launched with --cluster option it will
+dinamically add/remove nodes::
+
+    ./uwsgi --proxy 127.0.0.1:3031 --cluster 225.1.1.1:3333
+
+Now simply point your webserver uwsgi handler to 127.0.0.1:3031 and start
+adding new nodes that will be automagically load balanced and healthchecked
+
+The future
+============
+
+The clustering infrastructure will get lot of attention, we are already
+developing healthcheck system and request passing (if an overloaded node gets
+a request it will move it to another node and will simply wait for the response)
+
+
+.. note::
+    Remember that you can cut-out the logging-write performance impact using a
+    dedicated node see :ref:`udp logging <udplogging>`

docs/features/features.rst

+.. _features:
+
+:doc:`uWSGI </uWSGI>` supported features
+====================================================
+
+
+.. toctree::
+    :maxdepth: 2
+    
+    cache
+    spooler
+    ugreen
+    ldap
+    magic-variables
+    udplogging
+    management-flags
+    clustering
+    

docs/features/ldap.rst

+.. _config-ldap-details:
+
+.. index:: ldap
+
+====================
+LDAP configuration
+====================
+
+Prerequisite
+==============
+
+Starting from version 0.9.6 you can configure the uWSGI server via LDAP.
+
+This is an amazing configuration way for big clusters or infrastructure
+running a lot of uWSGI instances that need a centralized configuration system.
+
+First of all you need to enable LDAP support in uwsgiconfig.py (you need the
+ubiquitous libldap)
+
+Then you must import the uWSGIConfig schema in your ldap server:
+
+.. code-block:: bash
+
+    ./uwsgi --ldap-schema
+
+This will print a standard LDAP schema that you can import in your server. If
+you use a LDAP server that can be configured via LDIF (as latest OpenLDAP)
+you can run:
+
+.. code-block:: bash
+    
+    ./uwsgi --ldap-schema-ldif
+
+An example LDIF
+================
+
+This is a LDIF dump of a OpenLDAP server with a uWSGIConfig entry (yes this
+is a Trac instance)::
+
+    dn: dc=projects,dc=unbit,dc=it
+    objectclass: uWSGIConfig
+    objectclass: domain
+    dc: projects
+    uWSGIsocket: /var/run/uwsgi/projects.unbit.it.sock
+    uWSGIhome: /accounts/unbit/tracvenv
+    uWSGImodule: trac.web.main:dispatch_request
+    uWSGImaster: TRUE
+    uWSGIprocesses: 4
+    uWSGIenv: TRAC_ENV=/accounts/unbit/trac/uwsgi
+
+Usage
+======
+
+You only need to pass a valid LDAP url to the --ldap option. Only the first
+entry returned will be used as configuration.::
+
+    ./uwsgi --ldap ldap://ldap.unbit.it/dc=projects,dc=unbit,dc=it
+
+or (if you want a filter with sub scope)::
+
+    ./uwsgi --ldap ldap://ldap.unbit.it/dc=projects,dc=unbit,dc=it?sub?ou=Unbit
+
+this will return the first record under the tree dc=projects,dc=unbit,dc=it with ou=Unbit
+
+Authentication
+===============
+
+Authentication is currently unsupported

docs/features/magic-variables.rst

+.. _magic-variables:
+
+===============================
+`uwsgi` protocol magic variables
+===============================
+
+You can dinamically tune or configure various aspects of the uWSGI server using
+special variables passed by the webserver (or in general by a uwsgi compliant
+client)
+
+Example (in nginx)::
+
+    location / {
+        include uwsgi_params;
+        uwsgi_param UWSGI_SCHEME https;
+        uwsgi_pass 127.0.0.1:3031;
+    }
+
+.. index:: UWSGI_SCHEME
+
+UWSGI_SCHEME
+=============
+
+Set the url scheme when it cannot be reliably determined::
+
+    uwsgi_param UWSGI_SCHEME https;
+
+.. index:: UWSGI_SCRIPT
+
+UWSGI_SCRIPT
+=============
+
+Load the specified script as a new application mapped to SCRIPT_NAME (the app
+will be obviously loaded only the first time)::
+
+    uwsgi_param UWSGI_SCRIPT werkzeug.testapp:test_app;
+    uwsgi_param SCRIPT_NAME  /testapp;
+
+.. index:: UWSGI_MODULE, UWSGI_CALLABLE
+
+UWSGI_MODULE and UWSGI_CALLABLE
+=================================
+
+Load a new app (defined as module:callable) into SCRIPT_NAME::
+
+    uwsgi_param UWSGI_MODULE werkzeug.testapp;
+    uwsgi_param UWSGI_CALLABLE test_app;
+    uwsgi_param SCRIPT_NAME  /testapp;
+
+.. index:: UWSGI_PYHOME
+
+UWSGI_PYHOME
+=============
+
+Dinamically set the Python virtualenv for a dynamic application
+See DynamicVirtualenv
+
+.. index:: UWSGI_CHDIR
+
+UWSGI_CHDIR
+=============
+
+chdir() to the specified directory before managing the request
+
+.. index:: UWSGI_FILE
+
+UWSGI_FILE
+===========
+
+Load the specified file as a new dynamic app
+
+.. index:: UWSGI_TOUCH_RELOAD
+
+UWSGI_TOUCH_RELOAD
+===================
+
+Reload the uWSGI stack when the specified file modification time has changed
+from the last requests::
+
+    location / {
+        include uwsgi_params;
+        uwsgi_param UWSGI_TOUCH_RELOAD /tmp/touchme.foo;
+        uwsgi_pass /tmp/uwsgi.sock;
+    }
+
+.. index:: UWSGI_CACHE_GET
+
+UWSGI_CACHE_GET
+=================
+
+Check in the uWSGI cache for a specified key, if value is found it will be
+returned as a raw http output otherwise the request will normally goes on::
+
+    location / {
+       include uwsgi_params;
+       uwsgi_param UWSGI_CACHE_GET $request_uri;
+       uwsgi_pass 127.0.0.1:3031;
+    }
+
+.. index:: UWSGI_SETENV
+
+UWSGI_SETENV
+=============
+
+Set the specified environment variable for a new dynamic app (to allow this in
+python you need to add the --reload-os-env option to uWSGI)
+
+(dynamically load a django app without using a wsgi file/module::
+
+    location / {
+        include uwsgi_params;
+        uwsgi_param UWSGI_SCRIPT django.core.handlers.wsgi:WSGIHandler();
+        uwsgi_param UWSGI_CHDIR /mydjangoapp_path;
+        uwsgi_param UWSGI_SETENV DJANGO_SETTINGS_MODULE=myapp.settings;
+    }
+

docs/features/management-flags.rst

+.. _management-flags:
+
+=================
+Management Flags 
+=================
+
+You can remotely (and without taking offline the uWSGI server) modify the
+behaviour of the uWSGI stack. Using the uwsgi protocol you can
+enable/disable/setup the internal options.
+
+All the flags take an unsigned 32bit value (so the block size is always 4)
+that contain the value to set for the flag. If you do not specify this value
+(so you send only the uwsgi header) the server will count it as 0.
+
+This is a table of flag available:
+ 
++------+-----------------+-----------------------------------------------------------+ 
+| flag | action	         | note                                                      |
++======+=================+===========================================================+
+| 0    | logging         | enable/disable logging                                    |
++------+-----------------+-----------------------------------------------------------+
+| 1    | max_requests    | set maximum number of requests per worker                 |
++------+-----------------+-----------------------------------------------------------+  
+| 2    | socket_timeout	 | modify the internal socket timeout                        |
++------+-----------------+-----------------------------------------------------------+
+| 3    | memory_debug	 | enable/disable memory debug/report                        |
++------+-----------------+-----------------------------------------------------------+
+| 4    | master_interval | set the master process check interval                     |
++------+-----------------+-----------------------------------------------------------+
+| 5    | harakiri	 | set/unset the harakiri timeout                            |
++------+-----------------+-----------------------------------------------------------+
+| 6    | cgi_mode	 | enable/disable cgi mode                                   |
++------+-----------------+-----------------------------------------------------------+
+| 7    | threads	 | enable/disable python threads                             |
++------+-----------------+-----------------------------------------------------------+
+| 8    | reaper	         | enable/disable process reaper                             |
++------+-----------------+-----------------------------------------------------------+
+| 9    | log-zero	 | enable/disable logging of request with zero response size |
++------+-----------------+-----------------------------------------------------------+
+| 10   | log-slow	 | set/unset logging of slow requests                        |
++------+-----------------+-----------------------------------------------------------+
+| 11   | log-4xx	 | enable/disable logging of request with 4xx response status|
++------+-----------------+-----------------------------------------------------------+
+| 12   | log-5xx	 | enable/disable logging of request with 5xx response status|
++------+-----------------+-----------------------------------------------------------+
+| 13   | log-big	 | set/unset logging of request with big response size       |
++------+-----------------+-----------------------------------------------------------+
+
+A simple (and ugly) script is included to remotly change management flags::
+
+    ./uwsgi --no-server -w myadmin --pyargv "192.168.173.16 3031 0 0"
+
+the command will disable logging on the uWSGI server listening on 192.168.173.16 port 3031
+
+and::
+
+    ./uwsgi --no-server -w myadmin --pyargv "192.168.173.16 3031 0 1"
+
+will re-enable it

docs/features/spooler.rst

+.. _spooler:
+
+==========
+Spooler
+==========
+
+The Spooler is a queue manager that works very similar to a printing/mail
+system. You choose a directory as a spool then a process looply look for files
+in this spool and use each one as the arguments for a python callable. After
+the callable exits, the file is removed.
+
+For example you can enqueue the massive sending of emails, an image processing,
+a video encoding.. ecc. ecc. and let to spooler doing the hard work in
+background. Using the message passing feature of the uWSGI server you can even
+send your spool request to a remote uWSGI server.
+
+To use the spooler you need to pass the -Q argument followed by the directory
+you want to use as spool::
+
+    ./uwsgi26 -Q myspool -s /tmp/uwsgi.sock -b 8192 -w testapp -A 10
+
+If you think to pass big messages, set a bigger buffer size using the -b option.
+
+Add a new function to your wsgi script:
+
+.. code-block:: python
+
+    def myspooler(env):
+            print env
+            for i in range(1,100):
+                    time.sleep(1)
+    
+    uwsgi.spooler = myspooler
+
+
+Using the uwsgi.spooler attribute you will set the callable to execute for
+every spool/queue/message file
+
+Now if you want to enqueue a request (that is a simple python dictionary) use
+this function in your app::
+
+    uwsgi.send_to_spooler({'Name':'Serena', 'System':'Linux', 'Tizio':'Caio'})
+
+The only argument is the dictionary (a dictionary of string !!! ) to pass to
+the callable.
+
+How the uWSGI server recognize spooler request ?
+====================================================
+
+The queue/message/spool files are normally dictionaries (that contains only
+strings) encoded in the uwsgi protocol format. In this way we can use the uWSGI
+server to manage remote messaging.
+
+Setting the uwsgi_modifier1 to UWSGI_MODIFIER_SPOOL_REQUEST (value: 17) you
+will inform the uWSGI server that the request is a spooling request.
+
+This is transparent for your application using the uwsgi.send_to_spooler
+function, but you can use your webserver support for uwsgi_modifiers for doing
+funny things like passing spooler message without using your wsgi apps resource
+but only the spooler.
+
+NGINX example::
+
+    location /sendmassmail {
+        uwsgi_pass 192.168.1.1:3031;
+        uwsgi_modifier1 17;
+        uwsgi_param ToGroup  customers;
+     }
+
+Suppose you have a callable that sends email to a group specified in the
+ToGroup dict key, you can enqueue mass mails only using Nginx !.
+
+Tips and tricks
+==================
+
+You can re-enqueue a spooler request returning uwsgi.SPOOL_RETRY in your callable::
+
+    def looply_call(env):
+        return uwsgi.SPOOL_RETRY
+
+You can set the spooler-frequency using::
+
+    uwsgi.set_spooler_frequency(N)
+
+where N is the number of seconds to sleep before redoing a spooler scan
+So you can build a cron-like system in this way:
+
+.. code-block:: python
+    :linenos:
+
+    # run function every 22 secs
+    s_freq = 22
+    
+    def emu_cron(env):
+        
+        # run your function
+        long_func("Hello World")
+        # and re-enqueue it
+        return uwsgi.SPOOL_RETRY
+    
+    uwsgi.set_spooler_frequency(s_freq)
+    uwsgi.spooler = emu_cron
+    # start the emu_cron
+    uwsgi.send_to_spooler({'Name':'Alessandro'})
+

docs/features/udplogging.rst

+.. _udp-logging:
+
+================
+logging via UDP
+================
+
+.. versionadded:: 0.9.5
+    you can redirect uWSGI logs to udp.
+
+Using this feature you can "centralize" cluster logging or redirect the write
+of logs (that can be very heavy for your I/O resources) to another machine.
+
+.. note::
+    UDP logging works only when you daemonize the uWSGI server.
+
+To enable it you simply pass the address of a udp server to ``--daemonize``
+option::
+
+    ./uwsgi -s :3031 -w simple_app --daemonize 192.168.0.100:1717
+
+This will redirect all the `stdout/stderr` data to the udp socket on
+192.168.0.100 port 1717
+
+Now you need a udp server that will manage your udp messages.
+
+You can simply use netcat::
+
+    nc -u -p 1717 -s 192.168.0.100 -l
+
+Or even uWSGI::
+
+    ./uwsgi --udp 192.168.0.100:1717
+
+The second way is a bit more useful as it will print the source (ip:port)
+of every message. In case of multiple uWSGI server logging on the same udp
+server it will allows you to recognize one server from another.
+
+You can write advanced apps to manage/filter/save the logs received via udp.
+You can even pass them (if you use uWSGI as the udp server) to a python
+callable:
+
+    ./uwsgi --udp 192.168.0.100:1717 -w my_super_logger
+
+and my_super_logger.py:
+
+.. code-block:: python
+
+    import uwsgi
+    
+    def print_logs(ip, port, message):
+            print(message)
+    
+    
+    uwsgi.udp_callable = print_logs
+
+If you do not specify the uwsgi.udp_callable the packet is simply printed by
+uWSGI. 

docs/features/ugreen.rst

+.. _green-threads:
+
+===============
+Green Threads
+===============
+
+.. versionadded:: 0.9.5
+    ``--ugreen`` 
+
+
+uGreen is an implementation of green threads
+(http://en.wikipedia.org/wiki/Green_threads) on top of the uWSGI async platform.
+It is very similar to python's greenlet but it is built on top of the POSIX
+swapcontext() function. To take advantage of uGreen you have to set the number
+of async core that will be mapped to green threads.
+
+For example if you want to spawn 30 green threads::
+
+    ./uwsgi -w tests.cpubound_green -s :3031 --async 30 --ugreen
+
+The ``--ugreen`` flag will enable uGreen on top of async mode.
+
+Now in your app you have to simply call::
+
+    uwsgi.suspend()
+
+to switch to another green thread.
+
+security and performance
+==========================
+
+To ensure relative-isolation of green threads every stack area is protected
+by the so called "guard pages".
+
+An attempt to write out of the stack area of a green thread will result in a
+segmentation fault/bus error (and the process manager, if enabled, will respawn
+the worker without too much damages)
+
+The context switch is very fast, we can see it as :
+
+**-> on switch**
+
+1) save the Python Frame pointer
+2) save the recursion depth of the python environment (it is simply an int)
+3) switch to the main stack
+
+**-> on return**
+
+1) re-set the uGreen stack
+2) re-set the recursion depth
+3) re-set the frame pointer
+
+
+The stack/registers switch is done by POSIX' swapcontext()
+
+I/O
+====
+
+For managing async I/O you can use whatever async function exported by
+the async mode:
+
+.. code-block:: python
+
+    uwsgi.wait_fd_read(fd, timeout)
+    uwsgi.wait_fd_write(fd, timeout)
+
+Stack size
+===========
+
+You can choose the uGreen stack size using the ``--ugreen-stacksize <pages>``
+
+Warning: the argument is in pages !!!
+
+Is this better than Greenlet or Stackless python ?
+===================================================
+
+It depends. uGreen is faster (the stack is preallocated) but requires more
+memory (you have to allocate a stack area for every core). Stackless and
+Greenlet probably requires less memory and Stackless requires a heavily
+patched python.
+
+Make some test to choose the best one for you (you can move from each one
+without changing your code)
+
+What about python-coev ?
+=========================
+
+It gaves me a lot of idea for uGreen, and the author's way to map python
+threads to its implementation allows python-coev to be a little more
+"trustable" than stackless python. But as stackless it requires a patched
+version of python :(
+
+Can i use it to write comet apps ?
+=====================================
+
+In the distribution (or in the public mercurial repository) you will find the
+ugreenchat.py script. It is a simple/dumb multiuser comet chat:
+
+If you want to test it (for example 30 users) run it with::
+
+    ./uwsgi -s :3031 -w ugreenchat --async 30 --ugreen
+
+The code has comments for every ugreen-related line. You need bottle
+(an amazing python web microframework) to use it.
+
+Psycopg2 improvements
+======================
+
+uGreen can benefit from the new psycopg2 async extensions and the
+psycogreen project.
+
+Look at this examples:
+
+* http://projects.unbit.it/uwsgi/browser/tests/psycopg2_green.py
+* http://projects.unbit.it/uwsgi/browser/tests/psycogreen_green.py
    uWSGI
    install
    run-behind/webservers
+   features/features
    examples
    options
    FAQ
 ==================
 
 * :ref:`genindex`
-* :ref:`modindex`
 * :ref:`search`
 
 
     UWSGI_MAX_VARS="<n>"
 
+.. index:: xml
 .. _config-xml:
 
 xml
         <master/>
     </uwsgi>
 
+.. index:: ini
 .. _config-ini:
 
 ini
     socket = 127.0.0.1:3031
     master = true
 
+.. index:: yaml
 .. _config-yaml:
 
 yaml
       socket: 127.0.0.1
       master: 1
 
+
+
 .. _config-ldap:
 
 ldap
 -----
 
-it is a complex topic, you should check the dedicated wiki page. see useLDAP
+it is a complex topic, you should check the dedicated wiki page. See
+:ref:`ldap configuration <config-ldap-details>`
 
 
 
 Exhaustive list of options
 ============================
 
+.. index:: socket
+
 socket
 --------
 
     socket = 127.0.0.1:1717
     socket = 127.0.0.1:2626
 
+.. index:: worker, process
 
 processes or workers
 ---------------------
         <workers>3</workers>
     </uwsgi>
 
+.. index:: harakiri
 
 harakiri
 ---------
 
     --harakiri 60
 
+.. index:: harakiri-verbose
 
 harakiri-verbose
 -----------------
 
 The command line above automatically load the /etc/myapp.xml config file
 
+.. index:: daemonize
+
 daemonize
 ----------
 
     [uwsgi]
     daemonize = 192.168.0.100:4000
 
+.. index:: listen
+
 listen
 -------
 
 
 The maximum value is system/kernel dependent.
 
+.. index:: max-vars
+
 max-vars
 --------
 
 Set the max number of variables a uwsgi client (your webserver) can pass.
 This is only a security mesasure, probably you will never need to touch it.
 
+.. index:: buffer-size
+
 buffer-size
 ------------
 
 --buffer-size 32768
 
 
+.. index:: memory-report
+
 memory-report
 --------------
 
         <memory-report/>
     </uwsgi>
 
+.. index:: cgi-mode
+
 cgi-mode
 ---------
 
 Enable cgi mode. Responses will not be HTTP valid response, but cgi one
 (the Status: header will be added)
 
+.. index:: abstract-socket
+
 abstract-socket
 ----------------
 N/A
 
+.. index:: chmod-socket
+
 chmod-socket or chmod
 -----------------------
 
         <chmod-socket>644</chmod-socket>
     </uwsgi>
 
+.. index:: map-socket
 
 map-socket
 -----------
 If you host multiple apps in the same uWSGI instance, you can easily dedicate
 resources to each of them.
 
+.. index:: enable-threads
+
 enable-threads
 ---------------
 
 Enable threads in the embedded languages. This will allow to spawn threads in
 your app.
 
+.. index:: single-interpreter
+
 single-interpreter
 --------------------
 
 "multiple interpreters". They allows to isolate apps living in the same
 process. If you do not want this kind of feature use this option.
 
+.. index:: master
+
 master
 ------
 
 Start the master process
 
+.. index:: emperor
+
 emperor
 ---------
 
 Start the uWSGI Emperor
 
+.. index:: emperor-amqp-vhost
+
 emperor-amqp-vhost
 ------------------
 
 set virtualhost name in AMQP emperor mode
 
+.. index:: emperor-amqp-username
+
 emperor-amqp-username
 ----------------------
 
 set username name in AMQP emperor mode
 
+.. index:: emperor-amqp-password
+
 emperor-amqp-password
 -----------------------
 
 set password name in AMQP emperor mode
 
+.. index:: reload-mercy
+
 reload-mercy
 -------------
 
 
 --reload-mercy 8
 
+.. index:: exit-on-reload
 
 exit-on-reload
 ----------------
 
 force the uWSGI stack to terminate itself even if a reload is requested. This option is useful only in exotic cases.
 
+.. index:: help, usage
+
 help or usage
 -------------
 
 print the help on the stdout then exit
 
+.. index:: reaper
+
 reaper
 -------
 
 zombies all over the place you can enable this option. But you should fix your
 process spawning usage (if you can) ...
 
+.. index:: max-requests
+
 max-requests
 -------------
 
     [uwsgi]
     max-requests = 1000
 
+.. index:: socket-timeout
 
 socket-timeout
 ---------------
 
     --socket-timeout 10
 
+.. index:: sharedarea
+
 sharedarea
 -----------
 
 
 This will create a shared memory area of 10 pages
 
+.. index:: cache
+
 cache
 -------
 
 Enable the shared cache. See CachingFramework
 
+.. index:: cache-blocksize
+
 cache-blocksize
 -----------------
 
 Set the cache blocksize
 
+.. index:: cache-store
+
 cache-store
 -------------
 
 Enable persistent store for the uWSGI cache
 
+.. index:: Cache-store-sync
+
 Cache-store-sync
 -------------------
 
 set the msync() frequency for caching persistent store.
 
+.. index:: queue
+
 queue
 ------
 
 UNDOCUMENTED
 
+.. index:: queue-blocksize
 
 queue-blocksize
 ------------------
 UNDOCUMENTED
 
+.. index:: queue-store
 
 queue-store
 ------------
 
 UNDOCUMENTED
 
+.. index:: queue-store-sync
 
 queue-store-sync
 ------------------
 
 UNDOCUMENTED
 
+.. index:: spooler
 
 spooler
 --------
 
 will save spooler file in the /home/foo/spooler directory
 
+.. index:: disable-logging
+
 disable-logging
 -----------------
 
 Disable request logging. Log only errors and uWSGi internal messages
 
+.. index:: pidfile
+
 pidfile
 ---------
 
 Write the pidfile to the specified file before privileges drop
 
+.. index:: pidfile2
+
 pidfile2
 ---------
 
 write the pidfile to the specified file after privileges drop
 
+.. index:: chroot
+
 chroot
 -------
 
 chroot() to the specified directory
 
+.. index:: gid
+
 gid
 -----
 
 set the gid under the uWSGI server will run
 
+.. index:: uid
+
 uid
 ----
 
 ldap
 -----
 
-Load configuration fron an ldap server. See UseLdap?
+Load configuration fron an ldap server. See ref:`ldap configuration <config-ldap-details>`
+
+.. index:: ldap-schema
 
 ldap-schema
 ------------
 
 dump the LDAP schema (old-style format)
 
+.. index:: ldap-schema-ldif
+
 ldap-schema-ldif
 -----------------
 
 dump the LDAP schema in LDIF format (new openldap)
 
+.. index:: no-server
+
 no-server
 -----------
 
 initialize the uWSGI server but exit as soon as the initialization is complete (useful for testing)
 
+.. index:: no-defer-accept
+
 no-defer-accept
 ----------------
 
 some data is sent by the client (this is a security/performance measure). If
 you want to disable this feature specify this option.
 
+.. index:: limit-as
+
 limit-as
 ---------
 
 
 Read and understand this page before enabling it:  http://en.wikipedia.org/wiki/Virtual_memory
 
+.. index:: reload-on-as
+
 reload-on-as
 -------------
 
 
 will reload a worker if it consumes more than 128 megs of address space
 
+.. index:: reload-on-rss
+
 reload-on-rss
 --------------
 
 
 will recycle a workers when its address space usage is hgher than 128 megs or its rss usage is higher than 96 megs
 
+.. index:: touch-reload
+
 touch-reload
 --------------
 
 
 the uWSGI server will be gracefully reloaded
 
+.. index:: limit-post
+
 limit-post
 -------------
 
 
 will disallow request body higher than 64k
 
+.. index:: no-orphans
+
 no-orphans
 -------------
 
 automatically kill workers without a master process
 
+.. index:: prio
+
 prio
 -----
 
 
 will set the process priority to 20 (the value is system dependent)
 
+.. index:: cpu-affinity
+
 cpu-affinity
 -------------
 
 Set the CPU affinity (Linux Only) See  http://lists.unbit.it/pipermail/uwsgi/2011-March/001594.html
 
+.. index:: post-buffering
+
 post-buffering
 ----------------
 
 will save to disk all the HTTP body bigger than 8K. This option is required for
 Rack applications as they require a rewindable input stream.
 
+.. index:: post-buffering-bufsize
+
 post-buffering-bufsize
 -----------------------
 
 
 This is a very advanced option you will probably never need to touch.
 
+.. index:: upload-progress
+
 upload-progress
 ----------------
 
 probably your webserver has a very similar functionality, but if you need to
 hack it (or simply have more control) delegate this to the uWSGI server
 
+.. index:: no-default-app
+
 no-default-app
 ----------------
 
 (most of the time the app mounted under /). Enabling this option will return an
 error in case of unavailable app.
 
+.. index:: manage-script-name
+
 manage-script-name
 --------------------
 
 If for some reason your webserver cannot manage SCRIPT_NAME you can force
 uWSGI to rebuild the PATH_INFO automatically.
 
+.. index:: udp
+
 udp
 -----
 
 start a udp server. Mainly useful for snmp or as a shared logger for UdpLogging
 
+.. index:: multicast
+
 multicast
 -----------
 
 internal option, usable by third party plugins.
 
+.. index:: cluster
+
 cluster
 --------
 
 Join the specified cluster. See Clustering
 
+.. index:: cluster-nodes
+
 cluster-nodes
 --------------
 
 will get the list of nodes of the 225.1.1.1:1717 cluster. This list is used
 internally by the uwsgi load balancing api.
 
+.. index:: cluster-reload
+
 cluster-reload
 ----------------
 
 
 will reload all the nodes in the 225.1.1.1:1717 cluster
 
+.. index:: cluster-log
+
 cluster-log
 ------------
 
 
 will print "Hello World" to all the nodes logfiles
 
+.. index:: subscribe-to
+
 subscribe-to
 ---------------
 
     subscribe-to = 192.168.0.1:2626:unbit.it
     subscribe-to = 192.168.0.2:2626:uwsgi.it
 
+.. index:: shared-socket
+
 shared-socket
 --------------
 
 Advanced option for plugin writers or special needs. Allow to create a socket
 during server early startup and use it after privileges drop or jailing.
 
+.. index:: snmp
+
 snmp
 ------
 
 enable the SNMP server. See UseSnmp
 
+.. index:: snmp-community
+
 snmp-community
 ---------------
 
 set the snmp community string
 
+.. index:: check-interval
+
 check-interval
 ---------------
 
 The master process make a scan every seconds. You can increase this time if
 you need. DISCOURAGED.
 
+.. index:: binary-path
+
 binary-path
 ------------
 
 option to permit the reloading system and the Emperor to easily find the
 binary to execute.
 
+.. index:: async
+
 async
 -------
 
 Enable the async mode. See AsyncSupport
 
+.. index:: logto
+
 logto
 ---------
 
 Log to specific file or udp server
 
+.. index:: logfile-chown
+
 logfile-chown
 --------------
 
 N/A
 
+.. index:: log-syslog
+
 log-syslog
 -------------
 
 N/A
 
+.. index:: log-master
+
 log-master
 ------------
 
 the logging I/O to a single process). Useful for system with advanced
 I/O schedulers/elevators
 
+.. index:: logdate
+
 logdate
 ---------
 
 report the date in every log line. You can pass an option with strftime() syntax
 
+.. index:: log-zero
 
 log-zero
 ----------
 
 log requests with zero response size
 
+.. index:: log-slow
+
 log-slow
 ---------
 
 N/A
 
+.. index:: log-4xx
+
 log-4xx
 ----------
 
 N/A
 
+.. index:: log-5xx
+
 log-5xx
 ---------
 
 NA/
 
+.. index:: log-big
+
 log-big
 ---------
 
 N/A
 
+.. index:: log-sendfile
+
 log-sendfile
 ---------------
 
 N/A
 
+.. index:: log-micros
+
 log-micros
 -----------
 
 use microseconds resolution for response-time logging (milliseconds resolution is the default)
 
+.. index:: master-as-root
+
 master-as-root
 ----------------
 
 run the uWSGI master process as root
 
+.. index:: chdir
+
 chdir
 ------
 
 chdir() to specified directory before privileges drop
 
+.. index:: chdir2
+
 chdir2
 --------
 
 chdir() to specified directory after privileges drop
 
+.. index:: mount
+
 mount
 --------
 
 
     --mount /pinax=/var/www/pinax/deploy/pinax.wsgi
 
+.. index:: grunt
+
 grunt
 ------
 
 allows grunt processes
 
+.. index:: threads
+
 threads
 ---------
 
 
 will spawn two workers with 40 threads (total 80 threads)
 
+.. index:: vhost
+
 vhost
 ------
 
 enable virtual hosting mode. See VirtualHosting
 
+.. index:: vhost-host
+
 vhost-host
 ------------
 
 key. If you want to use the HTTP_HOST one (corresponding to the Host: header)
 add this option
 
+.. index:: check-static
+
 check-static
 -------------
 
 /var/www/example.com/foo.png uWSGI will directly serves it using the choosen
 method (sendfile() by default)
 
+.. index:: static-map
+
 static-map
 -----------
 
 Whenever a PATH_INFO starts with one of the configured resources, uWSGI will
 serve the file using the choosen method (sendfile() by default)
 
+.. index:: file-serve-mode
+
 file-serve-mode
 ----------------
 
 
     --file-serve-mode x-sendfile
 
+.. index:: check-cache
+
 check-cache
 ------------
 
 check if an item named as PATH_INFO is available in the uWSGI cache and
 eventually will serves it
 
+.. index:: close-on-exec
+
 close-on-exec
 ---------------
 
 set close-on-exec flag on the uWSGI socket. This will avoid external processes
 generated in a request to inherit the socket file descriptor.
 
+.. index:: mode
+
 mode
 ------
 
 generic option, the apps can read this value with uwsgi.mode
 
+.. index:: env
+
 env
 ----
 
 
 This will set DJANGO_SETTINGS_MODULE to mysite.settings
 
+.. index:: vacuum
+
 vacuum
 -------
 
 automatically remove unix socket and pidfiles on server exit
 
+.. index:: loop
+
 loop
 -----
 
 set the LoopEngine (advanced option)
 
+.. index:: worker-exec
+
 worker-exec
 -------------
 
 funny option to map a new executable to a uWSGI worker. You can run a php
-fastcgi server pool in this way
+fastcgi server pool in this way::
 
-/usr/bin/uwsgi --workers 4 --worker-exec /usr/bin/php53-cgi 
+    /usr/bin/uwsgi --workers 4 --worker-exec /usr/bin/php53-cgi 
+
+.. index:: attach-daemon
 
 attach-daemon
 ---------------
     master = true
     attach-daemom = memcached
 
+.. index:: plugins
+
 plugins
 --------
 
 
 will load the psgi plugin and the greenlet plugin
 
+.. index:: allowed-modifiers
+
 allowed-modifiers
 -------------------
 
 
 will allow access only the WSGI handler and the cache handler
 
+.. index:: remap-modifier
+
 remap-modifier
 ---------------
 
 N/A
 
+.. index:: dump-options
+
 dump-options
 -------------
 
 print all the available options then exit
 
+.. index:: show-config
+
 show-config
 ------------------
 
 print the current configuration in ini format (use this output when you ask
 for help in the mailing-list, THANKS)
 
+.. index:: print
+
 print
 ---------
 
 
 will print 'foo' on server startup
 
+.. index:: version
+
 version
 --------
 
 print the uWSGI version and exit
 
+.. index:: wsgi-file, file
+
 wsgi-file or file [python plugin required]
 -------------------------------------------
 
 load the specified WSGI file (compatible with Graham's mod_wsgi format)
 
+.. index:: eval
+
 eval [python plugin required]
 ---------------------------------
 
       </eval>
     </uwsgi>
 
+.. index:: module
+
 module [python plugin required]
 -----------------------------------
 
 load the specified python WSGI module (must be in the PYTHONPATH)
 
+.. index:: callable
+
 callable [python plugin required]
 ------------------------------------
 
 set the callable to use for WSGI modules (default 'application')
 
+.. index:: test
+
 test [python plugin required]
 -------------------------------
 
 test if a module can be imported successfully
 
+.. index:: home, virtualenv, venv, pyhome
+
 home or virtualenv or venv or pyhome [python plugin required]
 ---------------------------------------------------------------
 
 
 will use the virtualenv in /apps/env001
 
+.. index:: pythonpath, python-path, pp
+
 pythonpath or python-path or pp [python plugin required]
 ---------------------------------------------------------
 
     pp = myapp/lib
     pp = trac.egg
 
+.. index:: pymodule-alias
+
 pymodule-alias [python plugin required]
 ------------------------------------------
 
 magic option allowing python modules remapping. See PymoduleAlias
 
+.. index:: pyargv
+
 pyargv [python plugin required]
 ----------------------------------
 
 
 will set sys.argv to ('one','two','three')
 
+.. index:: optimize
+
 optimize
 -----------
 
 set the python optimizazion level (dangerous)
 
+.. index:: paste
+
 paste
 --------
 
 
     uwsgi --paste config:/foo/development.ini
 
+.. index:: ini-paste
+
 ini-paste
 ----------
 
 shortcut for --ini + --paste, after file parsing it will use the same file
 as paste.deploy config file
 
+.. index:: catch-exceptions
+
 catch-exceptions
 ------------------
 
 print traceback in your browser instead of the logfile
 (DO NOT USE IT IN PRODUCTION)
 
+.. index:: ignore-script-name
+
 ignore-script-name
 --------------------
 
 N/A
 
+.. index:: pep3333-input
+
 pep3333-input
 ---------------
 
 N/A
 
+.. index:: reload-os-env
+
 reload-os-env
 ----------------
 
 N/A
 
+.. index:: no-site 
+
 no-site [python plugin required]
 ---------------------------------
 
 Disable the import of python site.py module
 
+.. index:: ping 
+
 ping [ping plugin required]
 -----------------------------
 
 
 will ping the uWSGI server on 192.168.0.100:1717
 
+.. index:: ping-timeout
+
 ping-timeout [ping plugin required]
 --------------------------------------
 
 
 will set the ping timeout to 10 seconds
 
+.. index:: nagios
+
 nagios
 -------
 
 UNDOCUMENTED
 
+.. index:: fastrouter
+
 fastrouter
 ------------
 
 
 run the fastrouter on address 127.0.0.1 port 3017
 
+.. index:: fastrouter-use-cache 
+
 fastrouter-use-cache 
 ----------------------
 
 check the uwsgi cache to get hostname:address mapping
 
+.. index:: fastrouter-use-pattern
+
 fastrouter-use-pattern
 ------------------------
 
 use a filesystem pattern to get hostname:address mapping
 
+.. index:: fastrouter-use-base
+
 fastrouter-use-base
 --------------------
 
 N/A
 
+.. index:: fastrouter-events
+
 fastrouter-events
 -------------------
 
 limit the max number of async events the fastrouter can return in one cycle
 
+.. index:: fastrouter-subscription-server
+
 fastrouter-subscription-server
 -------------------------------
 
 add a SubscriptionServer to the fastrouter to build the hostname:address map
 
+.. index:: fastrouter-timeout
+
 fastrouter-timeout
 --------------------
 
 set the internal fastrouter timeout
 
+.. index:: http
+
 http
 -------
 
 enable the embedded http server/router/gateway/loadbalancer/proxy
 
+.. index:: http-var
+
 http-var
 ---------
 
 N/A
 
+.. index:: http-to
+
 http-to
 --------
 
 N/A
 
+.. index:: http-modifier1
+
 http-modifier1
 -----------------
 
 N/A
 
+.. index:: http-use-cache 
+
 http-use-cache 
 -----------------
 
 N/A
 
+.. index:: http-use-pattern 
+
 http-use-pattern 
 -----------------
 
 N/A
 
+.. index:: http-use-base 
+
 http-use-base 
 -----------------
 
 N/A
 
+.. index:: http-use-cluster 
+
 http-use-cluster 
 -----------------
 
 N/A
 
+.. index:: http-events 
+
 http-events 
 -----------------
 
 N/A
 
+.. index:: http-subscription-server 
+
 http-subscription-server 
 --------------------------
 
 enable the SubscriptionServer for clustering and massive hosting/load-balancing
 
+.. index:: http-timeout
+
 http-timeout
 --------------
 
 set the internal http socket timeout
 
+.. index:: ugreen
+
 ugreen [ugreen plugin required]
 ---------------------------------
 
 enable uGreen as suspend/resume engine. See uGreen
 
+.. index:: ugreen-stacksize
+
 ugreen-stacksize [ugreen plugin required]
 -------------------------------------------