--- nginx-0.7.63.orig/debian/rules +++ nginx-0.7.63/debian/rules @@ -0,0 +1,96 @@ +#!/usr/bin/make -f + +CFLAGS = -Wall -g + +DEB_BUILD_ARCH ?=$(shell dpkg-architecture -qDEB_BUILD_ARCH) +ifneq (,$(findstring sparc,$(DEB_BUILD_ARCH))) + CONFIGURE_OPTS = --with-cc-opt="-m32 -mcpu=ultrasparc" +endif + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +include /usr/share/dpatch/dpatch.make + +config.status: patch-stamp + dh_testdir +ifneq "$(wildcard /usr/share/misc/config.sub)" "" + cp -f /usr/share/misc/config.sub config.sub +endif +ifneq "$(wildcard /usr/share/misc/config.guess)" "" + cp -f /usr/share/misc/config.guess config.guess +endif + ./configure --conf-path=/etc/nginx/nginx.conf \ + --error-log-path=/var/log/nginx/error.log \ + --pid-path=/var/run/nginx.pid \ + --lock-path=/var/lock/nginx.lock \ + --http-log-path=/var/log/nginx/access.log \ + --http-client-body-temp-path=/var/lib/nginx/body \ + --http-proxy-temp-path=/var/lib/nginx/proxy \ + --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \ + --with-debug \ + --with-http_stub_status_module \ + --with-http_flv_module \ + --with-http_ssl_module \ + --with-http_dav_module \ + --with-http_gzip_static_module \ + --with-mail \ + --with-mail_ssl_module \ + --with-ipv6 \ + --add-module=$(CURDIR)/modules/nginx-upstream-fair \ + $(CONFIGURE_OPTS) + +build: config.status + $(MAKE) build + +build-stamp: + dh_testdir + touch $@ + +clean: unpatch + dh_testdir + dh_testroot + rm -f build-stamp + [ ! -f Makefile ] || $(MAKE) clean + +ifneq "$(wildcard /usr/share/misc/config.sub)" "" + rm -f config.sub +endif +ifneq "$(wildcard /usr/share/misc/config.guess)" "" + rm -f config.guess +endif + dh_clean + +install: + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + dh_install + +binary-indep: + +binary-arch: install + dh_testdir + dh_testroot + dh_installchangelogs CHANGES + dh_installdocs + dh_installinit -r --no-start + dh_installman debian/nginx.1 + dh_installlogrotate + dh_link + dh_strip + dh_compress + dh_fixperms + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch + +.PHONY: build clean binary-indep binary-arch binary install --- nginx-0.7.63.orig/debian/control +++ nginx-0.7.63/debian/control @@ -0,0 +1,22 @@ +Source: nginx +Section: httpd +Priority: optional +Maintainer: Jose Parrella +Uploaders: Fabio Tranchitella +Build-Depends: debhelper (>= 5), autotools-dev, libpcre3-dev, zlib1g-dev, libssl-dev, dpatch +Standards-Version: 3.8.3 +Homepage: http://nginx.net +Vcs-Svn: svn://svn.debian.org/svn/collab-maint/deb-maint/nginx/trunk +Vcs-Browser: http://svn.debian.org/wsvn/collab-maint/deb-maint/nginx/trunk + +Package: nginx +Architecture: any +Depends: ${shlibs:Depends}, lsb-base (>= 3.2-14) +Provides: httpd +Description: small, but very powerful and efficient web server and mail proxy + Nginx (engine x) is a web server created by Igor Sysoev and kindly provided to + the open-source community. This server can be used as standalone HTTP server + and as a reverse proxy server before some Apache or another big server to + reduce load to backend servers by many concurrent HTTP-sessions. + . + It can also act as a POP3/IMAP mail proxy with SSL and TLS SNI support. --- nginx-0.7.63.orig/debian/postinst +++ nginx-0.7.63/debian/postinst @@ -0,0 +1,51 @@ +#!/bin/sh + +set -e + +case "$1" in + configure) + if [ -z $2 ] && [ ! -e /etc/nginx/sites-enabled/default ] ; + then + ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default + fi + ;; + abort-upgrade|abort-remove|abort-deconfigure) + ;; + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +if [ -x /etc/init.d/nginx ] +then + if [ -f /var/run/nginx.pid ] && pidof /usr/sbin/nginx >/dev/null + then + echo "Trying a soft restart" + NGX_PID=`cat /var/run/nginx.pid` + if kill -s USR2 $NGX_PID 2>/dev/null + then + echo "PID IS RIGHT" + while [ ! -f /var/run/nginx.pid.oldbin ] + do + echo "WAITING" + cnt=`expr $cnt + 1` + if [ $cnt -gt 10 ] + then + echo "Nginx 'soft' update failed, doing restart" + kill -s KILL $NGX_PID + invoke-rc.d nginx start + exit 0 + fi + sleep 1 + done + echo "QUIT" + NGX_OLD_PID=`cat /var/run/nginx.pid.oldbin` + kill -s QUIT $NGX_OLD_PID + fi + fi +fi + +#DEBHELPER# + +exit 0 --- nginx-0.7.63.orig/debian/nginx.1 +++ nginx-0.7.63/debian/nginx.1 @@ -0,0 +1,47 @@ +.TH "nginx" "1" "" "" "" +.SH "NAME" +nginx \- small, but very powerful and efficient web server +.br + +.br +.SH "SYNOPSIS" +\fBnginx\fR [options] +.br + +.br +.SH "DESCRIPTION" +\fBnginx\fR is a server that can be used as standalone HTTP server and as +a reverse proxy server before some Apache or another big server to reduce +load to backend servers by many concurrent HTTP\-sessions. +.br + +.br +.SH "OPTIONS" +A summary of options is included below: +.br + +.br +\fB\-c\fR +Specifies a particular configuration file for nginx to load. +.br +\fB\-v\fR +Show version of program. +.br +\fB\-t\fR +Tests nginx configuration +.br +.br + +.br +You can find further information about this webserver in http://nginx.net/docs_en.txt. +.br + +.br +.SH "AUTHORS" +\fBnginx\fR was written by Igor Sysoev. +.br + +.br +This manual page was written by Jose Parrella , +for the Debian project (but may be used by others). + --- nginx-0.7.63.orig/debian/docs +++ nginx-0.7.63/debian/docs @@ -0,0 +1 @@ +README --- nginx-0.7.63.orig/debian/prerm +++ nginx-0.7.63/debian/prerm @@ -0,0 +1,34 @@ +#!/bin/sh + +set -e + +case "$1" in + + remove|remove-in-favour|deconfigure|deconfigure-in-favour) + + if [ -x /etc/init.d/nginx ]; then + if [ -x /usr/sbin/invoke-rc.d ] ; then + invoke-rc.d nginx stop + else + /etc/init.d/nginx stop + fi + fi + + ;; + + upgrade|failed-upgrade) + + ;; + + *) + + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + + ;; + +esac + +#DEBHELPER# + +exit 0 --- nginx-0.7.63.orig/debian/init.d +++ nginx-0.7.63/debian/init.d @@ -0,0 +1,87 @@ +#! /bin/sh + +### BEGIN INIT INFO +# Provides: nginx +# Required-Start: $all +# Required-Stop: $all +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: starts the nginx web server +# Description: starts nginx using start-stop-daemon +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/sbin/nginx +NAME=nginx +DESC=nginx + +test -x $DAEMON || exit 0 + +# Include nginx defaults if available +if [ -f /etc/default/nginx ] ; then + . /etc/default/nginx +fi + +set -e + +. /lib/lsb/init-functions + +test_nginx_config() { + if nginx -t + then + return 0 + else + return $? + fi +} + +case "$1" in + start) + echo -n "Starting $DESC: " + test_nginx_config + start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ + --exec $DAEMON -- $DAEMON_OPTS || true + echo "$NAME." + ;; + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \ + --exec $DAEMON || true + echo "$NAME." + ;; + restart|force-reload) + echo -n "Restarting $DESC: " + start-stop-daemon --stop --quiet --pidfile \ + /var/run/$NAME.pid --exec $DAEMON || true + sleep 1 + test_nginx_config + start-stop-daemon --start --quiet --pidfile \ + /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS || true + echo "$NAME." + ;; + reload) + echo -n "Reloading $DESC configuration: " + test_nginx_config + start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/$NAME.pid \ + --exec $DAEMON || true + echo "$NAME." + ;; + configtest) + echo -n "Testing $DESC configuration: " + if test_nginx_config + then + echo "$NAME." + else + exit $? + fi + ;; + status) + status_of_proc -p /var/run/$NAME.pid "$DAEMON" nginx && exit 0 || exit $? + ;; + *) + echo "Usage: $NAME {start|stop|restart|reload|force-reload|status|configtest}" >&2 + exit 1 + ;; +esac + +exit 0 --- nginx-0.7.63.orig/debian/copyright +++ nginx-0.7.63/debian/copyright @@ -0,0 +1,30 @@ +This package was debianized by Jose Parrella on +Tue, 5 Sep 2006 11:33:34 -0400. + +It was downloaded from http://nginx.net/ + +Upstream Author: Igor Sysoev + +Copyright (C) 2002-2006 Igor Sysoev + +License: + Redistribution and use in source and binary forms, with or without + modification, are permitted under the terms of the BSD License. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +On Debian systems, the complete text of the BSD License can be +found in `/usr/share/common-licenses/BSD'. + +The Debian packaging is (C) 2006, Jose Parrella and +is licensed under the GPL, see `/usr/share/common-licenses/GPL'. --- nginx-0.7.63.orig/debian/nginx.install +++ nginx-0.7.63/debian/nginx.install @@ -0,0 +1,3 @@ +objs/nginx usr/sbin +debian/conf/* etc/nginx +debian/NEWS.Debian usr/share/doc/nginx --- nginx-0.7.63.orig/debian/compat +++ nginx-0.7.63/debian/compat @@ -0,0 +1 @@ +5 --- nginx-0.7.63.orig/debian/postrm +++ nginx-0.7.63/debian/postrm @@ -0,0 +1,25 @@ +#!/bin/sh + +set -e + +case "$1" in + + purge) + + rm -rf /var/lib/nginx /var/log/nginx /etc/nginx + ;; + + remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + + ;; + + *) + + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + +esac + +#DEBHELPER# + +exit 0 --- nginx-0.7.63.orig/debian/changelog +++ nginx-0.7.63/debian/changelog @@ -0,0 +1,292 @@ +nginx (0.7.63-1) unstable; urgency=low + + * New upstream release. + + -- Fabio Tranchitella Sun, 08 Nov 2009 09:53:46 +0100 + +nginx (0.7.62-4) unstable; urgency=low + + * debian/conf/nginx.conf: commented out the mail proxy example. + (Closes: #551682) + * debian/init.d: do not redirect the output of nginx -t. + (Closes: #551683) + + -- Fabio Tranchitella Thu, 22 Oct 2009 19:50:05 +0200 + +nginx (0.7.62-3) unstable; urgency=low + + * debian/rules: fix the FTBFS on sparc. + + -- Fabio Tranchitella Fri, 16 Oct 2009 06:39:22 +0000 + +nginx (0.7.62-2) unstable; urgency=low + + * debian/rules: added --with-mail and --with-mail_ssl_module. + * debian/patches/nginx-upstream-fair.dpatch: added support for the + nginx-upstream-fair module. (Closes: #521447) + * debian/patches/dlopen.dpatch: applied patch to remove the unnecesssary link + to libdl. (Closes: #540599) + + -- Fabio Tranchitella Thu, 15 Oct 2009 18:32:00 +0000 + +nginx (0.7.62-1) unstable; urgency=low + + * New upstream release. + * debian/rules: added --with-ipv6. (Closes: #547249) + + -- Fabio Tranchitella Sun, 27 Sep 2009 22:25:16 +0200 + +nginx (0.7.61-2) unstable; urgency=low + + * debian/control: bumped Standards-Version to 3.8.3, no changes needed. + * debian/init.d: added status action. (Closes: #541228) + * debian/rules: + - added -with-http_gzip_static_module. (Closes: #541229) + - use the switch --with-cc-opt="-m32 -mcpu=ultrasparc" on sparc. + (Closes: #543571) + + -- Fabio Tranchitella Sat, 29 Aug 2009 17:03:44 +0200 + +nginx (0.7.61-1) unstable; urgency=low + + * New upstream version: + *) Bugfix: nginx could not be built --without-http-cache; the bug had + appeared in 0.7.60. + *) Bugfix: a segmentation fault occurred in worker process, if a + backend 401 error was intercepted and the backend did not set the + "WWW-Authenticate" response header line. + Thanks to Eugene Mychlo. + *) Feature: the "keepalive_requests" directive. + *) Bugfix: in open_file_cache and proxy/fastcgi cache interaction on + start up. + *) Bugfix: open_file_cache might cache open file descriptors too long. + *) Bugfix: XLST filter did not work in subrequests. + * Fix "gzip_disable in default conf for old IE", adding ignore rules for + certain MSIE versions in the default configuration (Closes: #540025) + * Fix "init.d: Config test before allowing a restart" adding a function + and calling it before reloading, restarting and starting (Closes: #539778) + * Drops path for pidof call in postinst script. + + -- Jose Parrella Wed, 05 Aug 2009 14:00:11 -0500 + +nginx (0.7.59-1) unstable; urgency=low + + * New upstream release, first in Debian for the 0.7 branch. Among other + issues, it also fixes the problem with wildcard dns names used with SSL. + (Closes: #515904) + * debian/watch: updated. + * debian/postinst: fixed a bashism. (Closes: #507913) + * debian/conf/nginx.conf: removed default_type. (Closes: #509390) + * debian/control: updated Standards-Version to 3.8.1, no changes needed. + * debian/NEWS.Debian: documented the issues with + server_names_hash_bucket_size. (Closes: #524785) + + -- Fabio Tranchitella Sun, 31 May 2009 18:38:56 +0200 + +nginx (0.7.14-1) experimental; urgency=low + + * New upstream release. + * Adding configtest to the init.d script (Closes: #496279) + * postinst now calls the builtin kill, so tweaks on the specific signal + calls were needed. + * Default HTML files are no longer installed. + * The default configuration file no longer requires a 50x file under + /var/www. + + -- Jose Parrella Tue, 02 Sep 2008 20:48:58 -0430 + +nginx (0.6.34-2) unstable; urgency=low + + * Added support for realip module. (Closes: #507419) + + -- Fabio Tranchitella Sat, 06 Dec 2008 10:34:01 +0100 + +nginx (0.6.34-1) unstable; urgency=low + + * New upstream release. + * debian/rules: removed the --with-debug configure switch. (Closes: #500891) + + -- Fabio Tranchitella Sun, 30 Nov 2008 11:37:13 +0100 + +nginx (0.6.32-3) unstable; urgency=low + + * debian/control: build again on all the architectures, but use the switch + --with-cc-opt="-m32 -mcpu=ultrasparc" on sparch. (Closes: #479185) + + -- Fabio Tranchitella Thu, 25 Sep 2008 17:14:27 +0200 + +nginx (0.6.32-2) unstable; urgency=low + + * debian/control: disabled support for sparc. (Closes: #479185) + + -- Fabio Tranchitella Sat, 20 Sep 2008 11:48:48 +0200 + +nginx (0.6.32-1) unstable; urgency=low + + * New upstream release. + + -- Fabio Tranchitella Fri, 18 Jul 2008 09:15:58 +0200 + +nginx (0.6.31-2) unstable; urgency=low + + * debian/control: removed httpd-cgi, nginx doesn't support executing + external programs. (Closes: #482332) + + -- Fabio Tranchitella Thu, 22 May 2008 08:18:52 +0200 + +nginx (0.6.31-1) unstable; urgency=low + + * New upstream release. + + -- Fabio Tranchitella Mon, 12 May 2008 22:34:55 +0200 + +nginx (0.6.30-2) unstable; urgency=low + + * Upload into unstable. + + -- Fabio Tranchitella Mon, 12 May 2008 14:24:53 +0200 + +nginx (0.6.30-1) experimental; urgency=low + + * New upstream release. + * Sync with the unstable packages. + * debian/conf/nginx.conf: add support for a conf.d directory. + (Closes: #476952) + + -- Fabio Tranchitella Fri, 02 May 2008 09:32:46 +0200 + +nginx (0.5.35-3) unstable; urgency=low + + * debian/conf/sites-available/default: adding support for /doc and /images + namespaces (Closes: #474519) + + -- Jose Parrella Mon, 07 Apr 2008 13:22:32 -0430 + +nginx (0.5.35-2) unstable; urgency=low + + * debian/init.d: do not break if start-stop-daemon exits with an error. + (Closes: #464453) + + -- Fabio Tranchitella Sun, 10 Feb 2008 17:57:57 +0100 + +nginx (0.5.35-1) unstable; urgency=low + + * New upstream release. + + -- Fabio Tranchitella Wed, 09 Jan 2008 07:58:56 +0100 + +nginx (0.5.34-1) unstable; urgency=low + + * New upstream release. + * debian/control: added Homepage, Vcs-Svn, Vcs-Browser fields; updated + Standard-Versions to 3.7.3. + + -- Fabio Tranchitella Mon, 24 Dec 2007 12:26:27 +0100 + +nginx (0.5.33-1) unstable; urgency=low + + * New stable upstream release (Closes: #451173) + * nginx now provides httpd, httpd-cgi virtual packages + (Closes: #439468, #452025) + * sites-enabled/default link is now provided only on fresh + installations (Closes: #432961) + * Updated code for online upgrading of nginx (Closes: #445246) + * Reviewed maintainer scripts for correct behaviour on updates + (Closes: #452787, #435965) + * Removed debian/nginx.links and debian/preinst. + * Changing Maintainer address to bureado@debian.org. + * Welcoming Fabio Tranchitella as an nginx + uploader for Debian. Thanks for your patches. + + -- Jose Parrella Sat, 08 Dec 2007 11:27:54 -0400 + +nginx (0.5.30-1) unstable; urgency=low + + * New stable upstream release. + * Adding mime.types (and other upstream conffiles) to the package + since it was lost on 0.5.26 (Closes: #435964) + + -- Jose Parrella Sat, 04 Aug 2007 10:39:40 -0400 + +nginx (0.5.26-1) unstable; urgency=low + + * New stable upstream release. + * Updating init.d usage message. + * Installing logrotate script (Closes: #397978) + + -- Jose Parrella Sun, 17 Jun 2007 20:43:35 +0100 + +nginx (0.5.18-1) unstable; urgency=low + + * New upstream version (Closes: #420063) + * Adding DAV support (Closes: #415678) + * Adding support for sites-[available|enabled]/ (Closes: #419912) + + -- Jose Parrella Thu, 19 Apr 2007 21:50:37 -0400 + +nginx (0.5.13-1) unstable; urgency=low + + * Adding FLV support. (Closes: #411105) + * Adding SSL support. + + -- Jose Parrella Mon, 19 Feb 2007 10:30:07 -0400 + +nginx (0.5.12-2) unstable; urgency=low + + * Patching src/core/ngx_shmtx.h in order to solve FTBFS problems in + non-x86 archs (Thanks to Igor Sysoev) (Closes: #410884) + + -- Jose Parrella Wed, 14 Feb 2007 13:32:01 -0400 + +nginx (0.5.12-1) unstable; urgency=low + + * New upstream version fixes FTBFS problems in non-x86 archs + (Closes: #409878) + + -- Jose Parrella Mon, 12 Feb 2007 19:37:07 -0400 + +nginx (0.5.11-1) unstable; urgency=low + + * New upstream version. (Closes: #405983) + + -- Jose Parrella Sun, 5 Feb 2007 19:35:56 -0400 + +nginx (0.4.13-2) unstable; urgency=low + + * Fixed default installation paths for www/ files, avoiding the + default installation of index.html in /var/www (Closes: #400103) + * Alexey Besciokov provided new postinst and prerm + scripts with the ability to reload the master binary (Closes: #398009) + + -- Jose Parrella Fri, 24 Nov 2006 07:12:46 -0400 + +nginx (0.4.13-1) unstable; urgency=low + + * New upstream version + * Fixed default configuration file which made nginx to fail at + installation and purge. + + -- Jose Parrella Thu, 16 Nov 2006 22:44:33 -0400 + +nginx (0.4.12-1) unstable; urgency=low + + * New upstream version (Closes: #397969) + * nginx will now compile with debugging and status support + (Closes: #397967) + * Added configuration reload support in the init.d script + (Closes: #397980) + * Added logrotate script (Closes: #397978) + * Added debian/upstream.pl as a brief helper for new + upstream version packaging. + * Thanks to Alexey Besciokov for + suggestions, bug reports and patches. + + -- Jose Parrella Sun, 12 Nov 2006 18:31:24 -0400 + +nginx (0.4.2-1) unstable; urgency=low + + * Initial release (Closes: #386151) + * Tweaked the configuration file and the path handling for Debian. + + -- Jose Parrella Thu, 14 Sep 2006 11:40:20 -0400 + --- nginx-0.7.63.orig/debian/README.source +++ nginx-0.7.63/debian/README.source @@ -0,0 +1 @@ +Please refer to /usr/share/doc/dpatch/README.source.gz. --- nginx-0.7.63.orig/debian/NEWS.Debian +++ nginx-0.7.63/debian/NEWS.Debian @@ -0,0 +1,42 @@ +nginx (0.7.59-1) unstable; urgency=low + + As stated by upstream, the 0.6.x branch is consedered legacy and 0.7.x will + be the new stable branch. For this reason, the nginx maintainers decided to + upload 0.7.59 to unstable. + + Should you get the following error while starting nginx: + + could not build the server_names_hash, you should increase + server_names_hash_bucket_size: 32 + + Please add the following parameter to your nginx.conf: + + server_names_hash_bucket_size 100; + + Where 100 is the size of your server names hash bucket. For more information + about this option, please read the following resources: + + http://wiki.nginx.org/NginxHttpCoreModule#server_names_hash_bucket_size + http://thread.gmane.org/gmane.comp.web.nginx.english/820/focus=821 + http://thread.gmane.org/gmane.comp.web.nginx.english/985/focus=989 + + -- Fabio Tranchitella Sun, 31 May 2009 18:30:10 +0200 + +nginx (0.6.30-2) unstable; urgency=low + + As of May 4th., nginx 0.5.x branch is considered legacy and 0.6.x will + be the new stable branch. The announcement was made by Igor Sysoev when + releasing the last 0.5.x version, nginx 0.5.36. + + Debian, the universal operating system, has provided binary packages for + both 0.5 and 0.6 branches in unstable and experimental, and will now offer + only 0.6 packages in the unstable distribution, starting with the + 0.6.30-1 package. + + In the future, Debian will also provide experimental packages for the + next testing branch of nginx, at the moment upstream announces it. + + Should you have any problem with nginx in Debian, please file a bug in + the Debian Bug Tracking System. + + -- Fabio Tranchitella Mon, 12 May 2008 14:24:53 +0200 --- nginx-0.7.63.orig/debian/dirs +++ nginx-0.7.63/debian/dirs @@ -0,0 +1,7 @@ +usr/sbin +etc/nginx +etc/nginx/sites-available +etc/nginx/sites-enabled +etc/nginx/conf.d +var/log/nginx +var/lib/nginx --- nginx-0.7.63.orig/debian/watch +++ nginx-0.7.63/debian/watch @@ -0,0 +1,11 @@ +# Example watch control file for uscan +# Rename this file to "watch" and then you can run the "uscan" command +# to check for upstream updates and more. +# See uscan(1) for format + +# Compulsory line, this is a version 3 file +version=3 + +# Uncomment to examine a Webpage +# +http://sysoev.ru/nginx/ nginx-([\.0-9]+)\.tar\.gz --- nginx-0.7.63.orig/debian/nginx.logrotate +++ nginx-0.7.63/debian/nginx.logrotate @@ -0,0 +1,13 @@ +/var/log/nginx/*.log { + daily + missingok + rotate 52 + compress + delaycompress + notifempty + create 640 root adm + sharedscripts + postrotate + [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid` + endscript +} --- nginx-0.7.63.orig/debian/conf/fastcgi_params +++ nginx-0.7.63/debian/conf/fastcgi_params @@ -0,0 +1,23 @@ + +fastcgi_param QUERY_STRING $query_string; +fastcgi_param REQUEST_METHOD $request_method; +fastcgi_param CONTENT_TYPE $content_type; +fastcgi_param CONTENT_LENGTH $content_length; + +fastcgi_param SCRIPT_NAME $fastcgi_script_name; +fastcgi_param REQUEST_URI $request_uri; +fastcgi_param DOCUMENT_URI $document_uri; +fastcgi_param DOCUMENT_ROOT $document_root; +fastcgi_param SERVER_PROTOCOL $server_protocol; + +fastcgi_param GATEWAY_INTERFACE CGI/1.1; +fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + +fastcgi_param REMOTE_ADDR $remote_addr; +fastcgi_param REMOTE_PORT $remote_port; +fastcgi_param SERVER_ADDR $server_addr; +fastcgi_param SERVER_PORT $server_port; +fastcgi_param SERVER_NAME $server_name; + +# PHP only, required if PHP was built with --enable-force-cgi-redirect +fastcgi_param REDIRECT_STATUS 200; --- nginx-0.7.63.orig/debian/conf/koi-utf +++ nginx-0.7.63/debian/conf/koi-utf @@ -0,0 +1,109 @@ + +# This map is not a full koi8-r <> utf8 map: it does not contain +# box-drawing and some other characters. Besides this map contains +# several koi8-u and Byelorussian letters which are not in koi8-r. +# If you need a full and standard map, use contrib/unicode2nginx/koi-utf +# map instead. + +charset_map koi8-r utf-8 { + + 80 E282AC ; # euro + + 95 E280A2 ; # bullet + + 9A C2A0 ; #   + + 9E C2B7 ; # · + + A3 D191 ; # small yo + A4 D194 ; # small Ukrainian ye + + A6 D196 ; # small Ukrainian i + A7 D197 ; # small Ukrainian yi + + AD D291 ; # small Ukrainian soft g + AE D19E ; # small Byelorussian short u + + B0 C2B0 ; # ° + + B3 D081 ; # capital YO + B4 D084 ; # capital Ukrainian YE + + B6 D086 ; # capital Ukrainian I + B7 D087 ; # capital Ukrainian YI + + B9 E28496 ; # numero sign + + BD D290 ; # capital Ukrainian soft G + BE D18E ; # capital Byelorussian short U + + BF C2A9 ; # (C) + + C0 D18E ; # small yu + C1 D0B0 ; # small a + C2 D0B1 ; # small b + C3 D186 ; # small ts + C4 D0B4 ; # small d + C5 D0B5 ; # small ye + C6 D184 ; # small f + C7 D0B3 ; # small g + C8 D185 ; # small kh + C9 D0B8 ; # small i + CA D0B9 ; # small j + CB D0BA ; # small k + CC D0BB ; # small l + CD D0BC ; # small m + CE D0BD ; # small n + CF D0BE ; # small o + + D0 D0BF ; # small p + D1 D18F ; # small ya + D2 D180 ; # small r + D3 D181 ; # small s + D4 D182 ; # small t + D5 D183 ; # small u + D6 D0B6 ; # small zh + D7 D0B2 ; # small v + D8 D18C ; # small soft sign + D9 D18B ; # small y + DA D0B7 ; # small z + DB D188 ; # small sh + DC D18D ; # small e + DD D189 ; # small shch + DE D187 ; # small ch + DF D18A ; # small hard sign + + E0 D0AE ; # capital YU + E1 D090 ; # capital A + E2 D091 ; # capital B + E3 D0A6 ; # capital TS + E4 D094 ; # capital D + E5 D095 ; # capital YE + E6 D0A4 ; # capital F + E7 D093 ; # capital G + E8 D0A5 ; # capital KH + E9 D098 ; # capital I + EA D099 ; # capital J + EB D09A ; # capital K + EC D09B ; # capital L + ED D09C ; # capital M + EE D09D ; # capital N + EF D09E ; # capital O + + F0 D09F ; # capital P + F1 D0AF ; # capital YA + F2 D0A0 ; # capital R + F3 D0A1 ; # capital S + F4 D0A2 ; # capital T + F5 D0A3 ; # capital U + F6 D096 ; # capital ZH + F7 D092 ; # capital V + F8 D0AC ; # capital soft sign + F9 D0AB ; # capital Y + FA D097 ; # capital Z + FB D0A8 ; # capital SH + FC D0AD ; # capital E + FD D0A9 ; # capital SHCH + FE D0A7 ; # capital CH + FF D0AA ; # capital hard sign +} --- nginx-0.7.63.orig/debian/conf/koi-win +++ nginx-0.7.63/debian/conf/koi-win @@ -0,0 +1,103 @@ + +charset_map koi8-r windows-1251 { + + 80 88 ; # euro + + 95 95 ; # bullet + + 9A A0 ; #   + + 9E B7 ; # · + + A3 B8 ; # small yo + A4 BA ; # small Ukrainian ye + + A6 B3 ; # small Ukrainian i + A7 BF ; # small Ukrainian yi + + AD B4 ; # small Ukrainian soft g + AE A2 ; # small Byelorussian short u + + B0 B0 ; # ° + + B3 A8 ; # capital YO + B4 AA ; # capital Ukrainian YE + + B6 B2 ; # capital Ukrainian I + B7 AF ; # capital Ukrainian YI + + B9 B9 ; # numero sign + + BD A5 ; # capital Ukrainian soft G + BE A1 ; # capital Byelorussian short U + + BF A9 ; # (C) + + C0 FE ; # small yu + C1 E0 ; # small a + C2 E1 ; # small b + C3 F6 ; # small ts + C4 E4 ; # small d + C5 E5 ; # small ye + C6 F4 ; # small f + C7 E3 ; # small g + C8 F5 ; # small kh + C9 E8 ; # small i + CA E9 ; # small j + CB EA ; # small k + CC EB ; # small l + CD EC ; # small m + CE ED ; # small n + CF EE ; # small o + + D0 EF ; # small p + D1 FF ; # small ya + D2 F0 ; # small r + D3 F1 ; # small s + D4 F2 ; # small t + D5 F3 ; # small u + D6 E6 ; # small zh + D7 E2 ; # small v + D8 FC ; # small soft sign + D9 FB ; # small y + DA E7 ; # small z + DB F8 ; # small sh + DC FD ; # small e + DD F9 ; # small shch + DE F7 ; # small ch + DF FA ; # small hard sign + + E0 DE ; # capital YU + E1 C0 ; # capital A + E2 C1 ; # capital B + E3 D6 ; # capital TS + E4 C4 ; # capital D + E5 C5 ; # capital YE + E6 D4 ; # capital F + E7 C3 ; # capital G + E8 D5 ; # capital KH + E9 C8 ; # capital I + EA C9 ; # capital J + EB CA ; # capital K + EC CB ; # capital L + ED CC ; # capital M + EE CD ; # capital N + EF CE ; # capital O + + F0 CF ; # capital P + F1 DF ; # capital YA + F2 D0 ; # capital R + F3 D1 ; # capital S + F4 D2 ; # capital T + F5 D3 ; # capital U + F6 C6 ; # capital ZH + F7 C2 ; # capital V + F8 DC ; # capital soft sign + F9 DB ; # capital Y + FA C7 ; # capital Z + FB D8 ; # capital SH + FC DD ; # capital E + FD D9 ; # capital SHCH + FE D7 ; # capital CH + FF DA ; # capital hard sign +} --- nginx-0.7.63.orig/debian/conf/win-utf +++ nginx-0.7.63/debian/conf/win-utf @@ -0,0 +1,126 @@ + +# This map is not a full windows-1251 <> utf8 map: it does not +# contain Serbian and Macedonian letters. If you need a full map, +# use contrib/unicode2nginx/win-utf map instead. + +charset_map windows-1251 utf-8 { + + 82 E2809A ; # single low-9 quotation mark + + 84 E2809E ; # double low-9 quotation mark + 85 E280A6 ; # ellipsis + 86 E280A0 ; # dagger + 87 E280A1 ; # double dagger + 88 E282AC ; # euro + 89 E280B0 ; # per mille + + 91 E28098 ; # left single quotation mark + 92 E28099 ; # right single quotation mark + 93 E2809C ; # left double quotation mark + 94 E2809D ; # right double quotation mark + 95 E280A2 ; # bullet + 96 E28093 ; # en dash + 97 E28094 ; # em dash + + 99 E284A2 ; # trade mark sign + + A0 C2A0 ; #   + A1 D18E ; # capital Byelorussian short U + A2 D19E ; # small Byelorussian short u + + A4 C2A4 ; # currency sign + A5 D290 ; # capital Ukrainian soft G + A6 C2A6 ; # borken bar + A7 C2A7 ; # section sign + A8 D081 ; # capital YO + A9 C2A9 ; # (C) + AA D084 ; # capital Ukrainian YE + AB C2AB ; # left-pointing double angle quotation mark + AC C2AC ; # not sign + AD C2AD ; # soft hypen + AE C2AE ; # (R) + AF D087 ; # capital Ukrainian YI + + B0 C2B0 ; # ° + B1 C2B1 ; # plus-minus sign + B2 D086 ; # capital Ukrainian I + B3 D196 ; # small Ukrainian i + B4 D291 ; # small Ukrainian soft g + B5 C2B5 ; # micro sign + B6 C2B6 ; # pilcrow sign + B7 C2B7 ; # · + B8 D191 ; # small yo + B9 E28496 ; # numero sign + BA D194 ; # small Ukrainian ye + BB C2BB ; # right-pointing double angle quotation mark + + BF D197 ; # small Ukrainian yi + + C0 D090 ; # capital A + C1 D091 ; # capital B + C2 D092 ; # capital V + C3 D093 ; # capital G + C4 D094 ; # capital D + C5 D095 ; # capital YE + C6 D096 ; # capital ZH + C7 D097 ; # capital Z + C8 D098 ; # capital I + C9 D099 ; # capital J + CA D09A ; # capital K + CB D09B ; # capital L + CC D09C ; # capital M + CD D09D ; # capital N + CE D09E ; # capital O + CF D09F ; # capital P + + D0 D0A0 ; # capital R + D1 D0A1 ; # capital S + D2 D0A2 ; # capital T + D3 D0A3 ; # capital U + D4 D0A4 ; # capital F + D5 D0A5 ; # capital KH + D6 D0A6 ; # capital TS + D7 D0A7 ; # capital CH + D8 D0A8 ; # capital SH + D9 D0A9 ; # capital SHCH + DA D0AA ; # capital hard sign + DB D0AB ; # capital Y + DC D0AC ; # capital soft sign + DD D0AD ; # capital E + DE D0AE ; # capital YU + DF D0AF ; # capital YA + + E0 D0B0 ; # small a + E1 D0B1 ; # small b + E2 D0B2 ; # small v + E3 D0B3 ; # small g + E4 D0B4 ; # small d + E5 D0B5 ; # small ye + E6 D0B6 ; # small zh + E7 D0B7 ; # small z + E8 D0B8 ; # small i + E9 D0B9 ; # small j + EA D0BA ; # small k + EB D0BB ; # small l + EC D0BC ; # small m + ED D0BD ; # small n + EE D0BE ; # small o + EF D0BF ; # small p + + F0 D180 ; # small r + F1 D181 ; # small s + F2 D182 ; # small t + F3 D183 ; # small u + F4 D184 ; # small f + F5 D185 ; # small kh + F6 D186 ; # small ts + F7 D187 ; # small ch + F8 D188 ; # small sh + F9 D189 ; # small shch + FA D18A ; # small hard sign + FB D18B ; # small y + FC D18C ; # small soft sign + FD D18D ; # small e + FE D18E ; # small yu + FF D18F ; # small ya +} --- nginx-0.7.63.orig/debian/conf/mime.types +++ nginx-0.7.63/debian/conf/mime.types @@ -0,0 +1,69 @@ + +types { + text/html html htm shtml; + text/css css; + text/xml xml rss; + image/gif gif; + image/jpeg jpeg jpg; + application/x-javascript js; + application/atom+xml atom; + + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; + + image/png png; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; + + application/java-archive jar war ear; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.ms-excel xls; + application/vnd.ms-powerpoint ppt; + application/vnd.wap.wmlc wmlc; + application/vnd.wap.xhtml+xml xhtml; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/zip zip; + + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream eot; + application/octet-stream iso img; + application/octet-stream msi msp msm; + + audio/midi mid midi kar; + audio/mpeg mp3; + audio/x-realaudio ra; + + video/3gpp 3gpp 3gp; + video/mpeg mpeg mpg; + video/quicktime mov; + video/x-flv flv; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; +} --- nginx-0.7.63.orig/debian/conf/nginx.conf +++ nginx-0.7.63/debian/conf/nginx.conf @@ -0,0 +1,50 @@ +user www-data; +worker_processes 1; + +error_log /var/log/nginx/error.log; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; + # multi_accept on; +} + +http { + include /etc/nginx/mime.types; + + access_log /var/log/nginx/access.log; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + tcp_nodelay on; + + gzip on; + gzip_disable "MSIE [1-6]\.(?!.*SV1)"; + + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; +} + +# mail { +# # See sample authentication script at: +# # http://wiki.nginx.org/NginxImapAuthenticateWithApachePhpScript +# +# # auth_http localhost/auth.php; +# # pop3_capabilities "TOP" "USER"; +# # imap_capabilities "IMAP4rev1" "UIDPLUS"; +# +# server { +# listen localhost:110; +# protocol pop3; +# proxy on; +# } +# +# server { +# listen localhost:143; +# protocol imap; +# proxy on; +# } +# } --- nginx-0.7.63.orig/debian/conf/sites-available/default +++ nginx-0.7.63/debian/conf/sites-available/default @@ -0,0 +1,97 @@ +# You may add here your +# server { +# ... +# } +# statements for each of your virtual hosts + +server { + listen 80; + server_name localhost; + + access_log /var/log/nginx/localhost.access.log; + + location / { + root /var/www/nginx-default; + index index.html index.htm; + } + + location /doc { + root /usr/share; + autoindex on; + allow 127.0.0.1; + deny all; + } + + location /images { + root /usr/share; + autoindex on; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + #error_page 500 502 503 504 /50x.html; + #location = /50x.html { + # root /var/www/nginx-default; + #} + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + #proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + #location ~ \.php$ { + #fastcgi_pass 127.0.0.1:9000; + #fastcgi_index index.php; + #fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + #includefastcgi_params; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + #deny all; + #} +} + + +# another virtual host using mix of IP-, name-, and port-based configuration +# +#server { +#listen 8000; +#listen somename:8080; +#server_name somename alias another.alias; + +#location / { +#root html; +#index index.html index.htm; +#} +#} + + +# HTTPS server +# +#server { +#listen 443; +#server_name localhost; + +#ssl on; +#ssl_certificate cert.pem; +#ssl_certificate_key cert.key; + +#ssl_session_timeout 5m; + +#ssl_protocols SSLv2 SSLv3 TLSv1; +#ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; +#ssl_prefer_server_ciphers on; + +#location / { +#root html; +#index index.html index.htm; +#} +#} --- nginx-0.7.63.orig/debian/patches/dlopen.dpatch +++ nginx-0.7.63/debian/patches/dlopen.dpatch @@ -0,0 +1,39 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 99-unnamed.dpatch by Fabio Tranchitella +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: No description. + +@DPATCH@ +diff -urN nginx-0.7.62/auto/os/features nginx-0.7.62.debian/auto/os/features +--- nginx-0.7.62/auto/os/features 2009-06-15 08:49:53.000000000 +0000 ++++ nginx-0.7.62.debian/auto/os/features 2009-10-15 18:30:58.000000000 +0000 +@@ -232,28 +232,6 @@ + . auto/feature + + +-ngx_feature="dlopen()" +-ngx_feature_name= +-ngx_feature_run=no +-ngx_feature_incs="#include " +-ngx_feature_path= +-ngx_feature_libs= +-ngx_feature_test="dlopen(NULL, 0)" +-. auto/feature +- +- +-if [ $ngx_found != yes ]; then +- +- ngx_feature="dlopen() in libdl" +- ngx_feature_libs="-ldl" +- . auto/feature +- +- if [ $ngx_found = yes ]; then +- NGX_LIBDL="-ldl" +- fi +-fi +- +- + ngx_feature="sched_yield()" + ngx_feature_name="NGX_HAVE_SCHED_YIELD" + ngx_feature_run=no --- nginx-0.7.63.orig/debian/patches/nginx-upstream-fair.dpatch +++ nginx-0.7.63/debian/patches/nginx-upstream-fair.dpatch @@ -0,0 +1,1372 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## nginx-upstream-fair.dpatch by Fabio Tranchitella +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: nginx-upstream-fair module + +@DPATCH@ +diff -urN nginx/modules/nginx-upstream-fair/config nginx.debian/modules/nginx-upstream-fair/config +--- nginx/modules/nginx-upstream-fair/config 1970-01-01 00:00:00.000000000 +0000 ++++ nginx.debian/modules/nginx-upstream-fair/config 2009-10-15 18:10:40.000000000 +0000 +@@ -0,0 +1,3 @@ ++ngx_addon_name=ngx_http_upstream_fair_module ++HTTP_MODULES="$HTTP_MODULES ngx_http_upstream_fair_module" ++NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_upstream_fair_module.c" +diff -urN nginx/modules/nginx-upstream-fair/ngx_http_upstream_fair_module.c nginx.debian/modules/nginx-upstream-fair/ngx_http_upstream_fair_module.c +--- nginx/modules/nginx-upstream-fair/ngx_http_upstream_fair_module.c 1970-01-01 00:00:00.000000000 +0000 ++++ nginx.debian/modules/nginx-upstream-fair/ngx_http_upstream_fair_module.c 2009-10-15 18:10:54.000000000 +0000 +@@ -0,0 +1,1354 @@ ++/* ++ * Copyright (C) 2007 Grzegorz Nosek ++ * Work sponsored by Ezra Zygmuntowicz & EngineYard.com ++ * ++ * Based on nginx source (C) Igor Sysoev ++ */ ++ ++#include ++#include ++#include ++ ++typedef struct { ++ ngx_uint_t nreq; ++ ngx_uint_t total_req; ++ ngx_uint_t last_req_id; ++ ngx_uint_t fails; ++ ngx_uint_t current_weight; ++} ngx_http_upstream_fair_shared_t; ++ ++typedef struct ngx_http_upstream_fair_peers_s ngx_http_upstream_fair_peers_t; ++ ++typedef struct { ++ ngx_rbtree_node_t node; ++ ngx_uint_t generation; ++ uintptr_t peers; /* forms a unique cookie together with generation */ ++ ngx_uint_t total_nreq; ++ ngx_uint_t total_requests; ++ ngx_atomic_t lock; ++ ngx_http_upstream_fair_shared_t stats[1]; ++} ngx_http_upstream_fair_shm_block_t; ++ ++/* ngx_spinlock is defined without a matching unlock primitive */ ++#define ngx_spinlock_unlock(lock) (void) ngx_atomic_cmp_set(lock, ngx_pid, 0) ++ ++typedef struct { ++ ngx_http_upstream_fair_shared_t *shared; ++ struct sockaddr *sockaddr; ++ socklen_t socklen; ++ ngx_str_t name; ++ ++ ngx_uint_t weight; ++ ngx_uint_t max_fails; ++ time_t fail_timeout; ++ ++ time_t accessed; ++ ngx_uint_t down:1; ++ ++#if (NGX_HTTP_SSL) ++ ngx_ssl_session_t *ssl_session; /* local to a process */ ++#endif ++ ++} ngx_http_upstream_fair_peer_t; ++ ++#define NGX_HTTP_UPSTREAM_FAIR_NO_RR (1<<26) ++#define NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_IDLE (1<<27) ++#define NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_PEAK (1<<28) ++#define NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_MASK ((1<<27) | (1<<28)) ++ ++enum { WM_DEFAULT = 0, WM_IDLE, WM_PEAK }; ++ ++struct ngx_http_upstream_fair_peers_s { ++ ngx_http_upstream_fair_shm_block_t *shared; ++ ngx_uint_t current; ++ ngx_uint_t size_err:1; ++ ngx_uint_t no_rr:1; ++ ngx_uint_t weight_mode:2; ++ ngx_uint_t number; ++ ngx_str_t *name; ++ ngx_http_upstream_fair_peers_t *next; /* for backup peers support, not really used yet */ ++ ngx_http_upstream_fair_peer_t peer[1]; ++}; ++ ++ ++#define NGX_PEER_INVALID (~0UL) ++ ++typedef struct { ++ ngx_http_upstream_fair_peers_t *peers; ++ ngx_uint_t current; ++ uintptr_t *tried; ++ uintptr_t *done; ++ uintptr_t data; ++ uintptr_t data2; ++} ngx_http_upstream_fair_peer_data_t; ++ ++ ++static ngx_int_t ngx_http_upstream_init_fair(ngx_conf_t *cf, ++ ngx_http_upstream_srv_conf_t *us); ++static ngx_int_t ngx_http_upstream_get_fair_peer(ngx_peer_connection_t *pc, ++ void *data); ++static void ngx_http_upstream_free_fair_peer(ngx_peer_connection_t *pc, ++ void *data, ngx_uint_t state); ++static ngx_int_t ngx_http_upstream_init_fair_peer(ngx_http_request_t *r, ++ ngx_http_upstream_srv_conf_t *us); ++static char *ngx_http_upstream_fair(ngx_conf_t *cf, ngx_command_t *cmd, ++ void *conf); ++static char *ngx_http_upstream_fair_set_shm_size(ngx_conf_t *cf, ++ ngx_command_t *cmd, void *conf); ++static ngx_int_t ngx_http_upstream_fair_init_module(ngx_cycle_t *cycle); ++ ++#if (NGX_HTTP_EXTENDED_STATUS) ++static ngx_chain_t *ngx_http_upstream_fair_report_status(ngx_http_request_t *r, ++ ngx_int_t *length); ++#endif ++ ++#if (NGX_HTTP_SSL) ++static ngx_int_t ngx_http_upstream_fair_set_session(ngx_peer_connection_t *pc, ++ void *data); ++static void ngx_http_upstream_fair_save_session(ngx_peer_connection_t *pc, ++ void *data); ++#endif ++ ++static ngx_command_t ngx_http_upstream_fair_commands[] = { ++ ++ { ngx_string("fair"), ++ NGX_HTTP_UPS_CONF|NGX_CONF_ANY, ++ ngx_http_upstream_fair, ++ 0, ++ 0, ++ NULL }, ++ ++ { ngx_string("upstream_fair_shm_size"), ++ NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, ++ ngx_http_upstream_fair_set_shm_size, ++ 0, ++ 0, ++ NULL }, ++ ++ ngx_null_command ++}; ++ ++ ++static ngx_http_module_t ngx_http_upstream_fair_module_ctx = { ++ NULL, /* preconfiguration */ ++ NULL, /* postconfiguration */ ++ ++ NULL, /* create main configuration */ ++ NULL, /* init main configuration */ ++ ++ NULL, /* create server configuration */ ++ NULL, /* merge server configuration */ ++ ++ NULL, /* create location configuration */ ++ NULL, /* merge location configuration */ ++ ++#if (NGX_HTTP_EXTENDED_STATUS) ++ ngx_http_upstream_fair_report_status, ++#endif ++}; ++ ++ ++ngx_module_t ngx_http_upstream_fair_module = { ++ NGX_MODULE_V1, ++ &ngx_http_upstream_fair_module_ctx, /* module context */ ++ ngx_http_upstream_fair_commands, /* module directives */ ++ NGX_HTTP_MODULE, /* module type */ ++ NULL, /* init master */ ++ ngx_http_upstream_fair_init_module, /* init module */ ++ NULL, /* init process */ ++ NULL, /* init thread */ ++ NULL, /* exit thread */ ++ NULL, /* exit process */ ++ NULL, /* exit master */ ++ NGX_MODULE_V1_PADDING ++}; ++ ++ ++static ngx_uint_t ngx_http_upstream_fair_shm_size; ++static ngx_shm_zone_t * ngx_http_upstream_fair_shm_zone; ++static ngx_rbtree_t * ngx_http_upstream_fair_rbtree; ++static ngx_uint_t ngx_http_upstream_fair_generation; ++ ++static int ++ngx_http_upstream_fair_compare_rbtree_node(const ngx_rbtree_node_t *v_left, ++ const ngx_rbtree_node_t *v_right) ++{ ++ ngx_http_upstream_fair_shm_block_t *left, *right; ++ ++ left = (ngx_http_upstream_fair_shm_block_t *) v_left; ++ right = (ngx_http_upstream_fair_shm_block_t *) v_right; ++ ++ if (left->generation < right->generation) { ++ return -1; ++ } else if (left->generation > right->generation) { ++ return 1; ++ } else { /* left->generation == right->generation */ ++ if (left->peers < right->peers) { ++ return -1; ++ } else if (left->peers > right->peers) { ++ return 1; ++ } else { ++ return 0; ++ } ++ } ++} ++ ++/* ++ * generic functions start here ++ */ ++static void ++ngx_rbtree_generic_insert(ngx_rbtree_node_t *temp, ++ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel, ++ int (*compare)(const ngx_rbtree_node_t *left, const ngx_rbtree_node_t *right)) ++{ ++ for ( ;; ) { ++ if (node->key < temp->key) { ++ ++ if (temp->left == sentinel) { ++ temp->left = node; ++ break; ++ } ++ ++ temp = temp->left; ++ ++ } else if (node->key > temp->key) { ++ ++ if (temp->right == sentinel) { ++ temp->right = node; ++ break; ++ } ++ ++ temp = temp->right; ++ ++ } else { /* node->key == temp->key */ ++ if (compare(node, temp) < 0) { ++ ++ if (temp->left == sentinel) { ++ temp->left = node; ++ break; ++ } ++ ++ temp = temp->left; ++ ++ } else { ++ ++ if (temp->right == sentinel) { ++ temp->right = node; ++ break; ++ } ++ ++ temp = temp->right; ++ } ++ } ++ } ++ ++ node->parent = temp; ++ node->left = sentinel; ++ node->right = sentinel; ++ ngx_rbt_red(node); ++} ++ ++#define NGX_BITVECTOR_ELT_SIZE (sizeof(uintptr_t) * 8) ++ ++static uintptr_t * ++ngx_bitvector_alloc(ngx_pool_t *pool, ngx_uint_t size, uintptr_t *small) ++{ ++ ngx_uint_t nelts = (size + NGX_BITVECTOR_ELT_SIZE - 1) / NGX_BITVECTOR_ELT_SIZE; ++ ++ if (small && nelts == 1) { ++ *small = 0; ++ return small; ++ } ++ ++ return ngx_pcalloc(pool, nelts * NGX_BITVECTOR_ELT_SIZE); ++} ++ ++static ngx_int_t ++ngx_bitvector_test(uintptr_t *bv, ngx_uint_t bit) ++{ ++ ngx_uint_t n, m; ++ ++ n = bit / NGX_BITVECTOR_ELT_SIZE; ++ m = 1 << (bit % NGX_BITVECTOR_ELT_SIZE); ++ ++ return bv[n] & m; ++} ++ ++static void ++ngx_bitvector_set(uintptr_t *bv, ngx_uint_t bit) ++{ ++ ngx_uint_t n, m; ++ ++ n = bit / NGX_BITVECTOR_ELT_SIZE; ++ m = 1 << (bit % NGX_BITVECTOR_ELT_SIZE); ++ ++ bv[n] |= m; ++} ++ ++/* ++ * generic functions end here ++ */ ++ ++static ngx_int_t ++ngx_http_upstream_fair_init_module(ngx_cycle_t *cycle) ++{ ++ ngx_http_upstream_fair_generation++; ++ return NGX_OK; ++} ++ ++static void ++ngx_http_upstream_fair_rbtree_insert(ngx_rbtree_node_t *temp, ++ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) { ++ ++ ngx_rbtree_generic_insert(temp, node, sentinel, ++ ngx_http_upstream_fair_compare_rbtree_node); ++} ++ ++ ++static ngx_int_t ++ngx_http_upstream_fair_init_shm_zone(ngx_shm_zone_t *shm_zone, void *data) ++{ ++ ngx_slab_pool_t *shpool; ++ ngx_rbtree_t *tree; ++ ngx_rbtree_node_t *sentinel; ++ ++ if (data) { ++ shm_zone->data = data; ++ return NGX_OK; ++ } ++ ++ shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; ++ tree = ngx_slab_alloc(shpool, sizeof *tree); ++ if (tree == NULL) { ++ return NGX_ERROR; ++ } ++ ++ sentinel = ngx_slab_alloc(shpool, sizeof *sentinel); ++ if (sentinel == NULL) { ++ return NGX_ERROR; ++ } ++ ++ ngx_rbtree_sentinel_init(sentinel); ++ tree->root = sentinel; ++ tree->sentinel = sentinel; ++ tree->insert = ngx_http_upstream_fair_rbtree_insert; ++ shm_zone->data = tree; ++ ngx_http_upstream_fair_rbtree = tree; ++ ++ return NGX_OK; ++} ++ ++ ++static char * ++ngx_http_upstream_fair_set_shm_size(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ++{ ++ ssize_t new_shm_size; ++ ngx_str_t *value; ++ ++ value = cf->args->elts; ++ ++ new_shm_size = ngx_parse_size(&value[1]); ++ if (new_shm_size == NGX_ERROR) { ++ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Invalid memory area size `%V'", &value[1]); ++ return NGX_CONF_ERROR; ++ } ++ ++ new_shm_size = ngx_align(new_shm_size, ngx_pagesize); ++ ++ if (new_shm_size < 8 * (ssize_t) ngx_pagesize) { ++ ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "The upstream_fair_shm_size value must be at least %udKiB", (8 * ngx_pagesize) >> 10); ++ new_shm_size = 8 * ngx_pagesize; ++ } ++ ++ if (ngx_http_upstream_fair_shm_size && ++ ngx_http_upstream_fair_shm_size != (ngx_uint_t) new_shm_size) { ++ ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "Cannot change memory area size without restart, ignoring change"); ++ } else { ++ ngx_http_upstream_fair_shm_size = new_shm_size; ++ } ++ ngx_conf_log_error(NGX_LOG_DEBUG, cf, 0, "Using %udKiB of shared memory for upstream_fair", new_shm_size >> 10); ++ ++ return NGX_CONF_OK; ++} ++ ++ ++static char * ++ngx_http_upstream_fair(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ++{ ++ ngx_http_upstream_srv_conf_t *uscf; ++ ngx_uint_t i; ++ ngx_uint_t extra_peer_flags = 0; ++ ++ for (i = 1; i < cf->args->nelts; i++) { ++ ngx_str_t *value = cf->args->elts; ++ if (ngx_strcmp(value[i].data, "no_rr") == 0) { ++ extra_peer_flags |= NGX_HTTP_UPSTREAM_FAIR_NO_RR; ++ } else if (ngx_strcmp(value[i].data, "weight_mode=peak") == 0) { ++ if (extra_peer_flags & NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_MASK) { ++ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "weight_mode= options are mutually exclusive"); ++ return NGX_CONF_ERROR; ++ } ++ extra_peer_flags |= NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_PEAK; ++ } else if (ngx_strcmp(value[i].data, "weight_mode=idle") == 0) { ++ if (extra_peer_flags & NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_MASK) { ++ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "weight_mode= options are mutually exclusive"); ++ return NGX_CONF_ERROR; ++ } ++ extra_peer_flags |= NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_IDLE; ++ } else { ++ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Invalid `fair' parameter `%V'", &value[i]); ++ return NGX_CONF_ERROR; ++ } ++ } ++ ++ uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); ++ ++ uscf->peer.init_upstream = ngx_http_upstream_init_fair; ++ ++ uscf->flags = NGX_HTTP_UPSTREAM_CREATE ++ |NGX_HTTP_UPSTREAM_WEIGHT ++ |NGX_HTTP_UPSTREAM_MAX_FAILS ++ |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT ++ |NGX_HTTP_UPSTREAM_DOWN ++ |extra_peer_flags; ++ ++ return NGX_CONF_OK; ++} ++ ++ ++static ngx_int_t ++ngx_http_upstream_cmp_servers(const void *one, const void *two) ++{ ++ const ngx_http_upstream_fair_peer_t *first, *second; ++ ++ first = one; ++ second = two; ++ ++ return (first->weight < second->weight); ++} ++ ++ ++/* TODO: Actually support backup servers */ ++static ngx_int_t ++ngx_http_upstream_init_fair_rr(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) ++{ ++ ngx_url_t u; ++ ngx_uint_t i, j, n; ++ ngx_http_upstream_server_t *server; ++ ngx_http_upstream_fair_peers_t *peers, *backup; ++ ++ if (us->servers) { ++ server = us->servers->elts; ++ ++ n = 0; ++ ++ for (i = 0; i < us->servers->nelts; i++) { ++ if (server[i].backup) { ++ continue; ++ } ++ ++ n += server[i].naddrs; ++ } ++ ++ peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_fair_peers_t) ++ + sizeof(ngx_http_upstream_fair_peer_t) * (n - 1)); ++ if (peers == NULL) { ++ return NGX_ERROR; ++ } ++ ++ peers->number = n; ++ peers->name = &us->host; ++ ++ n = 0; ++ ++ for (i = 0; i < us->servers->nelts; i++) { ++ for (j = 0; j < server[i].naddrs; j++) { ++ if (server[i].backup) { ++ continue; ++ } ++ ++ peers->peer[n].sockaddr = server[i].addrs[j].sockaddr; ++ peers->peer[n].socklen = server[i].addrs[j].socklen; ++ peers->peer[n].name = server[i].addrs[j].name; ++ peers->peer[n].max_fails = server[i].max_fails; ++ peers->peer[n].fail_timeout = server[i].fail_timeout; ++ peers->peer[n].down = server[i].down; ++ peers->peer[n].weight = server[i].down ? 0 : server[i].weight; ++ n++; ++ } ++ } ++ ++ us->peer.data = peers; ++ ++ ngx_sort(&peers->peer[0], (size_t) n, ++ sizeof(ngx_http_upstream_fair_peer_t), ++ ngx_http_upstream_cmp_servers); ++ ++ /* backup servers */ ++ ++ n = 0; ++ ++ for (i = 0; i < us->servers->nelts; i++) { ++ if (!server[i].backup) { ++ continue; ++ } ++ ++ n += server[i].naddrs; ++ } ++ ++ if (n == 0) { ++ return NGX_OK; ++ } ++ ++ backup = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_fair_peers_t) ++ + sizeof(ngx_http_upstream_fair_peer_t) * (n - 1)); ++ if (backup == NULL) { ++ return NGX_ERROR; ++ } ++ ++ backup->number = n; ++ backup->name = &us->host; ++ ++ n = 0; ++ ++ for (i = 0; i < us->servers->nelts; i++) { ++ for (j = 0; j < server[i].naddrs; j++) { ++ if (!server[i].backup) { ++ continue; ++ } ++ ++ backup->peer[n].sockaddr = server[i].addrs[j].sockaddr; ++ backup->peer[n].socklen = server[i].addrs[j].socklen; ++ backup->peer[n].name = server[i].addrs[j].name; ++ backup->peer[n].weight = server[i].weight; ++ backup->peer[n].max_fails = server[i].max_fails; ++ backup->peer[n].fail_timeout = server[i].fail_timeout; ++ backup->peer[n].down = server[i].down; ++ n++; ++ } ++ } ++ ++ peers->next = backup; ++ ++ ngx_sort(&backup->peer[0], (size_t) n, ++ sizeof(ngx_http_upstream_fair_peer_t), ++ ngx_http_upstream_cmp_servers); ++ ++ return NGX_OK; ++ } ++ ++ ++ /* an upstream implicitly defined by proxy_pass, etc. */ ++ ++ if (us->port == 0 && us->default_port == 0) { ++ ngx_log_error(NGX_LOG_EMERG, cf->log, 0, ++ "no port in upstream \"%V\" in %s:%ui", ++ &us->host, us->file_name, us->line); ++ return NGX_ERROR; ++ } ++ ++ ngx_memzero(&u, sizeof(ngx_url_t)); ++ ++ u.host = us->host; ++ u.port = (in_port_t) (us->port ? us->port : us->default_port); ++ ++ if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) { ++ if (u.err) { ++ ngx_log_error(NGX_LOG_EMERG, cf->log, 0, ++ "%s in upstream \"%V\" in %s:%ui", ++ u.err, &us->host, us->file_name, us->line); ++ } ++ ++ return NGX_ERROR; ++ } ++ ++ n = u.naddrs; ++ ++ peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_fair_peers_t) ++ + sizeof(ngx_http_upstream_fair_peer_t) * (n - 1)); ++ if (peers == NULL) { ++ return NGX_ERROR; ++ } ++ ++ peers->number = n; ++ peers->name = &us->host; ++ ++ for (i = 0; i < u.naddrs; i++) { ++ peers->peer[i].sockaddr = u.addrs[i].sockaddr; ++ peers->peer[i].socklen = u.addrs[i].socklen; ++ peers->peer[i].name = u.addrs[i].name; ++ peers->peer[i].weight = 1; ++ peers->peer[i].max_fails = 1; ++ peers->peer[i].fail_timeout = 10; ++ } ++ ++ us->peer.data = peers; ++ ++ /* implicitly defined upstream has no backup servers */ ++ ++ return NGX_OK; ++} ++ ++static ngx_int_t ++ngx_http_upstream_init_fair(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) ++{ ++ ngx_http_upstream_fair_peers_t *peers; ++ ngx_uint_t n; ++ ngx_str_t *shm_name; ++ ++ /* do the dirty work using rr module */ ++ if (ngx_http_upstream_init_fair_rr(cf, us) != NGX_OK) { ++ return NGX_ERROR; ++ } ++ ++ /* setup our wrapper around rr */ ++ peers = ngx_palloc(cf->pool, sizeof *peers); ++ if (peers == NULL) { ++ return NGX_ERROR; ++ } ++ peers = us->peer.data; ++ n = peers->number; ++ ++ shm_name = ngx_palloc(cf->pool, sizeof *shm_name); ++ shm_name->len = sizeof("upstream_fair"); ++ shm_name->data = (unsigned char *) "upstream_fair"; ++ ++ if (ngx_http_upstream_fair_shm_size == 0) { ++ ngx_http_upstream_fair_shm_size = 8 * ngx_pagesize; ++ } ++ ++ ngx_http_upstream_fair_shm_zone = ngx_shared_memory_add( ++ cf, shm_name, ngx_http_upstream_fair_shm_size, &ngx_http_upstream_fair_module); ++ if (ngx_http_upstream_fair_shm_zone == NULL) { ++ return NGX_ERROR; ++ } ++ ngx_http_upstream_fair_shm_zone->init = ngx_http_upstream_fair_init_shm_zone; ++ ++ peers->shared = NULL; ++ peers->current = n - 1; ++ if (us->flags & NGX_HTTP_UPSTREAM_FAIR_NO_RR) { ++ peers->no_rr = 1; ++ } ++ if (us->flags & NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_IDLE) { ++ peers->weight_mode = WM_IDLE; ++ } else if (us->flags & NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_PEAK) { ++ peers->weight_mode = WM_PEAK; ++ } ++ peers->size_err = 0; ++ ++ us->peer.init = ngx_http_upstream_init_fair_peer; ++ ++ return NGX_OK; ++} ++ ++ ++static void ++ngx_http_upstream_fair_update_nreq(ngx_http_upstream_fair_peer_data_t *fp, int delta, ngx_log_t *log) ++{ ++ ngx_uint_t nreq; ++ ngx_uint_t total_nreq; ++ ++ nreq = (fp->peers->peer[fp->current].shared->nreq += delta); ++ total_nreq = (fp->peers->shared->total_nreq += delta); ++ ++ ngx_log_debug6(NGX_LOG_DEBUG_HTTP, log, 0, ++ "[upstream_fair] nreq for peer %ui @ %p/%p now %d, total %d, delta %d", ++ fp->current, fp->peers, fp->peers->peer[fp->current].shared, nreq, ++ total_nreq, delta); ++} ++ ++/* ++ * SCHED_COUNTER_BITS is the portion of an ngx_uint_t which represents ++ * the req_delta part (number of requests serviced on _other_ ++ * backends). The rest (top bits) represents the number of currently ++ * processed requests. ++ * ++ * The value is not too critical because overflow is handled via ++ * saturation. With the default value of 20, scheduling is exact for ++ * fewer than 4k concurrent requests per backend (on 32-bit ++ * architectures) and fewer than 1M concurrent requests to all backends ++ * together. Beyond these limits, the algorithm essentially falls back ++ * to pure weighted round-robin. ++ * ++ * A higher score means less suitable. ++ * ++ * The `delta' parameter is bit-negated so that high values yield low ++ * scores and get chosen more often. ++ */ ++ ++#define SCHED_COUNTER_BITS 20 ++#define SCHED_NREQ_MAX ((~0UL) >> SCHED_COUNTER_BITS) ++#define SCHED_COUNTER_MAX ((1 << SCHED_COUNTER_BITS) - 1) ++#define SCHED_SCORE(nreq,delta) (((nreq) << SCHED_COUNTER_BITS) | (~(delta))) ++#define ngx_upstream_fair_min(a,b) (((a) < (b)) ? (a) : (b)) ++ ++static ngx_uint_t ++ngx_http_upstream_fair_sched_score(ngx_peer_connection_t *pc, ++ ngx_http_upstream_fair_peer_data_t *fp, ++ ngx_uint_t n) ++{ ++ ngx_http_upstream_fair_peer_t *peer = &fp->peers->peer[n]; ++ ngx_http_upstream_fair_shared_t *fs = peer->shared; ++ ngx_uint_t req_delta = fp->peers->shared->total_requests - fs->last_req_id; ++ ++ /* sanity check */ ++ if ((ngx_int_t)fs->nreq < 0) { ++ ngx_log_error(NGX_LOG_WARN, pc->log, 0, "[upstream_fair] upstream %ui has negative nreq (%i)", n, fs->nreq); ++ return SCHED_SCORE(0, req_delta); ++ } ++ ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] peer %ui: nreq = %i, req_delta = %ui", n, fs->nreq, req_delta); ++ ++ return SCHED_SCORE( ++ ngx_upstream_fair_min(fs->nreq, SCHED_NREQ_MAX), ++ ngx_upstream_fair_min(req_delta, SCHED_COUNTER_MAX)); ++} ++ ++/* ++ * the core of load balancing logic ++ */ ++ ++static ngx_int_t ++ngx_http_upstream_fair_try_peer(ngx_peer_connection_t *pc, ++ ngx_http_upstream_fair_peer_data_t *fp, ++ ngx_uint_t peer_id) ++{ ++ ngx_http_upstream_fair_peer_t *peer; ++ ++ if (ngx_bitvector_test(fp->tried, peer_id)) ++ return NGX_BUSY; ++ ++ peer = &fp->peers->peer[peer_id]; ++ ++ if (!peer->down) { ++ if (peer->max_fails == 0 || peer->shared->fails < peer->max_fails) { ++ return NGX_OK; ++ } ++ ++ if (ngx_time() - peer->accessed > peer->fail_timeout) { ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] resetting fail count for peer %d, time delta %d > %d", ++ peer_id, ngx_time() - peer->accessed, peer->fail_timeout); ++ peer->shared->fails = 0; ++ return NGX_OK; ++ } ++ } ++ ++ return NGX_BUSY; ++} ++ ++static ngx_uint_t ++ngx_http_upstream_choose_fair_peer_idle(ngx_peer_connection_t *pc, ++ ngx_http_upstream_fair_peer_data_t *fp) ++{ ++ ngx_uint_t i, n; ++ ngx_uint_t npeers = fp->peers->number; ++ ngx_uint_t weight_mode = fp->peers->weight_mode; ++ ngx_uint_t best_idx = NGX_PEER_INVALID; ++ ngx_uint_t best_nreq = ~0U; ++ ++ for (i = 0, n = fp->current; i < npeers; i++, n = (n + 1) % npeers) { ++ ngx_uint_t nreq = fp->peers->peer[n].shared->nreq; ++ ngx_uint_t weight = fp->peers->peer[n].weight; ++ ++ if (fp->peers->peer[n].shared->fails > 0) ++ continue; ++ ++ if (nreq >= weight || (nreq > 0 && weight_mode != WM_IDLE)) { ++ continue; ++ } ++ ++ if (ngx_http_upstream_fair_try_peer(pc, fp, n) != NGX_OK) { ++ continue; ++ } ++ ++ /* not in WM_IDLE+no_rr mode: the first completely idle backend gets chosen */ ++ if (weight_mode != WM_IDLE || !fp->peers->no_rr) { ++ best_idx = n; ++ break; ++ } ++ ++ /* in WM_IDLE+no_rr mode we actually prefer slightly loaded backends ++ * to totally idle ones, under the assumption that they're spawned ++ * on demand and can handle up to 'weight' concurrent requests ++ */ ++ if (best_idx == NGX_PEER_INVALID || nreq) { ++ if (best_nreq <= nreq) { ++ continue; ++ } ++ best_idx = n; ++ best_nreq = nreq; ++ } ++ } ++ ++ return best_idx; ++} ++ ++static ngx_int_t ++ngx_http_upstream_choose_fair_peer_busy(ngx_peer_connection_t *pc, ++ ngx_http_upstream_fair_peer_data_t *fp) ++{ ++ ngx_uint_t i, n; ++ ngx_uint_t npeers = fp->peers->number; ++ ngx_uint_t weight_mode = fp->peers->weight_mode; ++ ngx_uint_t best_idx = NGX_PEER_INVALID; ++ ngx_uint_t sched_score; ++ ngx_uint_t best_sched_score = ~0UL; ++ ++ /* ++ * calculate sched scores for all the peers, choosing the lowest one ++ */ ++ for (i = 0, n = fp->current; i < npeers; i++, n = (n + 1) % npeers) { ++ ngx_http_upstream_fair_peer_t *peer; ++ ngx_uint_t nreq; ++ ngx_uint_t weight; ++ ++ peer = &fp->peers->peer[n]; ++ nreq = fp->peers->peer[n].shared->nreq; ++ ++ if (weight_mode == WM_PEAK && nreq >= peer->weight) { ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] backend %d has nreq %ui >= weight %ui in WM_PEAK mode", n, nreq, peer->weight); ++ continue; ++ } ++ ++ if (ngx_http_upstream_fair_try_peer(pc, fp, n) != NGX_OK) { ++ if (!pc->tries) { ++ ngx_log_debug(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] all backends exhausted"); ++ return NGX_PEER_INVALID; ++ } ++ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] backend %d already tried", n); ++ continue; ++ } ++ ++ sched_score = ngx_http_upstream_fair_sched_score(pc, fp, n); ++ ++ if (weight_mode == WM_DEFAULT) { ++ /* ++ * take peer weight into account ++ */ ++ weight = peer->shared->current_weight; ++ if (peer->max_fails) { ++ ngx_uint_t mf = peer->max_fails; ++ weight = peer->shared->current_weight * (mf - peer->shared->fails) / mf; ++ } ++ if (weight > 0) { ++ sched_score /= weight; ++ } ++ ngx_log_debug8(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] bss = %ui, ss = %ui (n = %d, w = %d/%d, f = %d/%d, weight = %d)", ++ best_sched_score, sched_score, n, peer->shared->current_weight, peer->weight, peer->shared->fails, peer->max_fails, weight); ++ } ++ ++ if (sched_score <= best_sched_score) { ++ best_idx = n; ++ best_sched_score = sched_score; ++ } ++ } ++ ++ return best_idx; ++} ++ ++static ngx_int_t ++ngx_http_upstream_choose_fair_peer(ngx_peer_connection_t *pc, ++ ngx_http_upstream_fair_peer_data_t *fp, ngx_uint_t *peer_id) ++{ ++ ngx_uint_t npeers; ++ ngx_uint_t best_idx = NGX_PEER_INVALID; ++ ngx_uint_t weight_mode; ++ ++ npeers = fp->peers->number; ++ weight_mode = fp->peers->weight_mode; ++ ++ /* just a single backend */ ++ if (npeers == 1) { ++ *peer_id = 0; ++ return NGX_OK; ++ } ++ ++ /* any idle backends? */ ++ best_idx = ngx_http_upstream_choose_fair_peer_idle(pc, fp); ++ if (best_idx != NGX_PEER_INVALID) { ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] peer %i is idle", best_idx); ++ goto chosen; ++ } ++ ++ /* no idle backends, choose the least loaded one */ ++ best_idx = ngx_http_upstream_choose_fair_peer_busy(pc, fp); ++ if (best_idx != NGX_PEER_INVALID) { ++ goto chosen; ++ } ++ ++ return NGX_BUSY; ++ ++chosen: ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] chose peer %i", best_idx); ++ *peer_id = best_idx; ++ ngx_bitvector_set(fp->tried, best_idx); ++ ++ if (weight_mode == WM_DEFAULT) { ++ ngx_http_upstream_fair_peer_t *peer = &fp->peers->peer[best_idx]; ++ ++ if (peer->shared->current_weight-- == 0) { ++ peer->shared->current_weight = peer->weight; ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] peer %d expired weight, reset to %d", best_idx, peer->weight); ++ } ++ } ++ return NGX_OK; ++} ++ ++ngx_int_t ++ngx_http_upstream_get_fair_peer(ngx_peer_connection_t *pc, void *data) ++{ ++ ngx_int_t ret; ++ ngx_uint_t peer_id, i; ++ ngx_http_upstream_fair_peer_data_t *fp = data; ++ ngx_http_upstream_fair_peer_t *peer; ++ ngx_atomic_t *lock; ++ ++ peer_id = fp->current; ++ fp->current = (fp->current + 1) % fp->peers->number; ++ ++ lock = &fp->peers->shared->lock; ++ ngx_spinlock(lock, ngx_pid, 1024); ++ ret = ngx_http_upstream_choose_fair_peer(pc, fp, &peer_id); ++ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] fp->current = %d, peer_id = %d, ret = %d", ++ fp->current, peer_id, ret); ++ ++ if (pc) ++ pc->tries--; ++ ++ if (ret == NGX_BUSY) { ++ for (i = 0; i < fp->peers->number; i++) { ++ fp->peers->peer[i].shared->fails = 0; ++ } ++ ++ pc->name = fp->peers->name; ++ fp->current = NGX_PEER_INVALID; ++ ngx_spinlock_unlock(lock); ++ return NGX_BUSY; ++ } ++ ++ /* assert(ret == NGX_OK); */ ++ peer = &fp->peers->peer[peer_id]; ++ fp->current = peer_id; ++ if (!fp->peers->no_rr) { ++ fp->peers->current = peer_id; ++ } ++ pc->sockaddr = peer->sockaddr; ++ pc->socklen = peer->socklen; ++ pc->name = &peer->name; ++ ++ peer->shared->last_req_id = fp->peers->shared->total_requests; ++ ngx_http_upstream_fair_update_nreq(fp, 1, pc->log); ++ peer->shared->total_req++; ++ ngx_spinlock_unlock(lock); ++ return ret; ++} ++ ++ ++void ++ngx_http_upstream_free_fair_peer(ngx_peer_connection_t *pc, void *data, ++ ngx_uint_t state) ++{ ++ ngx_http_upstream_fair_peer_data_t *fp = data; ++ ngx_http_upstream_fair_peer_t *peer; ++ ngx_atomic_t *lock; ++ ++ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] fp->current = %d, state = %ui, pc->tries = %d, pc->data = %p", ++ fp->current, state, pc->tries, pc->data); ++ ++ if (fp->current == NGX_PEER_INVALID) { ++ return; ++ } ++ ++ lock = &fp->peers->shared->lock; ++ ngx_spinlock(lock, ngx_pid, 1024); ++ if (!ngx_bitvector_test(fp->done, fp->current)) { ++ ngx_bitvector_set(fp->done, fp->current); ++ ngx_http_upstream_fair_update_nreq(fp, -1, pc->log); ++ } ++ ++ if (fp->peers->number == 1) { ++ pc->tries = 0; ++ } ++ ++ if (state & NGX_PEER_FAILED) { ++ peer = &fp->peers->peer[fp->current]; ++ ++ peer->shared->fails++; ++ peer->accessed = ngx_time(); ++ } ++ ngx_spinlock_unlock(lock); ++} ++ ++/* ++ * walk through the rbtree, removing old entries and looking for ++ * a matching one -- compared by (cycle, peers) pair ++ * ++ * no attempt at optimisation is made, for two reasons: ++ * - the tree will be quite small, anyway ++ * - being called once per worker startup per upstream block, ++ * this code isn't really the hot path ++ */ ++static ngx_http_upstream_fair_shm_block_t * ++ngx_http_upstream_fair_walk_shm( ++ ngx_slab_pool_t *shpool, ++ ngx_rbtree_node_t *node, ++ ngx_rbtree_node_t *sentinel, ++ ngx_http_upstream_fair_peers_t *peers) ++{ ++ ngx_http_upstream_fair_shm_block_t *uf_node; ++ ngx_http_upstream_fair_shm_block_t *found_node = NULL; ++ ngx_http_upstream_fair_shm_block_t *tmp_node; ++ ++ if (node == sentinel) { ++ return NULL; ++ } ++ ++ /* visit left node */ ++ if (node->left != sentinel) { ++ tmp_node = ngx_http_upstream_fair_walk_shm(shpool, node->left, ++ sentinel, peers); ++ if (tmp_node) { ++ found_node = tmp_node; ++ } ++ } ++ ++ /* visit right node */ ++ if (node->right != sentinel) { ++ tmp_node = ngx_http_upstream_fair_walk_shm(shpool, node->right, ++ sentinel, peers); ++ if (tmp_node) { ++ found_node = tmp_node; ++ } ++ } ++ ++ /* visit current node */ ++ uf_node = (ngx_http_upstream_fair_shm_block_t *) node; ++ if (uf_node->generation != ngx_http_upstream_fair_generation) { ++ ngx_spinlock(&uf_node->lock, ngx_pid, 1024); ++ if (uf_node->total_nreq == 0) { ++ /* don't bother unlocking */ ++ ngx_rbtree_delete(ngx_http_upstream_fair_rbtree, node); ++ ngx_slab_free_locked(shpool, node); ++ } ++ ngx_spinlock_unlock(&uf_node->lock); ++ } else if (uf_node->peers == (uintptr_t) peers) { ++ found_node = uf_node; ++ } ++ ++ return found_node; ++} ++ ++static ngx_int_t ++ngx_http_upstream_fair_shm_alloc(ngx_http_upstream_fair_peers_t *usfp, ngx_log_t *log) ++{ ++ ngx_slab_pool_t *shpool; ++ ngx_uint_t i; ++ ++ if (usfp->shared) { ++ return NGX_OK; ++ } ++ ++ shpool = (ngx_slab_pool_t *)ngx_http_upstream_fair_shm_zone->shm.addr; ++ ++ ngx_shmtx_lock(&shpool->mutex); ++ ++ usfp->shared = ngx_http_upstream_fair_walk_shm(shpool, ++ ngx_http_upstream_fair_rbtree->root, ++ ngx_http_upstream_fair_rbtree->sentinel, ++ usfp); ++ ++ if (usfp->shared) { ++ ngx_shmtx_unlock(&shpool->mutex); ++ return NGX_OK; ++ } ++ ++ usfp->shared = ngx_slab_alloc_locked(shpool, ++ sizeof(ngx_http_upstream_fair_shm_block_t) + ++ (usfp->number - 1) * sizeof(ngx_http_upstream_fair_shared_t)); ++ ++ if (!usfp->shared) { ++ ngx_shmtx_unlock(&shpool->mutex); ++ if (!usfp->size_err) { ++ ngx_log_error(NGX_LOG_EMERG, log, 0, ++ "upstream_fair_shm_size too small (current value is %udKiB)", ++ ngx_http_upstream_fair_shm_size >> 10); ++ usfp->size_err = 1; ++ } ++ return NGX_ERROR; ++ } ++ ++ usfp->shared->node.key = ngx_crc32_short((u_char *) &ngx_cycle, sizeof ngx_cycle) ^ ++ ngx_crc32_short((u_char *) &usfp, sizeof(usfp)); ++ ++ usfp->shared->generation = ngx_http_upstream_fair_generation; ++ usfp->shared->peers = (uintptr_t) usfp; ++ usfp->shared->total_nreq = 0; ++ usfp->shared->total_requests = 0; ++ ++ for (i = 0; i < usfp->number; i++) { ++ usfp->shared->stats[i].nreq = 0; ++ usfp->shared->stats[i].last_req_id = 0; ++ usfp->shared->stats[i].total_req = 0; ++ } ++ ++ ngx_rbtree_insert(ngx_http_upstream_fair_rbtree, &usfp->shared->node); ++ ++ ngx_shmtx_unlock(&shpool->mutex); ++ return NGX_OK; ++} ++ ++ngx_int_t ++ngx_http_upstream_init_fair_peer(ngx_http_request_t *r, ++ ngx_http_upstream_srv_conf_t *us) ++{ ++ ngx_http_upstream_fair_peer_data_t *fp; ++ ngx_http_upstream_fair_peers_t *usfp; ++ ngx_uint_t n; ++ ++ fp = r->upstream->peer.data; ++ ++ if (fp == NULL) { ++ fp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_fair_peer_data_t)); ++ if (fp == NULL) { ++ return NGX_ERROR; ++ } ++ ++ r->upstream->peer.data = fp; ++ } ++ ++ usfp = us->peer.data; ++ ++ fp->tried = ngx_bitvector_alloc(r->pool, usfp->number, &fp->data); ++ fp->done = ngx_bitvector_alloc(r->pool, usfp->number, &fp->data2); ++ ++ if (fp->tried == NULL || fp->done == NULL) { ++ return NGX_ERROR; ++ } ++ ++ /* set up shared memory area */ ++ ngx_http_upstream_fair_shm_alloc(usfp, r->connection->log); ++ ++ fp->current = usfp->current; ++ fp->peers = usfp; ++ usfp->shared->total_requests++; ++ ++ for (n = 0; n < usfp->number; n++) { ++ usfp->peer[n].shared = &usfp->shared->stats[n]; ++ } ++ ++ r->upstream->peer.get = ngx_http_upstream_get_fair_peer; ++ r->upstream->peer.free = ngx_http_upstream_free_fair_peer; ++ r->upstream->peer.tries = usfp->number; ++#if (NGX_HTTP_SSL) ++ r->upstream->peer.set_session = ++ ngx_http_upstream_fair_set_session; ++ r->upstream->peer.save_session = ++ ngx_http_upstream_fair_save_session; ++#endif ++ ++ return NGX_OK; ++} ++ ++#if (NGX_HTTP_SSL) ++static ngx_int_t ++ngx_http_upstream_fair_set_session(ngx_peer_connection_t *pc, void *data) ++{ ++ ngx_http_upstream_fair_peer_data_t *fp = data; ++ ++ ngx_int_t rc; ++ ngx_ssl_session_t *ssl_session; ++ ngx_http_upstream_fair_peer_t *peer; ++ ++ if (fp->current == NGX_PEER_INVALID) ++ return NGX_OK; ++ ++ peer = &fp->peers->peer[fp->current]; ++ ++ /* TODO: threads only mutex */ ++ /* ngx_lock_mutex(fp->peers->mutex); */ ++ ++ ssl_session = peer->ssl_session; ++ ++ rc = ngx_ssl_set_session(pc->connection, ssl_session); ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "set session: %p:%d", ++ ssl_session, ssl_session ? ssl_session->references : 0); ++ ++ /* ngx_unlock_mutex(fp->peers->mutex); */ ++ ++ return rc; ++} ++ ++static void ++ngx_http_upstream_fair_save_session(ngx_peer_connection_t *pc, void *data) ++{ ++ ngx_http_upstream_fair_peer_data_t *fp = data; ++ ++ ngx_ssl_session_t *old_ssl_session, *ssl_session; ++ ngx_http_upstream_fair_peer_t *peer; ++ ++ if (fp->current == NGX_PEER_INVALID) ++ return; ++ ++ ssl_session = ngx_ssl_get_session(pc->connection); ++ ++ if (ssl_session == NULL) { ++ return; ++ } ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "save session: %p:%d", ssl_session, ssl_session->references); ++ ++ peer = &fp->peers->peer[fp->current]; ++ ++ /* TODO: threads only mutex */ ++ /* ngx_lock_mutex(fp->peers->mutex); */ ++ ++ old_ssl_session = peer->ssl_session; ++ peer->ssl_session = ssl_session; ++ ++ /* ngx_unlock_mutex(fp->peers->mutex); */ ++ ++ if (old_ssl_session) { ++ ++ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, ++ "old session: %p:%d", ++ old_ssl_session, old_ssl_session->references); ++ ++ /* TODO: may block */ ++ ++ ngx_ssl_free_session(old_ssl_session); ++ } ++} ++ ++#endif ++ ++#if (NGX_HTTP_EXTENDED_STATUS) ++static void ++ngx_http_upstream_fair_walk_status(ngx_pool_t *pool, ngx_chain_t *cl, ngx_int_t *length, ++ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) ++{ ++ ngx_http_upstream_fair_shm_block_t *s_node = (ngx_http_upstream_fair_shm_block_t *) node; ++ ngx_http_upstream_fair_peers_t *peers; ++ ngx_chain_t *new_cl; ++ ngx_buf_t *b; ++ ngx_uint_t size, i; ++ ++ if (node == sentinel) { ++ return; ++ } ++ ++ if (node->left != sentinel) { ++ ngx_http_upstream_fair_walk_status(pool, cl, length, node->left, sentinel); ++ } ++ ++ if (s_node->generation != ngx_http_upstream_fair_generation) { ++ size = 100; ++ peers = NULL; ++ } else { ++ /* this is rather ugly (casting an uintptr_t back into a pointer ++ * but as long as the generation is still the same (verified above), ++ * it should be still safe ++ */ ++ peers = (ngx_http_upstream_fair_peers_t *) s_node->peers; ++ if (!peers->shared) { ++ goto next; ++ } ++ ++ size = 200 + peers->number * 120; /* LOTS of slack */ ++ } ++ ++ b = ngx_create_temp_buf(pool, size); ++ if (!b) { ++ goto next; ++ } ++ ++ new_cl = ngx_alloc_chain_link(pool); ++ if (!new_cl) { ++ goto next; ++ } ++ ++ new_cl->buf = b; ++ new_cl->next = NULL; ++ ++ while (cl->next) { ++ cl = cl->next; ++ } ++ cl->next = new_cl; ++ ++ if (peers) { ++ b->last = ngx_sprintf(b->last, "upstream %V (%p): current peer %d/%d, total requests: %ui\n", peers->name, (void*) node, peers->current, peers->number, s_node->total_requests); ++ for (i = 0; i < peers->number; i++) { ++ ngx_http_upstream_fair_peer_t *peer = &peers->peer[i]; ++ ngx_http_upstream_fair_shared_t *sh = peer->shared; ++ b->last = ngx_sprintf(b->last, " peer %d: %V weight: %d/%d, fails: %d/%d, acc: %d, down: %d, nreq: %d, total_req: %ui, last_req: %ui\n", ++ i, &peer->name, sh->current_weight, peer->weight, sh->fails, peer->max_fails, peer->accessed, peer->down, ++ sh->nreq, sh->total_req, sh->last_req_id); ++ } ++ } else { ++ b->last = ngx_sprintf(b->last, "upstream %p: gen %ui != %ui, total_nreq = %ui", (void*) node, s_node->generation, ngx_http_upstream_fair_generation, s_node->total_nreq); ++ } ++ b->last = ngx_sprintf(b->last, "\n"); ++ b->last_buf = 1; ++ ++ *length += b->last - b->pos; ++ ++ if (cl->buf) { ++ cl->buf->last_buf = 0; ++ } ++ ++ cl = cl->next; ++next: ++ ++ if (node->right != sentinel) { ++ ngx_http_upstream_fair_walk_status(pool, cl, length, node->right, sentinel); ++ } ++} ++ ++static ngx_chain_t* ++ngx_http_upstream_fair_report_status(ngx_http_request_t *r, ngx_int_t *length) ++{ ++ ngx_buf_t *b; ++ ngx_chain_t *cl; ++ ngx_slab_pool_t *shpool; ++ ++ b = ngx_create_temp_buf(r->pool, sizeof("\nupstream_fair status report:\n")); ++ if (!b) { ++ return NULL; ++ } ++ ++ cl = ngx_alloc_chain_link(r->pool); ++ if (!cl) { ++ return NULL; ++ } ++ cl->next = NULL; ++ cl->buf = b; ++ ++ b->last = ngx_cpymem(b->last, "\nupstream_fair status report:\n", ++ sizeof("\nupstream_fair status report:\n") - 1); ++ ++ *length = b->last - b->pos; ++ ++ shpool = (ngx_slab_pool_t *)ngx_http_upstream_fair_shm_zone->shm.addr; ++ ++ ngx_shmtx_lock(&shpool->mutex); ++ ++ ngx_http_upstream_fair_walk_status(r->pool, cl, ++ length, ++ ngx_http_upstream_fair_rbtree->root, ++ ngx_http_upstream_fair_rbtree->sentinel); ++ ++ ngx_shmtx_unlock(&shpool->mutex); ++ ++ if (!cl->next || !cl->next->buf) { ++ /* no upstream_fair status to report */ ++ return NULL; ++ } ++ ++ return cl; ++} ++#endif ++ ++/* vim: set et ts=4 sw=4: */ --- nginx-0.7.63.orig/debian/patches/00list +++ nginx-0.7.63/debian/patches/00list @@ -0,0 +1,2 @@ +dlopen.dpatch +nginx-upstream-fair.dpatch